Same filename and directory in other branches
  1. 1.1.x src/Plugin/Field/FieldFormatter/EntityReferenceFilteredLinkFormatter.php 1 comment

Namespace

Drupal\entity_ref_filtering_link\Plugin\Field\FieldFormatter

File

src/Plugin/Field/FieldFormatter/EntityReferenceFilteredLinkFormatter.php

View source
<?php

declare (strict_types=1);
namespace Drupal\entity_ref_filtering_link\Plugin\Field\FieldFormatter;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Path\PathValidatorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'entity_reference_filtered_link' formatter.
 *
 * @FieldFormatter(
 *   id = "entity_reference_filtered_link",
 *   label = @Translation("Filter Link"),
 *   description = @Translation("Display the label of the referenced entities linking to a pre-filtered view"),
 *   field_types = {
 *     "entity_reference"
 *   }
 * )
 */
class EntityReferenceFilteredLinkFormatter extends EntityReferenceFormatterBase {
    
    /**
     * Path Validator Service.
     *
     * @var \Drupal\Core\Path\PathValidatorInterface
     */
    protected PathValidatorInterface $pathValidator;
    
    /**
     * Constructs a FormatterBase object.
     *
     * @param string $plugin_id
     *   The plugin_id for the formatter.
     * @param mixed[] $plugin_definition
     *   The plugin implementation definition.
     * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
     *   The definition of the field to which the formatter is associated.
     * @param mixed[] $settings
     *   The formatter settings.
     * @param string $label
     *   The formatter label display setting.
     * @param string $view_mode
     *   The view mode.
     * @param mixed[] $third_party_settings
     *   Any third party settings.
     * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
     *   The path validator service.
     */
    public function __construct(string $plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, string $label, string $view_mode, array $third_party_settings, PathValidatorInterface $path_validator) {
        parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
        $this->pathValidator = $path_validator;
    }
    
    /**
     * {@inheritdoc}
     */
    public function settingsForm(array $form, FormStateInterface $form_state) {
        $elements = [];
        $elements['view_url'] = [
            '#title' => $this->t('Url to the base page to apply the filter'),
            '#type' => 'textfield',
            '#default_value' => $this->getSetting('view_url'),
            '#required' => TRUE,
            '#description' => $this->t('If linking to a node or similar entity, it is strongly recommended to use the /node/### form to ensure that the link works even if the friendly url is changed.'),
        ];
        $elements['argument_name'] = [
            '#title' => $this->t('Argument Name'),
            '#type' => 'textfield',
            '#default_value' => $this->getArgumentName(),
            '#required' => TRUE,
            '#description' => $this->t('The argument identifier for within urls.'),
        ];
        $elements['mode'] = [
            '#title' => $this->t('Argument Mode'),
            '#required' => TRUE,
            '#type' => 'select',
            '#options' => [
                'id' => $this->t('Standard [$id]'),
                'id_multiple' => $this->t('Standard Multiple[] [$id]'),
                'id_multiple_d9' => $this->t('Standard Double Bracketed Multiple[$id] [$id]'),
                'autocomplete' => $this->t('Autocomplete [$label ($id)]'),
                'facet' => $this->t('Facet - ID [$id]'),
                'label' => $this->t('Facet - Label [$label]'),
                'label_no_facet' => $this->t('Label [$label]'),
            ],
            '#default_value' => $this->getSetting('mode'),
        ];
        $elements['skip_access_check'] = [
            '#title' => $this->t('Skip Access Check'),
            '#type' => 'checkbox',
            '#default_value' => $this->getSetting('skip_access_check'),
            '#description' => $this->t('If the view url is permission controlled but you still want to display it for users without access (such as to have them be able to click and be redirected to login page), enable this.'),
        ];
        $elements['disable'] = [
            '#title' => $this->t('Skip Linking'),
            '#type' => 'textfield',
            '#default_value' => $this->getSetting('disable'),
            '#description' => $this->t('Add comma seperated list of entity labels, if some references on this field should not have filter links generated for them.'),
        ];
        return $elements;
    }
    
