From 6386363df15ffd7e501fdbb5aa1a68766589340a Mon Sep 17 00:00:00 2001 From: EarthlingDavey <15802017+EarthlingDavey@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:27:03 +0100 Subject: [PATCH 1/6] Initial commit WIP. --- .../clarity/inc/content-filter/search.php | 165 ++++++++---- .../app/themes/clarity/inc/pagination.tpl.php | 21 ++ public/app/themes/clarity/page_news.php | 14 +- .../c-article-item/view-news-feed.tpl.php | 33 +++ .../src/components/c-content-filter/view.php | 61 +++-- .../src/components/c-pagination/style.styl | 5 + .../src/globals/js/blog-content_filter.js | 252 +++++++++++++----- 7 files changed, 404 insertions(+), 147 deletions(-) create mode 100644 public/app/themes/clarity/inc/pagination.tpl.php create mode 100644 public/app/themes/clarity/src/components/c-article-item/view-news-feed.tpl.php diff --git a/public/app/themes/clarity/inc/content-filter/search.php b/public/app/themes/clarity/inc/content-filter/search.php index fe92d8727..ddd279c62 100644 --- a/public/app/themes/clarity/inc/content-filter/search.php +++ b/public/app/themes/clarity/inc/content-filter/search.php @@ -14,8 +14,59 @@ use MOJ\Intranet\EventsHelper; use WP_Query; + +/** + * QueryProps + * + * This class is responsible for handling the query properties. + * + * @package Clarity + * + * @property string $agency - The active agency. + * @property string $post_type - The post type. + * @property string $page - The page number. + * @property string $posts_per_page - The number of posts per page. + * @property string $keywords_filter - The keywords filter. + * @property string $date_filter - The date filter. + * + * @return void + */ + +class QueryProps +{ + public $agency_term_id; + public $post_type; + public $page; + public $posts_per_page; + public $keywords_filter; + public $date_filter; + public $news_category_id; + public $region_id; + + public function __construct( + $agency_term_id, + $post_type, + $page, + $posts_per_page = 10, + $keywords_filter = null, + $date_filter = null, + $news_category_id = null, + $region_id = null + ) { + $this->agency_term_id = $agency_term_id; + $this->post_type = $post_type; + $this->page = $page; + $this->posts_per_page = $posts_per_page; + $this->date_filter = $date_filter; + $this->keywords_filter = $keywords_filter; + $this->news_category_id = $news_category_id; + $this->region_id = $region_id; + } +} + class FilterSearch { + /** * FilterSearch constructor. * @@ -113,6 +164,20 @@ public function loadEventSearchResults() die(); } + public function mapResults(\WP_Post $post) + { + return [ + 'ID' => $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_type' => get_post_type($post->ID), // ? Is not used in the template. + '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), + ]; + } + /** * Load results for post types except for events. * @@ -121,7 +186,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,32 +196,41 @@ 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 + $query_props = new QueryProps( + (new Agency())->getCurrentAgency()['wp_tag_id'], + sanitize_text_field($_POST['post_type']), + $page, + $posts_per_page, + 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($this->getQueryArgs($query_props)); + + // include locate_template('src/components/c-article-item/view-news-feed.php'); + 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' => array_map([$this, 'mapResults'], $query->posts), ]); + } /** @@ -165,29 +239,14 @@ public function loadSearchResults() * @return array */ - function getQueryArgs() + function getQueryArgs(QueryProps $props) { - // 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; + $offset = $props->page ? (($props->page - 1) * $props->posts_per_page) : 0; $args = [ - 'numberposts' => $post_per_page, - 'post_type' => $post_type, + 'numberposts' => $props->posts_per_page, + 'post_type' => $props->post_type, 'post_status' => 'publish', 'offset' => $offset, 'tax_query' => [ @@ -195,30 +254,27 @@ function getQueryArgs() [ 'taxonomy' => 'agency', 'field' => 'term_id', - 'terms' => $active_agency['wp_tag_id'] + 'terms' => $props->agency_term_id ], // If the region is set add its ID to the taxonomy query - ...($is_regional ? [ + ...(!empty($props->region_id) ? [ 'taxonomy' => 'region', 'field' => 'region_id', - 'terms' => $news_category_id, + 'terms' => $props->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($news_category_id) && !$is_regional ? [ + ...(!empty($props->news_category_id) && empty($props->region_id) ? [ 'taxonomy' => 'news_category', 'field' => 'category_id', - 'terms' => $news_category_id, + 'terms' => $props->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); + // Parse dates from the date filter. + if (!empty($props->date_filter)) { + preg_match('/&after=([^&]*)&before=([^&]*)/', $props->date_filter, $matches); $args['date_query'] = [ 'after' => date('Y-m-d', strtotime($matches[1])), 'before' => date('Y-m-d', strtotime($matches[2])), @@ -226,13 +282,10 @@ function getQueryArgs() ]; } - // Get the search query. - $query = sanitize_text_field($_POST['query'] ?? ''); - // If there is a search query, set the orderby to relevance. - if (!empty($query)) { + if (!empty($props->keywords_filter)) { $args['orderby'] = 'relevance'; - $args['s'] = $query; + $args['s'] = $props->keywords_filter; } return $args; diff --git a/public/app/themes/clarity/inc/pagination.tpl.php b/public/app/themes/clarity/inc/pagination.tpl.php new file mode 100644 index 000000000..10f1eb11e --- /dev/null +++ b/public/app/themes/clarity/inc/pagination.tpl.php @@ -0,0 +1,21 @@ + + + + + diff --git a/public/app/themes/clarity/page_news.php b/public/app/themes/clarity/page_news.php index 5a712ca4d..c52d26852 100644 --- a/public/app/themes/clarity/page_news.php +++ b/public/app/themes/clarity/page_news.php @@ -1,25 +1,35 @@ getCurrentAgency(); + +// TODO: Add this to a function later +get_template_part('src/components/c-article-item/view-news-feed.tpl'); +// TODO: Add this to a function later +require_once 'inc/pagination.tpl.php'; + ?>{$post->post_excerpt}
", 'permalink' => get_permalink($post->ID), - 'post_type' => get_post_type($post->ID), // ? Is not used in the template. '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), ]; } + public function mapPostResult(\WP_Post $post) + { + + $thumbnail = get_the_post_thumbnail_url($post->ID, 'user-thumb'); + $thumbnail_alt = get_post_meta(get_post_thumbnail_id($post->ID), '_wp_attachment_image_alt', true); + + $author = $post->post_author; + $author_display_name = $author ? get_the_author_meta('display_name', $author) : ''; + + if (!$thumbnail) { + // Mutate thumbnail with author image. + $thumbnail = $author ? get_the_author_meta('thumbnail_avatar', $author) : false; + $thumbnail_alt = $author_display_name; + } + + 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' => $thumbnail, + 'post_thumbnail' => false, + 'post_thumbnail_alt' => $thumbnail_alt, + 'author_display_name' => $author ? get_the_author_meta('display_name', $author) : '', + ]; + } + /** * Load results for post types except for events. * @@ -197,20 +266,29 @@ public function loadSearchResults() add_filter('ep_enable_do_weighting', '__return_true'); $page = (int) $_POST['page'] ?? 1; - if($page < 1 || $page > 1000) { + 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) { + if ($posts_per_page < 1 || $posts_per_page > 100) { $posts_per_page = 10; } - $query_props = new QueryProps( + $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'], - sanitize_text_field($_POST['post_type']), + $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), @@ -218,9 +296,9 @@ public function loadSearchResults() ); // Run a query based on generated query arguments. - $query = new WP_Query($this->getQueryArgs($query_props)); + $query = new WP_Query($query_args->get()); - // include locate_template('src/components/c-article-item/view-news-feed.php'); + $map_function = $post_type === 'news' ? 'mapNewsResult' : 'mapPostResult'; return wp_send_json([ 'aggregates' => [ @@ -228,98 +306,36 @@ public function loadSearchResults() 'resultsPerPage' => $posts_per_page, 'currentPage' => $page, ], - 'results' => array_map([$this, 'mapResults'], $query->posts), + '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(QueryProps $props) + public function addAjaxTemplates() { - // Pagination. - $offset = $props->page ? (($props->page - 1) * $props->posts_per_page) : 0; - $args = [ - 'numberposts' => $props->posts_per_page, - 'post_type' => $props->post_type, - 'post_status' => 'publish', - 'offset' => $offset, - 'tax_query' => [ - 'relation' => 'AND', - [ - 'taxonomy' => 'agency', - 'field' => 'term_id', - 'terms' => $props->agency_term_id - ], - // If the region is set add its ID to the taxonomy query - ...(!empty($props->region_id) ? [ - 'taxonomy' => 'region', - 'field' => 'region_id', - 'terms' => $props->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($props->news_category_id) && empty($props->region_id) ? [ - 'taxonomy' => 'news_category', - 'field' => 'category_id', - 'terms' => $props->news_category_id, - ] : []), - ] - ]; - - // Parse dates from the date filter. - if (!empty($props->date_filter)) { - preg_match('/&after=([^&]*)&before=([^&]*)/', $props->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 (is_page_template('page_blog.php') || is_page_template('page_news.php')) { + get_template_part('src/components/c-pagination/view-infinite.ajax'); + echo ''; } - // If there is a search query, set the orderby to relevance. - if (!empty($props->keywords_filter)) { - $args['orderby'] = 'relevance'; - $args['s'] = $props->keywords_filter; + 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 - */ - - 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_news.php')) { + get_template_part('src/components/c-article-item/view-news-feed.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) { ?> -