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();
}