Skip to content

Commit

Permalink
PLANET-6552: Extract search filters
Browse files Browse the repository at this point in the history
Extract search filters to their own classes
Use consistent taxonomy
  • Loading branch information
lithrel committed May 13, 2022
1 parent 21803db commit 9bd771d
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 126 deletions.
142 changes: 23 additions & 119 deletions src/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -727,85 +727,21 @@ protected function set_general_context( &$context ) {
* @throws UnexpectedValueException When filter type is not recognized.
*/
protected function set_filters_context( &$context ) {
// Retrieve P4 settings in order to check that we add only categories that are children of the Issues category.
$options = get_option( 'planet4_options' );
// Categories.
$context['categories'] = Search\Filters\Categories::get_filters();
uasort( $context['categories'], fn ( $a, $b ) => strcmp( $a['name'], $b['name'] ) );

// Category <-> Issue.
// Consider Issues that have multiple Categories.
$categories = get_categories( [ 'child_of' => $options['issues_parent_category'] ] );
if ( $categories ) {
foreach ( $categories as $category ) {
$context['categories'][ $category->term_id ] = [
'term_id' => $category->term_id,
'name' => $category->name,
'results' => 0,
];
}
}
// Post Types.
$context['post_types'] = Search\Filters\PostTypes::get_filters();

// Tag <-> Campaign.
$tags = get_terms(
[
'taxonomy' => 'post_tag',
'hide_empty' => false,
]
// Content Types.
$context['content_types'] = Search\Filters\ContentTypes::get_filters(
self::should_include_archive()
);
if ( $tags ) {
foreach ( (array) $tags as $tag ) {
// Tag filters.
$context['tags'][ $tag->term_id ] = [
'term_id' => $tag->term_id,
'name' => $tag->name,
'results' => 0,
];
}
}

// Page Type <-> Category.
$page_types = get_terms(
[
'taxonomy' => 'p4-page-type',
'hide_empty' => false,
]
);
if ( $page_types ) {
foreach ( (array) $page_types as $page_type ) {
// p4-page-type filters.
$context['page_types'][ $page_type->term_id ] = [
'term_id' => $page_type->term_id,
'name' => $page_type->name,
'results' => 0,
];
}
}

// Post Type (+Action) <-> Content Type.
$context['content_types']['0'] = [
'name' => __( 'Action', 'planet4-master-theme' ),
'results' => 0,
];
$context['content_types']['4'] = [
'name' => __( 'Campaign', 'planet4-master-theme' ),
'results' => 0,
];
$context['content_types']['1'] = [
'name' => __( 'Document', 'planet4-master-theme' ),
'results' => 0,
];
$context['content_types']['2'] = [
'name' => __( 'Page', 'planet4-master-theme' ),
'results' => 0,
];
$context['content_types']['3'] = [
'name' => __( 'Post', 'planet4-master-theme' ),
'results' => 0,
];
if ( self::should_include_archive() ) {
$context['content_types']['5'] = [
'name' => __( 'Archive', 'planet4-master-theme' ),
'results' => 0,
];
}
// Tag <-> Campaign.
$context['tags'] = Search\Filters\Tags::get_filters();
uasort( $context['tags'], fn ( $a, $b ) => strcmp( $a['name'], $b['name'] ) );

// Keep track of which filters are already checked.
if ( $this->filters ) {
Expand All @@ -819,7 +755,7 @@ protected function set_filters_context( &$context ) {
$context['tags'][ $filter['id'] ]['checked'] = 'checked';
break;
case 'ptype':
$context['page_types'][ $filter['id'] ]['checked'] = 'checked';
$context['post_types'][ $filter['id'] ]['checked'] = 'checked';
break;
case 'ctype':
$context['content_types'][ $filter['id'] ]['checked'] = 'checked';
Expand All @@ -830,34 +766,11 @@ protected function set_filters_context( &$context ) {
}
}
}

// Sort associative array with filters alphabetically.
if ( $context['categories'] ?? false ) {
uasort(
$context['categories'],
function ( $a, $b ) {
return strcmp( $a['name'], $b['name'] );
}
);
}
if ( $context['tags'] ?? false ) {
uasort(
$context['tags'],
function ( $a, $b ) {
return strcmp( $a['name'], $b['name'] );
}
);
}
}

/**
* Sets the context for the results of the Search.
*
* Categories are Issues.
* Tags are Campaigns.
* Page types are Categories.
* Post_types are Content Types.
*
* @param array $context Associative array with the data to be passed to the view.
*/
protected function set_results_context( &$context ) {
Expand Down Expand Up @@ -908,33 +821,24 @@ protected function set_results_context( &$context ) {
}

foreach ( $aggs['p4-page-type']['buckets'] as $p4_post_type_agg ) {
$p4_post_type_id = (int) $p4_post_type_agg['key'];

$p4_post_type = self::get_p4_post_type( $p4_post_type_id );

$context['page_types'][ $p4_post_type_id ] = [
'term_id' => $p4_post_type_id,
'name' => $p4_post_type->name ?? null,
'results' => $p4_post_type_agg['doc_count'],
];
if ( ! isset( $context['post_types'][ $p4_post_type_agg['key'] ] ) ) {
continue;
}
$context['post_types'][ $p4_post_type_agg['key'] ]['results'] = $p4_post_type_agg['doc_count'];
}

foreach ( $aggs['categories']['buckets'] as $category_agg ) {
// TODO get the parent from ES so no fetch is needed here.
$category = get_category( $category_agg['key'] );

// Category <-> Issue.
// Consider Issues that have multiple Categories.
if ( $category->parent === (int) $options['issues_parent_category'] ) {
$context['categories'][ $category->term_id ]['results'] = $category_agg['doc_count'];
if ( ! isset( $context['categories'][ $category_agg['key'] ] ) ) {
continue;
}
$context['categories'][ $category_agg['key'] ]['results'] = $category_agg['doc_count'];
}

foreach ( $aggs['tags']['buckets'] as $tag_agg ) {
// Tag filters.
$tag = get_tag( $tag_agg['key'] );

$context['tags'][ $tag->term_id ]['results'] = $tag_agg['doc_count'];
if ( ! isset( $context['tags'][ $tag_agg['key'] ] ) ) {
continue;
}
$context['tags'][ $tag_agg['key'] ]['results'] = $tag_agg['doc_count'];
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/Search/Filters/Categories.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace P4\MasterTheme\Search\Filters;

/**
* Categories used for search.
*/
class Categories {
/**
* @return array<WP_Term>
*/
public static function get_all(): array {
return get_categories();
}

/**
* @return array{int, array{term_id: int, name: string, results: int}}
*/
public static function get_filters(): array {
$categories = self::get_all();
$filters = [];

foreach ( $categories as $category ) {
if ( 'uncategorised' === $category->slug ) {
continue;
}

$filters[ $category->term_id ] = [
'term_id' => $category->term_id,
'name' => $category->name,
'results' => 0,
];
}

return $filters;
}
}
116 changes: 116 additions & 0 deletions src/Search/Filters/ContentTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

declare(strict_types=1);

namespace P4\MasterTheme\Search\Filters;

/**
* Content type used for search.
* Native types (post, page, attachment, etc.).
* Custom types (p4_action, etc.).
*/
class ContentTypes {
public const ACT_PAGE = 'action';
public const POST = 'post';
public const PAGE = 'page';
public const CAMPAIGN = 'campaign';
public const ATTACHMENT = 'attachment';
public const ARCHIVE = 'archive';

/**
* Get all content types.
*
* @return array<WP_Post_Type>
*/
public static function get_all(): array {
$config = self::get_config();
$types = get_post_types(
[
'public' => true,
'exclude_from_search' => false,
],
false
);

return array_filter(
$types,
function ( $type ) use ( $config ) {
return isset( $config[ $type->name ] );
}
);
}

/**
* @param bool $include_archive Include archive type.
*
* @return array{string, array{id: int, name: string, results: int}}
*/
public static function get_filters(
bool $include_archive = false
): array {
$types = self::get_all();
$config = self::get_config();

// ACT_PAGE are sub-pages of the Act page and not a real type, adding manually.
$filters = [
0 => [
'id' => 0,
'name' => __( 'Action', 'planet4-master-theme' ),
'results' => 0,
],
];

foreach ( $types as $name => $type ) {
if ( self::ARCHIVE === $name && ! $include_archive ) {
continue;
}

$type_data = $config[ $type->name ] ?? null;
if ( ! $type_data ) {
continue;
}

$filters[ $type_data['id'] ] = [
'id' => $type_data['id'],
'name' => $type_data['label'],
'results' => 0,
];
}

return $filters;
}

/**
* Get all content type config for search
*
* @return array{string, array{id: int, label: string}}
*/
public static function get_config(): array {
return [
self::ACT_PAGE => [
'id' => 0,
'label' => __( 'Action', 'planet4-master-theme' ),
],
self::ATTACHMENT => [
'id' => 1,
'label' => __( 'Document', 'planet4-master-theme' ),
],
self::PAGE => [
'id' => 2,
'label' => __( 'Page', 'planet4-master-theme' ),
],
self::POST => [
'id' => 3,
'label' => __( 'Post', 'planet4-master-theme' ),
],
self::CAMPAIGN => [
'id' => 4,
'label' => __( 'Campaign', 'planet4-master-theme' ),
],
self::ARCHIVE => [
'id' => 5,
'label' => __( 'Archive', 'planet4-master-theme' ),
],
];
}
}
53 changes: 53 additions & 0 deletions src/Search/Filters/PostTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace P4\MasterTheme\Search\Filters;

use WP_Term;

/**
* Post types used for search (Press release, News, Report, etc.).
* Configured in `Posts > Posts Types`
*/
class PostTypes {
/**
* @return WP_Term[]
*/
public static function get_all(): array {
$types = get_terms(
[
'taxonomy' => 'p4-page-type',
'hide_empty' => false,
]
);

if ( is_wp_error( $types )
|| ! is_array( $types )
|| empty( $types )
|| ! ( $types[0] instanceof WP_Term )
) {
return [];
}

return $types;
}

/**
* @return array{int, array{term_id: int, name: string, results: int}}
*/
public static function get_filters(): array {
$post_types = self::get_all();
$filters = [];

foreach ( $post_types as $post_type ) {
$filters[ $post_type->term_id ] = [
'term_id' => $post_type->term_id,
'name' => $post_type->name,
'results' => 0,
];
}

return $filters;
}
}
Loading

0 comments on commit 9bd771d

Please sign in to comment.