    /**
     * {@inheritdoc}
     */
    public function settingsSummary() {
        $summary = [];
        $summary[] = $this->t('View Url: @url', [
            '@url' => $this->getSetting('view_url'),
        ]);
        $summary[] = $this->t('Argument Name: @arg', [
            '@arg' => $this->getArgumentName(),
        ]);
        $summary[] = $this->t('Using @mode mode', [
            '@mode' => $this->getSetting('mode'),
        ]);
        if ($this->getSetting('skip_access_check')) {
            $summary[] = $this->t('Skipping access check');
        }
        return $summary;
    }
    
    /**
     * {@inheritdoc}
     */
    public function viewElements(FieldItemListInterface $items, $langcode) {
        $elements = [];
        $view_url = $this->getSetting('view_url');
        $skip_access = $this->getSetting('skip_access_check');
        $mode = $this->getSetting('mode');
        $argument = $this->getSetting('argument');
        $disable = $this->getSetting('disable');
        $disable = !empty($disable) ? explode(",", $disable) : [];
        foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
            $label = $entity->label();
            if (in_array($label, $disable)) {
                $elements[$delta] = [
                    '#plain_text' => $label,
                ];
                continue;
            }
            if ($id = $entity->id()) {
                if ($skip_access) {
                    $url = $this->pathValidator
                        ->getUrlIfValidWithoutAccessCheck($view_url);
                }
                else {
                    $url = $this->pathValidator
                        ->getUrlIfValid($view_url);
                }
                if (!$url) {
                    $elements[$delta] = [
                        '#plain_text' => $label,
                    ];
                    continue;
                }
                $options = $url->getOptions();
                switch ($mode) {
                    case 'id':
                        $options['query'][$argument] = $id;
                        break;
                    case 'id_multiple':
                        $options['query']["{$argument}[]"] = $id;
                        break;
                    case 'id_multiple_d9':
                        $options['query']["{$argument}[{$id}]"] = $id;
                        break;
                    case 'autocomplete':
                        $options['query'][$argument] = "{$entity->label()} ({$id})";
                        break;
                    case 'facet':
                        $options['query']['f[0]'] = "{$argument}:{$id}";
                        break;
                    case 'label':
                        $options['query']['f[0]'] = "{$argument}:{$entity->label()}";
                        break;
                    case 'label_no_facet':
                        $options['query'][$argument] = $entity->label();
                        break;
                }
                $url->setOptions($options);
                $elements[$delta] = [
                    '#type' => 'link',
                    '#title' => $label,
                    '#url' => $url,
                    '#options' => $options,
                ];
                if (!empty($items[$delta]->_attributes)) {
                    $elements[$delta]['#options'] += [
                        'attributes' => [],
                    ];
                    $elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
                    // Unset field item attributes since they have been included in the
                    // formatter output and shouldn't be rendered in the field template.
                    unset($items[$delta]->_attributes);
                }
            }
            else {
                $elements[$delta] = [
                    '#plain_text' => $label,
                ];
            }
            $elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
        }
        return $elements;
    }
    
    /**
     * {@inheritdoc}
     */
    public static function defaultSettings() {
        return [
            'view_url' => '',
            'argument_name' => '',
            'mode' => 'id',
            'skip_access_check' => FALSE,
            'disable' => '',
        ] + parent::defaultSettings();
    }
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode'], $configuration['third_party_settings'], $container->get('path.validator'));
    }
    
    /**
     * {@inheritdoc}
     */
    protected function checkAccess(EntityInterface $entity) {
        return $entity->access('view label', NULL, TRUE);
    }
    
    /**
     * Get a sensible default argument name if not yet set.
     *
     * @return string
     *   The argument name.
     */
    protected function getArgumentName() : string {
        if (!($argument_name = $this->getSetting('argument_name'))) {
            try {
                $argument_name = $this->fieldDefinition
                    ->getName();
            } catch (\Throwable $e) {
                $argument_name = '';
            }
        }
        return $argument_name;
    }

}

Classes

Title Deprecated Summary
EntityReferenceFilteredLinkFormatter Plugin implementation of the 'entity_reference_filtered_link' formatter.