3 namespace Drupal\KernelTests\Core\Entity\Element;
5 use Drupal\Core\Entity\Element\EntityAutocomplete;
6 use Drupal\Core\Entity\EntityInterface;
7 use Drupal\Core\Form\FormInterface;
8 use Drupal\Core\Form\FormState;
9 use Drupal\Core\Form\FormStateInterface;
10 use Drupal\entity_test\Entity\EntityTest;
11 use Drupal\entity_test\Entity\EntityTestStringId;
12 use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
13 use Drupal\user\Entity\User;
16 * Tests the EntityAutocomplete Form API element.
20 class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements FormInterface {
25 * @var \Drupal\user\UserInterface
30 * User for autocreate testing.
32 * @var \Drupal\user\UserInterface
34 protected $testAutocreateUser;
37 * An array of entities to be referenced in this test.
39 * @var \Drupal\Core\Entity\EntityInterface[]
41 protected $referencedEntities;
46 protected function setUp() {
49 $this->installSchema('system', ['key_value_expire']);
50 $this->installEntitySchema('entity_test_string_id');
51 \Drupal::service('router.builder')->rebuild();
53 $this->testUser = User::create([
55 'mail' => 'foobar1@example.com',
57 $this->testUser->save();
58 \Drupal::service('current_user')->setAccount($this->testUser);
60 $this->testAutocreateUser = User::create([
62 'mail' => 'foobar2@example.com',
64 $this->testAutocreateUser->save();
66 for ($i = 1; $i < 3; $i++) {
67 $entity = EntityTest::create([
68 'name' => $this->randomMachineName()
71 $this->referencedEntities[] = $entity;
74 // Use special characters in the ID of some of the test entities so we can
75 // test if these are handled correctly.
76 for ($i = 0; $i < 2; $i++) {
77 $entity = EntityTestStringId::create([
78 'name' => $this->randomMachineName(),
79 'id' => $this->randomMachineName() . '&</\\:?',
82 $this->referencedEntities[] = $entity;
89 public function getFormId() {
90 return 'test_entity_autocomplete';
96 public function buildForm(array $form, FormStateInterface $form_state) {
98 '#type' => 'entity_autocomplete',
99 '#target_type' => 'entity_test',
101 $form['single_autocreate'] = [
102 '#type' => 'entity_autocomplete',
103 '#target_type' => 'entity_test',
105 'bundle' => 'entity_test',
108 $form['single_autocreate_specific_uid'] = [
109 '#type' => 'entity_autocomplete',
110 '#target_type' => 'entity_test',
112 'bundle' => 'entity_test',
113 'uid' => $this->testAutocreateUser->id(),
118 '#type' => 'entity_autocomplete',
119 '#target_type' => 'entity_test',
122 $form['tags_autocreate'] = [
123 '#type' => 'entity_autocomplete',
124 '#target_type' => 'entity_test',
127 'bundle' => 'entity_test',
130 $form['tags_autocreate_specific_uid'] = [
131 '#type' => 'entity_autocomplete',
132 '#target_type' => 'entity_test',
135 'bundle' => 'entity_test',
136 'uid' => $this->testAutocreateUser->id(),
140 $form['single_no_validate'] = [
141 '#type' => 'entity_autocomplete',
142 '#target_type' => 'entity_test',
143 '#validate_reference' => FALSE,
145 $form['single_autocreate_no_validate'] = [
146 '#type' => 'entity_autocomplete',
147 '#target_type' => 'entity_test',
148 '#validate_reference' => FALSE,
150 'bundle' => 'entity_test',
154 $form['single_access'] = [
155 '#type' => 'entity_autocomplete',
156 '#target_type' => 'entity_test',
157 '#default_value' => $this->referencedEntities[0],
159 $form['tags_access'] = [
160 '#type' => 'entity_autocomplete',
161 '#target_type' => 'entity_test',
163 '#default_value' => [$this->referencedEntities[0], $this->referencedEntities[1]],
166 $form['single_string_id'] = [
167 '#type' => 'entity_autocomplete',
168 '#target_type' => 'entity_test_string_id',
170 $form['tags_string_id'] = [
171 '#type' => 'entity_autocomplete',
172 '#target_type' => 'entity_test_string_id',
182 public function submitForm(array &$form, FormStateInterface $form_state) {}
187 public function validateForm(array &$form, FormStateInterface $form_state) {}
190 * Tests valid entries in the EntityAutocomplete Form API element.
192 public function testValidEntityAutocompleteElement() {
193 $form_state = (new FormState())
195 'single' => $this->getAutocompleteInput($this->referencedEntities[0]),
196 'single_autocreate' => 'single - autocreated entity label',
197 'single_autocreate_specific_uid' => 'single - autocreated entity label with specific uid',
198 'tags' => $this->getAutocompleteInput($this->referencedEntities[0]) . ', ' . $this->getAutocompleteInput($this->referencedEntities[1]),
200 $this->getAutocompleteInput($this->referencedEntities[0])
201 . ', tags - autocreated entity label, '
202 . $this->getAutocompleteInput($this->referencedEntities[1]),
203 'tags_autocreate_specific_uid' =>
204 $this->getAutocompleteInput($this->referencedEntities[0])
205 . ', tags - autocreated entity label with specific uid, '
206 . $this->getAutocompleteInput($this->referencedEntities[1]),
207 'single_string_id' => $this->getAutocompleteInput($this->referencedEntities[2]),
208 'tags_string_id' => $this->getAutocompleteInput($this->referencedEntities[2]) . ', ' . $this->getAutocompleteInput($this->referencedEntities[3]),
210 $form_builder = $this->container->get('form_builder');
211 $form_builder->submitForm($this, $form_state);
214 $this->assertEqual(count($form_state->getErrors()), 0);
216 // Test the 'single' element.
217 $this->assertEqual($form_state->getValue('single'), $this->referencedEntities[0]->id());
219 // Test the 'single_autocreate' element.
220 $value = $form_state->getValue('single_autocreate');
221 $this->assertEqual($value['entity']->label(), 'single - autocreated entity label');
222 $this->assertEqual($value['entity']->bundle(), 'entity_test');
223 $this->assertEqual($value['entity']->getOwnerId(), $this->testUser->id());
225 // Test the 'single_autocreate_specific_uid' element.
226 $value = $form_state->getValue('single_autocreate_specific_uid');
227 $this->assertEqual($value['entity']->label(), 'single - autocreated entity label with specific uid');
228 $this->assertEqual($value['entity']->bundle(), 'entity_test');
229 $this->assertEqual($value['entity']->getOwnerId(), $this->testAutocreateUser->id());
231 // Test the 'tags' element.
233 ['target_id' => $this->referencedEntities[0]->id()],
234 ['target_id' => $this->referencedEntities[1]->id()],
236 $this->assertEqual($form_state->getValue('tags'), $expected);
238 // Test the 'single_autocreate' element.
239 $value = $form_state->getValue('tags_autocreate');
240 // First value is an existing entity.
241 $this->assertEqual($value[0]['target_id'], $this->referencedEntities[0]->id());
242 // Second value is an autocreated entity.
243 $this->assertTrue(!isset($value[1]['target_id']));
244 $this->assertEqual($value[1]['entity']->label(), 'tags - autocreated entity label');
245 $this->assertEqual($value[1]['entity']->getOwnerId(), $this->testUser->id());
246 // Third value is an existing entity.
247 $this->assertEqual($value[2]['target_id'], $this->referencedEntities[1]->id());
249 // Test the 'tags_autocreate_specific_uid' element.
250 $value = $form_state->getValue('tags_autocreate_specific_uid');
251 // First value is an existing entity.
252 $this->assertEqual($value[0]['target_id'], $this->referencedEntities[0]->id());
253 // Second value is an autocreated entity.
254 $this->assertTrue(!isset($value[1]['target_id']));
255 $this->assertEqual($value[1]['entity']->label(), 'tags - autocreated entity label with specific uid');
256 $this->assertEqual($value[1]['entity']->getOwnerId(), $this->testAutocreateUser->id());
257 // Third value is an existing entity.
258 $this->assertEqual($value[2]['target_id'], $this->referencedEntities[1]->id());
260 // Test the 'single_string_id' element.
261 $this->assertEquals($this->referencedEntities[2]->id(), $form_state->getValue('single_string_id'));
263 // Test the 'tags_string_id' element.
265 ['target_id' => $this->referencedEntities[2]->id()],
266 ['target_id' => $this->referencedEntities[3]->id()],
268 $this->assertEquals($expected, $form_state->getValue('tags_string_id'));
272 * Tests invalid entries in the EntityAutocomplete Form API element.
274 public function testInvalidEntityAutocompleteElement() {
275 $form_builder = $this->container->get('form_builder');
277 // Test 'single' with a entity label that doesn't exist
278 $form_state = (new FormState())
280 'single' => 'single - non-existent label',
282 $form_builder->submitForm($this, $form_state);
283 $this->assertEqual(count($form_state->getErrors()), 1);
284 $this->assertEqual($form_state->getErrors()['single'], t('There are no entities matching "%value".', ['%value' => 'single - non-existent label']));
286 // Test 'single' with a entity ID that doesn't exist.
287 $form_state = (new FormState())
289 'single' => 'single - non-existent label (42)',
291 $form_builder->submitForm($this, $form_state);
292 $this->assertEqual(count($form_state->getErrors()), 1);
293 $this->assertEqual($form_state->getErrors()['single'], t('The referenced entity (%type: %id) does not exist.', ['%type' => 'entity_test', '%id' => 42]));
295 // Do the same tests as above but on an element with '#validate_reference'
297 $form_state = (new FormState())
299 'single_no_validate' => 'single - non-existent label',
300 'single_autocreate_no_validate' => 'single - autocreate non-existent label'
302 $form_builder->submitForm($this, $form_state);
304 // The element without 'autocreate' support still has to emit a warning when
305 // the input doesn't end with an entity ID enclosed in parentheses.
306 $this->assertEqual(count($form_state->getErrors()), 1);
307 $this->assertEqual($form_state->getErrors()['single_no_validate'], t('There are no entities matching "%value".', ['%value' => 'single - non-existent label']));
309 $form_state = (new FormState())
311 'single_no_validate' => 'single - non-existent label (42)',
312 'single_autocreate_no_validate' => 'single - autocreate non-existent label (43)'
314 $form_builder->submitForm($this, $form_state);
316 // The input is complete (i.e. contains an entity ID at the end), no errors
318 $this->assertEqual(count($form_state->getErrors()), 0);
322 * Tests that access is properly checked by the EntityAutocomplete element.
324 public function testEntityAutocompleteAccess() {
325 $form_builder = $this->container->get('form_builder');
326 $form = $form_builder->getForm($this);
328 // Check that the current user has proper access to view entity labels.
329 $expected = $this->referencedEntities[0]->label() . ' (' . $this->referencedEntities[0]->id() . ')';
330 $this->assertEqual($form['single_access']['#value'], $expected);
332 $expected .= ', ' . $this->referencedEntities[1]->label() . ' (' . $this->referencedEntities[1]->id() . ')';
333 $this->assertEqual($form['tags_access']['#value'], $expected);
335 // Set up a non-admin user that is *not* allowed to view test entities.
336 \Drupal::currentUser()->setAccount($this->createUser([], []));
339 $form = $form_builder->getForm($this);
341 $expected = t('- Restricted access -') . ' (' . $this->referencedEntities[0]->id() . ')';
342 $this->assertEqual($form['single_access']['#value'], $expected);
344 $expected .= ', ' . t('- Restricted access -') . ' (' . $this->referencedEntities[1]->id() . ')';
345 $this->assertEqual($form['tags_access']['#value'], $expected);
349 * Tests ID input is handled correctly.
351 * E.g. This can happen with GET form parameters.
353 public function testEntityAutocompleteIdInput() {
354 /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
355 $form_builder = $this->container->get('form_builder');
356 // $form = $form_builder->getForm($this);
357 $form_state = (new FormState())
360 'single' => [['target_id' => $this->referencedEntities[0]->id()]],
361 'single_no_validate' => [['target_id' => $this->referencedEntities[0]->id()]],
364 $form_builder->submitForm($this, $form_state);
366 $form = $form_state->getCompleteForm();
368 $expected_label = $this->getAutocompleteInput($this->referencedEntities[0]);
369 $this->assertSame($expected_label, $form['single']['#value']);
370 $this->assertSame($expected_label, $form['single_no_validate']['#value']);
374 * Returns an entity label in the format needed by the EntityAutocomplete
377 * @param \Drupal\Core\Entity\EntityInterface $entity
381 * A string that can be used as a value for EntityAutocomplete elements.
383 protected function getAutocompleteInput(EntityInterface $entity) {
384 return EntityAutocomplete::getEntityLabels([$entity]);