| @@ -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(); |
| @@ -37,13 +41,14 @@ | ||
| 37 | 41 | } |
| 38 | 42 | |
| 39 | 43 | if( $setIds ){ |
| 40 | 44 | $this->setFilterKeys = $em->getSetFilterKeys( $setIds ); |
| 41 | - | |
| 42 | - foreach ($sets as $set) { | |
| 43 | - if( in_array( $set['ID'], $setIds ) ){ | |
| 44 | - $postType = $set['filtered_post_type']; | |
| 45 | - $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 | + } | |
| 46 | 51 | } |
| 47 | 52 | } |
| 48 | 53 | } |
| 49 | 54 | |
| @@ -50,26 +55,51 @@ | ||
| 50 | 55 | unset( $em ); |
| 51 | 56 | |
| 52 | 57 | } |
| 53 | 58 | |
| 54 | - 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 ) | |
| 55 | 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 | + { | |
| 56 | 76 | if( $this->queried || ( isset( $_GET['srch'] ) && $_GET['srch'] ) ) { |
| 57 | 77 | $em = Container::instance()->getEntityManager(); |
| 58 | 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(); | |
| 59 | 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 | + | |
| 60 | 89 | if ($this->showReset) { |
| 61 | - | |
| 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 | + } | |
| 62 | 94 | $toAdd = array( |
| 63 | 95 | 'link' => $urlManager->getResetUrl(), |
| 64 | 96 | 'name' => esc_html__('Reset all', 'filter-everything'), |
| 65 | - 'class' => 'wpc-chip-reset-all' | |
| 97 | + 'class' => $reset_button_class, | |
| 98 | + 'link_class' => $reset_button_class | |
| 66 | 99 | ); |
| 67 | 100 | |
| 68 | - if (!in_array($toAdd, $this->chips) ) { | |
| 69 | - $this->chips[$this->counter] = $toAdd; | |
| 70 | - $this->counter++; | |
| 71 | - } | |
| 101 | + $this->addChip( 'reset-all', $toAdd ); | |
| 72 | 102 | |
| 73 | 103 | } |
| 74 | 104 | |
| 75 | 105 | if ( $this->queried ) { |
| @@ -88,11 +118,17 @@ | ||
| 88 | 118 | |
| 89 | 119 | $entityObj = $em->getEntityByFilter($filter, $postType); |
| 90 | 120 | |
| 91 | 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 | + } | |
| 92 | 127 | |
| 93 | - if ( in_array($filter['entity'], ['post_meta_num', 'tax_numeric', 'post_date', 'post_meta_date'] ) ) { | |
| 128 | + if ( in_array($filter['entity'], ['post_date', 'post_meta_date'] ) ) { | |
| 94 | 129 | $termSlug = $key; |
| 130 | + $tempSlug = flrt_range_input_name( $filter['slug'], $key, 'date' ); | |
| 95 | 131 | } |
| 96 | 132 | |
| 97 | 133 | |
| 98 | 134 | $termId = $entityObj->getTermId( $termSlug ); |
| @@ -102,15 +138,55 @@ | ||
| 102 | 138 | if (!$term) { |
| 103 | 139 | continue; |
| 104 | 140 | } |
| 105 | 141 | |
| 142 | + $chips_button_class = ''; | |
| 143 | + if ($use_apply_button) { | |
| 144 | + $chips_button_class .= 'wpc-apply-button-chip'; | |
| 145 | + } | |
| 146 | + | |
| 106 | 147 | $toAdd = array( |
| 107 | - 'link' => $urlManager->getTermUrl( $termSlug, $filter['e_name'], $filter['entity'] ), | |
| 108 | - 'name' => apply_filters( 'wpc_chips_term_name', $term->name, $term, $filter ), | |
| 109 | - 'class' => 'wpc-chip-' . $filter['e_name'] . '-' . $termId, | |
| 110 | - 'label' => $filter['label'] | |
| 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'] | |
| 111 | 155 | ); |
| 112 | 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 | + | |
| 113 | 189 | if ( $filter['e_name'] === 'product_visibility') { |
| 114 | 190 | $rating_slugs = array( |
| 115 | 191 | 'rated-1', |
| 116 | 192 | 'rated-2', |
| @@ -128,12 +204,9 @@ | ||
| 128 | 204 | } |
| 129 | 205 | } |
| 130 | 206 | } |
| 131 | 207 | |
| 132 | - if ( ! in_array( $toAdd, $this->chips ) ) { | |
| 133 | - $this->chips[$this->counter] = $toAdd; | |
| 134 | - $this->counter++; | |
| 135 | - } | |
| 208 | + $this->addChip( 'term:' . $filter['e_name'] . ':' . $tempSlug, $toAdd ); | |
| 136 | 209 | } |
| 137 | 210 | } |
| 138 | 211 | } |
| 139 | 212 | |
| @@ -148,18 +221,17 @@ | ||
| 148 | 221 | 'class' => 'wpc-chip-search', |
| 149 | 222 | 'label' => $srch, |
| 150 | 223 | ); |
| 151 | 224 | |
| 152 | - if( ! in_array( $toAdd, $this->chips ) ) { | |
| 153 | - $this->chips[$this->counter] = $toAdd; | |
| 154 | - $this->counter++; | |
| 155 | - } | |
| 225 | + $this->addChip( 'search:' . $srch, $toAdd ); | |
| 156 | 226 | } |
| 157 | 227 | |
| 158 | 228 | if( count( $this->chips ) === 1 ){ |
| 159 | 229 | $singleChip = reset( $this->chips ); |
| 160 | - if( $singleChip['class'] === 'wpc-chip-reset-all' ){ | |
| 161 | - $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 = []; | |
| 162 | 234 | } |
| 163 | 235 | } |
| 164 | 236 | |
| 165 | 237 | unset( $em, $urlManager ); |