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