Jump to content

Synchronise users between sites with PW multi-instance


Robin S
 Share

Recommended Posts

I needed to do this and thought the code might be useful for others too.

In my case the organisation has a main site (Site A) and a related but separate site (Site B). The objective is for the users at Site B to be automatically kept in sync with the users of Site A via PW multi-instance. Users are only manually created or deleted in Site A. Both sites have the same roles configured.

// InputfieldPassword::processInput
$wire->addHookAfter('InputfieldPassword::processInput', function(HookEvent $event) {
	/** @var InputfieldPassword $inputfield */
	$inputfield = $event->object;
	$input = $event->arguments(0);
	/** @var UserPage $page */
	$page = $inputfield->hasPage;
	if($page->template != 'user') return;
	// Return early if there are any password errors
	if($inputfield->getErrors()) return;
	// Get the new password as cleartext from $input
	$pass = $input->get($inputfield->name);
	if(!$pass) return;
	// Set the password as a custom property on the Page object
	$page->newPass = $pass;
});

// Pages::saved
$pages->addHookAfter('saved', function(HookEvent $event) {
	/** @var UserPage $page */
	$page = $event->arguments(0);
	if($page->template != 'user') return;
	if($page->isUnpublished()) return;

	// Update or create user in Site B
	$site_b = new ProcessWire('/home/siteb/siteb.domain.nz/', 'https://siteb.domain.nz/');
	/** @var UserPage $u */
	$u = $site_b->users->get($page->name);
	// Create a new user if none exists with this name
	if(!$u->id) $u = $site_b->users->add($page->name);
	// Set the password if the custom property was set in the InputfieldPassword::processInput hook
	if($page->newPass) $u->pass = $page->newPass;
	// Set email address
	$u->email = $page->email;
	// Set roles
	$u->roles->removeAll();
	foreach($page->roles as $role) {
		$u->addRole($role->name);
	}
	$u->save();
});

// Pages::deleteReady
$pages->addHookAfter('deleteReady', function(HookEvent $event) {
	/** @var Page $page */
	$page = $event->arguments(0);
	if($page->template != 'user') return;

	// Delete user in Site B
	$site_b = new ProcessWire('/home/siteb/siteb.domain.nz/', 'https://siteb.domain.nz/');
	$u = $site_b->users->get($page->name);
	if(!$u->id) return;
	$site_b->users->delete($u);
});

This assumes the use of the default "user" template and not an alternative template. In my case the user template only has the default fields, but the code could be adapted if you have additional fields in your user template.

This doesn't handle renaming of users as that's not something I have a need for. But there would be ways to achieve this too, e.g. store the user ID for Site B in a field on the user template in Site A, and then get the Site B user by ID rather than name.

  • Like 5
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...