Advertisement
geminilabs

[site-reviews-filters] Multiple category and custom field filters

Sep 16th, 2022 (edited)
1,428
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.46 KB | None | 0 0
  1. /**
  2.  * Example usage:
  3.  *
  4.  * new CustomReviewFilters([
  5.  *     // Add a custom filter for some child categories
  6.  *     'filter_by_food' => [                    // filter name (must start with "filter_by_")
  7.  *         'parent_term' => 'foods',            // parent category ID or slug (must be a Site Reviews category!)
  8.  *         'placeholder' => 'All Foods',        // dropdown placeholder
  9.  *         'type' => 'term',                    // type of filter (term or custom)
  10.  *     ],
  11.  *     // Add a custom filter for a custom field named "surcharge"
  12.  *     'filter_by_surcharge' => [               // filter name (must start with "filter_by_")
  13.  *         'cast' => 'string',                  // What to cast the value as (string or int)
  14.  *         'type' => 'custom',                  // type of filter (term or custom)
  15.  *         'placeholder' => 'Any Surcharge',    // dropdown placeholder
  16.  *         'options' => [                       // dropdown options
  17.  *             'Yes' => 'Surcharge: Yes',
  18.  *             'No' => 'Surcharge: No',
  19.  *         ],
  20.  *     ],
  21.  * ]);
  22.  *
  23.  */
  24.  
  25. class CustomReviewFilters
  26. {
  27.     public $filters = [];
  28.  
  29.     public function __construct(array $filters = [])
  30.     {
  31.         add_action('init', function () use ($filters) {
  32.             if (!function_exists('glsr')
  33.                 || !function_exists('glsr_get')
  34.                 || !glsr()->addon('site-reviews-filters')
  35.                 || !class_exists('\GeminiLabs\SiteReviews\Addon\Filters\Defaults\FilteredDefaults')) {
  36.                 return;
  37.             }
  38.             $this->filters = $this->normalize($filters);
  39.             foreach ($this->filters as $filter => $values) {
  40.                 if ('custom' === $values['type']) {
  41.                     add_action('site-reviews-filters/sql-and/build/'.$filter, [$this, 'filterSqlAndForCustom'], 10, 3);
  42.                     add_action('site-reviews-filters/sql-join/build/'.$filter, [$this, 'filterSqlJoinForCustom'], 10, 3);
  43.                 }
  44.             }
  45.             add_filter('site-reviews-filters/defaults/filtered/defaults', [$this, 'filterDefaults']);
  46.             add_filter('site-reviews-filters/defaults/filtered/casts', [$this, 'filterCasts']);
  47.             add_filter('site-reviews-filters/config/forms/filters-form', [$this, 'filterConfig']);
  48.             add_filter('site-reviews-filters/status/filtered-by', [$this, 'filterFilteredBy'], 10, 2);
  49.             add_filter('site-reviews/shortcode/atts', [$this, 'filterShortcodeAttributes'], 10, 3);        
  50.         });
  51.     }
  52.    
  53.     public function filterDefaults(array $defaults)
  54.     {
  55.         foreach ($this->filters as $filter => $values) {
  56.             $defaults[$filter] = '';
  57.         }
  58.         return $defaults;
  59.     }
  60.  
  61.     public function filterCasts(array $casts)
  62.     {
  63.         foreach ($this->filters as $filter => $values) {
  64.             $casts[$filter] = glsr_get($values, 'cast', 'string');
  65.         }
  66.         return $casts;
  67.     }
  68.  
  69.     public function filterConfig(array $config)
  70.     {
  71.         foreach ($this->filters as $filter => $values) {
  72.             $config[$filter] = [
  73.                 'options' => ['' => $values['placeholder']] + $values['options'],
  74.                 'type' => 'select',
  75.                 'value' => filter_input(INPUT_GET, $filter, FILTER_SANITIZE_FULL_SPECIAL_CHARS),
  76.             ];
  77.         }
  78.         return $config;
  79.     }
  80.  
  81.     public function filterFilteredBy(array $filteredBy, array $filters)
  82.     {
  83.         foreach ($filters as $filter => $value) {
  84.             if (array_key_exists($filter, $this->filters)) {
  85.                 $filteredBy[] = $this->filters[$filter]['name'] ?? $this->filters[$filter]['options'][$value] ?? $value;
  86.             }
  87.         }
  88.         return $filteredBy;
  89.     }
  90.  
  91.     public function filterShortcodeAttributes(array $attributes, $type, $shortcode)
  92.     {
  93.         if ('site_reviews' !== $shortcode) {
  94.             return $attributes;
  95.         }
  96.         $parameters = glsr('Addon\Filters\Defaults\FilteredDefaults')->merge();
  97.         $terms = [$attributes['assigned_terms'] ?? ''];
  98.         foreach ($this->filters as $filter => $values) {
  99.             if ('term' === $values['type'] && !empty($parameters[$filter])) {
  100.                 $terms[] = $parameters[$filter];
  101.             }
  102.         }
  103.         $attributes['assigned_terms'] = implode(',', $terms);
  104.         return $attributes;
  105.     }
  106.  
  107.     public function filterSqlAndForCustom($value, $key, $modifier)
  108.     {
  109.         $tablekey = str_replace('filters/', '', $key);
  110.         $metakey = str_replace('filters/filter_by_', '_custom_', $key);
  111.         $modifier->values[$key] = sprintf("AND (%s.meta_key = '%s' AND %s.meta_value = '%s')", $tablekey, $metakey, $tablekey, $value);
  112.     }
  113.  
  114.     public function filterSqlJoinForCustom($value, $key, $modifier)
  115.     {
  116.         global $wpdb;
  117.         $tablekey = str_replace('filters/', '', $key);
  118.         $modifier->values[$key] = "INNER JOIN {$wpdb->posts} AS p ON r.review_id = p.ID";
  119.         $modifier->values[$key] = sprintf("INNER JOIN {$wpdb->postmeta} AS %s ON r.review_id = %s.post_id", $tablekey, $tablekey);
  120.     }
  121.  
  122.     public function normalize(array $filters)
  123.     {
  124.         $normalized = [];
  125.         foreach ($filters as $filter => $values) {
  126.             $filter = sanitize_key($filter);
  127.             if (!str_starts_with($filter, 'filter_by_')) {
  128.                 continue;
  129.             }
  130.             $values = wp_parse_args($values, [
  131.                 'cast' => '',
  132.                 'name' => null,
  133.                 'options' => [],
  134.                 'parent_term' => '',
  135.                 'placeholder' => '',
  136.                 'type' => '',
  137.             ]);
  138.             if ('custom' === $values['type']) {
  139.                 $normalized[$filter] = $this->normalizeCustomFilter($values);
  140.             } elseif ('term' === $values['type']) {
  141.                 $term = term_exists($values['parent_term'], glsr()->taxonomy);
  142.                 if (!empty($term)) {
  143.                     $normalized[$filter] = $this->normalizeTermFilter($values, $term['term_id']);
  144.                 }
  145.             }
  146.         }
  147.         return $normalized;
  148.     }
  149.  
  150.     protected function normalizeCustomFilter(array $values)
  151.     {
  152.         $values['options'] = is_array($values['options']) ? $values['options'] : [];
  153.         return $values;
  154.     }
  155.  
  156.     protected function normalizeTermFilter(array $values, int $termId)
  157.     {
  158.         $values['cast'] = 'int';
  159.         $values['options'] = get_terms([
  160.             'count' => false,
  161.             'fields' => 'id=>name',
  162.             'hide_empty' => true,
  163.             'parent' => $termId,
  164.             'taxonomy' => glsr()->taxonomy,
  165.         ]);
  166.         $values['parent_term'] = $termId;
  167.         return $values;
  168.     }
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement