TaxonomyIndexTid.php
Same filename in this branch
Same filename in other branches
- 9 core/modules/taxonomy/src/Plugin/views/field/TaxonomyIndexTid.php
- 9 core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
- 8.9.x core/modules/taxonomy/src/Plugin/views/field/TaxonomyIndexTid.php
- 8.9.x core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
- 10 core/modules/taxonomy/src/Plugin/views/field/TaxonomyIndexTid.php
- 10 core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
Namespace
Drupal\taxonomy\Plugin\views\filterFile
-
core/
modules/ taxonomy/ src/ Plugin/ views/ filter/ TaxonomyIndexTid.php
View source
<?php
namespace Drupal\taxonomy\Plugin\views\filter;
use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\TermStorageInterface;
use Drupal\taxonomy\VocabularyStorageInterface;
use Drupal\views\Attribute\ViewsFilter;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\ManyToOne;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Filter by term id.
*
* @ingroup views_filter_handlers
*/
class TaxonomyIndexTid extends ManyToOne {
/**
* Stores the exposed input for this filter.
*
* @var array|null
*/
// phpcs:ignore Drupal.NamingConventions.ValidVariableName.LowerCamelName
public $validated_exposed_input = NULL;
/**
* The vocabulary storage.
*
* @var \Drupal\taxonomy\VocabularyStorageInterface
*/
protected $vocabularyStorage;
/**
* The term storage.
*
* @var \Drupal\taxonomy\TermStorageInterface
*/
protected $termStorage;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a TaxonomyIndexTid object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\taxonomy\VocabularyStorageInterface $vocabulary_storage
* The vocabulary storage.
* @param \Drupal\taxonomy\TermStorageInterface $term_storage
* The term storage.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->vocabularyStorage = $vocabulary_storage;
$this->termStorage = $term_storage;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('entity_type.manager')
->getStorage('taxonomy_vocabulary'), $container->get('entity_type.manager')
->getStorage('taxonomy_term'), $container->get('current_user'));
}
/**
* {@inheritdoc}
*/
public function init(ViewExecutable $view, DisplayPluginBase $display, ?array &$options = NULL) {
parent::init($view, $display, $options);
if (!empty($this->definition['vocabulary'])) {
$this->options['vid'] = $this->definition['vocabulary'];
}
}
public function hasExtraOptions() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getValueOptions() {
return $this->valueOptions;
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['type'] = [
'default' => 'textfield',
];
$options['limit'] = [
'default' => TRUE,
];
$options['vid'] = [
'default' => '',
];
$options['hierarchy'] = [
'default' => FALSE,
];
$options['error_message'] = [
'default' => TRUE,
];
return $options;
}
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
$vocabularies = $this->vocabularyStorage
->loadMultiple();
$options = [];
foreach ($vocabularies as $voc) {
$options[$voc->id()] = $voc->label();
}
if ($this->options['limit']) {
// We only do this when the form is displayed.
if (empty($this->options['vid'])) {
$first_vocabulary = reset($vocabularies);
$this->options['vid'] = $first_vocabulary->id();
}
if (empty($this->definition['vocabulary'])) {
$form['vid'] = [
'#type' => 'radios',
'#title' => $this->t('Vocabulary'),
'#options' => $options,
'#description' => $this->t('Select which vocabulary to show terms for in the regular options.'),
'#default_value' => $this->options['vid'],
];
}
}
$form['type'] = [
'#type' => 'radios',
'#title' => $this->t('Selection type'),
'#options' => [
'select' => $this->t('Dropdown'),
'textfield' => $this->t('Autocomplete'),
],
'#default_value' => $this->options['type'],
];
$form['hierarchy'] = [
'#type' => 'checkbox',
'#title' => $this->t('Show hierarchy in dropdown'),
'#default_value' => !empty($this->options['hierarchy']),
'#states' => [
'visible' => [
':input[name="options[type]"]' => [
'value' => 'select',
],
],
],
];
}
protected function valueForm(&$form, FormStateInterface $form_state) {
$vocabulary = $this->vocabularyStorage
->load($this->options['vid']);
if (empty($vocabulary) && $this->options['limit']) {
$form['markup'] = [
'#markup' => '<div class="js-form-item form-item">' . $this->t('An invalid vocabulary is selected. Change it in the options.') . '</div>',
];
return;
}
if ($this->options['type'] == 'textfield') {
$terms = $this->value ? Term::loadMultiple($this->value) : [];
$form['value'] = [
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', [
'@voc' => $vocabulary->label(),
]) : $this->t('Select terms'),
'#type' => 'textfield',
'#default_value' => EntityAutocomplete::getEntityLabels($terms),
];
if ($this->options['limit']) {
$form['value']['#type'] = 'entity_autocomplete';
$form['value']['#target_type'] = 'taxonomy_term';
$form['value']['#selection_settings']['target_bundles'] = [
$vocabulary->id(),
];
$form['value']['#tags'] = TRUE;
$form['value']['#process_default_value'] = FALSE;
}
}
else {
if (!empty($this->options['hierarchy']) && $this->options['limit']) {
$tree = $this->termStorage
->loadTree($vocabulary->id(), 0, NULL, TRUE);
$options = [];
if ($tree) {
foreach ($tree as $term) {
if (!$term->isPublished() && !$this->currentUser
->hasPermission('administer taxonomy')) {
continue;
}
$choice = new \stdClass();
$choice->option = [
$term->id() => str_repeat('-', $term->depth) . \Drupal::service('entity.repository')->getTranslationFromContext($term)
->label(),
];
$options[] = $choice;
}
}
}
else {
$options = [];
$query = \Drupal::entityQuery('taxonomy_term')->accessCheck(TRUE)
->sort('weight')
->sort('name')
->addTag('taxonomy_term_access');
if (!$this->currentUser
->hasPermission('administer taxonomy')) {
$query->condition('status', 1);
}
if ($this->options['limit']) {
$query->condition('vid', $vocabulary->id());
}
$terms = Term::loadMultiple($query->execute());
foreach ($terms as $term) {
$options[$term->id()] = \Drupal::service('entity.repository')->getTranslationFromContext($term)
->label();
}
}
$default_value = (array) $this->value;
if ($exposed = $form_state->get('exposed')) {
$identifier = $this->options['expose']['identifier'];
if (!empty($this->options['expose']['reduce'])) {
$options = $this->reduceValueOptions($options);
if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) {
$default_value = [];
}
}
if (empty($this->options['expose']['multiple'])) {
if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
$default_value = 'All';
}
elseif (empty($default_value)) {
$keys = array_keys($options);
$default_value = array_shift($keys);
}
elseif ($default_value == [
'',
]) {
$default_value = 'All';
}
else {
$copy = $default_value;
$default_value = array_shift($copy);
}
}
}
$form['value'] = [
'#type' => 'select',
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', [
'@voc' => $vocabulary->label(),
]) : $this->t('Select terms'),
'#multiple' => TRUE,
'#options' => $options,
'#size' => min(9, count($options)),
'#default_value' => $default_value,
];
$user_input = $form_state->getUserInput();
if ($exposed && isset($identifier) && !isset($user_input[$identifier])) {
$user_input[$identifier] = $default_value;
$form_state->setUserInput($user_input);
}
}
if (!$form_state->get('exposed')) {
// Retain the helper option
$this->helper
->buildOptionsForm($form, $form_state);
// Show help text if not exposed to end users.
$form['value']['#description'] = $this->t('Leave blank for all. Otherwise, the first selected term will be the default instead of "Any".');
}
}
protected function valueValidate($form, FormStateInterface $form_state) {
// We only validate if they've chosen the text field style.
if ($this->options['type'] != 'textfield') {
return;
}
$tids = [];
if ($values = $form_state->getValue([
'options',
'value',
])) {
foreach ($values as $value) {
$tids[] = $value['target_id'];
}
}
$form_state->setValue([
'options',
'value',
], $tids);
}
public function acceptExposedInput($input) {
if (empty($this->options['exposed'])) {
return TRUE;
}
// We need to know the operator, which is normally set in
// \Drupal\views\Plugin\views\filter\FilterPluginBase::acceptExposedInput(),
// before we actually call the parent version of ourselves.
if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
$this->operator = $input[$this->options['expose']['operator_id']];
}
// If view is an attachment and is inheriting exposed filters, then assume
// exposed input has already been validated
if (!empty($this->view->is_attachment) && $this->view->display_handler
->usesExposed()) {
$this->validated_exposed_input = (array) $this->view->exposed_raw_input[$this->options['expose']['identifier']];
}
// If we're checking for EMPTY or NOT, we don't need any input, and we can
// say that our input conditions are met by just having the right operator.
if ($this->operator == 'empty' || $this->operator == 'not empty') {
return TRUE;
}
// If it's non-required and there's no value don't bother filtering.
if (!$this->options['expose']['required'] && empty($this->validated_exposed_input)) {
return FALSE;
}
$rc = parent::acceptExposedInput($input);
if ($rc) {
// If we have previously validated input, override.
if (isset($this->validated_exposed_input)) {
$this->value = $this->validated_exposed_input;
}
}
return $rc;
}
public function validateExposed(&$form, FormStateInterface $form_state) {
if (empty($this->options['exposed'])) {
return;
}
$identifier = $this->options['expose']['identifier'];
$input = $form_state->getValue($identifier);
if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) {
$this->validated_exposed_input = $this->options['group_info']['group_items'][$input]['value'];
return;
}
// We only validate if they've chosen the text field style.
if ($this->options['type'] != 'textfield') {
if ($form_state->getValue($identifier) != 'All') {
$this->validated_exposed_input = (array) $form_state->getValue($identifier);
}
return;
}
if (empty($this->options['expose']['identifier'])) {
return;
}
if ($values = $form_state->getValue($identifier)) {
foreach ($values as $value) {
$this->validated_exposed_input[] = $value['target_id'];
}
}
}
protected function valueSubmit($form, FormStateInterface $form_state) {
// Prevent array_filter from messing up our arrays in parent submit.
}
public function buildExposeForm(&$form, FormStateInterface $form_state) {
parent::buildExposeForm($form, $form_state);
if ($this->options['type'] != 'select') {
unset($form['expose']['reduce']);
}
$form['error_message'] = [
'#type' => 'checkbox',
'#title' => $this->t('Display error message'),
'#default_value' => !empty($this->options['error_message']),
];
}
public function adminSummary() {
// Set up $this->valueOptions for the parent summary
$this->valueOptions = [];
if ($this->value) {
$this->value = array_filter($this->value);
$terms = Term::loadMultiple($this->value);
foreach ($terms as $term) {
$this->valueOptions[$term->id()] = \Drupal::service('entity.repository')->getTranslationFromContext($term)
->label();
}
}
return parent::adminSummary();
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
$vocabulary = $this->vocabularyStorage
->load($this->options['vid']);
$dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName();
foreach ($this->termStorage
->loadMultiple($this->options['value']) as $term) {
$dependencies[$term->getConfigDependencyKey()][] = $term->getConfigDependencyName();
}
return $dependencies;
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
TaxonomyIndexTid | Filter by term id. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.