Upgraded drupal core with security updates
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / EntityAutocompleteTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Entity;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Component\Utility\Crypt;
7 use Drupal\Component\Utility\Html;
8 use Drupal\Component\Utility\Tags;
9 use Drupal\Core\Site\Settings;
10 use Drupal\system\Controller\EntityAutocompleteController;
11 use Symfony\Component\HttpFoundation\Request;
12 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
13
14 /**
15  * Tests the autocomplete functionality.
16  *
17  * @group Entity
18  */
19 class EntityAutocompleteTest extends EntityKernelTestBase {
20
21   /**
22    * The entity type used in this test.
23    *
24    * @var string
25    */
26   protected $entityType = 'entity_test';
27
28   /**
29    * The bundle used in this test.
30    *
31    * @var string
32    */
33   protected $bundle = 'entity_test';
34
35   /**
36    * {@inheritdoc}
37    */
38   protected function setUp() {
39     parent::setUp();
40     $this->installSchema('system', ['key_value']);
41   }
42
43   /**
44    * Tests autocompletion edge cases with slashes in the names.
45    */
46   public function testEntityReferenceAutocompletion() {
47     // Add an entity with a slash in its name.
48     $entity_1 = $this->container->get('entity_type.manager')
49       ->getStorage($this->entityType)
50       ->create(['name' => '10/16/2011']);
51     $entity_1->save();
52
53     // Add another entity that differs after the slash character.
54     $entity_2 = $this->container->get('entity_type.manager')
55       ->getStorage($this->entityType)
56       ->create(['name' => '10/17/2011']);
57     $entity_2->save();
58
59     // Add another entity that has both a comma, a slash and markup.
60     $entity_3 = $this->container->get('entity_type.manager')
61       ->getStorage($this->entityType)
62       ->create(['name' => 'label with, and / test']);
63     $entity_3->save();
64
65     // Try to autocomplete a entity label that matches both entities.
66     // We should get both entities in a JSON encoded string.
67     $input = '10/';
68     $data = $this->getAutocompleteResult($input);
69     $this->assertIdentical($data[0]['label'], Html::escape($entity_1->name->value), 'Autocomplete returned the first matching entity');
70     $this->assertIdentical($data[1]['label'], Html::escape($entity_2->name->value), 'Autocomplete returned the second matching entity');
71
72     // Try to autocomplete a entity label that matches the first entity.
73     // We should only get the first entity in a JSON encoded string.
74     $input = '10/16';
75     $data = $this->getAutocompleteResult($input);
76     $target = [
77       'value' => $entity_1->name->value . ' (1)',
78       'label' => Html::escape($entity_1->name->value),
79     ];
80     $this->assertIdentical(reset($data), $target, 'Autocomplete returns only the expected matching entity.');
81
82     // Try to autocomplete a entity label that matches the second entity, and
83     // the first entity  is already typed in the autocomplete (tags) widget.
84     $input = $entity_1->name->value . ' (1), 10/17';
85     $data = $this->getAutocompleteResult($input);
86     $this->assertIdentical($data[0]['label'], Html::escape($entity_2->name->value), 'Autocomplete returned the second matching entity');
87
88     // Try to autocomplete a entity label with both a comma, a slash and markup.
89     $input = '"label with, and /"';
90     $data = $this->getAutocompleteResult($input);
91     $n = $entity_3->name->value . ' (3)';
92     // Entity labels containing commas or quotes must be wrapped in quotes.
93     $n = Tags::encode($n);
94     $target = [
95       'value' => $n,
96       'label' => Html::escape($entity_3->name->value),
97     ];
98     $this->assertIdentical(reset($data), $target, 'Autocomplete returns an entity label containing a comma and a slash.');
99   }
100
101   /**
102    * Tests that missing or invalid selection setting key are handled correctly.
103    */
104   public function testSelectionSettingsHandling() {
105     $entity_reference_controller = EntityAutocompleteController::create($this->container);
106     $request = Request::create('entity_reference_autocomplete/' . $this->entityType . '/default');
107     $request->query->set('q', $this->randomString());
108
109     try {
110       // Pass an invalid selection settings key (i.e. one that does not exist
111       // in the key/value store).
112       $selection_settings_key = $this->randomString();
113       $entity_reference_controller->handleAutocomplete($request, $this->entityType, 'default', $selection_settings_key);
114
115       $this->fail('Non-existent selection settings key throws an exception.');
116     }
117     catch (AccessDeniedHttpException $e) {
118       $this->pass('Non-existent selection settings key throws an exception.');
119     }
120
121     try {
122       // Generate a valid hash key but store a modified settings array.
123       $selection_settings = [];
124       $selection_settings_key = Crypt::hmacBase64(serialize($selection_settings) . $this->entityType . 'default', Settings::getHashSalt());
125
126       $selection_settings[$this->randomMachineName()] = $this->randomString();
127       \Drupal::keyValue('entity_autocomplete')->set($selection_settings_key, $selection_settings);
128
129       $entity_reference_controller->handleAutocomplete($request, $this->entityType, 'default', $selection_settings_key);
130     }
131     catch (AccessDeniedHttpException $e) {
132       if ($e->getMessage() == 'Invalid selection settings key.') {
133         $this->pass('Invalid selection settings key throws an exception.');
134       }
135       else {
136         $this->fail('Invalid selection settings key throws an exception.');
137       }
138     }
139
140   }
141
142   /**
143    * Returns the result of an Entity reference autocomplete request.
144    *
145    * @param string $input
146    *   The label of the entity to query by.
147    *
148    * @return mixed
149    *   The JSON value encoded in its appropriate PHP type.
150    */
151   protected function getAutocompleteResult($input) {
152     $request = Request::create('entity_reference_autocomplete/' . $this->entityType . '/default');
153     $request->query->set('q', $input);
154
155     $selection_settings = [];
156     $selection_settings_key = Crypt::hmacBase64(serialize($selection_settings) . $this->entityType . 'default', Settings::getHashSalt());
157     \Drupal::keyValue('entity_autocomplete')->set($selection_settings_key, $selection_settings);
158
159     $entity_reference_controller = EntityAutocompleteController::create($this->container);
160     $result = $entity_reference_controller->handleAutocomplete($request, $this->entityType, 'default', $selection_settings_key)->getContent();
161
162     return Json::decode($result);
163   }
164
165 }