PluginProbe
Filter Everything — WordPress & WooCommerce Filters / 1.9.7
Filter Everything — WordPress & WooCommerce Filters v1.9.7
1.9.7 1.9.6 1.9.5 1.9.4 1.9.3 1.9.2.2 1.9.2.1 trunk 1.2.1 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.1 1.4.4 1.4.5 1.4.8 1.4.9 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 All 52 releases
← All changes | src/Chips.php +163 -54 1.6.11.9.7 View file →
@@ -1,10 +1,10 @@
1 1 <?php
2 2
3 3 namespace FilterEverything\Filter;
4 4
5 -if ( ! defined('WPINC') ) {
6 - wp_die();
5 +if ( ! defined('ABSPATH') ) {
6 + exit;
7 7 }
8 8
9 9 class Chips
10 10 {
@@ -13,12 +13,16 @@
13 13 private $queried;
14 14
15 15 private $showReset;
16 16
17 + private $use_apply_button;
18 +
17 19 private $counter = 1;
18 20
19 21 private $setFilterKeys = [];
20 22
23 + private $chipKeys = [];
24 +
21 25 public function __construct( $showReset = false, $setIds = [] )
22 26 {
23 27 $em = Container::instance()->getEntityManager();
24 28 $wpManager = Container::instance()->getWpManager();
@@ -25,27 +29,26 @@
25 29
26 30 $this->queried = $wpManager->getQueryVar('queried_values');
27 31 $sets = $wpManager->getQueryVar('wpc_page_related_set_ids');
28 32
29 - if( ! $wpManager->getQueryVar( 'allowed_filter_page' ) ){
30 - return false;
31 - }
32 -
33 33 $this->showReset = $showReset;
34 34
35 35 if( ! $setIds || empty( $setIds ) ){
36 - foreach ( $sets as $set ){
37 - $setIds[] = $set['ID'];
36 + if(!empty($sets) && is_array( $sets ) ) {
37 + foreach ($sets as $set) {
38 + $setIds[] = $set['ID'];
39 + }
38 40 }
39 41 }
40 42
41 43 if( $setIds ){
42 44 $this->setFilterKeys = $em->getSetFilterKeys( $setIds );
43 -
44 - foreach ($sets as $set) {
45 - if( in_array( $set['ID'], $setIds ) ){
46 - $postType = $set['filtered_post_type'];
47 - $this->fillChips( $postType );
45 + if(!empty($sets) && is_array( $sets ) ) {
46 + foreach ($sets as $set) {
47 + if (in_array($set['ID'], $setIds)) {
48 + $postType = $set['filtered_post_type'];
49 + $this->fillChips($set['ID'], $postType );
50 + }
48 51 }
49 52 }
50 53 }
51 54
@@ -52,77 +55,183 @@
52 55 unset( $em );
53 56
54 57 }
55 58
56 - private function fillChips( $postType = '' )
59 + /**
60 + * Chips are collected across all page-related Sets; the same queried
61 + * value must produce ONE chip even when the Sets disagree on
62 + * mode-dependent attributes (e.g. Apply-button link classes),
63 + * so deduplication goes by identity key, not by the whole array.
64 + */
65 + private function addChip( $key, $toAdd )
57 66 {
67 + if ( ! isset( $this->chipKeys[ $key ] ) ) {
68 + $this->chips[ $this->counter ] = $toAdd;
69 + $this->chipKeys[ $key ] = true;
70 + $this->counter++;
71 + }
72 + }
58 73
59 - if( $this->queried ){
60 - $em = Container::instance()->getEntityManager();
61 - $urlManager = new UrlManager();
74 + private function fillChips( $setId, $postType = '' )
75 + {
76 + if( $this->queried || ( isset( $_GET['srch'] ) && $_GET['srch'] ) ) {
77 + $em = Container::instance()->getEntityManager();
78 + $urlManager = Container::instance()->getUrlManager();
79 + $filterSet = Container::instance()->getFilterSetService();
80 + $filter_set_params = $filterSet->getSet($setId);
81 + $use_apply_button = (isset($filter_set_params['use_apply_button'] ) && $filter_set_params['use_apply_button']['value'] === 'yes') && flrt_instant_recount();
62 82
63 - if( $this->showReset ){
83 + // Crawler-links option: in free every term chip becomes a <span>
84 + // (filter pages are noindex there by design); in PRO (smart spans) a
85 + // term chip keeps its real <a> only when its removal target is indexable
86 + $hide_chip_links = flrt_get_option('disable_filter_links_for_bots') === 'on';
87 + $judge_chip_links = $hide_chip_links && function_exists('flrt_indexable_link_target');
64 88
89 + if ($this->showReset) {
90 + $reset_button_class = 'wpc-chip-reset-all';
91 + if ($use_apply_button) {
92 + $reset_button_class .= ' wpc-apply-button-chip wpc-apply-button-chips-reset';
93 + }
65 94 $toAdd = array(
66 95 'link' => $urlManager->getResetUrl(),
67 96 'name' => esc_html__('Reset all', 'filter-everything'),
68 - 'class' => 'wpc-chip-reset-all'
97 + 'class' => $reset_button_class,
98 + 'link_class' => $reset_button_class
69 99 );
70 100
71 - if( ! in_array( $toAdd, $this->chips ) ){
72 - $this->chips[$this->counter] = $toAdd;
73 - $this->counter++;
74 - }
101 + $this->addChip( 'reset-all', $toAdd );
75 102
76 103 }
77 104
78 - foreach ( $this->queried as $slug => $filter ) {
105 + if ( $this->queried ) {
106 + foreach ($this->queried as $slug => $filter) {
79 107
80 - if( isset( $filter['show_chips'] ) && ( $filter['show_chips'] !== 'yes' ) ){
81 - continue;
82 - }
108 + if (isset($filter['show_chips']) && ($filter['show_chips'] !== 'yes')) {
109 + continue;
110 + }
83 111
84 - if( ! empty( $this->setFilterKeys ) ){
85 - $queried_value_key = $filter['entity'].'#'.$filter['e_name'];
86 - if( ! in_array( $queried_value_key, $this->setFilterKeys ) ){
87 - continue;
112 + if (!empty($this->setFilterKeys)) {
113 + $queried_value_key = $filter['entity'] . '#' . $filter['e_name'];
114 + if (!in_array($queried_value_key, $this->setFilterKeys)) {
115 + continue;
116 + }
88 117 }
89 - }
90 118
91 - $entityObj = $em->getEntityByFilter( $filter, $postType );
119 + $entityObj = $em->getEntityByFilter($filter, $postType);
92 120
93 - foreach( $filter['values'] as $key => $termSlug ){
121 + foreach ($filter['values'] as $key => $termSlug) {
122 + $tempSlug = $termSlug;
123 + if ( in_array($filter['entity'], ['post_meta_num', 'tax_numeric'] ) ) {
124 + $termSlug = $key;
125 + $tempSlug = $key . $filter['e_name'];
126 + }
94 127
95 - if( $filter['entity'] === 'post_meta_num' ){
96 - $termSlug = $key;
97 - }
128 + if ( in_array($filter['entity'], ['post_date', 'post_meta_date'] ) ) {
129 + $termSlug = $key;
130 + $tempSlug = flrt_range_input_name( $filter['slug'], $key, 'date' );
131 + }
98 132
99 - $termId = $entityObj->getTermId( $termSlug );
100 - $term = $entityObj->getTerm( $termId );
101 133
102 - // In case if we have no terms for this post type
103 - if( ! $term ){
104 - continue;
105 - }
134 + $termId = $entityObj->getTermId( $termSlug );
135 + $term = $entityObj->getTerm( $termId );
106 136
107 - $toAdd = array(
108 - 'link' => $urlManager->getTermUrl( $termSlug, $filter['e_name'] ),
109 - 'name' => $term->name,
110 - 'class' => 'wpc-chip-' . $filter['e_name'] .'-'. $termId,
111 - 'label' => $filter['label']
112 - );
137 + // In case if we have no terms for this post type
138 + if (!$term) {
139 + continue;
140 + }
113 141
114 - if( ! in_array( $toAdd, $this->chips ) ){
115 - $this->chips[$this->counter] = $toAdd;
116 - $this->counter++;
142 + $chips_button_class = '';
143 + if ($use_apply_button) {
144 + $chips_button_class .= 'wpc-apply-button-chip';
145 + }
146 +
147 + $toAdd = array(
148 + 'link' => $urlManager->getTermUrl($termSlug, $filter['e_name'], $filter['entity']),
149 + 'link_class' => $chips_button_class,
150 + 'name' => apply_filters('wpc_chips_term_name', $term->name, $term, $filter),
151 + 'class' => 'wpc-chip-' . $filter['e_name'] . '-' . $termId,
152 + 'e_name' => $filter['e_name'],
153 + 'slug' => $tempSlug,
154 + 'label' => $filter['label']
155 + );
156 +
157 + if ( $judge_chip_links ) {
158 + $toAdd['crawlable'] = flrt_indexable_link_target( $term, $filter );
159 +
160 + // Removing one value of an OR multi-selection NARROWS the
161 + // results to the remaining values — a zero-result target
162 + // gets noindexed at runtime (SeoFrontend::countTerms). The
163 + // remaining term's cross_count is exactly that target count.
164 + if ( $toAdd['crawlable']
165 + && isset( $filter['logic'] ) && $filter['logic'] === 'or'
166 + && count( $filter['values'] ) > 1 ) {
167 +
168 + $remaining_alive = false;
169 + foreach ( $filter['values'] as $otherSlug ) {
170 + if ( $otherSlug === $termSlug ) {
171 + continue;
172 + }
173 + $otherTerm = $entityObj->getTerm( $entityObj->getTermId( $otherSlug ) );
174 + if ( $otherTerm && ( ! isset( $otherTerm->cross_count ) || (int) $otherTerm->cross_count > 0 ) ) {
175 + $remaining_alive = true;
176 + break;
177 + }
178 + }
179 +
180 + if ( ! $remaining_alive ) {
181 + $toAdd['crawlable'] = false;
182 + }
183 + }
184 + } elseif ( $hide_chip_links ) {
185 + // Free: no indexability judge — every term chip is a span
186 + $toAdd['crawlable'] = false;
187 + }
188 +
189 + if ( $filter['e_name'] === 'product_visibility') {
190 + $rating_slugs = array(
191 + 'rated-1',
192 + 'rated-2',
193 + 'rated-3',
194 + 'rated-4',
195 + 'rated-5'
196 + );
197 +
198 + if(in_array($termSlug, $rating_slugs)){
199 + $pieces = explode("-", $termSlug);
200 + $rating = isset( $pieces[1] ) ? $pieces[1] : 0;
201 + if ($rating){
202 + $toAdd['link'] = $urlManager->getTermUrl( $termSlug, $filter['e_name'], $filter['entity'], '', ['rating_slug' => $termSlug]);
203 + $toAdd['rating'] = $rating;
204 + }
205 + }
206 + }
207 +
208 + $this->addChip( 'term:' . $filter['e_name'] . ':' . $tempSlug, $toAdd );
117 209 }
118 210 }
119 211 }
120 212
213 + $srch = isset( $_GET['srch'] ) ? filter_input( INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS ) : '';
214 + if ( $srch ){
215 +
216 + $clear_search_url = $urlManager->getTermUrl( '', '', '', '', [ 'srch'=> true ] );
217 +
218 + $toAdd = array(
219 + 'link' => $clear_search_url,
220 + 'name' => sprintf( __( 'search: %s', 'filter-everything' ), $srch ),
221 + 'class' => 'wpc-chip-search',
222 + 'label' => $srch,
223 + );
224 +
225 + $this->addChip( 'search:' . $srch, $toAdd );
226 + }
227 +
121 228 if( count( $this->chips ) === 1 ){
122 229 $singleChip = reset( $this->chips );
123 - if( $singleChip['class'] === 'wpc-chip-reset-all' ){
124 - $this->chips = [];
230 + // strpos: the Apply-button variant carries extra classes after 'wpc-chip-reset-all'
231 + if( strpos( $singleChip['class'], 'wpc-chip-reset-all' ) === 0 ){
232 + $this->chips = [];
233 + $this->chipKeys = [];
125 234 }
126 235 }
127 236
128 237 unset( $em, $urlManager );