Commit 089b6ab0 authored by Nick Veenhof's avatar Nick Veenhof Committed by Thomas Seidl
Browse files

Issue #2983640 by Nick_vh, L_VanDamme, drunken monkey, Marios Anagnostopoulos,...

Issue #2983640 by Nick_vh, L_VanDamme, drunken monkey, Marios Anagnostopoulos, estoyausente, jsst, yogeshmpawar, borisson_, legolasbo: Added an option to create an excerpt even when no keywords are present.
parent 82d1beea
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
Search API 1.x, dev (xxxx-xx-xx):
---------------------------------
- #2983640 by Nick_vh, L_VanDamme, drunken monkey, Marios Anagnostopoulos,
  estoyausente, jsst, yogeshmpawar, borisson_, legolasbo: Added an option to
  create an excerpt even when no keywords are present.
- #3221345 by drunken monkey, jan kellermann: Fixed handling of invalid date
  values during indexing.
- #3220283 by james.williams, drunken monkey: Fixed automatic reindexing of
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ plugin.plugin_configuration.search_api_processor.highlight:
    excerpt:
      type: boolean
      label: 'When enabled, an excerpt will be created for searches with keywords, containing all occurrences of keywords in a fulltext field.'
    excerpt_always:
      type: boolean
      label: 'When enabled, an excerpt will be created even with an empty query string.'
    excerpt_length:
      type: integer
      label: 'The requested length of the excerpt, in characters'
+34 −4
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
      'suffix' => '</strong>',
      'excerpt' => TRUE,
      'excerpt_length' => 256,
      'excerpt_always' => FALSE,
      'highlight' => 'always',
      'highlight_partial' => FALSE,
      'exclude_fields' => [],
