Security update for Core, with self-updated composer
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / Element / EntityAutocompleteElementFormTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Entity\Element;
4
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;
14
15 /**
16  * Tests the EntityAutocomplete Form API element.
17  *
18  * @group Form
19  */
20 class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements FormInterface {
21
22   /**
23    * User for testing.
24    *
25    * @var \Drupal\user\UserInterface
26    */
27   protected $testUser;
28
29   /**
30    * User for autocreate testing.
31    *
32    * @var \Drupal\user\UserInterface
33    */
34   protected $testAutocreateUser;
35
36   /**
37    * An array of entities to be referenced in this test.
38    *
39    * @var \Drupal\Core\Entity\EntityInterface[]
40    */
41   protected $referencedEntities;
42
43   /**
44    * {@inheritdoc}
45    */
46   protected function setUp() {
47     parent::setUp();
48
49     $this->installSchema('system', ['key_value_expire']);
50     $this->installEntitySchema('entity_test_string_id');
51     \Drupal::service('router.builder')->rebuild();
52
53     $this->testUser = User::create([
54       'name' => 'foobar1',
55       'mail' => 'foobar1@example.com',
56     ]);
57     $this->testUser->save();
58     \Drupal::service('current_user')->setAccount($this->testUser);
59
60     $this->testAutocreateUser = User::create([
61       'name' => 'foobar2',
62       'mail' => 'foobar2@example.com',
63     ]);
64     $this->testAutocreateUser->save();
65
66     for ($i = 1; $i < 3; $i++) {
67       $entity = EntityTest::create([
68         'name' => $this->randomMachineName()
69       ]);
70       $entity->save();
71       $this->referencedEntities[] = $entity;
72     }
73
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() . '&</\\:?',
80       ]);
81       $entity->save();
82       $this->referencedEntities[] = $entity;
83     }
84   }
85
86   /**
87    * {@inheritdoc}
88    */
89   public function getFormId() {
90     return 'test_entity_autocomplete';
91   }
92
93   /**
94    * {@inheritdoc}
95    */
96   public function buildForm(array $form, FormStateInterface $form_state) {
97     $form['single'] = [
98       '#type' => 'entity_autocomplete',
99       '#target_type' => 'entity_test',
100     ];
101     $form['single_autocreate'] = [
102       '#type' => 'entity_autocomplete',
103       '#target_type' => 'entity_test',
104       '#autocreate' => [
105         'bundle' => 'entity_test',
106       ],
107     ];
108     $form['single_autocreate_specific_uid'] = [
109       '#type' => 'entity_autocomplete',
110       '#target_type' => 'entity_test',
111       '#autocreate' => [
112         'bundle' => 'entity_test',
113         'uid' => $this->testAutocreateUser->id(),
114       ],
115     ];
116
117     $form['tags'] = [
118       '#type' => 'entity_autocomplete',
119       '#target_type' => 'entity_test',
120       '#tags' => TRUE,
121     ];
122     $form['tags_autocreate'] = [
123       '#type' => 'entity_autocomplete',
124       '#target_type' => 'entity_test',
125       '#tags' => TRUE,
126       '#autocreate' => [
127         'bundle' => 'entity_test',
128       ],
129     ];
130     $form['tags_autocreate_specific_uid'] = [
131       '#type' => 'entity_autocomplete',
132       '#target_type' => 'entity_test',
133       '#tags' => TRUE,
134       '#autocreate' => [
135         'bundle' => 'entity_test',
136         'uid' => $this->testAutocreateUser->id(),
137       ],
138     ];
139
140     $form['single_no_validate'] = [
141       '#type' => 'entity_autocomplete',
142       '#target_type' => 'entity_test',
143       '#validate_reference' => FALSE,
144     ];
145     $form['single_autocreate_no_validate'] = [
146       '#type' => 'entity_autocomplete',
147       '#target_type' => 'entity_test',
148       '#validate_reference' => FALSE,
149       '#autocreate' => [
150         'bundle' => 'entity_test',
151       ],
152     ];
153
154     $form['single_access'] = [
155       '#type' => 'entity_autocomplete',
156       '#target_type' => 'entity_test',
157       '#default_value' => $this->referencedEntities[0],
158     ];
159     $form['tags_access'] = [
160       '#type' => 'entity_autocomplete',
161       '#target_type' => 'entity_test',
162       '#tags' => TRUE,
163       '#default_value' => [$this->referencedEntities[0], $this->referencedEntities[1]],
164     ];
165
166     $form['single_string_id'] = [
167       '#type' => 'entity_autocomplete',
168       '#target_type' => 'entity_test_string_id',
169     ];
170     $form['tags_string_id'] = [
171       '#type' => 'entity_autocomplete',
172       '#target_type' => 'entity_test_string_id',
173       '#tags' => TRUE,
174     ];
175
176     return $form;
177   }
178
179   /**
180    * {@inheritdoc}
181    */
182   public function submitForm(array &$form, FormStateInterface $form_state) {}
183
184   /**
185    * {@inheritdoc}
186    */
187   public function validateForm(array &$form, FormStateInterface $form_state) {}
188
189   /**
190    * Tests valid entries in the EntityAutocomplete Form API element.
191    */
192   public function testValidEntityAutocompleteElement() {
193     $form_state = (new FormState())
194       ->setValues([
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]),
199         'tags_autocreate' =>
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]),
209       ]);
210     $form_builder = $this->container->get('form_builder');
211     $form_builder->submitForm($this, $form_state);
212
213     // Valid form state.
214     $this->assertEqual(count($form_state->getErrors()), 0);
215
216     // Test the 'single' element.
217     $this->assertEqual($form_state->getValue('single'), $this->referencedEntities[0]->id());
218
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());
224
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());
230
231     // Test the 'tags' element.
232     $expected = [
233       ['target_id' => $this->referencedEntities[0]->id()],
234       ['target_id' => $this->referencedEntities[1]->id()],
235     ];
236     $this->assertEqual($form_state->getValue('tags'), $expected);
237
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());
248
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());
259
260     // Test the 'single_string_id' element.
261     $this->assertEquals($this->referencedEntities[2]->id(), $form_state->getValue('single_string_id'));
262
263     // Test the 'tags_string_id' element.
264     $expected = [
265       ['target_id' => $this->referencedEntities[2]->id()],
266       ['target_id' => $this->referencedEntities[3]->id()],
267     ];
268     $this->assertEquals($expected, $form_state->getValue('tags_string_id'));
269   }
270
271   /**
272    * Tests invalid entries in the EntityAutocomplete Form API element.
273    */
274   public function testInvalidEntityAutocompleteElement() {
275     $form_builder = $this->container->get('form_builder');
276
277     // Test 'single' with a entity label that doesn't exist
278     $form_state = (new FormState())
279       ->setValues([
280         'single' => 'single - non-existent label',
281       ]);
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']));
285
286     // Test 'single' with a entity ID that doesn't exist.
287     $form_state = (new FormState())
288       ->setValues([
289         'single' => 'single - non-existent label (42)',
290       ]);
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]));
294
295     // Do the same tests as above but on an element with '#validate_reference'
296     // set to FALSE.
297     $form_state = (new FormState())
298       ->setValues([
299         'single_no_validate' => 'single - non-existent label',
300         'single_autocreate_no_validate' => 'single - autocreate non-existent label'
301       ]);
302     $form_builder->submitForm($this, $form_state);
303
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']));
308
309     $form_state = (new FormState())
310       ->setValues([
311         'single_no_validate' => 'single - non-existent label (42)',
312         'single_autocreate_no_validate' => 'single - autocreate non-existent label (43)'
313       ]);
314     $form_builder->submitForm($this, $form_state);
315
316     // The input is complete (i.e. contains an entity ID at the end), no errors
317     // are triggered.
318     $this->assertEqual(count($form_state->getErrors()), 0);
319   }
320
321   /**
322    * Tests that access is properly checked by the EntityAutocomplete element.
323    */
324   public function testEntityAutocompleteAccess() {
325     $form_builder = $this->container->get('form_builder');
326     $form = $form_builder->getForm($this);
327
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);
331
332     $expected .= ', ' . $this->referencedEntities[1]->label() . ' (' . $this->referencedEntities[1]->id() . ')';
333     $this->assertEqual($form['tags_access']['#value'], $expected);
334
335     // Set up a non-admin user that is *not* allowed to view test entities.
336     \Drupal::currentUser()->setAccount($this->createUser([], []));
337
338     // Rebuild the form.
339     $form = $form_builder->getForm($this);
340
341     $expected = t('- Restricted access -') . ' (' . $this->referencedEntities[0]->id() . ')';
342     $this->assertEqual($form['single_access']['#value'], $expected);
343
344     $expected .= ', ' . t('- Restricted access -') . ' (' . $this->referencedEntities[1]->id() . ')';
345     $this->assertEqual($form['tags_access']['#value'], $expected);
346   }
347
348   /**
349    * Tests ID input is handled correctly.
350    *
351    * E.g. This can happen with GET form parameters.
352    */
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())
358       ->setMethod('GET')
359       ->setValues([
360         'single' => [['target_id' => $this->referencedEntities[0]->id()]],
361         'single_no_validate' => [['target_id' => $this->referencedEntities[0]->id()]],
362       ]);
363
364     $form_builder->submitForm($this, $form_state);
365
366     $form = $form_state->getCompleteForm();
367
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']);
371   }
372
373   /**
374    * Returns an entity label in the format needed by the EntityAutocomplete
375    * element.
376    *
377    * @param \Drupal\Core\Entity\EntityInterface $entity
378    *   A Drupal entity.
379    *
380    * @return string
381    *   A string that can be used as a value for EntityAutocomplete elements.
382    */
383   protected function getAutocompleteInput(EntityInterface $entity) {
384     return EntityAutocomplete::getEntityLabels([$entity]);
385   }
386
387 }