3 namespace Drupal\Core\Entity\Plugin\EntityReferenceSelection;
5 use Drupal\Component\Utility\Html;
6 use Drupal\Component\Utility\Unicode;
9 * Defines an alternative to the default Entity Reference Selection plugin.
11 * This selection plugin uses PHP for more advanced cases when the entity query
12 * cannot filter properly, for example when the target entity type has no
13 * 'label' key provided in the entity type plugin definition.
15 * @see \Drupal\Core\Entity\Plugin\Derivative\DefaultSelectionDeriver
17 class PhpSelection extends DefaultSelection {
22 public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
23 // No input, return everything from the entity query.
24 if ($match === NULL || $match === '') {
25 return parent::getReferenceableEntities($match, $match_operator, $limit);
28 // Start with the selection results returned by the entity query. Don't use
29 // any limit because we have to apply a limit after filtering the items.
30 $options = parent::getReferenceableEntities($match, $match_operator);
32 // Always use a case-insensitive, escaped match. Entity labels returned by
33 // SelectionInterface::getReferenceableEntities() are already escaped, so
34 // the incoming $match needs to be escaped as well, making the comparison
36 // @see \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface::getReferenceableEntities()
37 if (is_string($match)) {
38 $match = Html::escape(Unicode::strtolower($match));
40 elseif (is_array($match)) {
41 array_walk($match, function (&$item) {
42 $item = Html::escape(Unicode::strtolower($item));
48 // Filter target entities by the output of their label() method.
49 foreach ($options as $bundle => &$items) {
50 foreach ($items as $entity_id => $label) {
51 if ($this->matchLabel($match, $match_operator, $label)) {
52 $filtered[$bundle][$entity_id] = $label;
55 if ($limit && $count >= $limit) {
68 public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') {
70 foreach ($this->getReferenceableEntities($match, $match_operator) as &$items) {
71 $count += count($items);
78 * Matches an entity label to an input string.
81 * The value to compare. This can be any valid entity query condition value.
82 * @param string $match_operator
83 * The comparison operator.
84 * @param string $label
85 * The entity label to match against.
88 * TRUE when matches, FALSE otherwise.
90 protected function matchLabel($match, $match_operator, $label) {
91 // Always use a case-insensitive value.
92 $label = Unicode::strtolower($label);
94 switch ($match_operator) {
96 return $label == $match;
98 return $label > $match;
100 return $label < $match;
102 return $label >= $match;
104 return $label <= $match;
106 return $label != $match;
108 return array_search($label, $match) !== FALSE;
110 return array_search($label, $match) === FALSE;
112 return strpos($label, $match) === 0;
114 return strpos($label, $match) !== FALSE;
116 return Unicode::substr($label, -Unicode::strlen($match)) === (string) $match;
122 // Invalid match operator.