Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 110 |
UserSelection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
506 | |
0.00% |
0 / 110 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
create | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 10 |
|||
buildConfigurationForm | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 43 |
|||
buildEntityQuery | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 13 |
|||
createNewEntity | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
validateReferenceableNewEntities | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
anonymous function | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
entityQueryAlter | |
0.00% |
0 / 1 |
72 | |
0.00% |
0 / 23 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\user\Plugin\EntityReferenceSelection\UserSelection. | |
*/ | |
namespace Drupal\user\Plugin\EntityReferenceSelection; | |
use Drupal\Core\Database\Connection; | |
use Drupal\Core\Database\Query\SelectInterface; | |
use Drupal\Core\Entity\EntityManagerInterface; | |
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; | |
use Drupal\Core\Extension\ModuleHandlerInterface; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Session\AccountInterface; | |
use Drupal\user\RoleInterface; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Provides specific access control for the user entity type. | |
* | |
* @EntityReferenceSelection( | |
* id = "default:user", | |
* label = @Translation("User selection"), | |
* entity_types = {"user"}, | |
* group = "default", | |
* weight = 1 | |
* ) | |
*/ | |
class UserSelection extends DefaultSelection { | |
/** | |
* The database connection. | |
* | |
* @var \Drupal\Core\Database\Connection | |
*/ | |
protected $connection; | |
/** | |
* The user storage. | |
* | |
* @var \Drupal\user\UserStorageInterface | |
*/ | |
protected $userStorage; | |
/** | |
* Constructs a new UserSelection object. | |
* | |
* @param array $configuration | |
* A configuration array containing information about the plugin instance. | |
* @param string $plugin_id | |
* The plugin_id for the plugin instance. | |
* @param mixed $plugin_definition | |
* The plugin implementation definition. | |
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
* The entity manager service. | |
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
* The module handler service. | |
* @param \Drupal\Core\Session\AccountInterface $current_user | |
* The current user. | |
* @param \Drupal\Core\Database\Connection $connection | |
* The database connection. | |
*/ | |
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, Connection $connection) { | |
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager, $module_handler, $current_user); | |
$this->connection = $connection; | |
$this->userStorage = $entity_manager->getStorage('user'); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
return new static( | |
$configuration, | |
$plugin_id, | |
$plugin_definition, | |
$container->get('entity.manager'), | |
$container->get('module_handler'), | |
$container->get('current_user'), | |
$container->get('database') | |
); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { | |
$selection_handler_settings = $this->configuration['handler_settings']; | |
// Merge in default values. | |
$selection_handler_settings += array( | |
'filter' => array( | |
'type' => '_none', | |
), | |
'include_anonymous' => TRUE, | |
); | |
$form['include_anonymous'] = array( | |
'#type' => 'checkbox', | |
'#title' => $this->t('Include the anonymous user.'), | |
'#default_value' => $selection_handler_settings['include_anonymous'], | |
); | |
// Add user specific filter options. | |
$form['filter']['type'] = array( | |
'#type' => 'select', | |
'#title' => $this->t('Filter by'), | |
'#options' => array( | |
'_none' => $this->t('- None -'), | |
'role' => $this->t('User role'), | |
), | |
'#ajax' => TRUE, | |
'#limit_validation_errors' => array(), | |
'#default_value' => $selection_handler_settings['filter']['type'], | |
); | |
$form['filter']['settings'] = array( | |
'#type' => 'container', | |
'#attributes' => array('class' => array('entity_reference-settings')), | |
'#process' => array(array('\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', 'formProcessMergeParent')), | |
); | |
if ($selection_handler_settings['filter']['type'] == 'role') { | |
// Merge in default values. | |
$selection_handler_settings['filter'] += array( | |
'role' => NULL, | |
); | |
$form['filter']['settings']['role'] = array( | |
'#type' => 'checkboxes', | |
'#title' => $this->t('Restrict to the selected roles'), | |
'#required' => TRUE, | |
'#options' => array_diff_key(user_role_names(TRUE), array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID)), | |
'#default_value' => $selection_handler_settings['filter']['role'], | |
); | |
} | |
$form += parent::buildConfigurationForm($form, $form_state); | |
return $form; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { | |
$query = parent::buildEntityQuery($match, $match_operator); | |
// The user entity doesn't have a label column. | |
if (isset($match)) { | |
$query->condition('name', $match, $match_operator); | |
} | |
// Filter by role. | |
$handler_settings = $this->configuration['handler_settings']; | |
if (!empty($handler_settings['filter']['role'])) { | |
$query->condition('roles', $handler_settings['filter']['role'], 'IN'); | |
} | |
// Adding the permission check is sadly insufficient for users: core | |
// requires us to also know about the concept of 'blocked' and 'active'. | |
if (!$this->currentUser->hasPermission('administer users')) { | |
$query->condition('status', 1); | |
} | |
return $query; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function createNewEntity($entity_type_id, $bundle, $label, $uid) { | |
$user = parent::createNewEntity($entity_type_id, $bundle, $label, $uid); | |
// In order to create a referenceable user, it needs to be active. | |
if (!$this->currentUser->hasPermission('administer users')) { | |
/** @var \Drupal\user\UserInterface $user */ | |
$user->activate(); | |
} | |
return $user; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function validateReferenceableNewEntities(array $entities) { | |
$entities = parent::validateReferenceableNewEntities($entities); | |
// Mirror the conditions checked in buildEntityQuery(). | |
if (!empty($this->configuration['handler_settings']['filter']['role'])) { | |
$entities = array_filter($entities, function ($user) { | |
/** @var \Drupal\user\UserInterface $user */ | |
return !empty(array_intersect($user->getRoles(), $this->configuration['handler_settings']['filter']['role'])); | |
}); | |
} | |
if (!$this->currentUser->hasPermission('administer users')) { | |
$entities = array_filter($entities, function ($user) { | |
/** @var \Drupal\user\UserInterface $user */ | |
return $user->isActive(); | |
}); | |
} | |
return $entities; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function entityQueryAlter(SelectInterface $query) { | |
// Bail out early if we do not need to match the Anonymous user. | |
$handler_settings = $this->configuration['handler_settings']; | |
if (isset($handler_settings['include_anonymous']) && !$handler_settings['include_anonymous']) { | |
return; | |
} | |
if ($this->currentUser->hasPermission('administer users')) { | |
// In addition, if the user is administrator, we need to make sure to | |
// match the anonymous user, that doesn't actually have a name in the | |
// database. | |
$conditions = &$query->conditions(); | |
foreach ($conditions as $key => $condition) { | |
if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users_field_data.name') { | |
// Remove the condition. | |
unset($conditions[$key]); | |
// Re-add the condition and a condition on uid = 0 so that we end up | |
// with a query in the form: | |
// WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0) | |
$or = db_or(); | |
$or->condition($condition['field'], $condition['value'], $condition['operator']); | |
// Sadly, the Database layer doesn't allow us to build a condition | |
// in the form ':placeholder = :placeholder2', because the 'field' | |
// part of a condition is always escaped. | |
// As a (cheap) workaround, we separately build a condition with no | |
// field, and concatenate the field and the condition separately. | |
$value_part = db_and(); | |
$value_part->condition('anonymous_name', $condition['value'], $condition['operator']); | |
$value_part->compile($this->connection, $query); | |
$or->condition(db_and() | |
->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => \Drupal::config('user.settings')->get('anonymous'))) | |
->condition('base_table.uid', 0) | |
); | |
$query->condition($or); | |
} | |
} | |
} | |
} | |
} |