class NodeSearchHooks

Same name in this branch
  1. main core/modules/node/src/Hook/NodeSearchHooks.php \Drupal\node\Hook\NodeSearchHooks
Same name and namespace in other branches
  1. 11.x core/modules/node/src/Hook/NodeSearchHooks.php \Drupal\node\Hook\NodeSearchHooks

Search related hook implementations originally in the Node module.

Hierarchy

Expanded class hierarchy of NodeSearchHooks

File

core/modules/search/modules/search_node/src/Hook/NodeSearchHooks.php, line 17

Namespace

Drupal\search_node\Hook
View source
class NodeSearchHooks {
  use StringTranslationTrait;
  public function __construct(protected readonly EntityTypeManagerInterface $entityTypeManager, protected readonly StateInterface $state, protected readonly ?SearchIndexInterface $searchIndex = NULL) {
  }
  
  /**
   * Implements hook_cron().
   */
  public function cron() : void {
    // Calculate the oldest and newest node created times, for use in search
    // rankings. (Note that field aliases have to be variables passed by
    // reference.)
    $min_alias = 'min_created';
    $max_alias = 'max_created';
    $result = $this->entityTypeManager
      ->getStorage('node')
      ->getAggregateQuery()
      ->accessCheck(FALSE)
      ->aggregate('created', 'MIN', NULL, $min_alias)
      ->aggregate('created', 'MAX', NULL, $max_alias)
      ->execute();
    if (isset($result[0])) {
      // Make an array with definite keys and store it in the state system.
      $array = [
        'min_created' => $result[0][$min_alias],
        'max_created' => $result[0][$max_alias],
      ];
      $this->state
        ->set('node.min_max_update_time', $array);
    }
  }
  
  /**
   * Implements hook_node_search_ranking().
   */
  public function ranking() : array {
    // Create the ranking array and add the basic ranking options.
    $ranking = [
      'relevance' => [
        'title' => $this->t('Keyword relevance'),
        // Average relevance values hover around 0.15
'score' => 'i.relevance',
      ],
      'sticky' => [
        'title' => $this->t('Content is sticky at top of lists'),
        // The sticky flag is either 0 or 1, which is automatically normalized.
'score' => 'n.sticky',
      ],
      'promote' => [
        'title' => $this->t('Content is promoted to the front page'),
        // The promote flag is either 0 or 1, which is automatically normalized.
'score' => 'n.promote',
      ],
    ];
    // Add relevance based on updated date, but only if it the scale values have
    // been calculated in node_cron().
    if ($node_min_max = $this->state
      ->get('node.min_max_update_time')) {
      $ranking['recent'] = [
        'title' => $this->t('Recently created'),
        // Exponential decay with half life of 14% of the age range of nodes.
'score' => 'EXP(-5 * (1 - (n.created - :node_oldest) / :node_range))',
        'arguments' => [
          ':node_oldest' => $node_min_max['min_created'],
          ':node_range' => max($node_min_max['max_created'] - $node_min_max['min_created'], 1),
        ],
      ];
    }
    return $ranking;
  }
  
  /**
   * Implements hook_node_update().
   */
  public function nodeUpdate(NodeInterface $node) : void {
    if ($node->isDefaultRevision()) {
      $this->reindexNodeForSearch($node->id());
    }
  }
  
  /**
   * Implements hook_ENTITY_TYPE_insert() for comment entities.
   */
  public function commentInsert($comment) : void {
    // Reindex the node when comments are added.
    if ($comment->getCommentedEntityTypeId() == 'node') {
      $this->reindexNodeForSearch($comment->getCommentedEntityId());
    }
  }
  
  /**
   * Implements hook_ENTITY_TYPE_update() for comment entities.
   */
  public function commentUpdate($comment) : void {
    // Reindex the node when comments are changed.
    if ($comment->getCommentedEntityTypeId() == 'node') {
      $this->reindexNodeForSearch($comment->getCommentedEntityId());
    }
  }
  
  /**
   * Implements hook_ENTITY_TYPE_delete() for comment entities.
   */
  public function commentDelete($comment) : void {
    // Reindex the node when comments are deleted.
    if ($comment->getCommentedEntityTypeId() == 'node') {
      $this->reindexNodeForSearch($comment->getCommentedEntityId());
    }
  }
  
  /**
   * Reindex a node for search.
   *
   * @param string|int $nid
   *   The node ID to reindex.
   */
  protected function reindexNodeForSearch(string|int $nid) : void {
    // Reindex node context indexed by the node module search plugin.
    $this->searchIndex?->markForReindex('node_search', (int) $nid);
  }

}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.