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/UrlManager.php +175 -187 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 UrlManager
10 10 {
@@ -9,10 +9,18 @@
9 9 class UrlManager
10 10 {
11 11 private $separator;
12 12
13 - private $order;
13 + private $em;
14 14
15 + private $wpManager;
16 +
17 + private $entityAndEnamesOrder;
18 +
19 + private $actualFilters;
20 +
21 + private $enameActualFilters;
22 +
15 23 private $resetUrl;
16 24
17 25 private $logicParam = 'logic'; // Should be an option
18 26
@@ -19,92 +27,162 @@
19 27 private $valuesSeparator = FLRT_QUERY_TERMS_SEPARATOR; // Should be an option
20 28
21 29 public function __construct()
22 30 {
23 - $this->separator = FLRT_PREFIX_SEPARATOR;
24 - $fse = Container::instance()->getFilterService();
25 - $this->order = $fse->getFiltersOrder();
26 - $this->permalinksOn = defined('FLRT_PERMALINKS_ENABLED') ? FLRT_PERMALINKS_ENABLED : false;
31 + $this->separator = FLRT_PREFIX_SEPARATOR;
32 + $fse = Container::instance()->getFilterService();
33 + $this->em = Container::instance()->getEntityManager();
34 + $this->wpManager = Container::instance()->getWpManager();
35 + $this->entityAndEnamesOrder = $fse->getFiltersOrder();
36 + $this->actualFilters = $this->em->getSetsRelatedFilters();
27 37
28 - if( $this->permalinksOn ){
29 - add_filter( 'wpc_filter_term_url', array( $this, 'processPermalink' ) );
38 + // E_name actual filters
39 + foreach ( $this->actualFilters as $actualFilter ) {
40 + $this->enameActualFilters[ $actualFilter['entity'].'#'.$actualFilter['e_name'] ] = $actualFilter;
30 41 }
31 42
32 43 unset( $fse );
33 44 }
34 45
35 - public function processPermalink( $url )
46 + public function getTermUrl( $termSlug = '', $e_name = '', $entity = '', $resetUrl = '', $exclude = [] )
36 47 {
37 - $em = Container::instance()->getEntityManager();
38 - $parts = explode('?', $url);
48 + $fse = Container::instance()->getFilterService();
49 + $e_nameActualFilters = $this->enameActualFilters;
50 + $url = $baseUrl = $resetUrl ? $resetUrl : $this->getResetUrl();
51 + $parts = [];
52 + $entity_and_e_name = $entity.'#'.$e_name;
39 53
40 - if (count($parts) !== 2) {
41 - return $url;
54 + if ( empty( $e_nameActualFilters ) ) {
55 + $the_filter = $this->getSingleActualFilter( $e_name );
56 + if( isset( $the_filter['entity'] ) && isset( $the_filter['e_name'] ) ) {
57 + $entity_and_e_name = $the_filter['entity'].'#'.$the_filter['e_name'];
58 + $e_nameActualFilters[$entity_and_e_name] = $the_filter;
59 + }
42 60 }
43 61
44 - list($path, $get) = $parts;
62 + foreach( $this->entityAndEnamesOrder as $entityAndEName ) {
45 63
46 - $query = [];
47 - $parts = [];
64 + if ( isset( $e_nameActualFilters[$entityAndEName] ) ) {
48 65
49 - parse_str( $get, $query );
66 + $filter = $e_nameActualFilters[$entityAndEName];
50 67
51 - foreach( $this->getEnamesOrder() as $entityName ){
68 + if ( empty( $filter['values'] ) && $entity_and_e_name !== $entityAndEName ) {
69 + continue;
70 + }
52 71
53 - $filter = $em->getFilterBy( 'e_name', $entityName, array( 'slug', 'e_name', 'logic', 'in_path' ) );
72 + if( $entity_and_e_name === $entityAndEName ){
73 + $queriedValues = $filter['values'];
74 + // Add only single filter value for views with single selection
75 + if( in_array( $filter['view'], array('dropdown', 'radio') ) ){
76 + if( in_array( $termSlug, $queriedValues ) ){
77 + $position = array_search( $termSlug, $queriedValues );
78 + unset( $queriedValues[$position] );
79 + }else{
80 + $queriedValues = array( $termSlug );
81 + }
82 + } else {
83 + // For Post Meta Num values have array index as termslug
84 + if ( in_array( $filter['entity'], [ 'post_meta_num', 'tax_numeric', 'post_date', 'post_meta_date' ] ) ) {
85 + if ( in_array( $termSlug, array_keys( $queriedValues ) ) ) {
86 + unset( $queriedValues[$termSlug] );
87 + } else {
88 + $queriedValues[] = $termSlug;
89 + }
90 + } else if ( in_array( $filter['view'], array('rating') ) ) {
91 + if(isset($filter['selected_and_above']) && $filter['selected_and_above'] === 'yes'){
92 + if(isset($exclude['rating_slug'])){
93 + foreach ($queriedValues as $key => $value){
94 + unset( $queriedValues[$key] );
95 + }
96 + }
54 97
55 - if( ! $filter || empty( $filter ) || ( $filter['in_path'] !== 'yes' ) ){
56 - continue;
57 - }
98 + if(!isset($exclude['rating_slug'])){
99 + $pieces = explode("-", $termSlug);
100 + $rating = isset( $pieces[1] ) ? $pieces[1] : 0;
101 + $i = 5;
102 + while ($i >= 1) {
103 + $new_termSlug = 'rated-' . $i;
104 + if(in_array( $new_termSlug, $queriedValues )){
105 + $position = array_search( $new_termSlug, $queriedValues );
106 + unset( $queriedValues[$position] );
107 + }
58 108
59 - if( isset( $query[ $filter['slug'] ] ) ){
109 + if($i >= $rating){
110 + $queriedValues[] = $new_termSlug;
111 + }
112 + $i--;
113 + }
114 + }
115 + } else if(in_array( $termSlug, $queriedValues ) && isset($filter['selected_and_above']) && $filter['selected_and_above'] === 'no'){
116 + $position = array_search( $termSlug, $queriedValues );
117 + unset( $queriedValues[$position] );
118 + }else{
119 + $queriedValues = array( $termSlug );
120 + }
121 + } else {
122 + if ( in_array( $termSlug, $queriedValues ) ) {
123 + $position = array_search( $termSlug, $queriedValues );
124 + unset( $queriedValues[$position] );
125 + } else {
126 + $queriedValues[] = $termSlug;
127 + }
128 + }
129 + }
130 + $filter['values'] = $queriedValues;
131 + }
60 132
61 - $termSlugs = $em->safeExplodeFilterValues( $query[ $filter['slug'] ], $filter['slug'], $this->getValuesSeparator() );
62 - $termSlugs = $em->safeImplodeFilterValues( $termSlugs, $this->getValuesSeparator() );
133 + foreach ($filter['values'] as $val_id => $term_slug){
134 + if(!empty($exclude[$term_slug]) && $exclude[$term_slug] === true){
135 + unset($filter['values'][$val_id]);
136 + }
137 + }
63 138
64 - $parts[] = $this->buildFilterSegment( $termSlugs, $filter );
139 + if( ! empty( $filter['values'] ) ) {
140 + $filter['values'] = $fse->sortTerms( $filter['values'] );
141 +
142 + if ( in_array( $filter['entity'], ['post_meta_num', 'tax_numeric'] ) ) {
143 + foreach ($filter['values'] as $edge => $value) {
144 + $paramName = $edge . '_' . $filter['slug'];
145 + $url = flrt_add_query_arg($this->getParamName($paramName), $value, $url);
146 + }
147 + } elseif ( in_array($filter['entity'], ['post_date', 'post_meta_date'] ) ) {
148 + foreach ($filter['values'] as $edge => $date_value) {
149 + $paramName = $filter['slug'] . '_' . $edge;
150 + $date_value = str_replace(' ', FLRT_DATE_TIME_SEPARATOR, $date_value);
151 + $url = flrt_add_query_arg($this->getParamName($paramName), $date_value, $url);
152 + }
153 + } else {
154 + if ( defined('FLRT_PERMALINKS_ENABLED') && FLRT_PERMALINKS_ENABLED ) {
155 + $parts[] = $this->buildFilterSegment( $filter['values'], $filter );
156 + } else {
157 + $url = flrt_add_query_arg( $this->getParamName($filter['slug'] ), implode($this->getValuesSeparator(), $filter['values']), $url);
158 + }
159 + }
160 + }
161 +
65 162 }
66 -
67 - unset( $query[ $filter['slug'] ] );
68 - unset( $query[ $this->getLogicParamName( $filter['slug'] ) ] );
69 163 }
70 164
71 - $path = trailingslashit( $path ) . implode('/', $parts );
72 - $path = user_trailingslashit( $path );
73 -
74 - $url = flrt_add_query_arg( $query, $path );
75 -
76 - unset($em);
77 -
78 - return $url;
79 - }
80 -
81 - private function getEnamesOrder()
82 - {
83 - $e_namesOrder = [];
84 - $fse = Container::instance()->getFilterService();
85 -
86 - foreach( $this->order as $entityName ){
87 - $e_namesOrder[] = $fse->getEntityEname( $entityName );
165 + // Assembly permalinks
166 + if ( defined('FLRT_PERMALINKS_ENABLED') && FLRT_PERMALINKS_ENABLED ) {
167 + $pieces = explode('?', $baseUrl);
168 + $path = $pieces[0];
169 + $path = trailingslashit( $path ) . implode('/', $parts );
170 + $path = user_trailingslashit( $path );
171 + $url = str_replace( $pieces[0], $path, $url );
88 172 }
89 173
90 - unset( $fse );
91 -
92 - return $e_namesOrder;
93 - }
94 -
95 - public function getSubArrayBy( $byKey, $value, &$array )
96 - {
97 - foreach ( $array as $index => $subArray ) {
98 - if( isset( $subArray[ $byKey ] ) && $subArray[ $byKey ] === $value ){
99 - return $subArray;
174 + if ( ! isset( $exclude['srch'] ) ){
175 + $search = isset( $_GET['srch'] ) ? filter_input( INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS ) : false;
176 + if ( $search ){
177 + $url = flrt_add_query_arg( 'srch' , $search, $url );
100 178 }
101 179 }
102 180
103 - return false;
181 + return apply_filters( 'wpc_filter_term_url', $url );
104 182 }
105 183
106 - public function getFormActionUrl( $queryParams = false )
184 + public function getFormActionOrFullPageUrl( $fullPageUrl = false )
107 185 {
108 186 $query = [];
109 187 $homeUrl = parse_url(home_url());
110 188 $post = Container::instance()->getThePost();
@@ -129,18 +207,14 @@
129 207 if( isset( $pieces['query'] ) ){
130 208 parse_str( $pieces['query'], $query );
131 209 }
132 210
133 - $formAction = preg_replace('%\/page/[0-9]+%', '', $fullPath);
134 - $formAction = preg_replace('%\/comment\-page\-[0-9]+%', '', $formAction);
135 - $formAction = preg_replace('%\/[0-9]+[\/]?$%m', '', $formAction);
211 + $formAction = $this->removePaginationBase( $fullPath );
136 212
137 - $formAction = FLRT_PERMALINKS_ENABLED ? user_trailingslashit( $formAction ) : rtrim( $formAction, '/' ) . '/';
138 -
139 213 // Add GET parameters
140 - if( $queryParams && ! empty( $query )) {
214 + if( $fullPageUrl && ! empty( $query ) ) {
141 215 foreach ($query as $name => $value) {
142 - $formAction = flrt_add_query_arg($name, $value, $formAction);
216 + $formAction = flrt_add_query_arg( $name, $value, $formAction );
143 217 }
144 218 }
145 219
146 220 return $formAction;
@@ -153,11 +227,14 @@
153 227 return apply_filters( 'wpc_unnecessary_get_parameters', $getKeys );
154 228 }
155 229
156 230 foreach ( $queried_values as $slug => $filter ){
157 - if( $filter['entity'] === 'post_meta_num' ){
158 - $getKeys['max_'.$slug] = $filter;
159 - $getKeys['min_'.$slug] = $filter;
231 + if( in_array( $filter['entity'], [ 'post_meta_num', 'tax_numeric' ] ) ) {
232 + $getKeys['max_' . $slug] = $filter;
233 + $getKeys['min_' . $slug] = $filter;
234 + } else if( in_array( $filter['entity'], [ 'post_date', 'post_meta_date'] ) ) {
235 + $getKeys[$slug .'_from'] = $filter;
236 + $getKeys[$slug . '_to'] = $filter;
160 237 }else{
161 238 $getKeys[$slug] = $filter;
162 239 }
163 240 }
@@ -168,32 +245,25 @@
168 245 public function getResetUrl()
169 246 {
170 247 if( ! $this->resetUrl ) {
171 248 $container = Container::instance();
172 - $wpManager = $container->getWpManager();
173 249 $get = $container->getTheGet();
174 250
175 251 // For compatibility with some Nginx configurations
176 252 unset($get['q']);
177 253
178 - $this->resetUrl = home_url( $wpManager->getQueryVar('wp_request') );
179 - $requested = $wpManager->getQueryVar('queried_values', [] );
180 - $pos = strpos($this->resetUrl, '/page');
254 + $this->resetUrl = home_url( $this->wpManager->getQueryVar('wp_request', '') );
255 + $requested = $this->wpManager->getQueryVar('queried_values', [] );
181 256
182 - if ($pos !== false) {
183 - $this->resetUrl = substr($this->resetUrl, 0, $pos);
184 - }
257 + $this->resetUrl = $this->removePaginationBase( $this->resetUrl );
185 258
186 - $this->resetUrl = preg_replace('%\/[0-9]+[\/]?$%m', '', $this->resetUrl);
259 + // Maybe add GET parameters
260 + $exclude_params = array_keys( $this->setCorrectGetKeys( $requested ) );
261 + $exclude_params[] = 'srch';
187 262
188 - $this->resetUrl = FLRT_PERMALINKS_ENABLED ? user_trailingslashit( $this->resetUrl ) : rtrim( $this->resetUrl, '/' ) . '/';
189 -
190 - // Maybe add GET parameters
191 263 if( ! empty( $get ) ){
192 -
193 264 foreach ( $get as $name => $value ) {
194 -
195 - if( ! in_array( $name, array_keys( $this->setCorrectGetKeys( $requested ) ) ) ){
265 + if( ! in_array( $name, $exclude_params ) ){
196 266 $this->resetUrl = add_query_arg( $name, $value, $this->resetUrl );
197 267 }
198 268 }
199 269 }
@@ -201,8 +271,27 @@
201 271
202 272 return $this->resetUrl;
203 273 }
204 274
275 + /**
276 + * Removes '/page/n' from URL
277 + * @param $url
278 + * @return string
279 + */
280 + public function removePaginationBase( $url = '' )
281 + {
282 + global $wp_rewrite;
283 +
284 + $pagination_base = str_replace( "-", "\-", $wp_rewrite->pagination_base );
285 + $comments_pagination_base = str_replace( "-", "\-", $wp_rewrite->comments_pagination_base );
286 +
287 + $url = preg_replace('%\/'.$pagination_base.'/[0-9]+%', '', $url );
288 + $url = preg_replace('%\/'.$comments_pagination_base.'\-[0-9]+%', '', $url );
289 + $url = preg_replace('%\/[0-9]+[\/]?$%m', '', $url );
290 +
291 + return apply_filters( 'wpc_remove_pagination_base', $url );
292 + }
293 +
205 294 public function getValuesSeparator()
206 295 {
207 296 return $this->valuesSeparator;
208 297 }
@@ -216,114 +305,15 @@
216 305 {
217 306 return sanitize_title( $slug );
218 307 }
219 308
220 - private function getSingleActualFilter($e_name )
309 + private function getSingleActualFilter( $e_name )
221 310 {
222 - $em = Container::instance()->getEntityManager();
223 - $filter = $em->getFilterBy( 'e_name', $e_name, array( 'slug', 'e_name', 'logic' ) );
311 + $filter = $this->em->getFilterByEname( $e_name );
224 312 $filter['values'] = [];
225 -
226 - unset( $em );
227 -
228 313 return $filter;
229 314 }
230 315
231 - public function getFiltersUrl( $filters, $resetUrl = '' )
232 - {
233 - $url = $resetUrl ? $resetUrl : $this->getResetUrl();
234 - $fse = Container::instance()->getFilterService();
235 -
236 - if( ! empty( $filters ) ){
237 -
238 - foreach( $filters as $filter ){
239 -
240 - if( ! empty( $filter['values'] ) ){
241 - $filter['values'] = $fse->sortTerms( $filter['values'] );
242 -
243 - if( $filter['entity'] === 'post_meta_num' ){
244 -
245 - foreach( $filter['values'] as $edge => $value ){
246 - $paramName = $edge.'_'.$filter['slug'];
247 - $url = flrt_add_query_arg( $this->getParamName( $paramName ) , $value, $url );
248 - }
249 -
250 - } else {
251 - $url = flrt_add_query_arg( $this->getParamName( $filter['slug'] ) , implode( $this->getValuesSeparator(), $filter['values'] ), $url );
252 - }
253 -
254 - }
255 - }
256 - }
257 -
258 - unset( $fse );
259 -
260 - return apply_filters( 'wpc_filter_term_url', $url );
261 - }
262 -
263 - public function getTermUrl( $termSlug, $e_name /*, $sets = [] */ )
264 - {
265 - $em = Container::instance()->getEntityManager();
266 -
267 - $filtersCombination = [];
268 - $actualFilters = $em->getSetsRelatedFilters( /* $sets */ );
269 -
270 - if( empty( $actualFilters ) ){
271 - $actualFilters[] = $this->getSingleActualFilter( $e_name );
272 - }
273 -
274 - foreach($this->getEnamesOrder() as $entityName ){
275 -
276 - if( $filter = $this->getSubArrayBy( 'e_name', $entityName, $actualFilters ) ) {
277 -
278 - $queriedValues = $filter['values'];
279 -
280 - if( $e_name === $entityName ){
281 - // Add only single filter value for views with single selection
282 - if( in_array( $filter['view'], array('dropdown', 'radio') ) ){
283 -
284 - if( in_array( $termSlug, $queriedValues ) ){
285 - $position = array_search( $termSlug, $queriedValues );
286 - unset( $queriedValues[$position] );
287 - }else{
288 - $queriedValues = array( $termSlug );
289 - }
290 -
291 - } else {
292 - // For Post Meta Num values have array index as termslug
293 - if( $filter['entity'] === 'post_meta_num' ){
294 -
295 - if( in_array( $termSlug, array_keys( $queriedValues ) ) ){
296 - unset( $queriedValues[$termSlug] );
297 - }else{
298 - $queriedValues[] = $termSlug;
299 - }
300 -
301 - }else{
302 -
303 - if( in_array( $termSlug, $queriedValues ) ){
304 - $position = array_search( $termSlug, $queriedValues );
305 - unset( $queriedValues[$position] );
306 - }else{
307 - $queriedValues[] = $termSlug;
308 - }
309 -
310 - }
311 -
312 - }
313 - }
314 -
315 - $filter['values'] = $queriedValues;
316 - $filtersCombination[] = $filter;
317 - }
318 - }
319 -
320 - unset($em);
321 -
322 - // URL already escaped
323 - return $this->getFiltersUrl( $filtersCombination );
324 - }
325 -
326 316 private function buildFilterSegment( $termSlugs, $filter ){
327 317 $segment = $filter['slug'] . $this->separator;
328 318 $fse = Container::instance()->getFilterService();
329 319
@@ -334,12 +324,10 @@
334 324 /**
335 325 * @bug if filter is present in two sets logic gets incorrect
336 326 */
337 327
338 - $termSlugs = array_map('urlencode', $termSlugs);
339 -
340 328 $termSlugs = $fse->sortTerms( $termSlugs );
341 - $terms = implode( $fse->getLogicSeparator( $filter ), $termSlugs );
329 + $terms = implode( $fse->getLogicSeparator( $filter['logic'] ), $termSlugs );
342 330 $segment .= $terms;
343 331
344 332 unset($fse);
345 333