Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x

PhpSelection.php

Namespace

Drupal\Core\Entity\Plugin\EntityReferenceSelection

File

core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php

View source
<?php

namespace Drupal\Core\Entity\Plugin\EntityReferenceSelection;

use Drupal\Component\Utility\Html;

/**
 * Defines an alternative to the default Entity Reference Selection plugin.
 *
 * This selection plugin uses PHP for more advanced cases when the entity query
 * cannot filter properly, for example when the target entity type has no
 * 'label' key provided in the entity type plugin definition.
 *
 * @see \Drupal\Core\Entity\Plugin\Derivative\DefaultSelectionDeriver
 */
class PhpSelection extends DefaultSelection {
    
    /**
     * {@inheritdoc}
     */
    public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
        // No input, return everything from the entity query.
        if ($match === NULL || $match === '') {
            return parent::getReferenceableEntities($match, $match_operator, $limit);
        }
        // Start with the selection results returned by the entity query. Don't use
        // any limit because we have to apply a limit after filtering the items.
        $options = parent::getReferenceableEntities($match, $match_operator);
        // Always use a case-insensitive, escaped match. Entity labels returned by
        // SelectionInterface::getReferenceableEntities() are already escaped, so
        // the incoming $match needs to be escaped as well, making the comparison
        // possible.
        // @see \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface::getReferenceableEntities()
        if (is_string($match)) {
            $match = Html::escape(mb_strtolower($match));
        }
        elseif (is_array($match)) {
            array_walk($match, function (&$item) {
                $item = Html::escape(mb_strtolower($item));
            });
        }
        $filtered = [];
        $count = 0;
        // Filter target entities by the output of their label() method.
        foreach ($options as $bundle => &$items) {
            foreach ($items as $entity_id => $label) {
                if ($this->matchLabel($match, $match_operator, $label)) {
                    $filtered[$bundle][$entity_id] = $label;
                    $count++;
                    if ($limit && $count >= $limit) {
                        break 2;
                    }
                }
            }
        }
        return $filtered;
    }
    
    /**
     * {@inheritdoc}
     */
    public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') {
        $count = 0;
        foreach ($this->getReferenceableEntities($match, $match_operator) as &$items) {
            $count += count($items);
        }
        return $count;
    }
    
    /**
     * Matches an entity label to an input string.
     *
     * @param mixed $match
     *   The value to compare. This can be any valid entity query condition value.
     * @param string $match_operator
     *   The comparison operator.
     * @param string $label
     *   The entity label to match against.
     *
     * @return bool
     *   TRUE when matches, FALSE otherwise.
     */
    protected function matchLabel($match, $match_operator, $label) {
        // Always use a case-insensitive value.
        $label = mb_strtolower($label);
        switch ($match_operator) {
            case '=':
                return $label == $match;
            case '>':
                return $label > $match;
            case '<':
                return $label < $match;
            case '>=':
                return $label >= $match;
            case '<=':
                return $label <= $match;
            case '<>':
                return $label != $match;
            case 'IN':
                return array_search($label, $match) !== FALSE;
            case 'NOT IN':
                return array_search($label, $match) === FALSE;
            case 'STARTS_WITH':
                return str_starts_with($label, $match);
            case 'CONTAINS':
                return str_contains($label, $match);
            case 'ENDS_WITH':
                return str_ends_with($label, $match);
            case 'IS NOT NULL':
                return TRUE;
            case 'IS NULL':
                return FALSE;
            default:
                // Invalid match operator.
                return FALSE;
        }
    }

}

Classes

Title Deprecated Summary
PhpSelection Defines an alternative to the default Entity Reference Selection plugin.

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal