Allow filtering by taxonomy term pathauto

Created on 10 August 2023, about 1 year ago
Updated 15 August 2023, about 1 year ago

Problem/Motivation

This validator does not consider the case when passing a taxonomy term which its pathauto is selecting 'Transliterate prior to creating alias', 'Reduce string to letters and numbers' and 'Strings to Remove'.
Examples:

  • Apple's color,
  • Banana for you to eat

Steps to reproduce

Step 1: Go to admin/config/search/path/settings, make sure

  • the checkbox of 'Transliterate prior to creating alias' is checked
  • the checkbox of 'Reduce strings to letters and numbers' is checked
  • the textbox of 'String to Remove' includes 'for, to, ...'

Step 2: Create a view and add a contextual filter that use "Taxonomy term name as ID" argument validator

Step 3: Configure contextual filter: Content: Has taxonomy term ID:

  • Select 'Transform dashes in term name filter values'
  • Select 'Show Page not found' under 'Action to take if filter value doesn't validate'

Step 4: Use the above two examples as taxonomy terms, the result shows 'Page not found' which is not correct

Proposed resolution

Add a checkbox for a new filter call 'Transform term name based on pathauto'
Use the below code in TermNameAsId.php, it shows the checkbox of 'Transform term name based on pathauto'.
By checking 'Transform term name based on pathauto' instead of 'Transform dashes in term name filter values', the result shows correctly instead of 'Page not found'.

<?php

namespace Drupal\views_taxonomy_term_name_into_id\Plugin\views\argument_validator;

use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\taxonomy\Plugin\views\argument_validator\TermName;

/**
 * Validates an argument as a term name and converts it to the term ID.
 *
 * @ViewsArgumentValidator(
 *   id = "taxonomy_term_name_into_id",
 *   title = @Translation("Taxonomy term name as ID"),
 *   entity_type = "taxonomy_term"
 * )
 */
class TermNameAsId extends TermName {
  /**
   * The taxonomy term storage.
   *
   * @var \Drupal\taxonomy\TermStorageInterface
   */
  protected $termStorage;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_type_bundle_info);
    // Not handling exploding term names.
    $this->multipleCapable = FALSE;
    $this->termStorage = $entity_type_manager->getStorage('taxonomy_term');
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['transform_pathauto'] = ['default' => FALSE];

    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

    $form['transform_pathauto'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Transform term name based on pathauto'),
      '#default_value' => $this->options['transform_pathauto'],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function validateArgument($argument) {
    $query = $this->termStorage->getQuery();

    // If bundles is set then restrict the loaded terms to the given bundles.
    if (!empty($this->options['bundles'])) {
      $query->condition('vid', $this->options['bundles']);
    }

    // If 'transform_pathauto' is checked.
    if ($this->options['transform_pathauto']) {

      // Get vocabularies from the options.
      $vocabularies = $this->options['bundles'];

      // Loop vocabularies to get terms.
      foreach ($vocabularies as $vocabulary) {

        // Get terms from the first vocabulary.
        $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')
          ->loadByProperties(['vid' => $vocabulary]);

        // Loop terms to get term id.
        foreach ($terms as $term) {
          $term_id = $term->id();
          // Get term alias from tid.
          $aliasManager = \Drupal::service('path_alias.manager');
          $alias = $aliasManager->getAliasByPath('/taxonomy/term/' . $term_id);
          // Get path from alias.
          $path = explode('/', $alias);
          // Set argument using tid when the path matches the argument.
          if (end($path) == $argument) {
            $this->argument->argument = $term_id;
            return TRUE;
          }
        }
        return FALSE;
      }
    }

  }

Remaining tasks

User interface changes

API changes

Data model changes

Feature request
Status

Needs work

Version

1.0

Component

Code

Created by

🇨🇦Canada lily.yan

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @lily.yan
  • 🇨🇦Canada ebremner

    Providing patch for this specific example.

  • 🇨🇦Canada lily.yan

    I apply the above patch issue-3380463-validate-pathauto.patch to 8.x-1.0-rc1, it works.

  • Status changed to RTBC about 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update about 1 year ago
    2 pass
  • Status changed to Needs work about 1 year ago
  • 🇨🇦Canada kpaxman

    I think that the Pathauto transform options should only appear/take effect if the Pathauto module itself is actually enabled.

    Additionally, it is possible to check both "transform dashes..." and "transform...based on pathauto" at the same time, but it looks like in the code, you can only do one or the other. I think it makes *sense* to do only one or the other, so I'd say the UI should change somehow so only one or the other can be selected (maybe a dropdown, with "no transformation" along with the two transformation types, as the options?).

    Aside from that, it does seem to work, but it seems to be set up differently than the default option, including exporting config as "1" instead of "true" - it would be nice if a maintainer could weight in on the method used here.

  • 🇨🇦Canada ebremner

    Here is a patch with most of the fixes, except the 1 => true as stated.

Production build 0.71.5 2024