From 0030acb197840924338310378d35c3dfaf955a89 Mon Sep 17 00:00:00 2001 From: Marc Berger Date: Tue, 19 Nov 2024 16:05:27 -0800 Subject: [PATCH] feat(IYY-263): Add new search index for CAS content, remove path from search view, replace with custom dynamic route and controller, update header settings form with new option to show CAS titles in search --- ..._view_display.node.event.search_result.yml | 19 +- ...y_view_display.node.page.search_result.yml | 19 +- ...y_view_display.node.post.search_result.yml | 24 +- ...iew_display.node.profile.search_result.yml | 19 +- .../sync/search_api.index.secure_index.yml | 165 ++++++++++ .../config/sync/views.view.search.yml | 26 -- .../config/sync/views.view.search_cas.yml | 285 ++++++++++++++++++ .../src/Controller/SearchController.php | 51 +++- .../ys_core/src/Form/HeaderSettingsForm.php | 7 +- .../custom/ys_core/ys_core.routing.yml | 3 +- 10 files changed, 558 insertions(+), 60 deletions(-) create mode 100644 web/profiles/custom/yalesites_profile/config/sync/search_api.index.secure_index.yml create mode 100644 web/profiles/custom/yalesites_profile/config/sync/views.view.search_cas.yml diff --git a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.event.search_result.yml b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.event.search_result.yml index c8bea2ac5b..6a7f21b2bc 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.event.search_result.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.event.search_result.yml @@ -51,7 +51,7 @@ content: content_moderation_control: settings: { } third_party_settings: { } - weight: -20 + weight: 0 region: content field_external_source: type: link_separate @@ -63,19 +63,29 @@ content: rel: '' target: '' third_party_settings: { } - weight: 2 + weight: 3 + region: content + field_login_required: + type: boolean + label: hidden + settings: + format: boolean + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 4 region: content field_teaser_text: type: text_default label: hidden settings: { } third_party_settings: { } - weight: 1 + weight: 2 region: content search_api_excerpt: settings: { } third_party_settings: { } - weight: 0 + weight: 1 region: content hidden: field_category: true @@ -100,7 +110,6 @@ hidden: field_localist_id: true field_localist_info: true field_localist_register_enabled: true - field_login_required: true field_metatags: true field_stream_embed_code: true field_stream_url: true diff --git a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.page.search_result.yml b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.page.search_result.yml index e4148b32b7..41a2174cd0 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.page.search_result.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.page.search_result.yml @@ -26,7 +26,7 @@ content: content_moderation_control: settings: { } third_party_settings: { } - weight: -20 + weight: 0 region: content field_external_source: type: link_separate @@ -38,23 +38,32 @@ content: rel: '' target: '' third_party_settings: { } - weight: 2 + weight: 3 + region: content + field_login_required: + type: boolean + label: hidden + settings: + format: true-false + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 4 region: content field_teaser_text: type: text_default label: hidden settings: { } third_party_settings: { } - weight: 1 + weight: 2 region: content search_api_excerpt: settings: { } third_party_settings: { } - weight: 0 + weight: 1 region: content hidden: field_category: true - field_login_required: true field_metatags: true field_tags: true field_teaser_media: true diff --git a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.post.search_result.yml b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.post.search_result.yml index 55223405ec..ffbfc299a9 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.post.search_result.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.post.search_result.yml @@ -17,6 +17,7 @@ dependencies: - field.field.node.post.layout_builder__layout - node.type.post module: + - link - text - user id: node.post.search_result @@ -24,6 +25,11 @@ targetEntityType: node bundle: post mode: search_result content: + content_moderation_control: + settings: { } + third_party_settings: { } + weight: 0 + region: content field_external_source: type: link_separate label: hidden @@ -34,24 +40,33 @@ content: rel: '' target: '' third_party_settings: { } - weight: 2 + weight: 3 + region: content + field_login_required: + type: boolean + label: above + settings: + format: boolean + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 4 region: content field_teaser_text: type: text_default label: hidden settings: { } third_party_settings: { } - weight: 1 + weight: 2 region: content search_api_excerpt: settings: { } third_party_settings: { } - weight: 0 + weight: 1 region: content hidden: field_author: true field_category: true - field_login_required: true field_metatags: true field_publish_date: true field_tags: true @@ -59,3 +74,4 @@ hidden: field_teaser_title: true layout_builder__layout: true links: true + workflow_buttons: true diff --git a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.profile.search_result.yml b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.profile.search_result.yml index c4154d40db..a540cf2f2c 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.profile.search_result.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/core.entity_view_display.node.profile.search_result.yml @@ -42,7 +42,7 @@ content: content_moderation_control: settings: { } third_party_settings: { } - weight: -20 + weight: 0 region: content field_external_source: type: link_separate @@ -54,19 +54,29 @@ content: rel: '' target: '' third_party_settings: { } - weight: 2 + weight: 3 + region: content + field_login_required: + type: boolean + label: hidden + settings: + format: boolean + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 4 region: content field_teaser_text: type: text_default label: hidden settings: { } third_party_settings: { } - weight: 1 + weight: 2 region: content search_api_excerpt: settings: { } third_party_settings: { } - weight: 0 + weight: 1 region: content hidden: field_address: true @@ -76,7 +86,6 @@ hidden: field_first_name: true field_honorific_prefix: true field_last_name: true - field_login_required: true field_media: true field_metatags: true field_position: true diff --git a/web/profiles/custom/yalesites_profile/config/sync/search_api.index.secure_index.yml b/web/profiles/custom/yalesites_profile/config/sync/search_api.index.secure_index.yml new file mode 100644 index 0000000000..22aebb6baf --- /dev/null +++ b/web/profiles/custom/yalesites_profile/config/sync/search_api.index.secure_index.yml @@ -0,0 +1,165 @@ +uuid: eaac8aa4-ebe9-48a6-8d40-2aefff92390f +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_teaser_text + - search_api.server.database_server + module: + - node + - search_api + - search_api_exclude + - search_api_html_element_filter +id: secure_index +name: 'Secure Index' +description: '' +read_only: false +field_settings: + field_teaser_text: + label: 'Teaser Text' + datasource_id: 'entity:node' + property_path: field_teaser_text + type: text + dependencies: + config: + - field.storage.node.field_teaser_text + rendered_item: + label: 'Rendered HTML output' + property_path: rendered_item + type: text + configuration: + roles: + - authenticated + view_mode: + 'entity:node': + event: default + page: default + post: default + profile: default + status: + label: Published + datasource_id: 'entity:node' + property_path: status + type: boolean + dependencies: + module: + - node + type: + label: 'Content type' + datasource_id: 'entity:node' + property_path: type + type: string + dependencies: + module: + - node + uid: + label: 'Authored by' + datasource_id: 'entity:node' + property_path: uid + type: integer + dependencies: + module: + - node +datasource_settings: + 'entity:node': + bundles: + default: true + selected: { } + languages: + default: true + selected: { } +processor_settings: + add_url: { } + aggregated_field: { } + custom_value: { } + entity_status: { } + entity_type: { } + highlight: + weights: + postprocess_query: 0 + prefix: '' + suffix: '' + excerpt: true + excerpt_always: true + excerpt_length: 256 + exclude_fields: { } + highlight: always + highlight_partial: false + html_element_filter: + weights: + postprocess_query: -30 + preprocess_index: -50 + all_fields: 0 + fields: + - field_teaser_text + - rendered_item + - type + css_selectors: .visually-hidden + html_filter: + weights: + preprocess_index: -49 + preprocess_query: -48 + all_fields: false + fields: + - field_teaser_text + - rendered_item + title: true + alt: true + tags: + b: 2 + h1: 5 + h2: 3 + h3: 2 + strong: 2 + ignorecase: + weights: + preprocess_index: -48 + preprocess_query: -47 + all_fields: true + fields: + - field_teaser_text + - rendered_item + - type + language_with_fallback: { } + node_exclude: { } + rendered_item: { } + stemmer: + weights: + preprocess_index: -42 + preprocess_query: -42 + all_fields: false + fields: + - field_teaser_text + - rendered_item + exceptions: + mexican: mexic + texan: texa + tokenizer: + weights: + preprocess_index: -45 + preprocess_query: -44 + all_fields: false + fields: + - field_teaser_text + - rendered_item + spaces: '' + ignored: ._- + overlap_cjk: 1 + minimum_word_size: '3' + transliteration: + weights: + preprocess_index: -47 + preprocess_query: -46 + all_fields: true + fields: + - field_teaser_text + - rendered_item + - type +tracker_settings: + default: + indexing_order: fifo +options: + cron_limit: 50 + index_directly: true + track_changes_in_references: true +server: database_server diff --git a/web/profiles/custom/yalesites_profile/config/sync/views.view.search.yml b/web/profiles/custom/yalesites_profile/config/sync/views.view.search.yml index e9cc3b5682..6c78b37827 100644 --- a/web/profiles/custom/yalesites_profile/config/sync/views.view.search.yml +++ b/web/profiles/custom/yalesites_profile/config/sync/views.view.search.yml @@ -279,29 +279,3 @@ display: - 'config:field.storage.node.field_teaser_text' - 'config:search_api.index.node_index' - 'search_api_list:node_index' - page_1: - id: page_1 - display_title: Page - display_plugin: page - position: 1 - display_options: - exposed_block: false - display_extenders: - metatag_display_extender: - metatags: - title: '[view:title] | [site:name]' - tokenize: true - path: search - cache_metadata: - max-age: -1 - contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url - - url.query_args - - 'user.node_grants:view' - - user.permissions - tags: - - 'config:field.storage.node.field_teaser_text' - - 'config:search_api.index.node_index' - - 'search_api_list:node_index' diff --git a/web/profiles/custom/yalesites_profile/config/sync/views.view.search_cas.yml b/web/profiles/custom/yalesites_profile/config/sync/views.view.search_cas.yml new file mode 100644 index 0000000000..fe8b1fd016 --- /dev/null +++ b/web/profiles/custom/yalesites_profile/config/sync/views.view.search_cas.yml @@ -0,0 +1,285 @@ +uuid: 9fc73ca3-3fb4-486a-af60-ebc8213dc241 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_teaser_text + - search_api.index.secure_index + module: + - search_api + - text +id: search_cas +label: 'Search CAS' +module: views +description: 'Shows CAS-only items (titles only)' +tag: '' +base_table: search_api_index_secure_index +base_field: search_api_id +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + title: 'Search CAS' + fields: + field_teaser_text: + id: field_teaser_text + table: search_api_index_secure_index + field: field_teaser_text + relationship: none + group_type: group + admin_label: '' + entity_type: null + entity_field: null + plugin_id: search_api_field + 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: text_default + 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 + fallback_options: + link_to_item: false + use_highlighting: false + multi_type: separator + multi_separator: ', ' + pager: + type: full + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + first: '« First' + last: 'Last »' + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + quantity: 9 + 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 + access: + type: none + options: { } + cache: + type: search_api_tag + options: { } + empty: + area: + id: area + table: views + field: area + relationship: none + group_type: group + admin_label: '' + plugin_id: text + empty: true + content: + value: 'There were no results for your search.' + format: basic_html + tokenize: false + sorts: + search_api_relevance: + id: search_api_relevance + table: search_api_index_secure_index + field: search_api_relevance + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api + order: DESC + expose: + label: '' + field_identifier: '' + exposed: false + arguments: + search_api_fulltext: + id: search_api_fulltext + table: search_api_index_secure_index + field: search_api_fulltext + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api_fulltext + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: true + title: 'Search results: {{ arguments.search_api_fulltext }}' + default_argument_type: query_parameter + default_argument_options: + query_param: keywords + fallback: '' + multiple: and + summary_options: { } + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: none + fail: empty + validate_options: { } + break_phrase: false + not: false + parse_mode: terms + conjunction: AND + fields: { } + search_api_datasource: + id: search_api_datasource + table: search_api_index_secure_index + field: search_api_datasource + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: query_parameter + default_argument_options: + query_param: type + fallback: '' + multiple: and + summary_options: { } + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: none + fail: ignore + validate_options: { } + break_phrase: false + not: false + filters: { } + style: + type: default + options: + row_class: '' + default_row_class: true + uses_fields: false + row: + type: search_api + options: + view_modes: + 'entity:node': + event: search_result + page: search_result + post: search_result + profile: search_result + query: + type: search_api_query + options: + bypass_access: true + skip_access: true + preserve_facet_query_args: false + query_tags: { } + relationships: { } + header: + result_plural: + id: result_plural + table: views + field: result_plural + relationship: none + group_type: group + admin_label: '' + plugin_id: result_plural + empty: false + content: '
@total search result
' + content_plural: '
@total search results
' + plural_count_token: '@total' + footer: { } + display_extenders: + metatag_display_extender: + metatags: { } + tokenize: false + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + tags: + - 'config:field.storage.node.field_teaser_text' + - 'config:search_api.index.secure_index' + - 'search_api_list:secure_index' diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Controller/SearchController.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Controller/SearchController.php index f98b8ae8e0..c27981922b 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Controller/SearchController.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Controller/SearchController.php @@ -27,7 +27,9 @@ class SearchController extends ControllerBase { * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory service. */ - public function __construct(ConfigFactoryInterface $config_factory) { + public function __construct( + ConfigFactoryInterface $config_factory, + ) { $this->configFactory = $config_factory; } @@ -36,33 +38,30 @@ public function __construct(ConfigFactoryInterface $config_factory) { */ public static function create(ContainerInterface $container) { return new static( - $container->get('config.factory') + $container->get('config.factory'), ); } /** * Dynamic search page to show CAS titles or not. + * + * @param Symfony\Component\HttpFoundation\Request $request + * The Drupal request. */ public function searchPage(Request $request) { - // Check your configuration value to decide which view to render. + // Only show CAS titles if it is enabled. $config = $this->configFactory->get('ys_core.header_settings'); - $view_name = $config->get('search.enable_cas_search') ? 'search_cas' : 'search'; + $view_name = $config->get('search.enable_cas_search') && $config->get('search.enable_search_form') ? 'search_cas' : 'search'; $view = Views::getView($view_name); if ($view) { - // Set the display (e.g., 'default' display or a custom display). $view->setDisplay('default'); // Retrieve the 'keywords' parameter from the request, if it exists. $keywords = $request->query->get('keywords'); if ($keywords) { - // If your view has a contextual filter for keywords, pass it here. + // Pass keywords to contextual filter. $view->setArguments([$keywords]); - $keywords_markup = Markup::create('' . $this->t('@keywords', ['@keywords' => $keywords]) . ''); - $title = $this->t('Search results: @keywords', ['@keywords' => $keywords_markup]); - } - else { - $title = $this->t('Search'); } // Execute the view and render it. @@ -70,7 +69,7 @@ public function searchPage(Request $request) { $view->execute(); return [ - '#title' => $title, + '#title' => $this->getTitle($request, TRUE), 'view' => $view->render(), '#cache' => [ 'contexts' => ['url.query_args:keywords'], @@ -79,8 +78,34 @@ public function searchPage(Request $request) { } return [ - '#markup' => $this->t('No view available.'), + '#markup' => $this->t('No search view available.'), ]; } + /** + * Title callback to set tag and H1 page title. + * + * @param Symfony\Component\HttpFoundation\Request $request + * The Drupal request. + * @param bool $withMarkup + * If set, outputs the title with formatting for use with H1 tag. + * + * @return Drupal\Core\StringTranslation\TranslatableMarkup + * Drupal's translatable markup for the title. + */ + public function getTitle(Request $request, $withMarkup = FALSE) { + $keywords = $request->query->get('keywords'); + + if (!$keywords) { + return $this->t('Search'); + } + + if ($withMarkup) { + $keywords = Markup::create('<em>' . $this->t('@keywords', ['@keywords' => $keywords]) . '</em>'); + } + $title = $this->t('Search results: @keywords', ['@keywords' => $keywords]); + + return $title; + } + } diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Form/HeaderSettingsForm.php b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Form/HeaderSettingsForm.php index 0a7d823e52..558fdedd51 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Form/HeaderSettingsForm.php +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/src/Form/HeaderSettingsForm.php @@ -377,7 +377,12 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $headerConfig->set('cta_content', $form_state->getValue('cta_content')); $headerConfig->set('cta_url', $form_state->getValue('cta_url')); $headerConfig->set('search.enable_search_form', $form_state->getValue('enable_search_form')); - $headerConfig->set('search.enable_cas_search', $form_state->getValue('enable_cas_search')); + if ($form_state->getValue('enable_search_form') && $form_state->getValue('enable_cas_search')) { + $headerConfig->set('search.enable_cas_search', $form_state->getValue('enable_cas_search')); + } + else { + $headerConfig->set('search.enable_cas_search', 0); + } $headerConfig->set('focus_header_image', $form_state->getValue('focus_header_image')); $headerConfig->save(); diff --git a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/ys_core.routing.yml b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/ys_core.routing.yml index 81d67c4473..9f99c75afd 100644 --- a/web/profiles/custom/yalesites_profile/modules/custom/ys_core/ys_core.routing.yml +++ b/web/profiles/custom/yalesites_profile/modules/custom/ys_core/ys_core.routing.yml @@ -50,6 +50,7 @@ ys_core.admin_views_settings: ys_core.search_page: path: '/search' defaults: + _title_callback: '\Drupal\ys_core\Controller\SearchController::getTitle' _controller: '\Drupal\ys_core\Controller\SearchController::searchPage' requirements: - _permission: 'TRUE' + _access: 'TRUE'