condition_path-1.0.0-beta2/src/Plugin/Condition/RequestPathInclexcl.php

src/Plugin/Condition/RequestPathInclexcl.php
<?php

namespace Drupal\condition_path\Plugin\Condition;

use Drupal\Core\Form\FormStateInterface;
use Drupal\system\Plugin\Condition\RequestPath;

/**
 * Provides a 'Request Path Include Exclude' condition.
 *
 * This condition can simultaneously in- and exclude paths.
 *
 * @Condition(
 *   id = "request_path_inclexcl",
 *   label = @Translation("Request Path Include Exclude"),
 * )
 */
class RequestPathInclexcl extends RequestPath {

  /**
   * Group name for included pages.
   */
  protected const string INCLUDED_GROUP = 'included';

  /**
   * Group name for excluded pages.
   */
  protected const string EXCLUDED_GROUP = 'excluded';

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    $form = parent::buildConfigurationForm($form, $form_state);

    $form['pages']['#description'] .= '<br>' . $this->t("Use a leading '!' character to exclude a path. An example excluded path is %excluded-path for a news overview page. To include all news subpages, use %included-path. The more specific the page, the lower it should be listed.", [
      '%excluded-path' => '!/news',
      '%included-path' => '/news/*',
    ]);

    $form['pages']['#attributes']['placeholder'] = $this->t('/this/page/is/included') . PHP_EOL . $this->t('!/this/page/is/excluded');

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $paths = $this->splitPages($form_state->getValue('pages'));
    foreach ($paths as $path) {
      if (empty($path)
        || in_array($path, ['<front>', '!<front>'])
        || str_starts_with($path, '*')
        || str_starts_with($path, '!*')
        || str_starts_with($path, '/')
        || str_starts_with($path, '!/')
      ) {
        continue;
      }
      $form_state->setErrorByName('pages', $this->t("The path %path requires a leading forward slash optionally preceded by an exclamation mark when used with the Pages setting.", ['%path' => $path]));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $this->configuration['pages'] = $form_state->getValue('pages');
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function summary(): string {
    if (empty($this->configuration['pages'])) {
      return $this->t('No page is specified');
    }

    $summary = '';
    $countIncluded = $countExcluded = 0;
    $pages = $this->splitPages($this->configuration['pages']);

    foreach ($pages as $page) {
      str_starts_with($page, '!') ? $countExcluded++ : $countIncluded++;
    }

    if (!empty($countIncluded)) {
      $summary .= $this->t('Pages included for visibility: @count', [
        '@count' => empty($this->configuration['negate']) ? $countIncluded : $countExcluded,
      ]);
    }

    if (!empty($countExcluded)) {
      $summary .= empty($summary) ? '' : '<br />';
      $summary .= $this->t('Pages excluded for visibility: @count', [
        '@count' => empty($this->configuration['negate']) ? $countExcluded : $countIncluded,
      ]);
    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(): bool {
    if (!isset($this->configuration['pages']) || NULL === $this->configuration['pages']) {
      return TRUE;
    }

    // Convert path to lowercase. This allows comparison of the same path
    // with different case. Ex: /Page, /page, /PAGE.
    $pages = mb_strtolower($this->configuration['pages']);
    if (!$pages) {
      return TRUE;
    }

    $request = $this->requestStack->getCurrentRequest();
    // Compare the lowercase path alias (if any) and internal path.
    $path = $this->currentPath->getPath($request);
    // Do not trim a trailing slash if that is the complete path.
    $path = $path === '/' ? $path : rtrim($path, '/');
    $pathAlias = mb_strtolower($this->aliasManager->getAliasByPath($path));

    $result = FALSE;
    $pages = $this->splitPages($pages);
    $pageGroups = $this->groupPages($pages);

    foreach ($pageGroups as $key => $group) {
      $group = implode(PHP_EOL, $group);
      $match = $this->pathMatcher->matchPath($pathAlias, $group) || (($path != $pathAlias) && $this->pathMatcher->matchPath($path, $group));

      // If we have a match, negate the result if the pages are to be excluded.
      if ($match) {
        $result = str_starts_with($key, self::INCLUDED_GROUP);
      }
    }

    return $result;
  }

  /**
   * Group pages in include and exclude groups respecting their given order.
   *
   * By splitting up in groups, several paths can be validated at the same time
   * using the pathMatcher instead of checking them one by one.
   * The returned array will contain sub arrays with numbered keys. The keys
   * will be prefixed with 'included' or 'excluded' to mark them as such.
   *
   * @param array $pages
   *   The listed pages as an array.
   *
   * @return array
   *   The listed pages divided into in- and exclude groups, respecting the
   *   input order.
   */
  protected function groupPages(array $pages): array {
    $groups = [];
    $groupIndex = 0;
    $currentGroupType = '';

    foreach ($pages as $page) {
      if (str_starts_with($page, '!')) {
        // Check if we are starting a new 'excluded' group and mark it so.
        if ($currentGroupType !== self::EXCLUDED_GROUP) {
          $currentGroupType = self::EXCLUDED_GROUP;
          $groupKey = $currentGroupType . '_' . $groupIndex++;
        }
      }
      else {
        // Check if we are starting a new 'included' group and mark it so.
        if ($currentGroupType !== self::INCLUDED_GROUP) {
          $currentGroupType = self::INCLUDED_GROUP;
          $groupKey = $currentGroupType . '_' . $groupIndex++;
        }
      }

      // Add the page to its group.
      if (!empty($groupKey)) {
        $groups[$groupKey][] = ltrim($page, '!');
      }
    }

    return $groups;
  }

  /**
   * Split pages as a string to an array where each page is an element.
   *
   * @param string $pages
   *   The listed pages as a string.
   *
   * @return array
   *   The listed pages split into an array.
   */
  protected function splitPages(string $pages): array {
    return array_map('trim', preg_split('/[\r\n]+/', $pages));
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc