Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / lib / Drupal / Core / Entity / Plugin / EntityReferenceSelection / PhpSelection.php
1 <?php
2
3 namespace Drupal\Core\Entity\Plugin\EntityReferenceSelection;
4
5 use Drupal\Component\Utility\Html;
6
7 /**
8  * Defines an alternative to the default Entity Reference Selection plugin.
9  *
10  * This selection plugin uses PHP for more advanced cases when the entity query
11  * cannot filter properly, for example when the target entity type has no
12  * 'label' key provided in the entity type plugin definition.
13  *
14  * @see \Drupal\Core\Entity\Plugin\Derivative\DefaultSelectionDeriver
15  */
16 class PhpSelection extends DefaultSelection {
17
18   /**
19    * {@inheritdoc}
20    */
21   public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
22     // No input, return everything from the entity query.
23     if ($match === NULL || $match === '') {
24       return parent::getReferenceableEntities($match, $match_operator, $limit);
25     }
26
27     // Start with the selection results returned by the entity query. Don't use
28     // any limit because we have to apply a limit after filtering the items.
29     $options = parent::getReferenceableEntities($match, $match_operator);
30
31     // Always use a case-insensitive, escaped match. Entity labels returned by
32     // SelectionInterface::getReferenceableEntities() are already escaped, so
33     // the incoming $match needs to be escaped as well, making the comparison
34     // possible.
35     // @see \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface::getReferenceableEntities()
36     if (is_string($match)) {
37       $match = Html::escape(mb_strtolower($match));
38     }
39     elseif (is_array($match)) {
40       array_walk($match, function (&$item) {
41         $item = Html::escape(mb_strtolower($item));
42       });
43     }
44
45     $filtered = [];
46     $count = 0;
47     // Filter target entities by the output of their label() method.
48     foreach ($options as $bundle => &$items) {
49       foreach ($items as $entity_id => $label) {
50         if ($this->matchLabel($match, $match_operator, $label)) {
51           $filtered[$bundle][$entity_id] = $label;
52           $count++;
53
54           if ($limit && $count >= $limit) {
55             break 2;
56           }
57         }
58       }
59     }
60
61     return $filtered;
62   }
63
64   /**
65    * {@inheritdoc}
66    */
67   public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') {
68     $count = 0;
69     foreach ($this->getReferenceableEntities($match, $match_operator) as &$items) {
70       $count += count($items);
71     }
72
73     return $count;
74   }
75
76   /**
77    * Matches an entity label to an input string.
78    *
79    * @param mixed $match
80    *   The value to compare. This can be any valid entity query condition value.
81    * @param string $match_operator
82    *   The comparison operator.
83    * @param string $label
84    *   The entity label to match against.
85    *
86    * @return bool
87    *   TRUE when matches, FALSE otherwise.
88    */
89   protected function matchLabel($match, $match_operator, $label) {
90     // Always use a case-insensitive value.
91     $label = mb_strtolower($label);
92
93     switch ($match_operator) {
94       case '=':
95         return $label == $match;
96       case '>':
97         return $label > $match;
98       case '<':
99         return $label < $match;
100       case '>=':
101         return $label >= $match;
102       case '<=':
103         return $label <= $match;
104       case '<>':
105         return $label != $match;
106       case 'IN':
107         return array_search($label, $match) !== FALSE;
108       case 'NOT IN':
109         return array_search($label, $match) === FALSE;
110       case 'STARTS_WITH':
111         return strpos($label, $match) === 0;
112       case 'CONTAINS':
113         return strpos($label, $match) !== FALSE;
114       case 'ENDS_WITH':
115         return mb_substr($label, -mb_strlen($match)) === (string) $match;
116       case 'IS NOT NULL':
117         return TRUE;
118       case 'IS NULL':
119         return FALSE;
120       default:
121         // Invalid match operator.
122         return FALSE;
123     }
124   }
125
126 }