Mercurial > hg > isophonics-drupal-site
comparison core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\user\Plugin\EntityReferenceSelection; | |
4 | |
5 use Drupal\Core\Database\Connection; | |
6 use Drupal\Core\Database\Query\Condition; | |
7 use Drupal\Core\Database\Query\SelectInterface; | |
8 use Drupal\Core\Entity\EntityManagerInterface; | |
9 use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; | |
10 use Drupal\Core\Extension\ModuleHandlerInterface; | |
11 use Drupal\Core\Form\FormStateInterface; | |
12 use Drupal\Core\Session\AccountInterface; | |
13 use Drupal\user\RoleInterface; | |
14 use Symfony\Component\DependencyInjection\ContainerInterface; | |
15 | |
16 /** | |
17 * Provides specific access control for the user entity type. | |
18 * | |
19 * @EntityReferenceSelection( | |
20 * id = "default:user", | |
21 * label = @Translation("User selection"), | |
22 * entity_types = {"user"}, | |
23 * group = "default", | |
24 * weight = 1 | |
25 * ) | |
26 */ | |
27 class UserSelection extends DefaultSelection { | |
28 | |
29 /** | |
30 * The database connection. | |
31 * | |
32 * @var \Drupal\Core\Database\Connection | |
33 */ | |
34 protected $connection; | |
35 | |
36 /** | |
37 * The user storage. | |
38 * | |
39 * @var \Drupal\user\UserStorageInterface | |
40 */ | |
41 protected $userStorage; | |
42 | |
43 /** | |
44 * Constructs a new UserSelection object. | |
45 * | |
46 * @param array $configuration | |
47 * A configuration array containing information about the plugin instance. | |
48 * @param string $plugin_id | |
49 * The plugin_id for the plugin instance. | |
50 * @param mixed $plugin_definition | |
51 * The plugin implementation definition. | |
52 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
53 * The entity manager service. | |
54 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
55 * The module handler service. | |
56 * @param \Drupal\Core\Session\AccountInterface $current_user | |
57 * The current user. | |
58 * @param \Drupal\Core\Database\Connection $connection | |
59 * The database connection. | |
60 */ | |
61 public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, Connection $connection) { | |
62 parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_manager, $module_handler, $current_user); | |
63 | |
64 $this->connection = $connection; | |
65 $this->userStorage = $entity_manager->getStorage('user'); | |
66 } | |
67 | |
68 /** | |
69 * {@inheritdoc} | |
70 */ | |
71 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
72 return new static( | |
73 $configuration, | |
74 $plugin_id, | |
75 $plugin_definition, | |
76 $container->get('entity.manager'), | |
77 $container->get('module_handler'), | |
78 $container->get('current_user'), | |
79 $container->get('database') | |
80 ); | |
81 } | |
82 | |
83 /** | |
84 * {@inheritdoc} | |
85 */ | |
86 public function defaultConfiguration() { | |
87 return [ | |
88 'filter' => [ | |
89 'type' => '_none', | |
90 'role' => NULL, | |
91 ], | |
92 'include_anonymous' => TRUE, | |
93 ] + parent::defaultConfiguration(); | |
94 } | |
95 | |
96 /** | |
97 * {@inheritdoc} | |
98 */ | |
99 public function buildConfigurationForm(array $form, FormStateInterface $form_state) { | |
100 $configuration = $this->getConfiguration(); | |
101 | |
102 $form['include_anonymous'] = [ | |
103 '#type' => 'checkbox', | |
104 '#title' => $this->t('Include the anonymous user.'), | |
105 '#default_value' => $configuration['include_anonymous'], | |
106 ]; | |
107 | |
108 // Add user specific filter options. | |
109 $form['filter']['type'] = [ | |
110 '#type' => 'select', | |
111 '#title' => $this->t('Filter by'), | |
112 '#options' => [ | |
113 '_none' => $this->t('- None -'), | |
114 'role' => $this->t('User role'), | |
115 ], | |
116 '#ajax' => TRUE, | |
117 '#limit_validation_errors' => [], | |
118 '#default_value' => $configuration['filter']['type'], | |
119 ]; | |
120 | |
121 $form['filter']['settings'] = [ | |
122 '#type' => 'container', | |
123 '#attributes' => ['class' => ['entity_reference-settings']], | |
124 '#process' => [['\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', 'formProcessMergeParent']], | |
125 ]; | |
126 | |
127 if ($configuration['filter']['type'] == 'role') { | |
128 $form['filter']['settings']['role'] = [ | |
129 '#type' => 'checkboxes', | |
130 '#title' => $this->t('Restrict to the selected roles'), | |
131 '#required' => TRUE, | |
132 '#options' => array_diff_key(user_role_names(TRUE), [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]), | |
133 '#default_value' => $configuration['filter']['role'], | |
134 ]; | |
135 } | |
136 | |
137 $form += parent::buildConfigurationForm($form, $form_state); | |
138 | |
139 return $form; | |
140 } | |
141 | |
142 /** | |
143 * {@inheritdoc} | |
144 */ | |
145 protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { | |
146 $query = parent::buildEntityQuery($match, $match_operator); | |
147 | |
148 $configuration = $this->getConfiguration(); | |
149 | |
150 // Filter out the Anonymous user if the selection handler is configured to | |
151 // exclude it. | |
152 if (!$configuration['include_anonymous']) { | |
153 $query->condition('uid', 0, '<>'); | |
154 } | |
155 | |
156 // The user entity doesn't have a label column. | |
157 if (isset($match)) { | |
158 $query->condition('name', $match, $match_operator); | |
159 } | |
160 | |
161 // Filter by role. | |
162 if (!empty($configuration['filter']['role'])) { | |
163 $query->condition('roles', $configuration['filter']['role'], 'IN'); | |
164 } | |
165 | |
166 // Adding the permission check is sadly insufficient for users: core | |
167 // requires us to also know about the concept of 'blocked' and 'active'. | |
168 if (!$this->currentUser->hasPermission('administer users')) { | |
169 $query->condition('status', 1); | |
170 } | |
171 return $query; | |
172 } | |
173 | |
174 /** | |
175 * {@inheritdoc} | |
176 */ | |
177 public function createNewEntity($entity_type_id, $bundle, $label, $uid) { | |
178 $user = parent::createNewEntity($entity_type_id, $bundle, $label, $uid); | |
179 | |
180 // In order to create a referenceable user, it needs to be active. | |
181 if (!$this->currentUser->hasPermission('administer users')) { | |
182 /** @var \Drupal\user\UserInterface $user */ | |
183 $user->activate(); | |
184 } | |
185 | |
186 return $user; | |
187 } | |
188 | |
189 /** | |
190 * {@inheritdoc} | |
191 */ | |
192 public function validateReferenceableNewEntities(array $entities) { | |
193 $entities = parent::validateReferenceableNewEntities($entities); | |
194 // Mirror the conditions checked in buildEntityQuery(). | |
195 if ($role = $this->getConfiguration()['filter']['role']) { | |
196 $entities = array_filter($entities, function ($user) use ($role) { | |
197 /** @var \Drupal\user\UserInterface $user */ | |
198 return !empty(array_intersect($user->getRoles(), $role)); | |
199 }); | |
200 } | |
201 if (!$this->currentUser->hasPermission('administer users')) { | |
202 $entities = array_filter($entities, function ($user) { | |
203 /** @var \Drupal\user\UserInterface $user */ | |
204 return $user->isActive(); | |
205 }); | |
206 } | |
207 return $entities; | |
208 } | |
209 | |
210 /** | |
211 * {@inheritdoc} | |
212 */ | |
213 public function entityQueryAlter(SelectInterface $query) { | |
214 parent::entityQueryAlter($query); | |
215 | |
216 // Bail out early if we do not need to match the Anonymous user. | |
217 if (!$this->getConfiguration()['include_anonymous']) { | |
218 return; | |
219 } | |
220 | |
221 if ($this->currentUser->hasPermission('administer users')) { | |
222 // In addition, if the user is administrator, we need to make sure to | |
223 // match the anonymous user, that doesn't actually have a name in the | |
224 // database. | |
225 $conditions = &$query->conditions(); | |
226 foreach ($conditions as $key => $condition) { | |
227 if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users_field_data.name') { | |
228 // Remove the condition. | |
229 unset($conditions[$key]); | |
230 | |
231 // Re-add the condition and a condition on uid = 0 so that we end up | |
232 // with a query in the form: | |
233 // WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0) | |
234 $or = new Condition('OR'); | |
235 $or->condition($condition['field'], $condition['value'], $condition['operator']); | |
236 // Sadly, the Database layer doesn't allow us to build a condition | |
237 // in the form ':placeholder = :placeholder2', because the 'field' | |
238 // part of a condition is always escaped. | |
239 // As a (cheap) workaround, we separately build a condition with no | |
240 // field, and concatenate the field and the condition separately. | |
241 $value_part = new Condition('AND'); | |
242 $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); | |
243 $value_part->compile($this->connection, $query); | |
244 $or->condition((new Condition('AND')) | |
245 ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) | |
246 ->condition('base_table.uid', 0) | |
247 ); | |
248 $query->condition($or); | |
249 } | |
250 } | |
251 } | |
252 } | |
253 | |
254 } |