88c367f2822a2c03a53db0cfc69a4423859b19cb
[yaffs-website] / web / core / modules / system / src / Controller / EntityAutocompleteController.php
1 <?php
2
3 namespace Drupal\system\Controller;
4
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Component\Utility\Tags;
7 use Drupal\Core\Controller\ControllerBase;
8 use Drupal\Core\Entity\EntityAutocompleteMatcher;
9 use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
10 use Drupal\Core\Site\Settings;
11 use Symfony\Component\DependencyInjection\ContainerInterface;
12 use Symfony\Component\HttpFoundation\JsonResponse;
13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
15
16 /**
17  * Defines a route controller for entity autocomplete form elements.
18  */
19 class EntityAutocompleteController extends ControllerBase {
20
21   /**
22    * The autocomplete matcher for entity references.
23    *
24    * @var \Drupal\Core\Entity\EntityAutocompleteMatcher
25    */
26   protected $matcher;
27
28   /**
29    * The key value store.
30    *
31    * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
32    */
33   protected $keyValue;
34
35   /**
36    * Constructs a EntityAutocompleteController object.
37    *
38    * @param \Drupal\Core\Entity\EntityAutocompleteMatcher $matcher
39    *   The autocomplete matcher for entity references.
40    * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $key_value
41    *   The key value factory.
42    */
43   public function __construct(EntityAutocompleteMatcher $matcher, KeyValueStoreInterface $key_value) {
44     $this->matcher = $matcher;
45     $this->keyValue = $key_value;
46   }
47
48   /**
49    * {@inheritdoc}
50    */
51   public static function create(ContainerInterface $container) {
52     return new static(
53       $container->get('entity.autocomplete_matcher'),
54       $container->get('keyvalue')->get('entity_autocomplete')
55     );
56   }
57
58   /**
59    * Autocomplete the label of an entity.
60    *
61    * @param \Symfony\Component\HttpFoundation\Request $request
62    *   The request object that contains the typed tags.
63    * @param string $target_type
64    *   The ID of the target entity type.
65    * @param string $selection_handler
66    *   The plugin ID of the entity reference selection handler.
67    * @param string $selection_settings_key
68    *   The hashed key of the key/value entry that holds the selection handler
69    *   settings.
70    *
71    * @return \Symfony\Component\HttpFoundation\JsonResponse
72    *   The matched entity labels as a JSON response.
73    *
74    * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
75    *   Thrown if the selection settings key is not found in the key/value store
76    *   or if it does not match the stored data.
77    */
78   public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) {
79     $matches = [];
80     // Get the typed string from the URL, if it exists.
81     if ($input = $request->query->get('q')) {
82       $typed_string = Tags::explode($input);
83       $typed_string = mb_strtolower(array_pop($typed_string));
84
85       // Selection settings are passed in as a hashed key of a serialized array
86       // stored in the key/value store.
87       $selection_settings = $this->keyValue->get($selection_settings_key, FALSE);
88       if ($selection_settings !== FALSE) {
89         $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt());
90         if ($selection_settings_hash !== $selection_settings_key) {
91           // Disallow access when the selection settings hash does not match the
92           // passed-in key.
93           throw new AccessDeniedHttpException('Invalid selection settings key.');
94         }
95       }
96       else {
97         // Disallow access when the selection settings key is not found in the
98         // key/value store.
99         throw new AccessDeniedHttpException();
100       }
101
102       $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string);
103     }
104
105     return new JsonResponse($matches);
106   }
107
108 }