elasticsearch_search_api-1.0.x-dev/src/KeymatchService.php

src/KeymatchService.php
<?php

namespace Drupal\elasticsearch_search_api;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\elasticsearch_search_api\Factory\KeymatchEntryFactory;

/**
 * Keymatch Service class.
 */
class KeymatchService {

  const SEARCH_KEYMATCH_TYPE_TERM = 'TERM';
  const SEARCH_KEYMATCH_TYPE_PHRASE = 'PHRASE';
  const SEARCH_KEYMATCH_TYPE_EXACT = 'EXACT';

  /**
   * The config instance.
   *
   * @var \Drupal\Core\Config\Config|\Drupal\Core\Config\ImmutableConfig
   */
  protected $configInstance;

  /**
   * The path validator.
   *
   * @var \Drupal\Core\Path\PathValidatorInterface
   */
  protected $pathValidator;

  /**
   * The keymatch entry factory.
   *
   * @var \Drupal\elasticsearch_search_api\Factory\KeymatchEntryFactory
   */
  protected $keymatchEntryFactory;

  /**
   * KeymatchForm constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config instance.
   * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
   *   The path validator.
   * @param \Drupal\elasticsearch_search_api\Factory\KeymatchEntryFactory $keymatch_entry_factory
   *   The keymatchEntry factory.
   */
  public function __construct(ConfigFactoryInterface $config_factory, PathValidatorInterface $path_validator, KeymatchEntryFactory $keymatch_entry_factory) {
    $this->configInstance = $config_factory->get('elasticsearch_search_api.keymatch');
    $this->pathValidator = $path_validator;
    $this->keymatchEntryFactory = $keymatch_entry_factory;
  }

  /**
   * Returns the available keymatch types.
   *
   * @return array
   *   Returns the types in an array.
   */
  public static function allKeymatchTypes() {
    return [
      KeymatchService::SEARCH_KEYMATCH_TYPE_TERM => KeymatchService::SEARCH_KEYMATCH_TYPE_TERM,
      KeymatchService::SEARCH_KEYMATCH_TYPE_PHRASE => KeymatchService::SEARCH_KEYMATCH_TYPE_PHRASE,
      KeymatchService::SEARCH_KEYMATCH_TYPE_EXACT => KeymatchService::SEARCH_KEYMATCH_TYPE_EXACT,
    ];
  }

  /**
   * Finds keymatches for the given query.
   *
   * @param string $search_query
   *   The search query to match keymatches with.
   *
   * @return KeymatchEntry[]
   *   Returns an array of KeymatchEntry objects.
   */
  public function find($search_query) {
    $keymatch_configuration = $this->getKeymatchConfiguration();
    $ordered_keymatches = $this->getKeymatchEntriesByType($keymatch_configuration);

    $keymatches_found = [];
    if (isset($search_query)) {
      foreach ($ordered_keymatches as $type => $keymatches) {
        $type_uppercase = strtoupper($type);

        /** @var KeymatchEntry $keymatch */
        foreach ($keymatches as $keymatch) {
          $matches = FALSE;
          switch ($type_uppercase) {
            case KeymatchService::SEARCH_KEYMATCH_TYPE_EXACT:
              $matches = $this->matchesExact($search_query, $keymatch->getQuery());
              break;

            case KeymatchService::SEARCH_KEYMATCH_TYPE_TERM:
              $matches = $this->matchesTerm($search_query, $keymatch->getQuery());
              break;

            case KeymatchService::SEARCH_KEYMATCH_TYPE_PHRASE:
              $matches = $this->matchesPhrase($search_query, $keymatch->getQuery());
              break;
          }
          if ($matches) {
            $keymatches_found[] = $keymatch;
          }
        }
      }
    }
    return $keymatches_found;
  }

  /**
   * Checks an exact keymatch.
   *
   * @param string $query
   *   The search query.
   * @param string $keymatch
   *   The keymatch.
   *
   * @return bool
   *   TRUE if query matches on specified keymatch
   */
  public function matchesExact($query, $keymatch) {
    return $query === $keymatch;
  }

