Commit 00c3b4d8 authored by RoSk0's avatar RoSk0

Added CrmCoreUserSyncRelation service.

parent 77f40d18
services:
crm_core_user_sync.relation:
class: Drupal\crm_core_user_sync\CrmCoreUserSyncRelation
arguments: ['@entity_type.manager', '@crm_core_user_sync.relation_rules']
crm_core_user_sync.relation_rules:
class: Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules
arguments: ['@config.factory', 'crm_core_user_sync.settings']
<?php
namespace Drupal\crm_core_user_sync;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\crm_core_contact\Entity\Individual;
use Drupal\crm_core_contact\IndividualInterface;
use Drupal\crm_core_user_sync\Entity\Relation;
use Drupal\user\UserInterface;
/**
* CrmCoreUserSyncRelation service.
*/
class CrmCoreUserSyncRelation {
/**
* Relation storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $storage;
/**
* Relation rules service.
*
* @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules
*/
protected $rules;
/**
* Constructs a CrmCoreUserSyncRelation object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\crm_core_user_sync\CrmCoreUserSyncRelationRules $rules
* Relation rules service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, CrmCoreUserSyncRelationRules $rules) {
$this->storage = $entity_type_manager->getStorage('crm_core_user_sync_relation');
$this->rules = $rules;
}
/**
* Retrieves the individual contact id for specified user.
*
* @return int|null
* Individual id, if relation exists.
*/
public function getUserIndividualId($user_id) {
$individual_id = NULL;
$rids = $this->storage->getQuery()
->condition('user_id', $user_id)
->range(0, 1)
->execute();
if (!empty($rids)) {
$relation_id = reset($rids);
/* @var $relation \Drupal\crm_core_user_sync\Entity\Relation */
$relation = $this->storage->load($relation_id);
$individual_id = $relation->getIndividualId();
}
return $individual_id;
}
/**
* Retrieves the user id for specified individual contact.
*
* @return int|null
* User id, if relation exists.
*/
public function getIndividualUserId($individual_id) {
$user_id = NULL;
$rids = $this->storage->getQuery()
->condition('individual_id', $individual_id)
->range(0, 1)
->execute();
if (!empty($rids)) {
$relation_id = reset($rids);
/* @var $relation \Drupal\crm_core_user_sync\Entity\Relation */
$relation = $this->storage->load($relation_id);
$user_id = $relation->getIndividualId();
}
return $user_id;
}
/**
* Retrieves the relation for specified user.
*
* @return int|null
* Relation ID, if exists.
*/
public function getUserRelationId($user_id) {
$rids = $this->storage->getQuery()
->condition('user_id', $user_id)
->range(0, 1)
->execute();
if (!empty($rids)) {
return reset($rids);
}
return NULL;
}
/**
* Retrieves the user id for specified individual contact.
*
* @return int|null
* Relation ID, if exists.
*/
public function getIndividualRelationId($individual_id) {
$rids = $this->storage->getQuery()
->condition('individual_id', $individual_id)
->range(0, 1)
->execute();
if (!empty($rids)) {
return reset($rids);
}
return NULL;
}
/**
* Synchronizes user and contact.
*
* @param \Drupal\user\UserInterface $account
* Account to be synchronized. Programmatically created accounts can
* override default behavior by setting
* $account->crm_core_no_auto_sync = TRUE.
* @param \Drupal\crm_core_contact\IndividualInterface $contact
* Contact to be associated with $account.
*
* @return \Drupal\crm_core_contact\ContactInterface
* A contact object.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function relate(UserInterface $account, IndividualInterface $contact = NULL) {
// No contact and $account->crm_core_no_auto_sync => no sync.
if (empty($contact) && !empty($account->crm_core_no_auto_sync)) {
return NULL;
}
if (empty($contact)) {
// Get corresponding contact type.
$contact_type = $this->rules->getContactType($account);
// No rules configured.
if (!$contact_type) {
return NULL;
}
// Create the contact.
$contact = Individual::create(array('type' => $contact_type));
$contact->setOwner($account);
// For now we just add the name.
$contact->name->given = $account->getAccountName();
$contact->save();
}
// Check if contact can be synchronized to a contact.
if (!$this->rules->valid($account, $contact)) {
return NULL;
}
// Check if crm_core_user_sync relation exists for any of endpoint.
if ($this->getUserIndividualId($account->id()) ||
$this->getIndividualUserId($contact->id())) {
return NULL;
}
$relation = Relation::create();
$relation->setUser($account);
$relation->setIndividual($contact);
$relation->save();
\Drupal::logger('crm_core_user_sync')->notice('User @user has been synchronized to the contact @contact_id, relation @rid has been created.', [
'@user' => $account->getDisplayName(),
'@contact_id' => $contact->id(),
'@rid' => $relation->id(),
]);
return $contact;
}
}
<?php
namespace Drupal\Tests\crm_core_user_sync\Kernel;
use Drupal\crm_core_contact\Entity\Individual;
use Drupal\crm_core_contact\Entity\IndividualType;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\user\Entity\User;
/**
* Test description.
*
* @group crm_core_user_sync
*/
class CrmCoreUserSyncRelationTest extends EntityKernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'user',
'name',
'crm_core_contact',
'crm_core_user_sync',
];
/**
* Relation service.
*
* @var \Drupal\crm_core_user_sync\CrmCoreUserSyncRelation
*/
protected $relationService;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// User::delete() fails without this.
$this->installSchema('user', ['users_data']);
$this->installEntitySchema('crm_core_individual');
$this->installEntitySchema('crm_core_user_sync_relation');
$this->installConfig(['crm_core_user_sync']);
$role_storage = $this->container->get('entity.manager')->getStorage('user_role');
$role_storage->create(['id' => 'customer'])->save();
$config = $this->config('crm_core_user_sync.settings');
$rules[] = [
'role' => 'customer',
'contact_type' => 'customer',
'enabled' => TRUE,
'weight' => 1,
];
$rules[] = [
'role' => 'authenticated',
'contact_type' => 'individual',
'enabled' => TRUE,
'weight' => 10,
];
$config
->set('rules', $rules)
->set('auto_sync_user_create', TRUE)
->save();
$individual_type = $this
->container
->get('entity_type.manager')
->getStorage('crm_core_individual_type')
->create([
'type' => 'individual',
'primary_fields' => [],
]);
$individual_type->save();
$customer_type = $this
->container
->get('entity_type.manager')
->getStorage('crm_core_individual_type')
->create(['type' => 'customer', 'primary_fields' => []]);
$customer_type->save();
$this->relationService = $this->container->get('crm_core_user_sync.relation');
}
/**
* Tests that relation and related individual was created.
*/
public function testRelationCreated() {
$account_authenticated = User::create(['name' => 'authenticated']);
$account_authenticated->save();
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
$authenticated_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
$this->assertNotEmpty($authenticated_individual_id, 'Related contact was created');
$related_account_id = $this->relationService->getIndividualUserId($authenticated_individual_id);
$this->assertEquals($related_account_id, $account_authenticated->id(), 'Related ');
}
/**
* Tests that configured rules are respected when related contacts created.
*/
public function testRulesRespected() {
$account_authenticated = User::create(['name' => 'authenticated']);
$account_authenticated->save();
$contact_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
$this->assertNotEmpty($contact_individual_id, 'Individual contact was created when authenticated user account was created.');
$contact_individual = Individual::load($contact_individual_id);
$this->assertEquals('individual', $contact_individual->bundle(), 'Individual contact has correct bundle');
$customer_values = [
'name' => 'customer',
'roles' => ['customer'],
];
$account_customer = User::create($customer_values);
$account_customer->save();
$contact_customer_id = $this->relationService->getUserIndividualId($account_customer->id());
$this->assertNotEmpty($contact_customer_id, 'Individual contact was created when customer user account was created.');
$contact_customer = Individual::load($contact_customer_id);
$this->assertEquals('customer', $contact_customer->bundle(), 'Individual contact has correct bundle');
}
/**
* Tests that relation is deleted when user account id deleted.
*/
public function testRelationDeleted() {
$account_authenticated = User::create(['name' => 'authenticated']);
$account_authenticated->save();
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
$authenticated_individual_id = $this->relationService->getUserIndividualId($account_authenticated->id());
$this->assertNotEmpty($authenticated_individual_id, 'Related contact was created');
$account_authenticated->delete();
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertEmpty($authenticated_relation_id, 'Relation was deleted');
$authenticated_individual = Individual::load($authenticated_individual_id);
$this->assertTrue(is_object($authenticated_individual), 'Related contact still exists');
$individual_relation_id = $this->relationService->getIndividualRelationId($authenticated_individual->id());
$this->assertEmpty($individual_relation_id, 'Relation was deleted');
}
/**
* Tests that configured rules could be programmatically overridden.
*
* @see \Drupal\crm_core_user_sync\CrmCoreUserSyncRelation::relate()
*/
public function testRulesOverride() {
$account_authenticated = User::create([
'name' => 'authenticated',
'crm_core_no_auto_sync' => TRUE,
]);
$account_authenticated->save();
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertEmpty($authenticated_relation_id, 'Relation was not created');
$individual_customer = Individual::create(['type' => 'customer']);
$individual_customer->save();
$this->relationService->relate($account_authenticated, $individual_customer);
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertEmpty($authenticated_relation_id, 'Relation was not created');
$individual_individual = Individual::create(['type' => 'individual']);
$individual_individual->save();
$this->relationService->relate($account_authenticated, $individual_individual);
$authenticated_relation_id = $this->relationService->getUserRelationId($account_authenticated->id());
$this->assertNotEmpty($authenticated_relation_id, 'Relation was created');
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment