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 / Walkers / WalkerCheckbox.php

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

381 lines 13.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
10 class WalkerCheckbox extends \Walker
11 {
12 /**
13 * What the class handles.
14 *
15 * @since 2.1.0
16 * @var string
17 *
18 * @see Walker::$tree_type
19 */
20 public $tree_type = 'Checkbox';
21
22 /**
23 * Database fields to use.
24 *
25 * @since 2.1.0
26 * @var array
27 *
28 * @see Walker::$db_fields
29 * @todo Decouple this
30 */
31 public $db_fields = array(
32 'parent' => 'parent',
33 'id' => 'term_id',
34 );
35
36 public $max_depth = 0;
37
38 public $has_not_empty_children = [];
39
40 public $parent_opened_elements = [];
41
42 /**
43 * Starts the list before the elements are added.
44 *
45 * @since 2.1.0
46 *
47 * @see Walker::start_lvl()
48 *
49 * @param string $output Used to append additional content. Passed by reference.
50 * @param int $depth Optional. Depth of category. Used for tab indentation. Default 0.
51 * @param array $args Optional. An array of arguments. Will only append content if style argument
52 * value is 'list'. See wp_list_categories(). Default empty array.
53 */
54 public function start_lvl( &$output, $depth = 0, $args = array() ) {
55 $indent = str_repeat( "\t", $depth );
56 $output .= "$indent<ul class='children'>\n";
57 }
58
59 /**
60 * Ends the list of after the elements are added.
61 *
62 * @since 2.1.0
63 *
64 * @see Walker::end_lvl()
65 *
66 * @param string $output Used to append additional content. Passed by reference.
67 * @param int $depth Optional. Depth of category. Used for tab indentation. Default 0.
68 * @param array $args Optional. An array of arguments. Will only append content if style argument
69 * value is 'list'. See wp_list_categories(). Default empty array.
70 */
71 public function end_lvl( &$output, $depth = 0, $args = array() ) {
72 $indent = str_repeat( "\t", $depth );
73 $output .= "$indent</ul>\n";
74 }
75
76 /**
77 * Starts the element output.
78 *
79 * @since 2.1.0
80 *
81 * @see Walker::start_el()
82 *
83 * @param string $output Used to append additional content (passed by reference).
84 * @param WP_Term $term Term data object.
85 * @param int $depth Optional. Depth of category in reference to parents. Default 0.
86 * @param array $args Optional. An array of arguments. See wp_list_categories(). Default empty array.
87 * @param int $id Optional. ID of the current category. Default 0.
88 */
89 public function start_el( &$output, $term, $depth = 0, $args = array(), $id = 0 ) {
90 $term_name = esc_attr( $term->name );
91 $url_manager = $args['url_manager'];
92 $filter = $args['filter'];
93 $checked = ( in_array( $term->slug, $filter['values'] ) ) ? 1 : 0;
94 $disabled = 0;
95
96 if( isset( $term->wp_queried ) && $term->wp_queried ){
97 $checked = 1;
98 $disabled = 1;
99 }
100
101 $id = $id ? $id : $term->term_id;
102 $toggleButton = '';
103 $visibility_class = '';
104
105 // Don't generate an element if the term name is empty.
106 if ( '' === $term_name ) {
107 return;
108 }
109
110 $atts = array();
111 $atts['href'] = flrt_get_filtered_term_url($term, $filter, $url_manager);
112
113 $atts['class'] = 'wpc-filter-link';
114
115 $attributes = '';
116 foreach ( $atts as $attr => $value ) {
117 if ( is_scalar( $value ) && '' !== $value && false !== $value ) {
118 $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
119 $attributes .= ' ' . $attr . '="' . $value . '"';
120 }
121 }
122
123 $link = apply_filters( 'wpc_filters_checkbox_term_html', '<a'.$attributes.'>'.$term->name.'</a>', $attributes, $term, $filter );
124
125 if ( isset( $args['set']['show_count']['value'] ) && $args['set']['show_count']['value'] === 'yes' ) {
126 $link .= flrt_filter_get_count( $term );
127 }
128 $is_hide_empty_terms = (isset($args['set']['hide_empty']['value']) && $args['set']['hide_empty']['value'] === 'yes');
129 $hide_for_apply_button_mode = flrt_check_apply_buttom_mode($args['set']);
130
131 $show_with_parent_class = '';
132 $isShowWithParentClass = false;
133 if(isset($term->show_with_parent)) {
134 if($term->show_with_parent === true){
135 $isShowWithParentClass = true;
136 $show_with_parent_class = 'wpc-show-with-parent-true';
137 }else{
138 $show_with_parent_class = 'wpc-show-with-parent-false';
139 }
140 }
141
142 if (!isset($term->show_with_parent)) {
143 if ($args['ask_to_select_parent'] !== false && $args['use_apply_button']) {
144 if ((!$checked)) {
145 $show_with_parent_class = 'wpc-show-with-parent-false';
146 }
147 }
148 }
149
150
151 $hidden_class_for_apply_button_mode = '';
152 $more_less_hidden_class = '';
153 if ($args['isMoreLess']) {
154 if (!empty($term->apply_button_style) && $term->apply_button_style === true) {
155 $more_less_hidden_class = 'wpc-not-hidden-term';
156 }
157 }
158 if($hide_for_apply_button_mode){
159 $hidden_class_for_apply_button_mode = ($term->cross_count <= 0 && $is_hide_empty_terms) ? esc_attr(' wpc-term-count-hidden-0') : '';
160 if($checked){
161 $hidden_class_for_apply_button_mode .= esc_attr('wpc-term-count-hidden-checked-0');
162 }
163 }
164
165 $output .= "\t<li";
166 $cross_count = isset( $term->cross_count ) ? esc_attr( $term->cross_count ) : '';
167
168 $css_classes = array(
169 0 => 'wpc-checkbox-item',
170 1 => 'wpc-term-item',
171 3 => 'wpc-term-count-' . $cross_count,
172 4 => 'wpc-term-id-'.$id,
173 5 => $hidden_class_for_apply_button_mode,
174 6 => $more_less_hidden_class,
175 7 => esc_attr($show_with_parent_class),
176 );
177
178 if( $this->max_depth > 0 ) {
179 $visibility_class = flrt_get_status_css_class( $id, FLRT_HIERARCHY_LIST_COOKIE_NAME );
180 // If has already saved visibility class
181 if ( $visibility_class === '' ) {
182 // If there is no saved visibility class
183 $parent_opened_elements_flipped = array_flip( $this->parent_opened_elements );
184
185 if ( isset( $parent_opened_elements_flipped[$id] ) ) {
186 $visibility_class = 'wpc-opened';
187 }
188
189 if ( $this->has_children && $checked && $visibility_class === '' ) {
190 $visibility_class = 'wpc-opened';
191 }
192 }
193
194 $css_classes[] = $visibility_class;
195 }
196
197
198 if( $checked ){
199 $css_classes[2] = 'wpc-term-selected';
200 }
201
202 if( $disabled ){
203 $css_classes[] = 'wpc-term-disabled';
204 }
205
206 if( $this->has_children ){
207 $css_classes[] = 'wpc-has-children';
208 $toggleButton = '<i class="wpc-toggle-children-list" data-tid="'.esc_attr($term->term_id).'"></i>';
209 }
210
211 $has_not_empty_children_flipped = array_flip( $this->has_not_empty_children );
212 if( isset( $has_not_empty_children_flipped[$id] ) ){
213 $css_classes[] = 'wpc-has-not-empty-children';
214 }
215
216 $css_classes = implode( ' ', $css_classes );
217 $css_classes = $css_classes ? ' class="' . esc_attr( $css_classes ) . '"' : '';
218
219 $rating_slugs = flrt_rating_slugs();
220
221 $rating_data = (isset($rating_slugs[$term->slug])) ? ' data-rating-num="' . esc_attr($rating_slugs[$term->slug]) . '" ' : '';
222
223 $output .= $css_classes;
224 $output .= ' id="'.flrt_term_id('term', $filter, $id, false).'">';
225 $output .= '<div class="wpc-term-item-content-wrapper"><input '.checked( 1, $checked, false ).' '.disabled( 1, $disabled, false ).' type="checkbox" data-wpc-link="'.esc_url($atts['href']).'" data-wpc-e-name="'.esc_attr($filter['e_name']).'" data-wpc-slug="'.esc_attr($term->slug).'" data-term-id="' . esc_attr($id) . '"';
226 $output .= ' id="'.flrt_term_id('checkbox', $filter, $id, false).'"' . $rating_data .' />'."\n";
227 $output .= '<label for="'.flrt_term_id('checkbox', $filter, $id, false).'">';
228 $output .= "$link\n";
229 $output .= "</label>\n";
230 $output .= $toggleButton;
231 $output .= "</div>\n";
232
233 }
234
235 /**
236 * Ends the element output, if needed.
237 *
238 * @since 2.1.0
239 *
240 * @see Walker::end_el()
241 *
242 * @param string $output Used to append additional content (passed by reference).
243 * @param object $page Not used.
244 * @param int $depth Optional. Depth of category. Not used.
245 * @param array $args Optional. An array of arguments. Only uses 'list' for whether should append
246 * to output. See wp_list_categories(). Default empty array.
247 */
248 public function end_el( &$output, $page, $depth = 0, $args = array() ) {
249 $output .= "</li>\n";
250 }
251
252 public function walk( $elements, $max_depth, ...$args ) {
253 $output = '';
254
255 $this->max_depth = $max_depth;
256
257 // Invalid parameter or nothing to walk.
258 if ( $max_depth < -1 || empty( $elements ) ) {
259 return $output;
260 }
261
262 $parent_field = $this->db_fields['parent'];
263
264 // Flat display.
265 $flrt_more_less_count = flrt_more_less_count();
266 $isParentFilter = flrtParentFilter($args[0]['filter']);
267 $hidden_terms_count = 1;
268 if ( -1 == $max_depth ) {
269 $empty_array = array();
270
271 foreach ( $elements as $e ) {
272 if ( $args[0]['isMoreLess'] ) {
273
274 $is_visible = !$isParentFilter || ( isset( $e->show_with_parent ) && $e->show_with_parent === true ) || !isset( $e->show_with_parent );
275 $has_results = !$args[0]['is_hide_empty_terms'] || $e->cross_count > 0;
276
277 if ( $is_visible && $has_results ) {
278 if ( $hidden_terms_count <= $flrt_more_less_count ) {
279 $e->apply_button_style = true;
280 }
281 $hidden_terms_count++;
282 }
283 }
284
285 $this->display_element( $e, $empty_array, 1, 0, $args, $output );
286 }
287 return $output;
288 }
289
290 /*
291 * Need to display in hierarchical order.
292 * Separate elements into two buckets: top level and children elements.
293 * Children_elements is two dimensional array, eg.
294 * Children_elements[10][] contains all sub-elements whose parent is 10.
295 */
296 $top_level_elements = array();
297 $children_elements = array();
298 $parent_opened_elements = array();
299
300 foreach ( $elements as $e ) {
301 if ( empty( $e->$parent_field ) ) {
302 $top_level_elements[] = $e;
303 } else {
304 $children_elements[ $e->$parent_field ][] = $e;
305 }
306
307 if( ! empty( $args[0]['filter']['values'] ) ){
308 if( in_array( $e->slug, $args[0]['filter']['values'] ) ){
309 $parent_opened_elements[] = $e->$parent_field;
310 flrt_get_all_parents( $elements, $e->$parent_field, $parent_opened_elements );
311 }
312 }
313
314 }
315
316 $this->parent_opened_elements = array_unique($parent_opened_elements);
317 $this->has_not_empty_children = flrt_get_parents_with_not_empty_children($elements);
318
319 /*
320 * When none of the elements is top level.
321 * Assume the first one must be root of the sub elements.
322 */
323 if ( empty( $top_level_elements ) ) {
324
325 $first = array_slice( $elements, 0, 1 );
326 $root = $first[0];
327
328 $top_level_elements = array();
329 $children_elements = array();
330 foreach ( $elements as $e ) {
331 if ( $root->$parent_field == $e->$parent_field ) {
332 $top_level_elements[] = $e;
333 } else {
334 $children_elements[ $e->$parent_field ][] = $e;
335 }
336 }
337 }
338
339 /*
340 * Same More/Less marking as in the flat branch above. Only top-level terms
341 * are counted: the reveal CSS (.wpc-filters-ul-list > li.wpc-not-hidden-term)
342 * targets direct children of the list, nested children follow their parent.
343 * Without this, a hierarchical More/Less list renders with all terms hidden
344 * until JS re-marks them.
345 */
346 if ( $args[0]['isMoreLess'] ) {
347 $has_not_empty_children_flipped = array_flip( $this->has_not_empty_children );
348
349 foreach ( $top_level_elements as $e ) {
350 $is_visible = !$isParentFilter || ( isset( $e->show_with_parent ) && $e->show_with_parent === true ) || !isset( $e->show_with_parent );
351 $has_results = !$args[0]['is_hide_empty_terms'] || $e->cross_count > 0 || isset( $has_not_empty_children_flipped[ $e->term_id ] );
352
353 if ( $is_visible && $has_results ) {
354 if ( $hidden_terms_count <= $flrt_more_less_count ) {
355 $e->apply_button_style = true;
356 }
357 $hidden_terms_count++;
358 }
359 }
360 }
361
362 foreach ( $top_level_elements as $e ) {
363 $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
364 }
365
366 /*
367 * If we are displaying all levels, and remaining children_elements is not empty,
368 * then we got orphans, which should be displayed regardless.
369 */
370 if ( ( 0 == $max_depth ) && count( $children_elements ) > 0 ) {
371 $empty_array = array();
372 foreach ( $children_elements as $orphans ) {
373 foreach ( $orphans as $op ) {
374 $this->display_element( $op, $empty_array, 1, 0, $args, $output );
375 }
376 }
377 }
378
379 return $output;
380 }
381 }