  /**
   * Checks a keymatch with the type 'phrase'.
   *
   * @param string $query
   *   The search query.
   * @param string $keymatch
   *   The keymatch.
   *
   * @return bool
   *   TRUE if query matches on specified keymatch
   */
  public function matchesPhrase($query, $keymatch) {
    $query_lower = strtolower($query);
    $keymatch_lower = strtolower($keymatch);

    $regex = '/\b' . $keymatch_lower . '\b/';
    preg_match($regex, $query_lower, $match);

    return isset($match) && !empty($match);
  }

  /**
   * Checks a keymatch with the type 'term'.
   *
   * @param string $query
   *   The search query.
   * @param string $keymatch
   *   The keymatch.
   *
   * @return bool
   *   TRUE if query matches on specified keymatch
   */
  public function matchesTerm($query, $keymatch) {
    $keymatch_terms = explode(' ', $keymatch);
    if (!isset($keymatch_terms) || $keymatch_terms === FALSE) {
      return FALSE;
    }

    foreach ($keymatch_terms as $term) {
      if (!$this->matchesPhrase($query, $term)) {
        return FALSE;
      };
    }

    return TRUE;
  }

  /**
   * Checks whether a keymatch string is valid or not.
   *
   * @param string $keymatch_entry
   *   Keymatch entry as a string, as it is stored in the config.
   * @param bool $strict
   *   Check if url is external or valid internal path.
   *
   * @return bool
   *   Whether the keymatch entry is valid or not.
   */
  public function isValid($keymatch_entry, $strict = FALSE) {
    $parts = explode(',', $keymatch_entry);
    if (!$parts || !is_array($parts) || empty($parts) || count($parts) < 4) {
      return FALSE;
    }

    $trimmed_query = trim($parts[0]);
    $trimmed_url = trim($parts[2]);
    $trimmed_title = trim($parts[3]);

    $valid_path = TRUE;
    if ($strict !== FALSE) {
      $valid_path = $this->pathValidator->isValid($trimmed_url);
    }

    return !empty($trimmed_query) && !empty($trimmed_title) && !empty($trimmed_url) && isset($this->allKeymatchTypes()[$parts[1]]) && $valid_path !== FALSE;
  }

  /**
   * Creates an array of keymatches as strings, either from a value or config.
   *
   * @param string|null $saved_keymatches
   *   Uses this value if provided, otherwise it gets the value stored in
   *   config.
   *
   * @return array
   *   Returns an array of keymatch strings.
   */
  public function getKeymatchConfiguration($saved_keymatches = NULL) {
    if (!isset($saved_keymatches)) {
      $config_keymatches = $this->configInstance->get('keymatches');
    }

    // If keymatches are empty, return an empty array.
    if (empty($config_keymatches)) {
      return [];
    }

    $saved_keymatches = $config_keymatches;

    // Convert newlines to array based on \r\n or \n without empty matches.
    $saved_keymatches = preg_split('/(\r\n?|\n)/', $saved_keymatches, -1, PREG_SPLIT_NO_EMPTY);
    // Filter out values with only spaces.
    $saved_keymatches = array_filter($saved_keymatches,
      function ($split) {
        $split_safe = trim($split);
        return !empty($split_safe);
      }
    );

    // Make sure our array indexes are reset in case entries were skipped.
    return array_values($saved_keymatches);
  }

  /**
   * Creates KeymatchEntry objects and orders them by type.
   *
   * @param array $config
   *   An array of keymatch strings as returned by getKeymatchConfiguration.
   *
   * @return array
   *   Returns KeymatchEntry objects ordered by type.
   */
  public function getKeymatchEntriesByType(array $config) {
    $keymatches_by_type = [];
    foreach ($config as $keymatch_entry) {
      if ($this->isValid($keymatch_entry)) {
        $entry = $this->keymatchEntryFactory->createEntry($keymatch_entry);
        $keymatches_by_type[$entry->getType()][] = $entry;
      }
    }
    return $keymatches_by_type;
  }

}

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

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