diff --git a/public/app/themes/clarity/functions.php b/public/app/themes/clarity/functions.php index 9763e6f9b..cdb9a3c78 100644 --- a/public/app/themes/clarity/functions.php +++ b/public/app/themes/clarity/functions.php @@ -59,7 +59,6 @@ require_once 'inc/amazon-s3-and-cloudfront-signing.php'; require_once 'inc/amazon-s3-and-cloudfront.php'; -require_once 'inc/api/get-posts-rest-api.php'; require_once 'inc/api/campaign-api.php'; require_once 'inc/api/get-campaign-posts-api.php'; require_once 'inc/api/get-news-rest-api.php'; @@ -76,6 +75,7 @@ require_once 'inc/cookies.php'; require_once 'inc/comments.php'; require_once 'inc/constants.php'; +require_once 'inc/content-filter/search-query.php'; require_once 'inc/content-filter/search.php'; require_once 'inc/enqueue.php'; require_once 'inc/form-builder.php'; @@ -94,7 +94,6 @@ require_once 'inc/menu.php'; require_once 'inc/utilities.php'; require_once 'inc/pagination.php'; -require_once 'inc/pagination-newscategory.php'; require_once 'inc/post-types/post.php'; require_once 'inc/post-types/event.php'; @@ -120,6 +119,9 @@ new MOJ\Intranet\WPOffloadMedia(); new MOJ\Intranet\WPElasticPress(); +$search = new MOJ\Intranet\Search(); +$search->hooks(); + /// Prevent the Agency Switcher page from being overwritten add_action('save_post', function ($post_id, $post) { if ($post->post_name === 'agency-switcher') { diff --git a/public/app/themes/clarity/inc/api/get-news-rest-api.php b/public/app/themes/clarity/inc/api/get-news-rest-api.php index 2e21c13ce..d28f654cc 100644 --- a/public/app/themes/clarity/inc/api/get-news-rest-api.php +++ b/public/app/themes/clarity/inc/api/get-news-rest-api.php @@ -17,7 +17,7 @@ function get_news_api($set_cpt = '') $oAgency = new Agency(); $activeAgency = $oAgency->getCurrentAgency(); $post_per_page = 10; - $post_type = 'news'; + $post_type = get_post_type(); $post_id = get_the_ID(); $region_id = get_the_terms($post_id, 'region'); $regional_template = get_post_meta(get_the_ID(), 'dw_regional_template', true); diff --git a/public/app/themes/clarity/inc/api/get-posts-rest-api.php b/public/app/themes/clarity/inc/api/get-posts-rest-api.php deleted file mode 100644 index a8628adb9..000000000 --- a/public/app/themes/clarity/inc/api/get-posts-rest-api.php +++ /dev/null @@ -1,41 +0,0 @@ -getCurrentAgency(); - - $args = [ - 'numberposts' => $blog_posts_number, - 'post_type' => 'post', - 'post_status' => 'publish', - 'tax_query' => [ - 'relation' => 'AND', - [ - 'taxonomy' => 'agency', - 'field' => 'term_id', - 'terms' => $activeAgency['wp_tag_id'] - ], - ] - ]; - - $posts = get_posts($args); - - echo '
'; - foreach ($posts as $key => $post) { - include locate_template('src/components/c-article-item/view-blog-feed.php'); - } - -} diff --git a/public/app/themes/clarity/inc/content-filter/search-query.php b/public/app/themes/clarity/inc/content-filter/search-query.php new file mode 100644 index 000000000..d719c66f7 --- /dev/null +++ b/public/app/themes/clarity/inc/content-filter/search-query.php @@ -0,0 +1,94 @@ +page ? (($this->page - 1) * $this->posts_per_page) : 0; + + $args = [ + 'posts_per_page' => $this->posts_per_page, + 'post_type' => $this->post_type, + 'post_status' => 'publish', + 'offset' => $offset, + ...($this->exclude_current ? ['post__not_in' => [get_the_ID()]] : []), + 'tax_query' => [ + 'relation' => 'AND', + [ + 'taxonomy' => 'agency', + 'field' => 'term_id', + 'terms' => $this->agency_term_id + ], + // If the region is set add its ID to the taxonomy query + ...(!empty($this->region_id) ? [ + 'taxonomy' => 'region', + 'field' => 'region_id', + 'terms' => $this->region_id, + ] : []), + // If the news category is set add its ID unless the query is regional, + // as it will have already been added to the tax query. + ...(!empty($this->news_category_id) && empty($this->region_id) ? [ + 'taxonomy' => 'news_category', + 'field' => 'category_id', + 'terms' => $this->news_category_id, + ] : []), + ] + ]; + + // Parse dates from the date filter. + if (!empty($this->date_filter)) { + preg_match('/&after=([^&]*)&before=([^&]*)/', $this->date_filter, $matches); + $args['date_query'] = [ + 'after' => date('Y-m-d', strtotime($matches[1])), + 'before' => date('Y-m-d', strtotime($matches[2])), + 'inclusive' => false, + ]; + } + + // If there is a search query, set the orderby to relevance. + if (!empty($this->keywords_filter)) { + $args['orderby'] = 'relevance'; + $args['s'] = $this->keywords_filter; + } + + return $args; + } +} \ No newline at end of file diff --git a/public/app/themes/clarity/inc/content-filter/search.php b/public/app/themes/clarity/inc/content-filter/search.php index fe92d8727..275145421 100644 --- a/public/app/themes/clarity/inc/content-filter/search.php +++ b/public/app/themes/clarity/inc/content-filter/search.php @@ -10,22 +10,23 @@ namespace MOJ\Intranet; +defined('ABSPATH') || exit; + use MOJ\Intranet\Agency; use MOJ\Intranet\EventsHelper; +use MOJ\Intranet\SearchQueryArgs; use WP_Query; -class FilterSearch +class Search { + /** * FilterSearch constructor. * * @return void */ - public function __construct() - { - $this->hooks(); - } + public function __construct() {} /** * Hooks @@ -34,10 +35,14 @@ public function __construct() */ public function hooks(): void { + // Add functions to handle AJAX requests. add_action('wp_ajax_load_search_results', [$this, 'loadSearchResults']); add_action('wp_ajax_nopriv_load_search_results', [$this, 'loadSearchResults']); add_action('wp_ajax_load_events_filter_results', [$this, 'loadEventSearchResults']); add_action('wp_ajax_nopriv_load_events_filter_results', [$this, 'loadEventSearchResults']); + + // Add templates to the footer. + add_action('wp_footer', [$this, 'addAjaxTemplates']); } /** @@ -48,69 +53,116 @@ public function hooks(): void public function loadEventSearchResults() { - if (!wp_verify_nonce($_POST['nonce_hash'], 'search_filter_nonce')) { + if (!wp_verify_nonce($_POST['_nonce'], 'search_filter_nonce')) { exit('Access not allowed.'); } - $active_agency = (new Agency())->getCurrentAgency(); - $agency_term_id = $active_agency['wp_tag_id']; - $date_filter = sanitize_text_field($_POST['valueSelected'] ?? 'all'); - $post_id = get_the_ID(); - $query = sanitize_text_field($_POST['query']); - - $filter_options = ['keyword_search' => $query]; - - if ($date_filter != 'all') { - $filter_options['date_filter'] = $date_filter; + + $agency_term_id =(new Agency())->getCurrentAgency()['wp_tag_id']; + + $filter_options = [ + 'keyword_search' => sanitize_text_field($_POST['keywords_filter'] ?? ''), + 'date_filter' => $_POST['date_filter'] == 'all' ? '' : sanitize_text_field($_POST['date_filter']), + ]; + + + if (isset($_POST['termID'])) { + $tax_id = sanitize_text_field($_POST['termID']); + + $filter_options['region_filter'] = $tax_id; } $events_helper = new EventsHelper(); - if (isset($_POST['termID'])) { - $tax_id = sanitize_text_field($_POST['termID']); + $events = $events_helper->get_events($agency_term_id, $filter_options) ?? []; - $filter_options['region_filter'] = $tax_id; + return wp_send_json([ + 'aggregates' => [ + 'totalResults' => count($events), + 'resultsPerPage' => -1, + 'currentPage' => 1, + ], + 'results' => [ + 'templateName' => "c-events-item-list", + 'posts' => array_map([$this, 'mapEventResult'], $events), + ], + ]); + } - $events = $events_helper->get_events($agency_term_id, $filter_options); - } else { - $events = $events_helper->get_events($agency_term_id, $filter_options); + public function mapEventResult($event) + { + // Assign some default values. + $time_formatted = 'All day'; + $datetime = 'P1D'; + + if (!$event->event_allday) { + $datetime = $event->event_start_time; + // If start date and end date selected are the same, just display first date. + if ($event->event_start_time === $event->event_end_time) { + $time_formatted = substr($event->event_start_time, 0, 5); + } else { + $time_formatted = substr($event->event_start_time, 0, 5) . ' - ' . substr($event->event_end_time, 0, 5); + } } - if ($events) { - echo ''; - - foreach ($events as $key => $event) : - $event_id = $event->ID; - $post_url = $event->url; - $event_title = $event->post_title; + if ($event->event_start_date === $event->event_end_date) { + $multi_date = date('d M', strtotime($event->event_start_date)); + } else { + $multi_date = date('d M', strtotime($event->event_start_date)) . ' - ' . date('d M', strtotime($event->event_end_date)); + } - $start_date = $event->event_start_date; - $end_date = $event->event_end_date; - $start_time = $event->event_start_time; - $end_time = $event->event_end_time; - $location = $event->event_location; - $date = $event->event_start_date; - $day = date('l', strtotime($start_date)); - $month = date('M', strtotime($start_date)); - $year = date('Y', strtotime($start_date)); - $all_day = $event->event_allday; + return [ + 'permalink' => $event->url, + 'post_title' => $event->post_title, + 'year' => date('Y', strtotime($event->event_start_date)), + 'day' => date('l', strtotime($event->event_start_date)), + 'location' => $event->event_location, + 'time_formatted' => $time_formatted, + 'datetime_formatted' => $datetime, + 'multi_date_formatted' => $multi_date + ]; + } - if ($all_day == true) { - $all_day = 'all_day'; - } + public function mapNewsResult(\WP_Post $post) + { + return [ + 'ID' => $post->ID, + 'post_type' => get_post_type($post->ID), + 'post_title' => $post->post_title, + 'post_date_formatted' => get_gmt_from_date($post->post_date, 'j M Y'), + 'post_excerpt_formatted' => empty($post->post_excerpt) ? '' : "{$post->post_excerpt}
", + 'permalink' => get_permalink($post->ID), + 'post_thumbnail' => get_the_post_thumbnail_url($post->ID, 'user-thumb'), + 'post_thumbnail_alt' => get_post_meta(get_post_thumbnail_id($post->ID), '_wp_attachment_image_alt', true), + ]; + } - echo '{$post->post_excerpt}
", + 'permalink' => get_permalink($post->ID), + 'post_thumbnail' => $thumbnail, + 'post_thumbnail_alt' => $thumbnail_alt, + 'author_display_name' => $author ? get_the_author_meta('display_name', $author) : '', + ]; } /** @@ -121,7 +173,7 @@ public function loadEventSearchResults() public function loadSearchResults() { - if (!wp_verify_nonce($_POST['nonce_hash'], 'search_filter_nonce')) { + if (!wp_verify_nonce($_POST['_nonce'], 'search_filter_nonce')) { exit('Access not allowed.'); } @@ -131,142 +183,81 @@ public function loadSearchResults() // Apply the weighting fields configuration to the query. add_filter('ep_enable_do_weighting', '__return_true'); - // Run a query based on generated query arguments. - $query = new WP_Query($this->getQueryArgs()); - - // Use output buffering to capture the HTML output. - // This is necessary to get the html without refactoring the component's code. - ob_start(); - echo ''; - foreach ($query->posts as $post) { - // $post is used in the included file. - include locate_template('src/components/c-article-item/view-news-feed.php'); + $page = (int) $_POST['page'] ?? 1; + if ($page < 1 || $page > 1000) { + $page = 1; + } + + $posts_per_page = (int) ($_POST['posts_per_page'] ?? 10); + if ($posts_per_page < 1 || $posts_per_page > 100) { + $posts_per_page = 10; } - $result_html = ob_get_clean(); - // Get the pagination HTML. - $pagination_html = $this->getPagination( - sanitize_text_field($_POST['valueSelected']), - sanitize_text_field($_POST['nextPageToRetrieve']), - $query->max_num_pages + $allowed_post_types = ['post', 'news']; + + if (!in_array($_POST['post_type'], $allowed_post_types)) { + throw new \Exception('Invalid post type.'); + } + + $post_type = $_POST['post_type']; + + $query_args = new SearchQueryArgs( + (new Agency())->getCurrentAgency()['wp_tag_id'], + $post_type, + $page, + $posts_per_page, + false, + sanitize_text_field($_POST['keywords_filter'] ?? null), + sanitize_text_field($_POST['date_filter'] ?? null), + sanitize_text_field($_POST['news_category_id'] ?? null), + sanitize_text_field($_POST['region_id'] ?? null) ); - // Return the results as JSON. + // Run a query based on generated query arguments. + $query = new WP_Query($query_args->get()); + + $map_function = $post_type === 'news' ? 'mapNewsResult' : 'mapPostResult'; + return wp_send_json([ - 'results' => $result_html, - 'total' => $query->found_posts . ' search results', - 'pagination' => $pagination_html + 'aggregates' => [ + 'totalResults' => $query->found_posts, + 'resultsPerPage' => $posts_per_page, + 'currentPage' => $page, + ], + 'results' => [ + 'posts' => array_map([$this, $map_function], $query->posts), + 'templateName' => "view-{$post_type}-feed", + ], ]); } + /** - * Get Query Args + * Add AJAX templates to the footer. * - * @return array + * These JS templates are used to render the AJAX results to html. + * + * @return void */ - function getQueryArgs() + public function addAjaxTemplates() { - // Get the active agency. - $active_agency = (new Agency())->getCurrentAgency(); - - // Pagination. - $post_per_page = 10; - $next_page_to_retrieve = sanitize_text_field($_POST['nextPageToRetrieve'] ?? ''); - $offset = $next_page_to_retrieve ? (($next_page_to_retrieve - 1) * $post_per_page) : 0; - - // Post type, with a cleanup of the value. - $post_type = sanitize_text_field($_POST['postType'] ?? ''); - $post_type = $post_type === 'posts' ? 'post' : $post_type; - - // Is the request for a news category? - $news_category_id = sanitize_text_field($_POST['newsCategoryValue'] ?? ''); - - // Check if the post type is regional. - $is_regional = $post_type === 'regional_news' ? true : false; - - $args = [ - 'numberposts' => $post_per_page, - 'post_type' => $post_type, - 'post_status' => 'publish', - 'offset' => $offset, - 'tax_query' => [ - 'relation' => 'AND', - [ - 'taxonomy' => 'agency', - 'field' => 'term_id', - 'terms' => $active_agency['wp_tag_id'] - ], - // If the region is set add its ID to the taxonomy query - ...($is_regional ? [ - 'taxonomy' => 'region', - 'field' => 'region_id', - 'terms' => $news_category_id, - ] : []), - // If the news category is set add its ID unless the query is regional, - // as it will have already been added to the tax query. - ...(!empty($news_category_id) && !$is_regional ? [ - 'taxonomy' => 'news_category', - 'field' => 'category_id', - 'terms' => $news_category_id, - ] : []), - ] - ]; - // Get the date filter value. - $value_selected = sanitize_text_field($_POST['valueSelected'] ?? ''); - - // Parse dates from the value selected. - if (!empty($value_selected)) { - preg_match('/&after=([^&]*)&before=([^&]*)/', $value_selected, $matches); - $args['date_query'] = [ - 'after' => date('Y-m-d', strtotime($matches[1])), - 'before' => date('Y-m-d', strtotime($matches[2])), - 'inclusive' => false, - ]; + if (is_page_template('page_blog.php') || is_page_template('page_news.php')) { + get_template_part('src/components/c-pagination/view-infinite.ajax'); + echo ''; } - // Get the search query. - $query = sanitize_text_field($_POST['query'] ?? ''); - - // If there is a search query, set the orderby to relevance. - if (!empty($query)) { - $args['orderby'] = 'relevance'; - $args['s'] = $query; + if (is_page_template('page_blog.php')) { + get_template_part('src/components/c-article-item/view-blog-feed.ajax'); } - return $args; - } - - /** - * Get Pagination - * - * @param string $selected - * @param int|string $next - * @param int $total - * @return string - */ + if (is_page_template('page_news.php')) { + get_template_part('src/components/c-article-item/view-news-feed.ajax'); + } - function getPagination(string $selected, int|string $next, int $total): string - { - $html = ''; - if ($next == $total) { - $html .= ''; - $html .= 'No More Results'; - $html .= ''; - } elseif ($total <= 1) { - $html .= ''; - } else { - $html .= ''; + if (is_page_template('page_events.php')) { + get_template_part('src/components/c-events-item/view-list.ajax'); } - return $html; } } - -new FilterSearch(); diff --git a/public/app/themes/clarity/inc/pagination-newscategory.php b/public/app/themes/clarity/inc/pagination-newscategory.php deleted file mode 100644 index e914a6ea0..000000000 --- a/public/app/themes/clarity/inc/pagination-newscategory.php +++ /dev/null @@ -1,54 +0,0 @@ -getCurrentAgency(); - - $post_per_page = 10; - - $args = [ - 'numberposts' => $post_per_page, - 'post_type' => 'news', - 'post_status' => 'publish', - 'tax_query' => [ - 'relation' => 'AND', - [ - 'taxonomy' => 'agency', - 'field' => 'term_id', - 'terms' => $activeAgency['wp_tag_id'] - ], - // If the category_id is set add it to the taxonomy query - ...( $category_id ? [ - 'taxonomy' => 'news_category', - 'field' => 'category_id', - 'terms' => $category_id, - ] : []), - ] - ]; - - $query = new WP_Query($args); - $pagetotal = $query->max_num_pages; - - ?> - - - 0) { ?> -