3

So I successfully migrated users from a Joomla 3 database into a Joomla 4 database. I am hoping there is a nicer way if anyone has done it.

In particular, I couldn't work out how to create a user using the UserModel with a specific Id. Hence I had to set the user table autoincrement in the database to a high number to avoid collisions for when I set them back.

I get the impression that using the UserModel here is completely redundant and this would be better as a raw sql insert - but the question is... is there a good way to programmatically create users with known ids and password hashes.

$options = [
    'host'  => 'localhost',
    'database' => 'xxxxxxxxxxxx',
    'password' => 'xxxxxxxxxxxx',
    'user' => 'xxxxxxxxxxxxxxx',
    'prefix' => 'xxxxxx_',
];

// Connect to Old Joomla 3 Database

$odb = (new DatabaseFactory)->getDriver('mysqli', $options);
   
$query = $odb->getQuery(true);
$query->select('*');
$query->from('#__users');
$query->order('id');
$odb->setQuery($query);
$existing_users = $odb->loadAssocList('username');

$MvcFactory = $app->bootComponent('com_users')->getMVCFactory();

foreach($existing_users as $data){

    // Start everyone as Registered
    $data['groups'] = [2];

    unset($data["id"]);
    unset($data["lastResetTime"]);
    unset($data["resetCount"]);
    unset($data["otpKey"]);
    unset($data["otep"]);
    unset($data["requireReset"]);
    unset($data["authProvider"]);
    unset($data["params"]);

    // This needs to be an array so either json_decode old value or set blank
    $data["params"] = [];

    // empty date should be NULL in these times
    if($data["lastvisitDate"] == "0000-00-00 00:00:00"){
        unset($data["lastvisitDate"]);
    }

    $userModel = $MvcFactory->createModel('User', 'Administrator', ['ignore_request' => true]);

    // This will make a new id and hash the old hashed password
    if (!$userModel->save($data)){
        throw new Exception($userModel->getError());
    }
}

// Now Set all the Ids and Passwords back as they were
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id,username');
$query->from('#__users');
$db->setQuery($query);
$users = $db->loadAssocList();

foreach($users as $u){

    // Skip any New Joomla 4 Users
    if(empty($existing_users[$u['username']])){continue;}

    $sql = 'UPDATE `#__users` SET `id` = ' . $existing_users[$u['username']]['id'] . ', `password` = "' . $existing_users[$u['username']]['password'] . '" WHERE `id` = ' . $u['id'];
    $sql2 = 'UPDATE `#__user_usergroup_map` SET `user_id` = ' . $existing_users[$u['username']]['id'] . ' WHERE `user_id` = ' . $u['id'];

    $db->setQuery($sql);
    $db->execute();
    $db->setQuery($sql2);
    $db->execute();

}
1
  • Since for this user migration the admin will use this script only one or max. few times, this script is good as it is (good help for anybody with the same problem) and this script does the job well as I see, does not require any Joomla optimization at the db query.
    – Zollie
    Mar 9 at 9:28

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.