PluginProbe
Filter Everything — WordPress & WooCommerce Filters / trunk
Filter Everything — WordPress & WooCommerce Filters vtrunk
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 1.6.3 All 51 releases
filter-everything / src / Chips.php

Chips.php in Filter Everything — WordPress & WooCommerce Filters trunk, at src/Chips.php

250 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FilterEverything\Filter;
4
5 if ( ! defined('ABSPATH') ) {
6 exit;
7 }
8
9 class Chips
10 {
11 public $chips = [];
12
13 private $queried;
14
15 private $showReset;
16
17 private $use_apply_button;
18
19 private $counter = 1;
20
21 private $setFilterKeys = [];
22
23 private $chipKeys = [];
24
25 public function __construct( $showReset = false, $setIds = [] )
26 {
27 $em = Container::instance()->getEntityManager();
28 $wpManager = Container::instance()->getWpManager();
29
30 $this->queried = $wpManager->getQueryVar('queried_values');
31 $sets = $wpManager->getQueryVar('wpc_page_related_set_ids');
32
33 $this->showReset = $showReset;
34
35 if( ! $setIds || empty( $setIds ) ){
36 if(!empty($sets) && is_array( $sets ) ) {
37 foreach ($sets as $set) {
38 $setIds[] = $set['ID'];
39 }
40 }
41 }
42
43 if( $setIds ){
44 $this->setFilterKeys = $em->getSetFilterKeys( $setIds );
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 }
51 }
52 }
53 }
54
55 unset( $em );
56
57 }
58
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 )
66 {
67 if ( ! isset( $this->chipKeys[ $key ] ) ) {
68 $this->chips[ $this->counter ] = $toAdd;
69 $this->chipKeys[ $key ] = true;
70 $this->counter++;
71 }
72 }
73
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();
82
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');
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 }
94 $toAdd = array(
95 'link' => $urlManager->getResetUrl(),
96 'name' => esc_html__('Reset all', 'filter-everything'),
97 'class' => $reset_button_class,
98 'link_class' => $reset_button_class
99 );
100
101 $this->addChip( 'reset-all', $toAdd );
102
103 }
104
105 if ( $this->queried ) {
106 foreach ($this->queried as $slug => $filter) {
107
108 if (isset($filter['show_chips']) && ($filter['show_chips'] !== 'yes')) {
109 continue;
110 }
111
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 }
117 }
118
119 $entityObj = $em->getEntityByFilter($filter, $postType);
120
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 }
127
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 }
132
133
134 $termId = $entityObj->getTermId( $termSlug );
135 $term = $entityObj->getTerm( $termId );
136
137 // In case if we have no terms for this post type
138 if (!$term) {
139 continue;
140 }
141
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 );
209 }
210 }
211 }
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
228 if( count( $this->chips ) === 1 ){
229 $singleChip = reset( $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 = [];
234 }
235 }
236
237 unset( $em, $urlManager );
238
239 }
240 }
241
242 public function getChips()
243 {
244 if( ! empty( $this->chips ) ){
245 return $this->chips;
246 }
247 return false;
248 }
249
250 }