@@ -171,6 +172,12 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
      '#description' => $this->t('When enabled, an excerpt will be created for searches with keywords, containing all occurrences of keywords in a fulltext field.'),
      '#default_value' => $this->configuration['excerpt'],
    ];
    $form['excerpt_always'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Create excerpt even if no search keys are available'),
      '#description' => $this->t('When enabled, an excerpt will be created even with an empty query string.'),
      '#default_value' => $this->configuration['excerpt_always'],
    ];
    $form['excerpt_length'] = [
      '#type' => 'number',
      '#title' => $this->t('Excerpt length'),
@@ -238,8 +245,14 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
  public function postprocessSearchResults(ResultSetInterface $results) {
    $query = $results->getQuery();
    if (!$results->getResultCount()
      || $query->getProcessingLevel() != QueryInterface::PROCESSING_FULL
      || !($keys = $this->getKeywords($query))) {
      || $query->getProcessingLevel() != QueryInterface::PROCESSING_FULL) {
      return;
    }

    // Only return an excerpt on an empty keyword if requested by configuration.
    $keys = $this->getKeywords($query);
    $excerpt_always = $this->configuration['excerpt_always'];
    if (!$excerpt_always && !$keys) {
      return;
    }

@@ -479,6 +492,12 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
      $context_length = round($excerpt_length / 2) - 1;
    }

    // If the text or the excerpt length are empty for some reason, we cannot
    // provide an excerpt. Bail early in that case.
    if (!$text || !$excerpt_length) {
      return NULL;
    }

    while ($length < $excerpt_length && !empty($remaining_keys)) {
      $found_keys = [];
      foreach ($remaining_keys as $key) {
@@ -559,8 +578,20 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
      $remaining_keys = $found_keys;
    }

    $ellipses = $this->getEllipses();

    // If no keys are given or no keys match the excerpt, either return an
    // excerpt from the beginning (if "excerpt_always" is enabled) or nothing.
    if (!$ranges) {
      // We didn't find any keyword matches, return NULL.
      if ($this->configuration['excerpt_always']) {
        $snippet = mb_substr($text, 0, $excerpt_length);
        $pos = mb_strrpos($snippet, ' ');
        if ($pos > $excerpt_length / 2) {
          $snippet = mb_substr($snippet, 0, $pos);
        }
        return trim($snippet) . $ellipses[2];
      }

      return NULL;
    }

@@ -601,7 +632,6 @@ class Highlight extends ProcessorPluginBase implements PluginFormInterface {
      return NULL;
    }

    $ellipses = $this->getEllipses();
    $excerpt = $ellipses[0] . implode($ellipses[1], $out) . $ellipses[2];

    // Since we stripped the tags at the beginning, highlighting doesn't need to
+220 −0
Original line number Diff line number Diff line
id: search_api_test_search_excerpt
base_field: search_api_id
base_table: search_api_index_database_search_index
core: 8.x
description: ''
status: true
display:
  default:
    display_plugin: default
    id: default
    display_title: Master
    position: 0
    display_options:
      access:
        type: none
        options: {  }
      cache:
        type: none
        options: {  }
      query:
        type: search_api_query
        options:
          skip_access: true
      exposed_form:
        type: basic
        options:
          submit_button: Search
          reset_button: false
          reset_button_label: Reset
          exposed_sorts_label: 'Sort by'
          expose_sort_order: true
          sort_asc_label: Asc
          sort_desc_label: Desc
      pager:
        type: full
        options:
          items_per_page: 10
          offset: 0
          id: 0
          total_pages: null
          expose:
            items_per_page: false
            items_per_page_label: 'Items per page'
            items_per_page_options: '5, 10, 20, 40, 60'
            items_per_page_options_all: false
            items_per_page_options_all_label: '- All -'
            offset: false
            offset_label: Offset
          tags:
            previous: ' previous'
            next: 'next ›'
            first: '« first'
            last: 'last »'
          quantity: 9
      style:
        type: default
      row:
        type: fields
        options:
          default_field_elements: true
          inline:
            search_api_excerpt: search_api_excerpt
          separator: ''
          hide_empty: false
      fields:
        id:
          table: search_api_index_database_search_index
          field: id
          id: id
          entity_type: null
          entity_field: null
          plugin_id: search_api_field
          relationship: none
          group_type: group
          admin_label: ''
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: true
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          click_sort_column: value
          type: number_integer
          settings: {  }
          group_column: value
          group_columns: {  }
          group_rows: true
          delta_limit: 0
          delta_offset: 0
          delta_reversed: false
          delta_first_last: false
          multi_type: separator
          separator: ', '
          field_api_classes: false
          field_rendering: true
          fallback_handler: search_api_numeric
          fallback_options:
            set_precision: false
            precision: 0
            decimal: .
            separator: ','
            format_plural: false
            format_plural_string: !!binary MQNAY291bnQ=
            prefix: ''
            suffix: ''
            link_to_item: false
            use_highlighting: false
            multi_type: separator
            multi_separator: ', '
            format_plural_values: {  }
        search_api_excerpt:
          id: search_api_excerpt
          table: search_api_index_database_search_index
          field: search_api_excerpt
          relationship: none
          group_type: group
          admin_label: ''
          label: Excerpt_label
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: excerpt
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: true
          empty_zero: false
          hide_alter_empty: true
          link_to_item: false
          use_highlighting: false
          multi_type: separator
          multi_separator: ', '
          plugin_id: search_api
      filters: {  }
      sorts: {  }
      title: 'Search API Test search excerpt'
      header: {  }
      footer: {  }
      empty: {  }
      relationships: {  }
      arguments: {  }
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
      tags: {  }
  page_1:
    display_plugin: page
    id: page_1
    display_title: Page
    position: 1
    display_options:
      path: search-api-test-search-excerpt
+11 −0
Original line number Diff line number Diff line
name: 'Search API Excerpt Test'
type: module
description: 'Support module for Search API Excerpt tests'
package: Search
core_version_requirement: ^8 || ^9
dependencies:
  - search_api:search_api
  - search_api:search_api_test_db
  - drupal:views
core: 8.x
hidden: true
Loading