| 1 |
<?php |
| 2 |
|
| 3 |
if (!defined('ABSPATH')) { |
| 4 |
exit; |
| 5 |
} |
| 6 |
|
| 7 |
use \FilterEverything\Filter\Container; |
| 8 |
use \FilterEverything\Filter\FilterSet; |
| 9 |
use \FilterEverything\Filter\FilterFields; |
| 10 |
use \FilterEverything\Filter\PostMetaNumEntity; |
| 11 |
use \FilterEverything\Filter\PostDateEntity; |
| 12 |
use \FilterEverything\Filter\PostMetaDateEntity; |
| 13 |
/** |
| 14 |
* Returns user's caps level that allows to use the plugin. |
| 15 |
* Developers can modify this level via hook 'wpc_plugin_user_caps' ot their own risk. |
| 16 |
* @return string |
| 17 |
*/ |
| 18 |
function flrt_plugin_user_caps() |
| 19 |
{ |
| 20 |
return apply_filters('wpc_plugin_user_caps', 'manage_options'); |
| 21 |
} |
| 22 |
|
| 23 |
function flrt_the_set($set_id = 0) |
| 24 |
{ |
| 25 |
global $flrt_sets; |
| 26 |
|
| 27 |
if (function_exists('brizy_load')) { |
| 28 |
if (!did_action('wp_print_scripts')) { |
| 29 |
return false; |
| 30 |
} |
| 31 |
} |
| 32 |
|
| 33 |
if ($set_id) { |
| 34 |
foreach ($flrt_sets as $k => $set) { |
| 35 |
if ($set['ID'] === $set_id) { |
| 36 |
unset($flrt_sets[$k]); |
| 37 |
return $set; |
| 38 |
} |
| 39 |
} |
| 40 |
} |
| 41 |
|
| 42 |
return array_shift($flrt_sets); |
| 43 |
} |
| 44 |
|
| 45 |
function flrt_print_filters_for($hook = '') |
| 46 |
{ |
| 47 |
global $wp_filter; |
| 48 |
if (empty($hook) || !isset($wp_filter[$hook])) |
| 49 |
return; |
| 50 |
return $wp_filter[$hook]; |
| 51 |
} |
| 52 |
|
| 53 |
function flrt_is_filter_request() |
| 54 |
{ |
| 55 |
$wpManager = Container::instance()->getWpManager(); |
| 56 |
return $wpManager->getQueryVar('wpc_is_filter_request'); |
| 57 |
} |
| 58 |
|
| 59 |
function flrt_include($filename) |
| 60 |
{ |
| 61 |
$path = flrt_get_path($filename); |
| 62 |
|
| 63 |
if (file_exists($path)) { |
| 64 |
include_once($path); |
| 65 |
} |
| 66 |
} |
| 67 |
|
| 68 |
function flrt_get_path($path = '') |
| 69 |
{ |
| 70 |
return FLRT_PLUGIN_DIR_PATH . ltrim($path, '/'); |
| 71 |
} |
| 72 |
|
| 73 |
function flrt_ucfirst($text) |
| 74 |
{ |
| 75 |
if (!is_string($text)) { |
| 76 |
return $text; |
| 77 |
} |
| 78 |
return mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1); |
| 79 |
} |
| 80 |
|
| 81 |
function flrt_lcfirst( $text ) |
| 82 |
{ |
| 83 |
if( ! is_string( $text ) ){ |
| 84 |
return $text; |
| 85 |
} |
| 86 |
return mb_strtolower( mb_substr( $text, 0, 1 ) ) . mb_substr( $text, 1 ); |
| 87 |
} |
| 88 |
|
| 89 |
function flrt_sanitize_tooltip($var ) |
| 90 |
{ |
| 91 |
return htmlspecialchars( |
| 92 |
wp_kses( |
| 93 |
html_entity_decode($var), |
| 94 |
array( |
| 95 |
'br' => array(), |
| 96 |
'em' => array(), |
| 97 |
'strong' => array(), |
| 98 |
'small' => array(), |
| 99 |
'span' => array(), |
| 100 |
'ul' => array(), |
| 101 |
'li' => array(), |
| 102 |
'ol' => array(), |
| 103 |
'p' => array(), |
| 104 |
'a' => array('href' => true) |
| 105 |
) |
| 106 |
) |
| 107 |
); |
| 108 |
} |
| 109 |
|
| 110 |
function flrt_help_tip($tip, $allow_html = false) |
| 111 |
{ |
| 112 |
if ($allow_html) { |
| 113 |
$tip = flrt_sanitize_tooltip($tip); |
| 114 |
} else { |
| 115 |
$tip = esc_attr($tip); |
| 116 |
} |
| 117 |
|
| 118 |
return '<span class="wpc-help-tip" data-tip="' . $tip . '"></span>'; |
| 119 |
} |
| 120 |
|
| 121 |
function flrt_tooltip($attr) |
| 122 |
{ |
| 123 |
if (!isset($attr['tooltip']) || !$attr['tooltip']) { |
| 124 |
return false; |
| 125 |
} |
| 126 |
|
| 127 |
return flrt_help_tip($attr['tooltip'], true); |
| 128 |
} |
| 129 |
|
| 130 |
function flrt_field_instructions($attr) |
| 131 |
{ |
| 132 |
if (!isset($attr['instructions']) || !$attr['instructions']) { |
| 133 |
return false; |
| 134 |
} |
| 135 |
$instructions = wp_kses( |
| 136 |
$attr['instructions'], |
| 137 |
array( |
| 138 |
'br' => array(), |
| 139 |
'span' => array('class' => true), |
| 140 |
'strong' => array(), |
| 141 |
'a' => array('href' => true, 'title' => true) |
| 142 |
) |
| 143 |
); |
| 144 |
return '<p class="wpc-field-description">' . $instructions . '</p>'; |
| 145 |
} |
| 146 |
|
| 147 |
function flrt_add_query_arg(...$args) |
| 148 |
{ |
| 149 |
if (is_array($args[0])) { |
| 150 |
if (count($args) < 2 || false === $args[1]) { |
| 151 |
$uri = $_SERVER['REQUEST_URI']; |
| 152 |
} else { |
| 153 |
$uri = $args[1]; |
| 154 |
} |
| 155 |
} else { |
| 156 |
if (count($args) < 3 || false === $args[2]) { |
| 157 |
$uri = $_SERVER['REQUEST_URI']; |
| 158 |
} else { |
| 159 |
$uri = $args[2]; |
| 160 |
} |
| 161 |
} |
| 162 |
|
| 163 |
$frag = strstr($uri, '#'); |
| 164 |
if ($frag) { |
| 165 |
$uri = substr($uri, 0, -strlen($frag)); |
| 166 |
} else { |
| 167 |
$frag = ''; |
| 168 |
} |
| 169 |
|
| 170 |
if (0 === stripos($uri, 'http://')) { |
| 171 |
$protocol = 'http://'; |
| 172 |
$uri = substr($uri, 7); |
| 173 |
} elseif (0 === stripos($uri, 'https://')) { |
| 174 |
$protocol = 'https://'; |
| 175 |
$uri = substr($uri, 8); |
| 176 |
} else { |
| 177 |
$protocol = ''; |
| 178 |
} |
| 179 |
|
| 180 |
if (strpos($uri, '?') !== false) { |
| 181 |
list($base, $query) = explode('?', $uri, 2); |
| 182 |
$base .= '?'; |
| 183 |
} elseif ($protocol || strpos($uri, '=') === false) { |
| 184 |
$base = $uri . '?'; |
| 185 |
$query = ''; |
| 186 |
} else { |
| 187 |
$base = ''; |
| 188 |
$query = $uri; |
| 189 |
} |
| 190 |
|
| 191 |
wp_parse_str($query, $qs); |
| 192 |
|
| 193 |
if (is_array($args[0])) { |
| 194 |
foreach ($args[0] as $k => $v) { |
| 195 |
$qs[$k] = $v; |
| 196 |
} |
| 197 |
} else { |
| 198 |
$qs[$args[0]] = $args[1]; |
| 199 |
} |
| 200 |
|
| 201 |
foreach ($qs as $k => $v) { |
| 202 |
if (false === $v) { |
| 203 |
unset($qs[$k]); |
| 204 |
} |
| 205 |
} |
| 206 |
|
| 207 |
$ret = build_query($qs); |
| 208 |
$ret = trim($ret, '?'); |
| 209 |
$ret = preg_replace('#=(&|$)#', '$1', $ret); |
| 210 |
$ret = $protocol . $base . $ret . $frag; |
| 211 |
$ret = rtrim($ret, '?'); |
| 212 |
return $ret; |
| 213 |
} |
| 214 |
|
| 215 |
/** |
| 216 |
* @param $terms array |
| 217 |
* @param $keys array |
| 218 |
* |
| 219 |
* @return array Array of objects with required keys |
| 220 |
*/ |
| 221 |
function flrt_extract_objects_vars($terms, $keys = []) |
| 222 |
{ |
| 223 |
$required = []; |
| 224 |
|
| 225 |
foreach ($terms as $i => $term) { |
| 226 |
$new_object = new \stdClass(); |
| 227 |
|
| 228 |
foreach ($keys as $key) { |
| 229 |
if (isset($term->$key)) { |
| 230 |
$new_object->$key = $term->$key; |
| 231 |
$required[$term->term_id] = $new_object; |
| 232 |
} |
| 233 |
} |
| 234 |
} |
| 235 |
|
| 236 |
return $required; |
| 237 |
} |
| 238 |
|
| 239 |
add_filter('wpc_check_broken_query_vars', function ($query_vars, $query) { |
| 240 |
if (is_admin()) { |
| 241 |
return $query_vars; |
| 242 |
} |
| 243 |
|
| 244 |
$detector_class = 'FilterEverything\\Filter\\WP_Query_Source_Detector'; |
| 245 |
$is_allowed_method = 'is_allowed'; |
| 246 |
$source_var = 'flrt_detected_source'; |
| 247 |
|
| 248 |
if (defined('FLRT_FILTERS_PRO')) { |
| 249 |
if (defined('FLRT_PRO_BUILDER_KEY')) { |
| 250 |
$builder_key = apply_filters('wpc_builder_key_pro', $query->get($source_var), constant('FLRT_PRO_BUILDER_KEY')); |
| 251 |
|
| 252 |
if ($detector_class::$is_allowed_method($builder_key)) { |
| 253 |
return $query_vars; |
| 254 |
} |
| 255 |
} |
| 256 |
} |
| 257 |
|
| 258 |
if (!defined('FLRT_FILTERS_PRO')) { |
| 259 |
$builder_key = apply_filters('wpc_builder_key', $query->get($source_var), $detector_class::$builder_key); |
| 260 |
|
| 261 |
if ($detector_class::$is_allowed_method($builder_key)) { |
| 262 |
return $query_vars; |
| 263 |
} |
| 264 |
} |
| 265 |
|
| 266 |
return []; |
| 267 |
}, 10, 2); |
| 268 |
|
| 269 |
add_filter('wpc_builder_key', function ($source, $builder_id) { |
| 270 |
return (int) sprintf("%u", crc32($source . $builder_id)); |
| 271 |
}, 10, 2); |
| 272 |
|
| 273 |
/** |
| 274 |
* Compatibility with membership / access-control plugins. |
| 275 |
* |
| 276 |
* Such plugins (e.g. Ultimate Membership Pro — indeed-membership-pro) inject |
| 277 |
* post__in / post__not_in into front-end queries to hide protected content from |
| 278 |
* non-authorised or logged-out visitors. That flips is_post__in / is_post__not_in |
| 279 |
* in the query-identity hash FE uses to match a Filter Set to a page query — so a |
| 280 |
* page that filters correctly for the (unrestricted) admin who saved the set stops |
| 281 |
* matching for restricted visitors, and filtering silently does nothing for them. |
| 282 |
* |
| 283 |
* We normalise those two flags back to their save-time value (false), but ONLY when |
| 284 |
* such a plugin is actually active. This keeps every saved query hash untouched on |
| 285 |
* sites that don't have this conflict. The per-page order counter still distinguishes |
| 286 |
* genuinely different same-shape queries, so filtering stays correct. |
| 287 |
*/ |
| 288 |
add_filter('wpc_check_broken_query_vars', function ($query_vars, $query) { |
| 289 |
// Add markers of other post-hiding plugins here if needed; overridable via the filter. |
| 290 |
$context_hides_posts = defined('IHC_PATH') // Ultimate Membership Pro |
| 291 |
|| defined('WCB2B_PLUGIN_FILE'); // WooCommerce B2B — hides "unallowed" products from guests/other groups via post__not_in |
| 292 |
|
| 293 |
if ( ! apply_filters('wpc_context_hides_posts', $context_hides_posts, $query) ) { |
| 294 |
return $query_vars; |
| 295 |
} |
| 296 |
|
| 297 |
// Only touch queries FE still considers filterable (its own callback empties the |
| 298 |
// rest at priority 10); never re-populate an emptied set. |
| 299 |
if ( is_array($query_vars) && array_key_exists('is_post__not_in', $query_vars) ) { |
| 300 |
$query_vars['is_post__in'] = false; |
| 301 |
$query_vars['is_post__not_in'] = false; |
| 302 |
} |
| 303 |
|
| 304 |
return $query_vars; |
| 305 |
}, 20, 2); |
| 306 |
|
| 307 |
function flrt_remove_level_array($array) |
| 308 |
{ |
| 309 |
/** |
| 310 |
* @feature maybe rewrite this full of shame code |
| 311 |
*/ |
| 312 |
if (!is_array($array)) { |
| 313 |
return []; |
| 314 |
} |
| 315 |
|
| 316 |
$flatten = []; |
| 317 |
|
| 318 |
array_map(function ($a) use (&$flatten) { |
| 319 |
if (is_array($a)) { |
| 320 |
$flatten = array_merge($flatten, $a); |
| 321 |
} |
| 322 |
}, |
| 323 |
$array); |
| 324 |
|
| 325 |
return $flatten; |
| 326 |
} |
| 327 |
|
| 328 |
add_filter('wpc_check_errors_ids', function ($error_ids, $query) { |
| 329 |
$source_key = 'flrt_detected_source'; |
| 330 |
if (empty($query->query_vars[$source_key])) { |
| 331 |
return $error_ids; |
| 332 |
} |
| 333 |
|
| 334 |
$source = $query->query_vars[$source_key]; |
| 335 |
$detector_class = 'FilterEverything\\Filter\\WP_Query_Source_Detector'; |
| 336 |
$is_allowed_method = 'is_allowed'; |
| 337 |
|
| 338 |
if (defined('FLRT_FILTERS_PRO')) { |
| 339 |
if (defined('FLRT_PRO_BUILDER_KEY')) { |
| 340 |
$builder_key = apply_filters('wpc_builder_key_pro', $source, constant('FLRT_PRO_BUILDER_KEY')); |
| 341 |
if ($detector_class::$is_allowed_method($builder_key)) { |
| 342 |
return $error_ids; |
| 343 |
} |
| 344 |
} |
| 345 |
} |
| 346 |
|
| 347 |
if (!defined('FLRT_FILTERS_PRO')) { |
| 348 |
$builder_key = apply_filters('wpc_builder_key', $source, $detector_class::$builder_key); |
| 349 |
|
| 350 |
if ($detector_class::$is_allowed_method($builder_key)) { |
| 351 |
return $error_ids; |
| 352 |
} |
| 353 |
} |
| 354 |
|
| 355 |
return []; |
| 356 |
}, 10, 2); |
| 357 |
|
| 358 |
function flrt_get_forbidden_prefixes() |
| 359 |
{ |
| 360 |
//@todo it seems all existing tax prefixes should be there |
| 361 |
// All them actual only when permalinks off |
| 362 |
$forbidden_prefixes = ['srch']; |
| 363 |
$permalinksEnabled = defined('FLRT_PERMALINKS_ENABLED') ? FLRT_PERMALINKS_ENABLED : false; |
| 364 |
if (!$permalinksEnabled) { |
| 365 |
$forbidden_prefixes = array_merge($forbidden_prefixes, array('cat', 'tag', 'page', 'author')); |
| 366 |
} |
| 367 |
|
| 368 |
if (flrt_wpml_active()) { |
| 369 |
$wpml_url_format = apply_filters('wpml_setting', 0, 'language_negotiation_type'); |
| 370 |
if ($wpml_url_format === '3') { |
| 371 |
$forbidden_prefixes[] = 'lang'; |
| 372 |
} |
| 373 |
} |
| 374 |
|
| 375 |
return apply_filters('wpc_forbidden_prefixes', $forbidden_prefixes); |
| 376 |
} |
| 377 |
|
| 378 |
function flrt_get_forbidden_meta_keys() |
| 379 |
{ |
| 380 |
$forbidden_meta_keys = array('wpc_filter_set_post_type', 'wpc_seo_rule_post_type'); |
| 381 |
return apply_filters('wpc_forbidden_meta_keys', $forbidden_meta_keys); |
| 382 |
} |
| 383 |
|
| 384 |
function flrt_array_contains_duplicate($array) |
| 385 |
{ |
| 386 |
return count($array) != count(array_unique($array)); |
| 387 |
} |
| 388 |
|
| 389 |
function flrt_maybe_hide_row($atts) |
| 390 |
{ |
| 391 |
if ($atts['type'] === 'Hidden') { |
| 392 |
echo ' style="display:none;"'; |
| 393 |
} |
| 394 |
} |
| 395 |
|
| 396 |
function flrt_filter_row_class($field_atts) |
| 397 |
{ |
| 398 |
$classes = ['wpc-filter-tr']; |
| 399 |
|
| 400 |
if (isset($field_atts['class'])) { |
| 401 |
$classes[] = $field_atts['class'] . '-tr'; |
| 402 |
} |
| 403 |
|
| 404 |
if (isset($field_atts['additional_class'])) { |
| 405 |
$classes[] = $field_atts['additional_class']; |
| 406 |
} |
| 407 |
|
| 408 |
return implode(" ", $classes); |
| 409 |
} |
| 410 |
|
| 411 |
|
| 412 |
function flrt_include_admin_view($path, $args = []) |
| 413 |
{ |
| 414 |
$templateManager = Container::instance()->getTemplateManager(); |
| 415 |
$templateManager->includeAdminView($path, $args); |
| 416 |
} |
| 417 |
|
| 418 |
function flrt_include_front_view($path, $args = []) |
| 419 |
{ |
| 420 |
$templateManager = Container::instance()->getTemplateManager(); |
| 421 |
$templateManager->includeFrontView($path, $args); |
| 422 |
} |
| 423 |
|
| 424 |
function flrt_create_filters_nonce() |
| 425 |
{ |
| 426 |
return FilterSet::createNonce(); |
| 427 |
} |
| 428 |
|
| 429 |
function flrt_get_filter_fields_mapping() |
| 430 |
{ |
| 431 |
return Container::instance()->getFilterFieldsService()->getFieldsMapping(); |
| 432 |
} |
| 433 |
|
| 434 |
function flrt_get_configured_filters($post_id) |
| 435 |
{ |
| 436 |
$filterFields = Container::instance()->getFilterFieldsService(); |
| 437 |
return $filterFields->getFiltersInputs($post_id); |
| 438 |
} |
| 439 |
|
| 440 |
function flrt_get_filter_view_name($view_key) |
| 441 |
{ |
| 442 |
$view_options = FilterFields::getViewOptions(); |
| 443 |
if (isset($view_options[$view_key])) { |
| 444 |
return esc_html($view_options[$view_key]); |
| 445 |
} |
| 446 |
|
| 447 |
return esc_html($view_key); |
| 448 |
} |
| 449 |
|
| 450 |
function flrt_get_filter_entity_name($entity_key) |
| 451 |
{ |
| 452 |
$em = Container::instance()->getEntityManager(); |
| 453 |
$entities = $em->getPossibleEntities(); |
| 454 |
|
| 455 |
foreach ($entities as $key => $entity_array) { |
| 456 |
if (isset($entity_array['entities'][$entity_key])) { |
| 457 |
return esc_html($entity_array['entities'][$entity_key]); |
| 458 |
} |
| 459 |
} |
| 460 |
|
| 461 |
if ($entity_key === 'post_meta_exists' && !defined('FLRT_FILTERS_PRO')) { |
| 462 |
return esc_html__('Available in PRO', 'filter-everything'); |
| 463 |
} |
| 464 |
|
| 465 |
return esc_html($entity_key); |
| 466 |
} |
| 467 |
|
| 468 |
function flrt_get_set_settings_fields($post_id) |
| 469 |
{ |
| 470 |
$filterSet = Container::instance()->getFilterSetService(); |
| 471 |
return $filterSet->getSettingsTypeFields($post_id); |
| 472 |
} |
| 473 |
|
| 474 |
function flrt_get_set_settings_location_fields($post_id) |
| 475 |
{ |
| 476 |
$filterSet = Container::instance()->getFilterSetService(); |
| 477 |
return $filterSet->getSettingsLocationTypeFields($post_id); |
| 478 |
} |
| 479 |
|
| 480 |
function flrt_render_input($atts) |
| 481 |
{ |
| 482 |
$className = isset($atts['type']) ? '\FilterEverything\Filter\\' . $atts['type'] : '\FilterEverything\Filter\Text'; |
| 483 |
|
| 484 |
if (class_exists($className)) { |
| 485 |
$input = new $className($atts); |
| 486 |
return $input->render(); |
| 487 |
} |
| 488 |
|
| 489 |
return false; |
| 490 |
} |
| 491 |
|
| 492 |
function flrt_extract_vars(&$array, $keys) |
| 493 |
{ |
| 494 |
$r = []; |
| 495 |
foreach ($keys as $key) { |
| 496 |
$var = flrt_extract_var($array, $key); |
| 497 |
if ($var) { |
| 498 |
$r[$key] = $var; |
| 499 |
} |
| 500 |
} |
| 501 |
return $r; |
| 502 |
} |
| 503 |
|
| 504 |
function flrt_extract_var(&$array, $key, $default = null) |
| 505 |
{ |
| 506 |
// check if exists |
| 507 |
// - uses array_key_exists to extract NULL values (isset will fail) |
| 508 |
if (is_array($array) && array_key_exists($key, $array)) { |
| 509 |
$v = $array[$key]; |
| 510 |
unset($array[$key]); |
| 511 |
return $v; |
| 512 |
} |
| 513 |
return $default; |
| 514 |
} |
| 515 |
|
| 516 |
function flrt_get_empty_filter($set_id) |
| 517 |
{ |
| 518 |
$filterFields = Container::instance()->getFilterFieldsService(); |
| 519 |
return $filterFields->getEmptyFilterObject($set_id); |
| 520 |
} |
| 521 |
|
| 522 |
function flrt_excluded_taxonomies() |
| 523 |
{ |
| 524 |
$excluded_taxonomies = array( |
| 525 |
'nav_menu', |
| 526 |
'link_category', |
| 527 |
'post_format', |
| 528 |
'template_category', |
| 529 |
'element_category', |
| 530 |
'fusion_tb_category', |
| 531 |
'slide-page', |
| 532 |
'elementor_font_type', |
| 533 |
'post_translations', |
| 534 |
'term_language', |
| 535 |
'term_translations', |
| 536 |
'wp_theme', |
| 537 |
'wp_template_part_area', |
| 538 |
'wp_pattern_category', |
| 539 |
'elementor_library_type', |
| 540 |
'elementor_library_category', |
| 541 |
); |
| 542 |
|
| 543 |
return apply_filters('wpc_excluded_taxonomies', $excluded_taxonomies); |
| 544 |
} |
| 545 |
|
| 546 |
function flrt_force_non_unique_slug($notNull, $originalSlug) |
| 547 |
{ |
| 548 |
return $originalSlug; |
| 549 |
} |
| 550 |
|
| 551 |
function flrt_redirect_to_error($post_id, $errors) |
| 552 |
{ |
| 553 |
$redirect = get_edit_post_link($post_id, 'url'); |
| 554 |
$error_code = 20; // Default error code |
| 555 |
|
| 556 |
if (!empty($errors) && is_array($errors)) { |
| 557 |
$error_code = reset($errors); |
| 558 |
} |
| 559 |
|
| 560 |
$redirect = add_query_arg('message', $error_code, $redirect); |
| 561 |
wp_redirect($redirect); |
| 562 |
exit; |
| 563 |
} |
| 564 |
|
| 565 |
function flrt_sanitize_int($var) |
| 566 |
{ |
| 567 |
return preg_replace('/[^\d]+/', '', $var); |
| 568 |
} |
| 569 |
|
| 570 |
function flrt_range_input_name($slug, $edge = 'min', $type = 'num') |
| 571 |
{ |
| 572 |
if ($type === 'date') { |
| 573 |
return PostDateEntity::inputName($slug, $edge); |
| 574 |
} |
| 575 |
|
| 576 |
return PostMetaNumEntity::inputName($slug, $edge); |
| 577 |
} |
| 578 |
|
| 579 |
function flrt_query_string_form_fields($values = null, $exclude = [], $current_key = '', $return = false) |
| 580 |
{ |
| 581 |
|
| 582 |
$filter_everything_exclude = array_keys(apply_filters('wpc_unnecessary_get_parameters', [])); |
| 583 |
$exclude = array_merge($exclude, $filter_everything_exclude); |
| 584 |
|
| 585 |
if (is_null($values)) { |
| 586 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 587 |
$values = Container::instance()->getTheGet(); |
| 588 |
// For compatibility with some Nginx configurations |
| 589 |
unset($values['q']); |
| 590 |
} elseif (is_string($values)) { |
| 591 |
$url_parts = wp_parse_url($values); |
| 592 |
$values = []; |
| 593 |
|
| 594 |
if (!empty($url_parts['query'])) { |
| 595 |
// This is to preserve full-stops, pluses and spaces in the query string when ran through parse_str. |
| 596 |
$replace_chars = array( |
| 597 |
'.' => '{dot}', |
| 598 |
'+' => '{plus}', |
| 599 |
); |
| 600 |
|
| 601 |
$query_string = str_replace(array_keys($replace_chars), array_values($replace_chars), $url_parts['query']); |
| 602 |
|
| 603 |
// Parse the string. |
| 604 |
parse_str($query_string, $parsed_query_string); |
| 605 |
|
| 606 |
// Convert the full-stops, pluses and spaces back and add to values array. |
| 607 |
foreach ($parsed_query_string as $key => $value) { |
| 608 |
$new_key = str_replace(array_values($replace_chars), array_keys($replace_chars), $key); |
| 609 |
$new_value = str_replace(array_values($replace_chars), array_keys($replace_chars), $value); |
| 610 |
$values[$new_key] = $new_value; |
| 611 |
} |
| 612 |
} |
| 613 |
} |
| 614 |
$html = ''; |
| 615 |
|
| 616 |
foreach ($values as $key => $value) { |
| 617 |
if (in_array($key, $exclude, true)) { |
| 618 |
continue; |
| 619 |
} |
| 620 |
if ($current_key) { |
| 621 |
$key = $current_key . '[' . $key . ']'; |
| 622 |
} |
| 623 |
if (is_array($value)) { |
| 624 |
$html .= flrt_query_string_form_fields($value, $exclude, $key, true); |
| 625 |
} else { |
| 626 |
$html .= '<input type="hidden" name="' . esc_attr($key) . '" value="' . esc_attr(wp_unslash($value)) . '" />'; |
| 627 |
} |
| 628 |
} |
| 629 |
|
| 630 |
if ($return) { |
| 631 |
return $html; |
| 632 |
} |
| 633 |
|
| 634 |
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 635 |
} |
| 636 |
|
| 637 |
function flrt_get_query_string_parameters() |
| 638 |
{ |
| 639 |
$container = Container::instance(); |
| 640 |
$get = $container->getTheGet(); |
| 641 |
$post = $container->getThePost(); |
| 642 |
|
| 643 |
// For compatibility with some Nginx configurations |
| 644 |
unset($get['q']); |
| 645 |
|
| 646 |
if (isset($post['flrt_ajax_link'])) { |
| 647 |
$parts = parse_url($post['flrt_ajax_link']); |
| 648 |
if (isset($parts['query'])) { |
| 649 |
parse_str($parts['query'], $output); |
| 650 |
return $output; |
| 651 |
} |
| 652 |
} |
| 653 |
|
| 654 |
return $get; |
| 655 |
} |
| 656 |
|
| 657 |
|
| 658 |
function flrt_count($term, $show = 'yes') |
| 659 |
{ |
| 660 |
_deprecated_function('flrt_count', '1.7.6', 'flrt_filter_count()'); |
| 661 |
flrt_filter_count($term, $show); |
| 662 |
} |
| 663 |
|
| 664 |
if (!function_exists('flrt_filter_count')) { |
| 665 |
function flrt_filter_count($term, $show = 'yes') |
| 666 |
{ |
| 667 |
if ($show === 'yes') : |
| 668 |
echo flrt_filter_get_count($term); |
| 669 |
endif; |
| 670 |
} |
| 671 |
} |
| 672 |
|
| 673 |
/** |
| 674 |
* @param $term |
| 675 |
* @return string |
| 676 |
* @since 1.0.5 |
| 677 |
*/ |
| 678 |
function flrt_filter_get_count($term) |
| 679 |
{ |
| 680 |
return '<span class="wpc-term-count"><span class="wpc-term-count-brackets-open">(</span><span class="wpc-term-count-value">' . esc_html($term->cross_count) . '</span><span class="wpc-term-count-brackets-close">)</span></span> '; |
| 681 |
} |
| 682 |
|
| 683 |
if (!function_exists('flrt_spinner_html')) { |
| 684 |
function flrt_spinner_html() |
| 685 |
{ |
| 686 |
return '<div class="wpc-spinner"></div>'; |
| 687 |
} |
| 688 |
} |
| 689 |
|
| 690 |
function flrt_filters_widget_content_class($setId) |
| 691 |
{ |
| 692 |
if (isset($_COOKIE[FLRT_OPEN_CLOSE_BUTTON_COOKIE_NAME])) { |
| 693 |
|
| 694 |
if ($_COOKIE[FLRT_OPEN_CLOSE_BUTTON_COOKIE_NAME] === $setId) { |
| 695 |
return ' wpc-opened'; |
| 696 |
} else { |
| 697 |
return ' wpc-closed'; |
| 698 |
} |
| 699 |
} |
| 700 |
} |
| 701 |
|
| 702 |
function flrt_filters_button($setId = 0, $class = '', $wrap_class = '') |
| 703 |
{ |
| 704 |
/** |
| 705 |
* @feature add nice wrapper to this functions to allow users put it into themes. |
| 706 |
*/ |
| 707 |
$classes = []; |
| 708 |
$sets = []; |
| 709 |
$wpManager = \FilterEverything\Filter\Container::instance()->getWpManager(); |
| 710 |
$templateManager = \FilterEverything\Filter\Container::instance()->getTemplateManager(); |
| 711 |
|
| 712 |
$draft_sets = $wpManager->getQueryVar('wpc_page_related_set_ids'); |
| 713 |
|
| 714 |
if ( ! is_array( $draft_sets ) ) { |
| 715 |
$draft_sets = []; |
| 716 |
} |
| 717 |
|
| 718 |
foreach ($draft_sets as $set) { |
| 719 |
if (isset($set['show_on_the_page']) && $set['show_on_the_page']) { |
| 720 |
$sets[] = $set; |
| 721 |
} |
| 722 |
} |
| 723 |
|
| 724 |
if (!$setId && isset($sets[0]['ID'])) { |
| 725 |
$setId = $sets[0]['ID']; |
| 726 |
} |
| 727 |
|
| 728 |
foreach ($sets as $set) { |
| 729 |
if ($set['ID'] === $setId) { |
| 730 |
$theSet = $set; |
| 731 |
break; |
| 732 |
} |
| 733 |
} |
| 734 |
|
| 735 |
if (flrt_get_option('mobile_filter_settings') === 'show_bottom_widget') { |
| 736 |
$classes[] = 'wpc-filters-open-widget'; |
| 737 |
} else { |
| 738 |
$classes[] = 'wpc-open-close-filters-button'; |
| 739 |
} |
| 740 |
|
| 741 |
if ($class) { |
| 742 |
$classes[] = trim($class); |
| 743 |
} |
| 744 |
|
| 745 |
$attrClass = implode(" ", $classes); |
| 746 |
$setId = preg_replace('/[^\d]+/', '', $setId); |
| 747 |
|
| 748 |
$wpc_found_posts = NULL; |
| 749 |
$srch = isset($_GET['srch']) ? filter_input(INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS) : ''; |
| 750 |
$all = false; |
| 751 |
if ($srch) { |
| 752 |
$all = true; |
| 753 |
} |
| 754 |
|
| 755 |
if ($wpManager->getQueryVar('wpc_is_filter_request') || $srch) { |
| 756 |
$wpc_found_posts = flrt_posts_found_quantity($setId, $all); |
| 757 |
} |
| 758 |
|
| 759 |
$button_error = []; |
| 760 |
|
| 761 |
if (current_user_can(flrt_plugin_user_caps())) { |
| 762 |
$button_error = [ |
| 763 |
'filter_set_error' => esc_html__('There are no filter sets on this page.', 'filter-everything'), |
| 764 |
'filter_widget_error' => esc_html__('There is no filter widget on this page.', 'filter-everything'), |
| 765 |
]; |
| 766 |
|
| 767 |
if (!empty($theSet)) { |
| 768 |
unset($button_error['filter_set_error']); |
| 769 |
} |
| 770 |
} |
| 771 |
|
| 772 |
$templateManager->includeFrontView('filters-button', array('wpc_found_posts' => $wpc_found_posts, 'class' => $attrClass, 'set_id' => $setId, 'wrap_class' => $wrap_class, 'button_error' => $button_error)); |
| 773 |
} |
| 774 |
|
| 775 |
function flrt_posts_found($setid = 0, $all = false, $hidden = false ) |
| 776 |
{ |
| 777 |
$templateManager = \FilterEverything\Filter\Container::instance()->getTemplateManager(); |
| 778 |
$fss = \FilterEverything\Filter\Container::instance()->getFilterSetService(); |
| 779 |
|
| 780 |
if (isset($_GET['srch']) && $_GET['srch']) { |
| 781 |
$all = true; |
| 782 |
} |
| 783 |
$count = flrt_posts_found_quantity($setid, $all); |
| 784 |
|
| 785 |
$theSet = $fss->getSet($setid); |
| 786 |
$postType = isset($theSet['post_type']['value']) ? $theSet['post_type']['value'] : ''; |
| 787 |
|
| 788 |
$obj = get_post_type_object($postType); |
| 789 |
$pluralLabel = isset($obj->label) ? apply_filters('wpc_label_singular_posts_found_msg', $obj->label) : esc_html__('items', 'filter-everything'); |
| 790 |
$singularLabel = isset($obj->labels->singular_name) ? apply_filters('wpc_label_plural_posts_found_msg', $obj->labels->singular_name) : esc_html__('item', 'filter-everything'); |
| 791 |
|
| 792 |
$templateManager->includeFrontView('posts-found', array('posts_found_count' => $count, 'singular_label' => $singularLabel, 'plural_label' => $pluralLabel, 'hidden' => $hidden)); |
| 793 |
} |
| 794 |
|
| 795 |
function flrt_get_option($key, $default = false) |
| 796 |
{ |
| 797 |
$settings = get_option('wpc_filter_settings'); |
| 798 |
|
| 799 |
if (isset($settings[$key])) { |
| 800 |
return apply_filters('wpc_get_option', $settings[$key], $key); |
| 801 |
} |
| 802 |
|
| 803 |
if ($default) { |
| 804 |
return $default; |
| 805 |
} |
| 806 |
|
| 807 |
return false; |
| 808 |
|
| 809 |
} |
| 810 |
|
| 811 |
function flrt_remove_option($key) |
| 812 |
{ |
| 813 |
$settings = get_option('wpc_filter_settings'); |
| 814 |
|
| 815 |
if (isset($settings[$key]) && $settings[$key]) { |
| 816 |
unset($settings[$key]); |
| 817 |
return update_option('wpc_filter_settings', $settings); |
| 818 |
} |
| 819 |
|
| 820 |
return false; |
| 821 |
} |
| 822 |
|
| 823 |
function flrt_change_option($option_key, $key, $value, $autoload = false) |
| 824 |
{ |
| 825 |
$settings = get_option($option_key); |
| 826 |
|
| 827 |
if ($settings[$key] === $value) { |
| 828 |
return true; |
| 829 |
} |
| 830 |
|
| 831 |
$settings = is_array($settings) ? $settings : []; |
| 832 |
$settings[$key] = $value; |
| 833 |
|
| 834 |
return update_option($option_key, $settings, $autoload); |
| 835 |
} |
| 836 |
|
| 837 |
function flrt_get_experimental_option($key, $default = false) |
| 838 |
{ |
| 839 |
/** |
| 840 |
* @todo This should be rewritten |
| 841 |
*/ |
| 842 |
$settings = get_option('wpc_filter_experimental'); |
| 843 |
|
| 844 |
if (isset($settings[$key])) { |
| 845 |
return apply_filters('wpc_get_option', $settings[$key], $key); |
| 846 |
} |
| 847 |
|
| 848 |
if ($default !== false) { |
| 849 |
return apply_filters('wpc_get_option', $default, $key); |
| 850 |
} |
| 851 |
|
| 852 |
return apply_filters('wpc_get_option', false, $key); |
| 853 |
|
| 854 |
} |
| 855 |
|
| 856 |
function flrt_get_status_css_class($id, $cookieName, $classes = ['opened' => 'wpc-opened', 'closed' => 'wpc-closed']) |
| 857 |
{ |
| 858 |
|
| 859 |
if (isset($_COOKIE[$cookieName])) { |
| 860 |
$openediDs = explode(",", $_COOKIE[$cookieName]); |
| 861 |
|
| 862 |
if (in_array($id, $openediDs)) { |
| 863 |
return $classes['opened']; |
| 864 |
} elseif (in_array(-$id, $openediDs)) { |
| 865 |
return $classes['closed']; |
| 866 |
} else { |
| 867 |
return ''; |
| 868 |
} |
| 869 |
} |
| 870 |
|
| 871 |
return ''; |
| 872 |
} |
| 873 |
|
| 874 |
if (!function_exists('flrt_filter_header')) { |
| 875 |
function flrt_filter_header($filter, $terms) |
| 876 |
{ |
| 877 |
$openButton = ($filter['collapse'] === 'yes') ? '<button><span class="wpc-wrap-icons">' : ''; |
| 878 |
$closeButton = ($filter['collapse'] === 'yes') ? '</span><span class="wpc-open-icon"></span></button>' : ''; |
| 879 |
$tooltip = ''; |
| 880 |
|
| 881 |
if ($filter['collapse'] === 'yes' && !empty($filter['values']) && !empty($terms)) { |
| 882 |
$selected = []; |
| 883 |
$list = '<span class="wpc-filter-selected-values">— '; |
| 884 |
// Does not work for numeric filters |
| 885 |
// @todo |
| 886 |
foreach ($terms as $id => $term_object) { |
| 887 |
|
| 888 |
if (in_array($term_object->slug, $filter['values'])) { |
| 889 |
$selected[] = $term_object->name; |
| 890 |
} |
| 891 |
} |
| 892 |
|
| 893 |
$list .= implode(", ", $selected) . '</span>'; |
| 894 |
|
| 895 |
$closeButton = $list . $closeButton; |
| 896 |
} |
| 897 |
|
| 898 |
if (isset($filter['tooltip']) && $filter['tooltip']) { |
| 899 |
$tooltip = flrt_help_tip($filter['tooltip'], true); |
| 900 |
} |
| 901 |
|
| 902 |
$filter_label = apply_filters('wpc_filter_title', $filter['label'], $filter); |
| 903 |
|
| 904 |
?> |
| 905 |
<div class="wpc-filter-header"> |
| 906 |
<div class="widget-title wpc-filter-title"><?php |
| 907 |
echo $openButton . esc_html($filter_label) . $tooltip . $closeButton; |
| 908 |
?></div></div><?php |
| 909 |
} |
| 910 |
} |
| 911 |
|
| 912 |
function flrt_filter_class($filter, $default_classes = [], $terms = [], $args = []) |
| 913 |
{ |
| 914 |
$digits = []; |
| 915 |
$length = 1; |
| 916 |
$isHideEmpty = (!empty($args['hide_empty']) && $args['hide_empty'] === 'yes'); |
| 917 |
$isParentFilter = flrtParentFilter($filter); |
| 918 |
$count_terms_greater_than_zero = 0; |
| 919 |
$total_terms_count = 0; |
| 920 |
|
| 921 |
if ( ! empty( $terms ) ) { |
| 922 |
foreach ( $terms as $term ) { |
| 923 |
$digits[] = $term->cross_count; |
| 924 |
|
| 925 |
if ( $term->cross_count > 0 ) { |
| 926 |
$total_terms_count += $term->cross_count; |
| 927 |
} |
| 928 |
|
| 929 |
$is_visible = ! $isParentFilter || ( isset( $term->show_with_parent ) && $term->show_with_parent === true ) || !isset($term->show_with_parent); |
| 930 |
$has_results = ! $isHideEmpty || $term->cross_count > 0; |
| 931 |
|
| 932 |
if ( $is_visible && $has_results ) { |
| 933 |
$count_terms_greater_than_zero++; |
| 934 |
} |
| 935 |
} |
| 936 |
} |
| 937 |
|
| 938 |
if (!empty($digits)) { |
| 939 |
$length = strlen((string)max($digits)); |
| 940 |
} |
| 941 |
|
| 942 |
$classes = array( |
| 943 |
'wpc-filters-section', |
| 944 |
'wpc-filters-section-' . esc_attr($filter['ID']), |
| 945 |
'wpc-filter-' . esc_attr($filter['e_name']), |
| 946 |
'wpc-filter-' . esc_attr($filter['entity']), |
| 947 |
'wpc-filter-layout-' . esc_attr($filter['view']), |
| 948 |
'wpc-counter-length-' . esc_attr($length) |
| 949 |
); |
| 950 |
|
| 951 |
if ((isset($args['hide_empty_filter']) && $args['hide_empty_filter'] === 'yes')) { |
| 952 |
if ($total_terms_count <= 0) { |
| 953 |
|
| 954 |
$classes[] = 'wpc-filters-section-0'; |
| 955 |
} |
| 956 |
} |
| 957 |
|
| 958 |
if ( |
| 959 |
$isParentFilter |
| 960 |
&& (!empty($filter['hide_until_parent']) && $filter['hide_until_parent'] === 'yes') |
| 961 |
&& (isset($args['hide_until_parent_class']) && $filter['hide_until_parent_class'] !== true) |
| 962 |
) { |
| 963 |
$classes[] = 'wpc-filters-hide-until-parent-section'; |
| 964 |
} |
| 965 |
|
| 966 |
if (isset($filter['values']) && !empty($filter['values'])) { |
| 967 |
$classes[] = 'wpc-filter-has-selected'; |
| 968 |
} |
| 969 |
|
| 970 |
// Set correct more/less class for specific views |
| 971 |
if (in_array($filter['view'], ['checkboxes', 'radio', 'labels'])) { |
| 972 |
if (isset($filter['more_less']) && $filter['more_less'] === 'yes') { |
| 973 |
|
| 974 |
$classes[] = 'wpc-filter-more-less'; |
| 975 |
|
| 976 |
if (in_array($filter['ID'], flrt_more_less_opened())) { |
| 977 |
$classes[] = 'wpc-show-more-reverse'; |
| 978 |
} |
| 979 |
|
| 980 |
$classes[] = flrt_get_status_css_class($filter['ID'], FLRT_MORELESS_COOKIE_NAME, ['opened' => 'wpc-show-more', 'closed' => 'wpc-show-less']); |
| 981 |
|
| 982 |
// We have to count only first-level terms if hierarchy is enabled |
| 983 |
if (isset($filter['hierarchy']) && $filter['hierarchy'] === 'yes') { |
| 984 |
if (!empty($terms)) { |
| 985 |
$only_parents = []; |
| 986 |
foreach ($terms as $term_id => $term) { |
| 987 |
if ($term->parent == 0) { |
| 988 |
$only_parents[$term_id] = $term; |
| 989 |
} |
| 990 |
} |
| 991 |
|
| 992 |
$terms = $only_parents; |
| 993 |
unset($only_parents); |
| 994 |
} |
| 995 |
} |
| 996 |
if (count($terms) <= flrt_more_less_count() || ($args['hide'] && !$args['use_apply_button'])) { |
| 997 |
$classes[] = 'wpc-filter-few-terms'; |
| 998 |
} |
| 999 |
|
| 1000 |
if ($count_terms_greater_than_zero <= flrt_more_less_count()) { |
| 1001 |
$classes[] = 'wpc-filter-few-terms'; |
| 1002 |
} |
| 1003 |
|
| 1004 |
|
| 1005 |
|
| 1006 |
} else { |
| 1007 |
$classes[] = 'wpc-filter-full-height'; |
| 1008 |
} |
| 1009 |
} |
| 1010 |
|
| 1011 |
if (isset($filter['collapse']) && $filter['collapse'] === 'yes') { |
| 1012 |
if (in_array($filter['ID'], flrt_folding_opened())) { |
| 1013 |
$classes[] = 'wpc-filter-collapsible-reverse'; |
| 1014 |
} |
| 1015 |
|
| 1016 |
$classes[] = 'wpc-filter-collapsible'; |
| 1017 |
|
| 1018 |
$classes[] = flrt_get_status_css_class($filter['ID'], FLRT_FOLDING_COOKIE_NAME); |
| 1019 |
} |
| 1020 |
|
| 1021 |
if (in_array($filter['ID'], flrt_hierarchy_opened())) { |
| 1022 |
if (isset($filter['hierarchy']) && $filter['hierarchy'] === 'yes') { |
| 1023 |
$classes[] = 'wpc-filter-hierarchy-reverse'; |
| 1024 |
} |
| 1025 |
} |
| 1026 |
|
| 1027 |
if (in_array($filter['entity'], ['post_date', 'post_meta_date'])) { |
| 1028 |
$classes[] = 'wpc-datetype-' . $filter['date_type']; |
| 1029 |
} |
| 1030 |
|
| 1031 |
if (!empty($default_classes)) { |
| 1032 |
$classes = array_merge($classes, $default_classes); |
| 1033 |
} |
| 1034 |
|
| 1035 |
$classes[] = 'wpc-filter-terms-count-' . count($terms); |
| 1036 |
|
| 1037 |
$classes = apply_filters('wpc_filter_classes', $classes, $filter, $default_classes, $terms, $args); |
| 1038 |
|
| 1039 |
return implode(" ", $classes); |
| 1040 |
} |
| 1041 |
|
| 1042 |
function flrt_filter_content_class($filter, $default_classes = []) |
| 1043 |
{ |
| 1044 |
$classes = array( |
| 1045 |
'wpc-filter-content' |
| 1046 |
); |
| 1047 |
|
| 1048 |
if (isset($filter['e_name'])) { |
| 1049 |
$classes[] = 'wpc-filter-' . $filter['e_name']; |
| 1050 |
} |
| 1051 |
|
| 1052 |
if (isset($filter['hierarchy']) && $filter['hierarchy'] === 'yes') { |
| 1053 |
$classes[] = 'wpc-filter-has-hierarchy'; |
| 1054 |
} |
| 1055 |
|
| 1056 |
if (!empty($default_classes)) { |
| 1057 |
$classes = array_merge($classes, $default_classes); |
| 1058 |
} |
| 1059 |
|
| 1060 |
$classes = apply_filters('wpc_filter_content_classes', $classes, $default_classes); |
| 1061 |
|
| 1062 |
return implode(" ", $classes); |
| 1063 |
|
| 1064 |
} |
| 1065 |
|
| 1066 |
if (!function_exists('flrt_filter_no_terms_message')) { |
| 1067 |
/** |
| 1068 |
* Outputs "No terms" message |
| 1069 |
* @param string $tag HTML tag name for the message wrapper |
| 1070 |
* @since 1.7.6 |
| 1071 |
*/ |
| 1072 |
function flrt_filter_no_terms_message($tag = 'li') |
| 1073 |
{ |
| 1074 |
if (!$tag || $tag === '') { |
| 1075 |
$tag = 'li'; |
| 1076 |
} |
| 1077 |
|
| 1078 |
$srch = isset($_GET['srch']) ? filter_input(INPUT_GET, 'srch', FILTER_SANITIZE_SPECIAL_CHARS) : ''; |
| 1079 |
|
| 1080 |
echo '<' . $tag . ' class="wpc-no-filter-terms">'; |
| 1081 |
if (!flrt_is_filter_request() && !$srch) { |
| 1082 |
esc_html_e('There are no filter terms yet', 'filter-everything'); |
| 1083 |
if (flrt_is_debug_mode()) { |
| 1084 |
echo ' ' . flrt_help_tip( |
| 1085 |
esc_html__('Possible reasons: 1) Filter\'s criterion doesn\'t contain any terms yet, and you have to add them 2) Terms may be created, but no one post that should be filtered attached to these terms 3) You excluded all possible terms in Filter\'s options.', 'filter-everything') |
| 1086 |
); |
| 1087 |
} |
| 1088 |
} else { |
| 1089 |
esc_html_e('N/A', 'filter-everything'); |
| 1090 |
} |
| 1091 |
echo '</' . $tag . '>'; |
| 1092 |
} |
| 1093 |
} |
| 1094 |
|
| 1095 |
if (!function_exists('flrt_filter_more_less')) { |
| 1096 |
/** |
| 1097 |
* Outputs More/Less toggle link |
| 1098 |
* @param array $filter Filter array |
| 1099 |
* @since 1.7.6 |
| 1100 |
*/ |
| 1101 |
function flrt_filter_more_less($filter) |
| 1102 |
{ |
| 1103 |
if (isset($filter['more_less']) && $filter['more_less'] === 'yes'): ?> |
| 1104 |
<a class="wpc-see-more-control wpc-toggle-a" href="javascript:void(0);" |
| 1105 |
data-fid="<?php echo esc_attr($filter['ID']); ?>"><?php esc_html_e('See more', 'filter-everything'); ?></a> |
| 1106 |
<a class="wpc-see-less-control wpc-toggle-a" href="javascript:void(0);" |
| 1107 |
data-fid="<?php echo esc_attr($filter['ID']); ?>"><?php esc_html_e('See less', 'filter-everything'); ?></a> |
| 1108 |
<?php endif; |
| 1109 |
} |
| 1110 |
} |
| 1111 |
|
| 1112 |
if (!function_exists('flrt_filter_search_field')) { |
| 1113 |
/** |
| 1114 |
* Outputs filter search field |
| 1115 |
* @since 1.7.6 |
| 1116 |
*/ |
| 1117 |
function flrt_filter_search_field($filter, $view_args, $terms) |
| 1118 |
{ |
| 1119 |
if (empty($terms)) { |
| 1120 |
return false; |
| 1121 |
} |
| 1122 |
|
| 1123 |
if ($filter['search'] === 'yes' && $view_args['ask_to_select_parent'] === false): ?> |
| 1124 |
<div class="wpc-filter-search-wrapper wpc-filter-search-wrapper-<?php echo esc_attr($filter['ID']); ?>"> |
| 1125 |
<span class="wpc-search-icon"></span> |
| 1126 |
<input class="wpc-filter-search-field" type="text" value="" |
| 1127 |
placeholder="<?php esc_html_e('Search', 'filter-everything') ?>"/> |
| 1128 |
<button class="wpc-search-clear" type="button" |
| 1129 |
title="<?php esc_html_e('Clear search', 'filter-everything') ?>"><span |
| 1130 |
class="wpc-search-clear-icon">×</span></button> |
| 1131 |
</div> |
| 1132 |
<?php endif; |
| 1133 |
} |
| 1134 |
} |
| 1135 |
|
| 1136 |
function flrt_get_contrast_ratio($hexColor) |
| 1137 |
{ |
| 1138 |
// hexColor RGB |
| 1139 |
$R1 = hexdec(substr($hexColor, 1, 2)); |
| 1140 |
$G1 = hexdec(substr($hexColor, 3, 2)); |
| 1141 |
$B1 = hexdec(substr($hexColor, 5, 2)); |
| 1142 |
|
| 1143 |
// Black RGB |
| 1144 |
$blackColor = "#000000"; |
| 1145 |
$R2BlackColor = hexdec(substr($blackColor, 1, 2)); |
| 1146 |
$G2BlackColor = hexdec(substr($blackColor, 3, 2)); |
| 1147 |
$B2BlackColor = hexdec(substr($blackColor, 5, 2)); |
| 1148 |
|
| 1149 |
// Calc contrast ratio |
| 1150 |
$L1 = 0.2126 * pow($R1 / 255, 2.2) + |
| 1151 |
0.7152 * pow($G1 / 255, 2.2) + |
| 1152 |
0.0722 * pow($B1 / 255, 2.2); |
| 1153 |
|
| 1154 |
$L2 = 0.2126 * pow($R2BlackColor / 255, 2.2) + |
| 1155 |
0.7152 * pow($G2BlackColor / 255, 2.2) + |
| 1156 |
0.0722 * pow($B2BlackColor / 255, 2.2); |
| 1157 |
|
| 1158 |
$contrastRatio = 0; |
| 1159 |
if ($L1 > $L2) { |
| 1160 |
$contrastRatio = (int)(($L1 + 0.05) / ($L2 + 0.05)); |
| 1161 |
} else { |
| 1162 |
$contrastRatio = (int)(($L2 + 0.05) / ($L1 + 0.05)); |
| 1163 |
} |
| 1164 |
return round($contrastRatio); |
| 1165 |
} |
| 1166 |
|
| 1167 |
function flrt_get_contrast_color($hexColor) |
| 1168 |
{ |
| 1169 |
|
| 1170 |
$contrastRatio = flrt_get_contrast_ratio($hexColor); |
| 1171 |
// If contrast is more than 5, return black color |
| 1172 |
if ($contrastRatio > 10) { |
| 1173 |
return '#333333'; |
| 1174 |
} else { |
| 1175 |
// if not, return white color. |
| 1176 |
return '#f5f5f5'; |
| 1177 |
} |
| 1178 |
} |
| 1179 |
|
| 1180 |
function flrt_hex_to_rgb($hexColor, $opacity = 100) |
| 1181 |
{ |
| 1182 |
$hexColor = ltrim($hexColor, '#'); |
| 1183 |
|
| 1184 |
$r = hexdec(substr($hexColor, 0, 2)); |
| 1185 |
$g = hexdec(substr($hexColor, 2, 2)); |
| 1186 |
$b = hexdec(substr($hexColor, 4, 2)); |
| 1187 |
$opacity = $opacity / 100; |
| 1188 |
return "rgb($r $g $b / $opacity)"; |
| 1189 |
} |
| 1190 |
|
| 1191 |
function flrt_add_color_opacity($hexColor, $opacity = 50) |
| 1192 |
{ |
| 1193 |
$contrastRatio = flrt_get_contrast_ratio($hexColor); |
| 1194 |
|
| 1195 |
if ($contrastRatio <= 15) { |
| 1196 |
return flrt_hex_to_rgb($hexColor, $opacity); |
| 1197 |
} else { |
| 1198 |
return $hexColor; |
| 1199 |
} |
| 1200 |
} |
| 1201 |
|
| 1202 |
|
| 1203 |
function flrt_default_posts_container() |
| 1204 |
{ |
| 1205 |
return apply_filters('wpc_theme_posts_container', '#primary'); |
| 1206 |
} |
| 1207 |
|
| 1208 |
function flrt_default_theme_color() |
| 1209 |
{ |
| 1210 |
return apply_filters('wpc_theme_color', '#0570e2'); |
| 1211 |
} |
| 1212 |
|
| 1213 |
function flrt_term_id($name, $filter, $id, $echo = true) |
| 1214 |
{ |
| 1215 |
$attr = esc_attr("wpc-" . $name . "-" . $filter['entity'] . "-" . esc_attr($filter['e_name']) . "-" . $id); |
| 1216 |
if ($echo) { |
| 1217 |
echo $attr; |
| 1218 |
} else { |
| 1219 |
return $attr; |
| 1220 |
} |
| 1221 |
} |
| 1222 |
|
| 1223 |
function flrt_get_icon_logo_svg($width = 24, $height = 24, $color = 'currentColor') |
| 1224 |
{ |
| 1225 |
return '<svg viewBox="0 0 53 53" fill="' . $color . '" width="' . $width . '" height="' . $height . '" xmlns="http://www.w3.org/2000/svg"> |
| 1226 |
<g id="Group 1"> |
| 1227 |
<g id="Layer_1_00000162333103265806981530000017146624247591674556_"> |
| 1228 |
<g id="Group"> |
| 1229 |
<g id="Clip path group"> |
| 1230 |
<mask id="mask0_5_4" maskUnits="userSpaceOnUse" x="0" y="0" width="53" height="53"> |
| 1231 |
<g id="SVGID_00000112608340804245442460000013986219178199086244_"> |
| 1232 |
<path id="Vector" fill="white" d="M0 0H53V53H0V0ZM23.3 37.2C24.7 37.2 25.8 36.1 25.8 34.7C25.8 33.3 24.7 32.2 23.3 32.2C21.9 32.2 20.8 33.3 20.8 34.7C20.8 36.1 21.9 37.2 23.3 37.2ZM33.4 27.2C34.8 27.2 35.9 26.1 35.9 24.7C35.9 23.3 34.8 22.2 33.4 22.2C32 22.2 30.9 23.3 30.9 24.7C30.9 26.1 32 27.2 33.4 27.2ZM23 22.8C24.6 22.8 25.9 21.5 25.9 19.9C25.9 18.3 24.6 17 23 17C21.4 17 20.1 18.3 20.1 19.9C20.2 21.5 21.5 22.8 23 22.8Z" /> |
| 1233 |
</g> |
| 1234 |
</mask> |
| 1235 |
<g mask="url(#mask0_5_4)"> |
| 1236 |
<g id="BarsClipped"> |
| 1237 |
<path id="Vector_2" d="M39.9 31.5L18 37.3C17.4 37.5 16.8 37.1 16.6 36.5C16.4 35.9 16.8 35.3 17.4 35.1L39.3 29.2C39.9 29 40.5 29.4 40.7 30C40.8 30.7 40.5 31.3 39.9 31.5Z" fill="currentColor"/> |
| 1238 |
<path id="Vector_3" d="M38.1 24.6L16.2 30.5C15.6 30.7 15 30.3 14.8 29.7C14.6 29.1 15 28.5 15.6 28.3L37.5 22.4C38.1 22.2 38.7 22.6 38.9 23.2C39 23.8 38.7 24.5 38.1 24.6Z" fill="currentColor"/> |
| 1239 |
<path id="Vector_4" d="M36.2 17.9L14.3 23.8C13.7 24 13.1 23.6 12.9 23C12.7 22.4 13.1 21.8 13.7 21.6L35.6 15.7C36.2 15.5 36.8 15.9 37 16.5C37.2 17.1 36.8 17.7 36.2 17.9Z" fill="currentColor"/> |
| 1240 |
</g> |
| 1241 |
</g> |
| 1242 |
</g> |
| 1243 |
</g> |
| 1244 |
<path id="Vector (Stroke)" d="M50 26.5C50 13.5284 39.4716 3 26.5 3C13.5284 3 3 13.5284 3 26.5C3 39.4716 13.5284 50 26.5 50C39.4716 50 50 39.4716 50 26.5ZM53 26.5C53 41.1284 41.1284 53 26.5 53C11.8716 53 0 41.1284 0 26.5C0 11.8716 11.8716 0 26.5 0C41.1284 0 53 11.8716 53 26.5Z" fill="currentColor"/> |
| 1245 |
</g> |
| 1246 |
<path id="Vector (Stroke)_2" d="M24.8 20.1C24.8 19.2716 24.1284 18.6 23.3 18.6C22.4716 18.6 21.8 19.2716 21.8 20.1C21.8 20.9284 22.4716 21.6 23.3 21.6C24.1284 21.6 24.8 20.9284 24.8 20.1ZM26.8 20.1C26.8 22.033 25.233 23.6 23.3 23.6C21.367 23.6 19.8 22.033 19.8 20.1C19.8 18.167 21.367 16.6 23.3 16.6C25.233 16.6 26.8 18.167 26.8 20.1Z" fill="currentColor"/> |
| 1247 |
<path id="Vector (Stroke)_3" d="M34.7 24.8C34.7 23.9716 34.0284 23.3 33.2 23.3C32.3716 23.3 31.7 23.9716 31.7 24.8C31.7 25.6284 32.3716 26.3 33.2 26.3C34.0284 26.3 34.7 25.6284 34.7 24.8ZM36.7 24.8C36.7 26.733 35.133 28.3 33.2 28.3C31.267 28.3 29.7 26.733 29.7 24.8C29.7 22.867 31.267 21.3 33.2 21.3C35.133 21.3 36.7 22.867 36.7 24.8Z" fill="currentColor"/> |
| 1248 |
<path id="Vector (Stroke)_4" d="M24.5 34.8C24.5 33.9716 23.8284 33.3 23 33.3C22.1716 33.3 21.5 33.9716 21.5 34.8C21.5 35.6284 22.1716 36.3 23 36.3C23.8284 36.3 24.5 35.6284 24.5 34.8ZM26.5 34.8C26.5 36.733 24.933 38.3 23 38.3C21.067 38.3 19.5 36.733 19.5 34.8C19.5 32.867 21.067 31.3 23 31.3C24.933 31.3 26.5 32.867 26.5 34.8Z" fill="currentColor"/> |
| 1249 |
</g> |
| 1250 |
</svg>'; |
| 1251 |
} |
| 1252 |
function flrt_get_icon_logo_svg_css($width = 24, $height = 24) |
| 1253 |
{ |
| 1254 |
return 'data:image/svg+xml;base64,' . base64_encode(flrt_get_icon_logo_svg($width, $height)); |
| 1255 |
} |
| 1256 |
function flrt_get_icon_svg($color = '#ffffff') |
| 1257 |
{ |
| 1258 |
$svg = flrt_get_icon_logo_svg(null, null, $color); |
| 1259 |
return 'data:image/svg+xml;base64,' . base64_encode($svg); |
| 1260 |
} |
| 1261 |
|
| 1262 |
function flrt_get_icon_html() |
| 1263 |
{ |
| 1264 |
?> |
| 1265 |
<span class="wpc-icon-html-wrapper"> |
| 1266 |
<span class="wpc-icon-line-1"></span> |
| 1267 |
<span class="wpc-icon-line-2"></span> |
| 1268 |
<span class="wpc-icon-line-3"></span> |
| 1269 |
</span> |
| 1270 |
<?php |
| 1271 |
} |
| 1272 |
|
| 1273 |
function flrt_get_plugin_name() |
| 1274 |
{ |
| 1275 |
if (defined('FLRT_FILTERS_PRO')) { |
| 1276 |
return esc_html__('Filter Everything Pro', 'filter-everything'); |
| 1277 |
} else { |
| 1278 |
return esc_html__('Filter Everything', 'filter-everything'); |
| 1279 |
} |
| 1280 |
} |
| 1281 |
|
| 1282 |
function flrt_get_plugin_url($type = 'about', $full = false) |
| 1283 |
{ |
| 1284 |
if ($full) { |
| 1285 |
return esc_url($full); |
| 1286 |
} |
| 1287 |
|
| 1288 |
return esc_url(FLRT_PLUGIN_URL . '/' . $type); |
| 1289 |
} |
| 1290 |
|
| 1291 |
function flrt_get_term_by_slug($prefix) |
| 1292 |
{ |
| 1293 |
global $wpdb; |
| 1294 |
|
| 1295 |
$sql = "SELECT {$wpdb->terms}.slug FROM {$wpdb->terms} WHERE {$wpdb->terms}.slug = '%s'"; |
| 1296 |
$sql = $wpdb->prepare($sql, $prefix); |
| 1297 |
$result = $wpdb->get_row($sql); |
| 1298 |
|
| 1299 |
if (isset($result->slug) && $result->slug) { |
| 1300 |
return $result->slug; |
| 1301 |
} |
| 1302 |
|
| 1303 |
return false; |
| 1304 |
} |
| 1305 |
|
| 1306 |
function flrt_walk_terms_tree($terms, $args) |
| 1307 |
{ |
| 1308 |
_deprecated_function('flrt_walk_terms_tree', '1.7.6', 'flrt_filter_walk_terms_tree()'); |
| 1309 |
flrt_filter_walk_terms_tree($terms, $args); |
| 1310 |
} |
| 1311 |
|
| 1312 |
function flrt_filter_walk_terms_tree($terms, $args) |
| 1313 |
{ |
| 1314 |
$walker = new \FilterEverything\Filter\WalkerCheckbox(); |
| 1315 |
|
| 1316 |
$depth = -1; |
| 1317 |
if (isset($args['filter']['hierarchy']) && $args['filter']['hierarchy'] === 'yes') { |
| 1318 |
$depth = 10; |
| 1319 |
} |
| 1320 |
|
| 1321 |
return $walker->walk($terms, $depth, $args); |
| 1322 |
} |
| 1323 |
|
| 1324 |
function flrt_get_all_parents($elements, $parent_id, &$ids) |
| 1325 |
{ |
| 1326 |
if (isset($elements[$parent_id]->parent) && $elements[$parent_id]->parent > 0) { |
| 1327 |
$id = $elements[$parent_id]->parent; |
| 1328 |
$ids_flipped = array_flip($ids); |
| 1329 |
|
| 1330 |
if (!isset($ids_flipped[$id])) { |
| 1331 |
$ids[] = $id; |
| 1332 |
} |
| 1333 |
|
| 1334 |
flrt_get_all_parents($elements, $id, $ids); |
| 1335 |
} else { |
| 1336 |
return $ids; |
| 1337 |
} |
| 1338 |
} |
| 1339 |
|
| 1340 |
function flrt_get_parents_with_not_empty_children($elements, $key = 'cross_count') |
| 1341 |
{ |
| 1342 |
$has_posts_in_children = []; |
| 1343 |
|
| 1344 |
if (empty($elements) || !is_array($elements)) { |
| 1345 |
return $has_posts_in_children; |
| 1346 |
} |
| 1347 |
|
| 1348 |
$new_elements = []; |
| 1349 |
|
| 1350 |
foreach ($elements as $k => $e) { |
| 1351 |
$new_elements[$e->term_id] = $e; |
| 1352 |
} |
| 1353 |
|
| 1354 |
$has_posts_in_children_flipped = array_flip($has_posts_in_children); |
| 1355 |
|
| 1356 |
foreach ($new_elements as $e) { |
| 1357 |
if (isset($e->parent) && !empty($e->parent) && $e->$key > 0) { |
| 1358 |
// Find all parents for term that contains posts |
| 1359 |
if (!isset($has_posts_in_children_flipped[$e->parent])) { |
| 1360 |
$has_posts_in_children[] = $e->parent; |
| 1361 |
} |
| 1362 |
|
| 1363 |
flrt_get_all_parents($new_elements, $e->parent, $has_posts_in_children); |
| 1364 |
} |
| 1365 |
} |
| 1366 |
|
| 1367 |
return $has_posts_in_children; |
| 1368 |
} |
| 1369 |
|
| 1370 |
/** |
| 1371 |
* Combines all filter sets for the same WP_Query |
| 1372 |
* |
| 1373 |
* @param array $all_sets - list of all page related sets |
| 1374 |
* @param $current_set |
| 1375 |
* @return array $queryRelatedSets IDs of all query related sets |
| 1376 |
*/ |
| 1377 |
function flrt_get_sets_with_the_same_query($all_sets, $current_set) |
| 1378 |
{ |
| 1379 |
$queryRelatedSets = []; |
| 1380 |
// First detect desired query index; |
| 1381 |
$query = ''; |
| 1382 |
$post_type = ''; |
| 1383 |
$location = ''; |
| 1384 |
$set_id = $current_set['ID']; |
| 1385 |
|
| 1386 |
foreach ($all_sets as $set) { |
| 1387 |
if ($set['ID'] === $set_id) { |
| 1388 |
// Current Set values |
| 1389 |
$query = $set['query']; |
| 1390 |
$post_type = $set['filtered_post_type']; |
| 1391 |
$location = $set['query_location']; |
| 1392 |
break; |
| 1393 |
} |
| 1394 |
} |
| 1395 |
|
| 1396 |
// Then find all sets with such query |
| 1397 |
foreach ($all_sets as $set) { |
| 1398 |
if ($set['query'] === $query && $post_type === $set['filtered_post_type'] && $location === $set['query_location']) { |
| 1399 |
$queryRelatedSets[] = $set['ID']; |
| 1400 |
} |
| 1401 |
} |
| 1402 |
|
| 1403 |
if (empty($queryRelatedSets)) { |
| 1404 |
$queryRelatedSets[] = $set_id; |
| 1405 |
} |
| 1406 |
|
| 1407 |
return $queryRelatedSets; |
| 1408 |
} |
| 1409 |
|
| 1410 |
function flrt_find_all_descendants($arr) |
| 1411 |
{ |
| 1412 |
$all_results = []; |
| 1413 |
|
| 1414 |
if (empty($arr) || !is_array($arr)) { |
| 1415 |
return $all_results; |
| 1416 |
} |
| 1417 |
|
| 1418 |
foreach ($arr as $k => $v) { |
| 1419 |
$curr_result = []; |
| 1420 |
|
| 1421 |
for ($stack = [$k]; count($stack);) { |
| 1422 |
$el = array_pop($stack); |
| 1423 |
|
| 1424 |
if (array_key_exists($el, $arr) && is_array($arr[$el])) { |
| 1425 |
foreach ($arr[$el] as $child) { |
| 1426 |
$curr_result [] = $child; |
| 1427 |
$stack [] = $child; |
| 1428 |
} |
| 1429 |
} |
| 1430 |
} |
| 1431 |
|
| 1432 |
if (count($curr_result)) { |
| 1433 |
$all_results[$k] = $curr_result; |
| 1434 |
} |
| 1435 |
} |
| 1436 |
|
| 1437 |
return $all_results; |
| 1438 |
} |
| 1439 |
|
| 1440 |
function flrt_debug_title() |
| 1441 |
{ |
| 1442 |
|
| 1443 |
echo '<div class="wpc-debug-title">' . esc_html__('Filter Everything debug', 'filter-everything'); |
| 1444 |
echo ' ' . flrt_help_tip( |
| 1445 |
sprintf( |
| 1446 |
__('Debug messages are visible for logged in administrators only. You can disable them in Filters -> <a href="%s">Settings</a> -> Debug mode.', 'filter-everything'), |
| 1447 |
admin_url('edit.php?post_type=filter-set&page=filters-settings') |
| 1448 |
), true) . '</div>'; |
| 1449 |
} |
| 1450 |
|
| 1451 |
function flrt_is_debug_mode() |
| 1452 |
{ |
| 1453 |
$debug_mode = false; |
| 1454 |
if (flrt_get_option('widget_debug_messages') === 'on') { |
| 1455 |
if (current_user_can(flrt_plugin_user_caps())) { |
| 1456 |
$debug_mode = true; |
| 1457 |
} |
| 1458 |
} |
| 1459 |
|
| 1460 |
return $debug_mode; |
| 1461 |
} |
| 1462 |
|
| 1463 |
function flrt_clean($var) |
| 1464 |
{ |
| 1465 |
if (is_array($var)) { |
| 1466 |
return array_map('flrt_clean', $var); |
| 1467 |
} else { |
| 1468 |
return is_scalar($var) ? sanitize_text_field($var) : $var; |
| 1469 |
} |
| 1470 |
} |
| 1471 |
|
| 1472 |
function flrt_sorting_option_value($order_by_value, $meta_keys, $orders, $i) |
| 1473 |
{ |
| 1474 |
$meta_key = isset($meta_keys[$i]) ? $meta_keys[$i] : ''; |
| 1475 |
$order = isset($orders[$i]) ? $orders[$i] : ''; |
| 1476 |
|
| 1477 |
$option_value = $order_by_value; |
| 1478 |
|
| 1479 |
if (in_array($order_by_value, ['m', 'n'], true)) { |
| 1480 |
$option_value .= $meta_key; |
| 1481 |
} |
| 1482 |
|
| 1483 |
$option_value .= ($order === 'desc') ? '-' . $order : ''; |
| 1484 |
|
| 1485 |
return $option_value; |
| 1486 |
} |
| 1487 |
|
| 1488 |
function flrt_get_active_plugins() |
| 1489 |
{ |
| 1490 |
|
| 1491 |
if (is_multisite()) { |
| 1492 |
$active_plugins = get_site_option('active_sitewide_plugins'); |
| 1493 |
if (is_array($active_plugins)) { |
| 1494 |
$active_plugins = array_keys($active_plugins); |
| 1495 |
} |
| 1496 |
|
| 1497 |
$site_active_plugins = apply_filters('active_plugins', get_option('active_plugins')); |
| 1498 |
$active_plugins = array_merge($active_plugins, $site_active_plugins); |
| 1499 |
} else { |
| 1500 |
$active_plugins = apply_filters('active_plugins', get_option('active_plugins')); |
| 1501 |
} |
| 1502 |
|
| 1503 |
return $active_plugins; |
| 1504 |
} |
| 1505 |
|
| 1506 |
/** |
| 1507 |
* Version tag for FE transient cache NAMES. Bump it whenever the cached data |
| 1508 |
* SHAPE changes (v2 = compact aggregated maps instead of raw SQL rows). |
| 1509 |
* Versioned key names keep branches/versions with different cache formats |
| 1510 |
* from ever reading each other's transients (e.g. when switching git branches |
| 1511 |
* on a dev site) - each format lives under its own keys and stale ones simply |
| 1512 |
* expire. |
| 1513 |
*/ |
| 1514 |
if ( ! defined( 'FLRT_CACHE_FORMAT_SUFFIX' ) ) { |
| 1515 |
define( 'FLRT_CACHE_FORMAT_SUFFIX', '_v2' ); |
| 1516 |
} |
| 1517 |
|
| 1518 |
function flrt_get_terms_transient_key( $salt, $include_lang = true ){ |
| 1519 |
$key = 'wpc_terms_' . $salt . FLRT_CACHE_FORMAT_SUFFIX; |
| 1520 |
if ( flrt_wpml_active() && defined( 'ICL_LANGUAGE_CODE' ) && $include_lang ) { |
| 1521 |
$key .= '_'.ICL_LANGUAGE_CODE; |
| 1522 |
} |
| 1523 |
|
| 1524 |
if (function_exists('pll_current_language') && $include_lang) { |
| 1525 |
$pll_lang = pll_current_language(); |
| 1526 |
if ($pll_lang) { |
| 1527 |
$key .= '_' . $pll_lang; |
| 1528 |
} |
| 1529 |
} |
| 1530 |
|
| 1531 |
return $key; |
| 1532 |
} |
| 1533 |
|
| 1534 |
function flrt_get_post_ids_transient_key( $salt ){ |
| 1535 |
$key = 'wpc_posts_' . $salt . FLRT_CACHE_FORMAT_SUFFIX; |
| 1536 |
if (flrt_wpml_active() && defined('ICL_LANGUAGE_CODE')) { |
| 1537 |
$key .= '_' . ICL_LANGUAGE_CODE; |
| 1538 |
} |
| 1539 |
|
| 1540 |
if (function_exists('pll_current_language')) { |
| 1541 |
$pll_lang = pll_current_language(); |
| 1542 |
if ($pll_lang) { |
| 1543 |
$key .= '_' . $pll_lang; |
| 1544 |
} |
| 1545 |
} |
| 1546 |
|
| 1547 |
return $key; |
| 1548 |
} |
| 1549 |
|
| 1550 |
function flrt_get_variations_transient_key( $salt ){ |
| 1551 |
$key = 'wpc_variations_' . $salt . FLRT_CACHE_FORMAT_SUFFIX; |
| 1552 |
if (flrt_wpml_active() && defined('ICL_LANGUAGE_CODE')) { |
| 1553 |
$key .= '_' . ICL_LANGUAGE_CODE; |
| 1554 |
} |
| 1555 |
|
| 1556 |
if (function_exists('pll_current_language')) { |
| 1557 |
$pll_lang = pll_current_language(); |
| 1558 |
if ($pll_lang) { |
| 1559 |
$key .= '_' . $pll_lang; |
| 1560 |
} |
| 1561 |
} |
| 1562 |
|
| 1563 |
return $key; |
| 1564 |
} |
| 1565 |
|
| 1566 |
function flrt_is_query_on_page($setPosts, $searchKey) |
| 1567 |
{ |
| 1568 |
$filterSet = Container::instance()->getFilterSetService(); |
| 1569 |
$sets = []; |
| 1570 |
if (!is_array($setPosts)) { |
| 1571 |
return $sets; |
| 1572 |
} |
| 1573 |
|
| 1574 |
foreach ($setPosts as $set) { |
| 1575 |
|
| 1576 |
$parameters = maybe_unserialize($set->post_content); |
| 1577 |
$query = isset($parameters['wp_filter_query']) ? $parameters['wp_filter_query'] : '-1'; |
| 1578 |
if ($filterSet->under_limit_filter_set($set->ID)) { |
| 1579 |
continue; |
| 1580 |
} |
| 1581 |
|
| 1582 |
if (isset($parameters['use_apply_button']) && $parameters['use_apply_button'] === 'yes') { |
| 1583 |
|
| 1584 |
$query_on_the_page = false; |
| 1585 |
$show_on_the_page = false; |
| 1586 |
|
| 1587 |
if (defined('FLRT_FILTERS_PRO') && FLRT_FILTERS_PRO) { |
| 1588 |
if (isset($parameters['apply_button_post_name'])) { |
| 1589 |
|
| 1590 |
if ($parameters['apply_button_post_name'] === $set->post_name || |
| 1591 |
$parameters['apply_button_post_name'] === 'no_page___no_page') { |
| 1592 |
$query_on_the_page = true; |
| 1593 |
} |
| 1594 |
|
| 1595 |
if (in_array($parameters['apply_button_post_name'], $searchKey) || ($parameters['apply_button_post_name'] === 'no_page___no_page')) { |
| 1596 |
$show_on_the_page = true; |
| 1597 |
} |
| 1598 |
} |
| 1599 |
|
| 1600 |
} else { |
| 1601 |
$query_on_the_page = true; |
| 1602 |
$show_on_the_page = true; |
| 1603 |
} |
| 1604 |
|
| 1605 |
$sets[] = array( |
| 1606 |
'ID' => (string)$set->ID, |
| 1607 |
'filtered_post_type' => $set->post_excerpt, |
| 1608 |
'query' => $query, // query hash |
| 1609 |
'query_location' => $set->post_name, |
| 1610 |
'query_on_the_page' => $query_on_the_page, |
| 1611 |
'page_search_keys' => $searchKey, |
| 1612 |
'show_on_the_page' => $show_on_the_page |
| 1613 |
); |
| 1614 |
|
| 1615 |
} else { |
| 1616 |
if (in_array($set->post_name, $searchKey)) { |
| 1617 |
$sets[] = array( |
| 1618 |
'ID' => (string)$set->ID, |
| 1619 |
'filtered_post_type' => $set->post_excerpt, |
| 1620 |
'query' => $query, // query hash |
| 1621 |
'query_location' => $set->post_name, |
| 1622 |
'query_on_the_page' => true, |
| 1623 |
'page_search_keys' => $searchKey, |
| 1624 |
'show_on_the_page' => true |
| 1625 |
); |
| 1626 |
} else { |
| 1627 |
// This set is for another page and was selected by Apply button location but the button disabled |
| 1628 |
continue; |
| 1629 |
} |
| 1630 |
} |
| 1631 |
|
| 1632 |
} |
| 1633 |
|
| 1634 |
return $sets; |
| 1635 |
} |
| 1636 |
|
| 1637 |
function flrt_remove_empty_terms($checkTerms, $filter, $has_not_empty_children_flipped = [], $use_apply_button = false) |
| 1638 |
{ |
| 1639 |
|
| 1640 |
if (!$use_apply_button) { |
| 1641 |
foreach ($checkTerms as $index => $term) { |
| 1642 |
if ($filter['hierarchy'] === 'yes') { |
| 1643 |
|
| 1644 |
if ($term->cross_count === 0 |
| 1645 |
&& !isset($has_not_empty_children_flipped[$term->term_id])) { |
| 1646 |
unset($checkTerms[$index]); |
| 1647 |
} |
| 1648 |
|
| 1649 |
} else { |
| 1650 |
if ($term->cross_count === 0) { |
| 1651 |
unset($checkTerms[$index]); |
| 1652 |
} |
| 1653 |
} |
| 1654 |
} |
| 1655 |
} |
| 1656 |
|
| 1657 |
return $checkTerms; |
| 1658 |
} |
| 1659 |
|
| 1660 |
function flrt_get_wp_queried_term($terms) |
| 1661 |
{ |
| 1662 |
$wp_queried_terms = false; |
| 1663 |
|
| 1664 |
foreach ($terms as $term) { |
| 1665 |
if ($term->wp_queried === true) { |
| 1666 |
$wp_queried_terms = $term; |
| 1667 |
break; |
| 1668 |
} |
| 1669 |
} |
| 1670 |
|
| 1671 |
return $wp_queried_terms; |
| 1672 |
} |
| 1673 |
|
| 1674 |
function flrt_get_filter_terms($filter, $posType, $em = false) |
| 1675 |
{ |
| 1676 |
if (!$em) { |
| 1677 |
$em = Container::instance()->getEntityManager(); |
| 1678 |
} |
| 1679 |
|
| 1680 |
$entityObj = $em->getEntityByFilter($filter, $posType); |
| 1681 |
|
| 1682 |
// The filter may lack entity/e_name (e.g. a parent_filter reference |
| 1683 |
// to a filter that is absent from the rendered set) |
| 1684 |
if (!$entityObj) { |
| 1685 |
return []; |
| 1686 |
} |
| 1687 |
|
| 1688 |
// Exclude or include terms |
| 1689 |
$isInclude = (isset($filter['include']) && $filter['include'] === 'yes'); |
| 1690 |
$entityObj->setExcludedTerms($filter['exclude'], $isInclude); |
| 1691 |
|
| 1692 |
$terms = $entityObj->getTerms(); |
| 1693 |
|
| 1694 |
return apply_filters('wpc_items_after_calc_term_count', $terms); |
| 1695 |
} |
| 1696 |
|
| 1697 |
function flrt_get_term_brand_image($term_id, $filter) |
| 1698 |
{ |
| 1699 |
$src = false; |
| 1700 |
|
| 1701 |
if ($filter['e_name'] === 'pwb-brand') { |
| 1702 |
$attachment_id = get_term_meta($term_id, 'pwb_brand_image', true); |
| 1703 |
$attachment_props = wp_get_attachment_image_src($attachment_id, 'small'); |
| 1704 |
$src = isset($attachment_props[0]) ? $attachment_props[0] : false; |
| 1705 |
} elseif (in_array($filter['e_name'], ['yith_product_brand', 'product_brand'])) { |
| 1706 |
$attachment_id = get_term_meta($term_id, 'thumbnail_id', true); |
| 1707 |
$attachment_props = wp_get_attachment_image_src($attachment_id, 'small'); |
| 1708 |
$src = isset($attachment_props[0]) ? $attachment_props[0] : false; |
| 1709 |
} else { |
| 1710 |
// pa_brand and other custom brand taxonomies. The plugin's own term |
| 1711 |
// Image field saves 'product_attribute_image' for pa_* taxonomies |
| 1712 |
// (see Swatches::save_image_field) — read the same key it writes. |
| 1713 |
$image_meta_key = ( strpos( $filter['e_name'], 'pa_' ) === 0 ) ? 'product_attribute_image' : 'image'; |
| 1714 |
$src = get_term_meta($term_id, $image_meta_key, true); |
| 1715 |
|
| 1716 |
if ( ! $src && $image_meta_key !== 'image' ) { |
| 1717 |
$src = get_term_meta($term_id, 'image', true); |
| 1718 |
} |
| 1719 |
|
| 1720 |
if (intval($src) > 0) { |
| 1721 |
$src = wp_get_attachment_image_url($src, 'full'); |
| 1722 |
} |
| 1723 |
|
| 1724 |
if (isset($src['id']) && $src['id']) { |
| 1725 |
$src = wp_get_attachment_image_url($src['id'], 'full'); |
| 1726 |
} |
| 1727 |
} |
| 1728 |
|
| 1729 |
return $src; |
| 1730 |
} |
| 1731 |
|
| 1732 |
function flrt_get_term_swatch_image($term_id, $filter) |
| 1733 |
{ |
| 1734 |
$src = false; |
| 1735 |
$image_key = 'image'; |
| 1736 |
|
| 1737 |
if (strpos($filter['e_name'], 'pa_') === 0) { |
| 1738 |
$image_key = 'product_attribute_' . $image_key; |
| 1739 |
} |
| 1740 |
|
| 1741 |
if ($filter['e_name'] === 'product_cat') { |
| 1742 |
$image_key = 'thumbnail_id'; |
| 1743 |
} |
| 1744 |
|
| 1745 |
$image_key = apply_filters('wpc_image_term_meta_key', $image_key, $filter); |
| 1746 |
|
| 1747 |
$image_id = get_term_meta($term_id, $image_key, true); |
| 1748 |
$swatch_image_size = apply_filters('wpc_swatch_image_size', 'thumbnail'); |
| 1749 |
|
| 1750 |
if ($image_id) { |
| 1751 |
$src = wp_get_attachment_image_url($image_id, $swatch_image_size); |
| 1752 |
} |
| 1753 |
|
| 1754 |
return $src; |
| 1755 |
} |
| 1756 |
|
| 1757 |
function flrt_get_term_swatch_color($term_id, $filter) |
| 1758 |
{ |
| 1759 |
$color = false; |
| 1760 |
$color_key = 'color'; |
| 1761 |
|
| 1762 |
if (strpos($filter['e_name'], 'pa_') === 0) { |
| 1763 |
$color_key = 'product_attribute_' . $color_key; |
| 1764 |
} |
| 1765 |
|
| 1766 |
$color_key = apply_filters('wpc_color_term_meta_key', $color_key, $filter); |
| 1767 |
$color = get_term_meta($term_id, $color_key, true); |
| 1768 |
|
| 1769 |
return $color; |
| 1770 |
} |
| 1771 |
|
| 1772 |
/** |
| 1773 |
* Checks and returns date format. |
| 1774 |
* Does not check if date is valid |
| 1775 |
* @param $date |
| 1776 |
* @return string|false date, time format or false |
| 1777 |
*/ |
| 1778 |
function flrt_detect_date_type($date_or_time) |
| 1779 |
{ |
| 1780 |
if (!$date_or_time) { |
| 1781 |
return false; |
| 1782 |
} |
| 1783 |
$format = false; |
| 1784 |
$date = false; |
| 1785 |
$time = false; |
| 1786 |
|
| 1787 |
$date_or_time = str_replace(FLRT_DATE_TIME_SEPARATOR, ' ', $date_or_time); |
| 1788 |
|
| 1789 |
$pcs = date_parse($date_or_time); |
| 1790 |
if ($pcs['year'] !== false && $pcs['month'] !== false && $pcs['day'] !== false) { |
| 1791 |
$date = true; |
| 1792 |
} |
| 1793 |
|
| 1794 |
if ($pcs['hour'] !== false && $pcs['minute'] !== false && $pcs['second'] !== false) { |
| 1795 |
$time = true; |
| 1796 |
} |
| 1797 |
|
| 1798 |
if ($date && $time) { |
| 1799 |
$format = 'datetime'; |
| 1800 |
} else { |
| 1801 |
if ($date) { |
| 1802 |
$format = 'date'; |
| 1803 |
} |
| 1804 |
if ($time) { |
| 1805 |
$format = 'time'; |
| 1806 |
} |
| 1807 |
} |
| 1808 |
|
| 1809 |
return $format; |
| 1810 |
} |
| 1811 |
|
| 1812 |
/** |
| 1813 |
* Modifies datetime to the human format |
| 1814 |
* @param $datetime |
| 1815 |
* @param $date_type |
| 1816 |
* @param string $sep |
| 1817 |
* @return mixed|string |
| 1818 |
*/ |
| 1819 |
function flrt_clean_date_time($datetime, $date_type, $sep = " ") |
| 1820 |
{ |
| 1821 |
if ($date_type === 'date' || $date_type === 'DATE') { |
| 1822 |
$pieces = explode($sep, $datetime); |
| 1823 |
return $pieces[0]; //date e.g. 2021-05-14 |
| 1824 |
} else if ($date_type === 'time' || $date_type === 'TIME') { |
| 1825 |
$pieces = explode($sep, $datetime); |
| 1826 |
if (isset($pieces[1])) { |
| 1827 |
return $pieces[1]; //time e.g. 14:15:47 |
| 1828 |
} |
| 1829 |
} else { |
| 1830 |
return $datetime; // str_replace( $sep, ' ', $datetime ); //datetime e.g. 2021-05-14 14:15:47 |
| 1831 |
} |
| 1832 |
} |
| 1833 |
|
| 1834 |
function flrt_apply_date_format($income_date, $format = "Y-m-d H:i:s") |
| 1835 |
{ |
| 1836 |
$timestamp = strtotime($income_date); |
| 1837 |
return flrt_date($format, $timestamp); |
| 1838 |
} |
| 1839 |
|
| 1840 |
function flrt_date($format, $timestamp = null) |
| 1841 |
{ |
| 1842 |
global $wp_locale; |
| 1843 |
|
| 1844 |
if (null === $timestamp) { |
| 1845 |
$timestamp = time(); |
| 1846 |
} elseif (!is_numeric($timestamp)) { |
| 1847 |
return false; |
| 1848 |
} |
| 1849 |
|
| 1850 |
$datetime = date_create('@' . $timestamp); |
| 1851 |
|
| 1852 |
if (empty($wp_locale->month) || empty($wp_locale->weekday)) { |
| 1853 |
$date = $datetime->format($format); |
| 1854 |
} else { |
| 1855 |
// We need to unpack shorthand `r` format because it has parts that might be localized. |
| 1856 |
$format = preg_replace('/(?<!\\\\)r/', DATE_RFC2822, $format); |
| 1857 |
|
| 1858 |
$new_format = ''; |
| 1859 |
$format_length = strlen($format); |
| 1860 |
$month = $wp_locale->get_month($datetime->format('m')); |
| 1861 |
$weekday = $wp_locale->get_weekday($datetime->format('w')); |
| 1862 |
|
| 1863 |
for ($i = 0; $i < $format_length; $i++) { |
| 1864 |
switch ($format[$i]) { |
| 1865 |
case 'D': |
| 1866 |
$new_format .= addcslashes($wp_locale->get_weekday_abbrev($weekday), '\\A..Za..z'); |
| 1867 |
break; |
| 1868 |
case 'F': |
| 1869 |
$new_format .= addcslashes($month, '\\A..Za..z'); |
| 1870 |
break; |
| 1871 |
case 'l': |
| 1872 |
$new_format .= addcslashes($weekday, '\\A..Za..z'); |
| 1873 |
break; |
| 1874 |
case 'M': |
| 1875 |
$new_format .= addcslashes($wp_locale->get_month_abbrev($month), '\\A..Za..z'); |
| 1876 |
break; |
| 1877 |
case 'a': |
| 1878 |
$new_format .= addcslashes($wp_locale->get_meridiem($datetime->format('a')), '\\A..Za..z'); |
| 1879 |
break; |
| 1880 |
case 'A': |
| 1881 |
$new_format .= addcslashes($wp_locale->get_meridiem($datetime->format('A')), '\\A..Za..z'); |
| 1882 |
break; |
| 1883 |
case '\\': |
| 1884 |
$new_format .= $format[$i]; |
| 1885 |
|
| 1886 |
// If character follows a slash, we add it without translating. |
| 1887 |
if ($i < $format_length) { |
| 1888 |
$new_format .= $format[++$i]; |
| 1889 |
} |
| 1890 |
break; |
| 1891 |
default: |
| 1892 |
$new_format .= $format[$i]; |
| 1893 |
break; |
| 1894 |
} |
| 1895 |
} |
| 1896 |
|
| 1897 |
$date = date_format($datetime, $new_format); |
| 1898 |
} |
| 1899 |
|
| 1900 |
return $date; |
| 1901 |
} |
| 1902 |
|
| 1903 |
function flrt_default_date_format($date_type = 'date') |
| 1904 |
{ |
| 1905 |
/** |
| 1906 |
* @todo date format depend from localization and geo settings |
| 1907 |
* we have to relate them here |
| 1908 |
*/ |
| 1909 |
$date_format = __('F j, Y'); |
| 1910 |
|
| 1911 |
switch ($date_type) { |
| 1912 |
case 'date': |
| 1913 |
$date_format = __('F j, Y'); //'d-m-Y'; |
| 1914 |
break; |
| 1915 |
case 'datetime': |
| 1916 |
$date_format = __('F j, Y g:i a'); //'d-m-Y H:i:s'; |
| 1917 |
break; |
| 1918 |
case 'time': |
| 1919 |
$date_format = __('g:i a'); // 'H:i:s'; |
| 1920 |
break; |
| 1921 |
} |
| 1922 |
|
| 1923 |
return $date_format; |
| 1924 |
} |
| 1925 |
|
| 1926 |
function flrt_convert_date_to_js($date_or_time) |
| 1927 |
{ |
| 1928 |
$date_php_to_js = Container::instance()->getParam('php_to_js_date_formats'); |
| 1929 |
return flrt_str_replace($date_or_time, $date_php_to_js); |
| 1930 |
} |
| 1931 |
|
| 1932 |
function flrt_convert_time_to_js($date_or_time) |
| 1933 |
{ |
| 1934 |
$time_php_to_js = Container::instance()->getParam('php_to_js_time_formats'); |
| 1935 |
return flrt_str_replace($date_or_time, $time_php_to_js); |
| 1936 |
} |
| 1937 |
|
| 1938 |
function flrt_str_replace($string = '', $search_replace = array()) |
| 1939 |
{ |
| 1940 |
$ignore = array(); |
| 1941 |
unset($search_replace['']); |
| 1942 |
|
| 1943 |
foreach ($search_replace as $search => $replace) { |
| 1944 |
if (in_array($search, $ignore)) { |
| 1945 |
continue; |
| 1946 |
} |
| 1947 |
if (strpos($string, $search) === false) { |
| 1948 |
continue; |
| 1949 |
} |
| 1950 |
$string = str_replace($search, $replace, $string); |
| 1951 |
$ignore[] = $replace; |
| 1952 |
} |
| 1953 |
|
| 1954 |
return $string; |
| 1955 |
} |
| 1956 |
|
| 1957 |
function flrt_split_date_time($date_time = '') |
| 1958 |
{ |
| 1959 |
$php_date = Container::instance()->getParam('php_to_js_date_formats'); |
| 1960 |
$php_time = Container::instance()->getParam('php_to_js_time_formats'); |
| 1961 |
$chars = str_split($date_time); |
| 1962 |
$type = 'date'; |
| 1963 |
|
| 1964 |
$data = array( |
| 1965 |
'date' => '', |
| 1966 |
'time' => '', |
| 1967 |
); |
| 1968 |
|
| 1969 |
foreach ($chars as $i => $c) { |
| 1970 |
if (isset($php_date[$c])) { |
| 1971 |
$type = 'date'; |
| 1972 |
} elseif (isset($php_time[$c])) { |
| 1973 |
$type = 'time'; |
| 1974 |
} |
| 1975 |
$data[$type] .= $c; |
| 1976 |
} |
| 1977 |
|
| 1978 |
$data['date'] = trim($data['date']); |
| 1979 |
$data['time'] = trim($data['time']); |
| 1980 |
|
| 1981 |
return $data; |
| 1982 |
} |
| 1983 |
|
| 1984 |
function flrt_string_polyfill($data) { |
| 1985 |
return map_deep( $data,'flrt_string_polyfill_body'); |
| 1986 |
} |
| 1987 |
|
| 1988 |
function flrt_string_polyfill_body( $string ){ |
| 1989 |
|
| 1990 |
if ( ! is_string( $string ) ) { |
| 1991 |
return $string; |
| 1992 |
} |
| 1993 |
|
| 1994 |
$str = preg_replace('/\x00|<[^>]*>?/', '', $string ); |
| 1995 |
return str_replace( ["'", '"'], [''', '"'], $str ); |
| 1996 |
} |
| 1997 |
|
| 1998 |
function flrt_rating_star() |
| 1999 |
{ |
| 2000 |
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25"> |
| 2001 |
<polygon class="cls-1" points="19.89 24.5 12.48 19.8 5.06 24.48 7.03 15.62 0.5 9.64 9.12 8.87 12.51 0.5 15.88 8.88 24.5 9.68 17.96 15.63 19.89 24.5"/> |
| 2002 |
</svg>'; |
| 2003 |
} |
| 2004 |
|
| 2005 |
function flrt_check_update_mobile_settings() |
| 2006 |
{ |
| 2007 |
|
| 2008 |
$settings = get_option('wpc_filter_settings', false); |
| 2009 |
if ($settings !== false) { |
| 2010 |
if (!flrt_get_option('mobile_filter_settings')) { |
| 2011 |
|
| 2012 |
$mobile_filter_settings = 'nothing'; |
| 2013 |
|
| 2014 |
if ((flrt_get_option('show_bottom_widget') === 'on' && flrt_get_option('show_open_close_button') === 'on') |
| 2015 |
|| (flrt_get_option('show_bottom_widget') === 'on' && !flrt_get_option('show_open_close_button'))) { |
| 2016 |
$mobile_filter_settings = 'show_bottom_widget'; |
| 2017 |
} elseif (flrt_get_option('show_open_close_button') == 'on' && !flrt_get_option('show_bottom_widget')) { |
| 2018 |
$mobile_filter_settings = 'show_open_close_button'; |
| 2019 |
} |
| 2020 |
|
| 2021 |
$settings = get_option('wpc_filter_settings'); |
| 2022 |
|
| 2023 |
if (isset($settings['show_bottom_widget']) && $settings['show_bottom_widget']) { |
| 2024 |
unset($settings['show_bottom_widget']); |
| 2025 |
} |
| 2026 |
|
| 2027 |
if (isset($settings['show_open_close_button']) && $settings['show_open_close_button']) { |
| 2028 |
unset($settings['show_open_close_button']); |
| 2029 |
} |
| 2030 |
|
| 2031 |
$settings['mobile_filter_settings'] = $mobile_filter_settings; |
| 2032 |
update_option('wpc_filter_settings', $settings); |
| 2033 |
} |
| 2034 |
} |
| 2035 |
} |
| 2036 |
|
| 2037 |
if (!function_exists('flrt_set_transient')) { |
| 2038 |
function flrt_set_transient($transient, $value, $expiration = 0) |
| 2039 |
{ |
| 2040 |
if (defined('FLRT_SET_TRANSIENT_ENABLED') && FLRT_SET_TRANSIENT_ENABLED) { |
| 2041 |
set_transient($transient, $value, $expiration); |
| 2042 |
} |
| 2043 |
} |
| 2044 |
} |
| 2045 |
|
| 2046 |
if (!function_exists('flrt_get_transient')) { |
| 2047 |
function flrt_get_transient($transient) |
| 2048 |
{ |
| 2049 |
if (defined('FLRT_SET_TRANSIENT_ENABLED') && FLRT_SET_TRANSIENT_ENABLED) { |
| 2050 |
return get_transient($transient); |
| 2051 |
} |
| 2052 |
return false; |
| 2053 |
} |
| 2054 |
} |
| 2055 |
|
| 2056 |
if (!class_exists('FlrtWooDiscountRules')) { |
| 2057 |
class FlrtWooDiscountRules |
| 2058 |
{ |
| 2059 |
|
| 2060 |
protected $rules; |
| 2061 |
|
| 2062 |
protected $base; |
| 2063 |
protected $rule_helper; |
| 2064 |
protected $discount_calculator; |
| 2065 |
protected $manage_discount; |
| 2066 |
|
| 2067 |
//public $filter; |
| 2068 |
public function __construct() |
| 2069 |
{ |
| 2070 |
$this->base = new Wdr\App\Controllers\Base(); |
| 2071 |
$this->rule_helper = new Wdr\App\Helpers\Rule(); |
| 2072 |
$this->manage_discount = new Wdr\App\Controllers\ManageDiscount(); |
| 2073 |
$this->rules = $this->manage_discount->getDiscountRules(); |
| 2074 |
$this->discount_calculator = new Wdr\App\Controllers\DiscountCalculator($this->rule_helper->getAvailableRules($this->base->getAvailableConditions())); |
| 2075 |
} |
| 2076 |
|
| 2077 |
public function getProductPriceToDisplay($product) |
| 2078 |
{ |
| 2079 |
return $this->discount_calculator->getProductPriceToDisplay($product, 1); |
| 2080 |
} |
| 2081 |
} |
| 2082 |
|
| 2083 |
function flrt_woo_discount_rules_class() |
| 2084 |
{ |
| 2085 |
return new FlrtWooDiscountRules(); |
| 2086 |
} |
| 2087 |
} |
| 2088 |
|
| 2089 |
|
| 2090 |
if (!function_exists('flrt_is_sitemap_exists')) { |
| 2091 |
function flrt_is_sitemap_exists() |
| 2092 |
{ |
| 2093 |
$filepath = rtrim(FLRT_XML_PATH, '/\\') . '/filter-sitemap-index.xml'; |
| 2094 |
return file_exists($filepath); |
| 2095 |
} |
| 2096 |
} |
| 2097 |
if (!function_exists('flrt_get_index_sitemap')) { |
| 2098 |
function flrt_get_index_sitemap() |
| 2099 |
{ |
| 2100 |
return fltr_get_url_from_absolute_path(FLRT_XML_PATH . '/filter-sitemap-index.xml'); |
| 2101 |
} |
| 2102 |
} |
| 2103 |
|
| 2104 |
if (!function_exists('fltr_get_url_from_absolute_path')) { |
| 2105 |
function fltr_get_url_from_absolute_path($absolute_path) |
| 2106 |
{ |
| 2107 |
$wp_root_path = realpath(ABSPATH); |
| 2108 |
$wp_url = site_url(); |
| 2109 |
|
| 2110 |
$file_path = realpath($absolute_path); |
| 2111 |
|
| 2112 |
if (!$file_path || strpos($file_path, $wp_root_path) !== 0) { |
| 2113 |
return false; |
| 2114 |
} |
| 2115 |
|
| 2116 |
|
| 2117 |
$relative_path = str_replace($wp_root_path, '', $file_path); |
| 2118 |
$relative_path = str_replace('\\', '/', $relative_path); |
| 2119 |
|
| 2120 |
return rtrim($wp_url, '/') . $relative_path; |
| 2121 |
} |
| 2122 |
} |
| 2123 |
|
| 2124 |
if (!function_exists('flrt_has_filter_seo_rules')) { |
| 2125 |
function flrt_has_filter_seo_rules() |
| 2126 |
{ |
| 2127 |
$args = [ |
| 2128 |
'post_type' => 'filter-seo-rule', |
| 2129 |
'post_status' => 'publish', |
| 2130 |
'posts_per_page' => 1, |
| 2131 |
'fields' => 'ids', |
| 2132 |
'no_found_rows' => true, |
| 2133 |
]; |
| 2134 |
|
| 2135 |
$query = new WP_Query($args); |
| 2136 |
return $query->have_posts(); |
| 2137 |
} |
| 2138 |
} |
| 2139 |
|
| 2140 |
if (!function_exists('flrt_get_last_modified_filter_seo_rule')) { |
| 2141 |
function flrt_get_last_modified_filter_post_type($post_type) |
| 2142 |
{ |
| 2143 |
global $wpdb; |
| 2144 |
$sql = " |
| 2145 |
SELECT post_modified |
| 2146 |
FROM {$wpdb->posts} |
| 2147 |
WHERE post_type = '%s' |
| 2148 |
AND post_status IN ('publish', 'trash') |
| 2149 |
ORDER BY post_modified DESC |
| 2150 |
LIMIT 1"; |
| 2151 |
$query = $wpdb->prepare($sql, $post_type); |
| 2152 |
$last_modified = $wpdb->get_var($query); |
| 2153 |
|
| 2154 |
if (!$last_modified) { |
| 2155 |
return false; |
| 2156 |
} |
| 2157 |
return $last_modified; |
| 2158 |
} |
| 2159 |
} |
| 2160 |
|
| 2161 |
if (!function_exists('flrt_check_to_update_xml')) { |
| 2162 |
function flrt_check_to_update_xml() |
| 2163 |
{ |
| 2164 |
$wpc_xml_write_date = get_option('wpc_xml_write_date'); |
| 2165 |
if (!$wpc_xml_write_date) return false; |
| 2166 |
|
| 2167 |
$last_modified_filter_seo_rule = flrt_get_last_modified_filter_post_type(FLRT_SEO_RULES_POST_TYPE); |
| 2168 |
$last_modified_filter_set = flrt_get_last_modified_filter_post_type(FLRT_FILTERS_SET_POST_TYPE); |
| 2169 |
|
| 2170 |
if (!$last_modified_filter_seo_rule && !$last_modified_filter_set) return false; |
| 2171 |
|
| 2172 |
$wpc_xml_write_date = strtotime($wpc_xml_write_date); |
| 2173 |
$last_modified_filter_seo_rule = strtotime($last_modified_filter_seo_rule); |
| 2174 |
$last_modified_filter_set = strtotime($last_modified_filter_set); |
| 2175 |
|
| 2176 |
if ($last_modified_filter_seo_rule > $wpc_xml_write_date || $last_modified_filter_set > $wpc_xml_write_date) { |
| 2177 |
return true; |
| 2178 |
} |
| 2179 |
if ($wpc_xml_write_date !== false && !flrt_has_filter_seo_rules()) { |
| 2180 |
return true; |
| 2181 |
} |
| 2182 |
return false; |
| 2183 |
} |
| 2184 |
} |
| 2185 |
|
| 2186 |
|
| 2187 |
if (!function_exists('flrt_post_type_underline_transform')) { |
| 2188 |
function flrt_post_type_underline_transform($post_type) |
| 2189 |
{ |
| 2190 |
if (mb_strpos($post_type, '-') !== false) { |
| 2191 |
return str_replace('-', '_', $post_type); |
| 2192 |
} |
| 2193 |
return $post_type; |
| 2194 |
} |
| 2195 |
} |
| 2196 |
|
| 2197 |
|
| 2198 |
if (!function_exists('flrt_generate_unique_copy_title')) { |
| 2199 |
|
| 2200 |
/** |
| 2201 |
* Generates a unique copy title in the format: |
| 2202 |
* "Base Title – {copy_text} {N}". |
| 2203 |
* |
| 2204 |
* @param string $original_title The original post title to derive the base title from. |
| 2205 |
* If it already ends with "– {copy_text} N", that suffix is stripped. |
| 2206 |
* @param string $post_type The WordPress post type within which to check for duplicate titles. |
| 2207 |
* By default expects the FLRT_FILTERS_SET_POST_TYPE constant. |
| 2208 |
* @param string $copy_text The suffix text for copies (e.g., 'copy', 'duplicate'). |
| 2209 |
* @param int $start_number Numbering threshold: |
| 2210 |
* - if 0 (default), the first copy gets number "1"; |
| 2211 |
* - if 1, the first copy has no number; numbering appears only when |
| 2212 |
* a "… – {copy_text} 1" already exists. |
| 2213 |
* |
| 2214 |
* @return string The generated unique copy title. |
| 2215 |
*/ |
| 2216 |
|
| 2217 |
function flrt_generate_unique_copy_title($original_title, $post_type = FLRT_FILTERS_SET_POST_TYPE, $copy_text = 'copy', $number_position = true) |
| 2218 |
{ |
| 2219 |
global $wpdb; |
| 2220 |
if ($number_position) { |
| 2221 |
$preg_match_pattern = '/^(.*) – ' . preg_quote($copy_text, '/') . ' \d+$/'; |
| 2222 |
} |
| 2223 |
|
| 2224 |
if (!$number_position) { |
| 2225 |
$preg_match_pattern = '/^(.*) \d+ – ' . preg_quote($copy_text, '/') . '$/'; |
| 2226 |
} |
| 2227 |
|
| 2228 |
if (preg_match($preg_match_pattern, $original_title, $matches)) { |
| 2229 |
$base_title = $matches[1]; |
| 2230 |
} else { |
| 2231 |
$base_title = $original_title; |
| 2232 |
} |
| 2233 |
|
| 2234 |
if ($number_position) { |
| 2235 |
$copy_pattern = $wpdb->esc_like($base_title) . ' – ' . $wpdb->esc_like($copy_text) . '%'; |
| 2236 |
$titles = $wpdb->get_col( |
| 2237 |
$wpdb->prepare( |
| 2238 |
"SELECT post_title FROM $wpdb->posts |
| 2239 |
WHERE (post_title = %s OR post_title LIKE %s) |
| 2240 |
AND post_type = %s", |
| 2241 |
$base_title, |
| 2242 |
$copy_pattern, |
| 2243 |
$post_type |
| 2244 |
) |
| 2245 |
); |
| 2246 |
} |
| 2247 |
if (!$number_position) { |
| 2248 |
$copy_pattern = $wpdb->esc_like($base_title) . ' % – ' . $wpdb->esc_like($copy_text); |
| 2249 |
$titles = $wpdb->get_col( |
| 2250 |
$wpdb->prepare( |
| 2251 |
"SELECT post_title FROM $wpdb->posts |
| 2252 |
WHERE post_title LIKE %s |
| 2253 |
AND post_type = %s", |
| 2254 |
$copy_pattern, |
| 2255 |
$post_type |
| 2256 |
) |
| 2257 |
); |
| 2258 |
} |
| 2259 |
|
| 2260 |
$max_copy_number = 0; |
| 2261 |
|
| 2262 |
if ($number_position) { |
| 2263 |
$preg_match_pattern_title = '/^' . preg_quote($base_title, '/') . ' – ' . preg_quote($copy_text, '/') . ' (\d+)$/'; |
| 2264 |
|
| 2265 |
} |
| 2266 |
if (!$number_position) { |
| 2267 |
$preg_match_pattern_title = '/^' . preg_quote($base_title, '/') . ' (\d+) – ' . preg_quote($copy_text, '/') . '$/'; |
| 2268 |
} |
| 2269 |
|
| 2270 |
foreach ($titles as $title) { |
| 2271 |
if (preg_match($preg_match_pattern_title, $title, $m)) { |
| 2272 |
if (isset($m[1]) && is_numeric($m[1])) { |
| 2273 |
$num = intval($m[1]); |
| 2274 |
if ($num > $max_copy_number) { |
| 2275 |
$max_copy_number = $num; |
| 2276 |
} |
| 2277 |
} |
| 2278 |
} |
| 2279 |
} |
| 2280 |
|
| 2281 |
$new_number = $max_copy_number + 1; |
| 2282 |
|
| 2283 |
if ($number_position) { |
| 2284 |
$text = $base_title . ' – ' . $copy_text . ' ' . $new_number; |
| 2285 |
} |
| 2286 |
if (!$number_position) { |
| 2287 |
$text = $base_title . ' ' . $new_number . ' – ' . $copy_text; |
| 2288 |
} |
| 2289 |
return $text; |
| 2290 |
} |
| 2291 |
} |
| 2292 |
|
| 2293 |
if (!function_exists('flrt_get_delete_set_transient')) { |
| 2294 |
function flrt_refresh_temp_transient($set_name, $data) |
| 2295 |
{ |
| 2296 |
if (get_transient($set_name) !== false) { |
| 2297 |
delete_transient($set_name); |
| 2298 |
} |
| 2299 |
set_transient($set_name, $data, 300); |
| 2300 |
} |
| 2301 |
} |
| 2302 |
|
| 2303 |
if (!function_exists('flrt_view_admin_error')) { |
| 2304 |
function flrt_view_admin_error($text) |
| 2305 |
{ |
| 2306 |
$error_str = '<div class="notice notice-error is-dismissible"><p>%s</p></div>'; |
| 2307 |
printf( |
| 2308 |
$error_str, |
| 2309 |
$text |
| 2310 |
); |
| 2311 |
} |
| 2312 |
} |
| 2313 |
if (!function_exists('flrt_export_setting_icon')) { |
| 2314 |
function flrt_export_setting_icon() |
| 2315 |
{ |
| 2316 |
return '<svg xmlns="http://www.w3.org/2000/svg" fill="#99a2b2" width="19px" height="19px" viewBox="0 0 24 20"><polyline id="primary" points="15 3 21 3 21 9" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/><line id="primary-2" data-name="primary" x1="11" y1="13" x2="21" y2="3" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/><path id="primary-3" data-name="primary" d="M21,13v7a1,1,0,0,1-1,1H4a1,1,0,0,1-1-1V4A1,1,0,0,1,4,3h7" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/></svg>'; |
| 2317 |
} |
| 2318 |
} |
| 2319 |
|
| 2320 |
if (!function_exists('flrt_import_setting_icon')) { |
| 2321 |
function flrt_import_setting_icon() |
| 2322 |
{ |
| 2323 |
return '<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" width="19px" height="19px" viewBox="0 0 24 23" id="wpc-import-icon"><polyline id="primary" points="17 13 11 13 11 7" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/><line id="primary-2" data-name="primary" x1="21" y1="3" x2="11" y2="13" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/><path id="primary-3" data-name="primary" d="M21,13v7a1,1,0,0,1-1,1H4a1,1,0,0,1-1-1V4A1,1,0,0,1,4,3h7" style="fill: none; stroke: rgb(153,162,178); stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"/></svg>'; |
| 2324 |
} |
| 2325 |
} |
| 2326 |
|
| 2327 |
if (!function_exists('flrt_open_in_new_tab_icon')) { |
| 2328 |
function flrt_open_in_new_tab_icon() |
| 2329 |
{ |
| 2330 |
$icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 21" width="18" height="18" aria-hidden="true" focusable="false"> |
| 2331 |
<path d="M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"></path></svg>'; |
| 2332 |
return wp_kses( |
| 2333 |
$icon, |
| 2334 |
array( |
| 2335 |
'svg' => array( |
| 2336 |
'xmlns' => true, |
| 2337 |
'viewbox' => true, |
| 2338 |
'width' => true, |
| 2339 |
'height' => true, |
| 2340 |
'aria-hidden' => true, |
| 2341 |
'focusable' => true, |
| 2342 |
), |
| 2343 |
'path' => array( |
| 2344 |
'd' => true |
| 2345 |
), |
| 2346 |
) |
| 2347 |
); |
| 2348 |
} |
| 2349 |
} |
| 2350 |
|
| 2351 |
if (!function_exists('flrt_vailable_in_pro_attr_link')) { |
| 2352 |
function flrt_vailable_in_pro_attr_link($target_blank = false): string |
| 2353 |
{ |
| 2354 |
$link = 'edit.php?post_type=' . FLRT_FILTERS_SET_POST_TYPE . '&page=flrt-pro'; |
| 2355 |
if ($target_blank) { |
| 2356 |
$link .= '_target=blank'; |
| 2357 |
} |
| 2358 |
return $link; |
| 2359 |
} |
| 2360 |
} |
| 2361 |
if (!function_exists('flrt_pro_promo_label')) { |
| 2362 |
function flrt_pro_promo_label($replace_class = false): string |
| 2363 |
{ |
| 2364 |
$class = $replace_class ? 'wpc-pro-badge' : 'wpc-pro-badge-transparent'; |
| 2365 |
$label = ' <span class="' . $class . '">' . esc_html__('PRO', 'filter-everything') . '</span>'; |
| 2366 |
|
| 2367 |
return wp_kses($label, [ |
| 2368 |
'span' => [ |
| 2369 |
'class' => [] |
| 2370 |
] |
| 2371 |
]); |
| 2372 |
} |
| 2373 |
} |
| 2374 |
|
| 2375 |
if(!function_exists( 'flrt_unlock_icon')){ |
| 2376 |
function flrt_unlock_icon($width = '20px', $height = '20px', $color = '#3858E9') |
| 2377 |
{ |
| 2378 |
return '<svg xmlns="http://www.w3.org/2000/svg" height="' . $height . '" viewBox="0 -960 960 960" width="' . $width . '" fill="' . $color . '"><path d="M264-624h336v-96q0-50-35-85t-85-35q-50 0-85 35t-35 85h-72q0-80 56.23-136 56.22-56 136-56Q560-912 616-855.84q56 56.16 56 135.84v96h24q29.7 0 50.85 21.15Q768-581.7 768-552v384q0 29.7-21.16 50.85Q725.68-96 695.96-96H263.72Q234-96 213-117.15T192-168v-384q0-29.7 21.15-50.85Q234.3-624 264-624Zm0 456h432v-384H264v384Zm216.21-120Q510-288 531-309.21t21-51Q552-390 530.79-411t-51-21Q450-432 429-410.79t-21 51Q408-330 429.21-309t51 21ZM264-168v-384 384Z"/></svg>'; |
| 2379 |
} |
| 2380 |
} |
| 2381 |
|
| 2382 |
if(!function_exists( 'flrt_crown_icon')){ |
| 2383 |
function flrt_crown_icon($width = '16px', $height = '16px', $color = '#FFFFFF') |
| 2384 |
{ |
| 2385 |
return '<svg xmlns="http://www.w3.org/2000/svg" fill="' . $color . '" viewBox="0 0 16 16" width="' . $width . '" height="' . $height . '" class="wpc-crown-icon"><path fill="' . $color . '" d="M8.687 1.932c-.238-.634-1.136-.634-1.374 0l-1.642 4.38-3.167-2.11a.733.733 0 0 0-1.126.753L3.333 12h9.334l1.955-7.045a.733.733 0 0 0-1.126-.754L10.33 6.313zM6.654 7.49 8 3.899l1.346 3.59c.166.442.7.614 1.094.352l2.59-1.727-1.363 4.553H4.333L2.97 6.114 5.56 7.841a.733.733 0 0 0 1.094-.352m6.013 5.844H3.333v1.334h9.334z"></path></svg>'; |
| 2386 |
} |
| 2387 |
} |
| 2388 |
|
| 2389 |
if(!function_exists( 'flrt_unlock_in_pro')){ |
| 2390 |
function flrt_unlock_in_pro($button_text = '') |
| 2391 |
{ |
| 2392 |
$string = '<a class="wpc-available-in-pro-button" href="' . admin_url(flrt_vailable_in_pro_attr_link()) . '">'; |
| 2393 |
$string .= !empty($button_text) ? $button_text . ' - ': ''; |
| 2394 |
$string .= flrt_unlock_icon(); |
| 2395 |
$string .= '<span>' . esc_html__('Unlock with PRO', 'filter-everything') . '</span></a>'; |
| 2396 |
return $string; |
| 2397 |
} |
| 2398 |
} |
| 2399 |
|
| 2400 |
|
| 2401 |
add_filter('wpc_filter_default_fields', 'flrt_add_pro_promo_fields', 10, 2); |
| 2402 |
function flrt_add_pro_promo_fields($defaultFields, $filterFields) |
| 2403 |
{ |
| 2404 |
|
| 2405 |
if (!defined('FLRT_FILTERS_PRO')) { |
| 2406 |
if (flrt_is_woocommerce()) { |
| 2407 |
$updatedFields = []; |
| 2408 |
foreach ($defaultFields as $key => $field) { |
| 2409 |
$updatedFields[$key] = $field; |
| 2410 |
|
| 2411 |
if ($key === 'hierarchy') { |
| 2412 |
$updatedFields['used_for_variations'] = array( |
| 2413 |
'type' => 'inProButton', |
| 2414 |
'pro_label' => flrt_pro_promo_label(), |
| 2415 |
'label' => esc_html__('Use for Variations', 'filter-everything'), |
| 2416 |
'class' => 'wpc-field-for-variations', |
| 2417 |
'default' => 'no', |
| 2418 |
'instructions' => esc_html__('If checked, filtering will take into account variations with this attribute or meta key', 'filter-everything'), |
| 2419 |
); |
| 2420 |
} |
| 2421 |
} |
| 2422 |
return $updatedFields; |
| 2423 |
} |
| 2424 |
} |
| 2425 |
|
| 2426 |
return $defaultFields; |
| 2427 |
|
| 2428 |
} |
| 2429 |
|
| 2430 |
function flrt_pro_features_link() |
| 2431 |
{ |
| 2432 |
return 'https://filtereverything.pro/?utm_source=free_plugin&utm_medium=internal&utm_campaign=free_plugin_upgrade&utm_content=popup_features_lnk#why-choose-pro'; |
| 2433 |
} |
| 2434 |
|
| 2435 |
function flrt_unlock_pro_link( $utm_content = '' ) |
| 2436 |
{ |
| 2437 |
return 'https://filtereverything.pro/pricing/?utm_source=free_plugin&utm_medium=internal&utm_campaign=free_plugin_upgrade&utm_content=' . $utm_content; |
| 2438 |
} |
| 2439 |
|
| 2440 |
/** |
| 2441 |
* Link to the refund policy. Currently a FAQ anchor on the main landing page; |
| 2442 |
* will point to a dedicated refund-policy page once that exists. |
| 2443 |
*/ |
| 2444 |
function flrt_refund_policy_link() |
| 2445 |
{ |
| 2446 |
return 'https://filtereverything.pro/#refund-policy'; |
| 2447 |
} |
| 2448 |
|
| 2449 |
|
| 2450 |
function wpc_clear_folder($directory) |
| 2451 |
{ |
| 2452 |
|
| 2453 |
if (!is_dir($directory)) { |
| 2454 |
return false; |
| 2455 |
} |
| 2456 |
|
| 2457 |
$files = glob(rtrim($directory, '/\\') . DIRECTORY_SEPARATOR . '*'); |
| 2458 |
|
| 2459 |
if(!empty($files)){ |
| 2460 |
foreach ($files as $file) { |
| 2461 |
if (is_file($file)) { |
| 2462 |
unlink($file); |
| 2463 |
} |
| 2464 |
} |
| 2465 |
} |
| 2466 |
} |
| 2467 |
|
| 2468 |
function flrt_diamond_icon($svg_fill = "var(--wpc-pro-color, #3858E9)") |
| 2469 |
{ |
| 2470 |
return '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="' . $svg_fill. '" version="1.1" id="Layer_1" width="16px" height="16px" viewBox="0 0 70 70" enable-background="new 0 0 70 70" xml:space="preserve"> |
| 2471 |
<g> |
| 2472 |
<path d="M67.142,23.641L55.405,10.456c-0.379-0.423-0.92-0.873-1.488-0.873h-37.98c-0.568,0-1.109,0.45-1.489,0.874L2.711,23.752 c-0.691,0.771-0.68,1.94,0.025,2.697L33.462,59.46c0.378,0.407,0.909,0.638,1.464,0.638s1.086-0.257,1.464-0.664l30.728-33.042 C67.822,25.634,67.833,24.411,67.142,23.641z M46.555,25.583L34.902,53.414L22.608,25.583H46.555z M21.725,23.583l-4.417-10h34.272 l-4.188,10H21.725z M32.231,52.152L7.586,25.583h12.879L32.231,52.152z M48.702,25.583H62c0.094,0,0.179-0.029,0.265-0.054 L37.462,52.318L48.702,25.583z M61.871,23.583H49.543l3.971-9.447L61.871,23.583z M15.714,14.851l3.867,8.732H8.027L15.714,14.851z "/> |
| 2473 |
<path d="M35,14.583H23c-0.552,0-1,0.447-1,1s0.448,1,1,1h12c0.552,0,1-0.447,1-1S35.552,14.583,35,14.583z"/> |
| 2474 |
<path d="M45,14.583h-5c-0.552,0-1,0.447-1,1s0.448,1,1,1h5c0.552,0,1-0.447,1-1S45.552,14.583,45,14.583z"/> |
| 2475 |
</g> |
| 2476 |
</svg>'; |
| 2477 |
} |
| 2478 |
|
| 2479 |
|
| 2480 |
add_action('wp_footer', function () { |
| 2481 |
if (current_user_can(flrt_plugin_user_caps())) |
| 2482 |
if (!wp_script_is('wpc-filter-everything')) { |
| 2483 |
{ |
| 2484 |
?> |
| 2485 |
<script> |
| 2486 |
jQuery(function ($) { |
| 2487 |
$(document).on('click', '.wpc-open-close-filters-button', function (e) { |
| 2488 |
e.preventDefault(); |
| 2489 |
let openCloseButton = $(this); |
| 2490 |
let wpcButtonFilterSetError = openCloseButton.data('wpcButtonFilterSetError'); |
| 2491 |
let wpcButtonWidgetError = openCloseButton.data('wpcButtonWidgetError'); |
| 2492 |
|
| 2493 |
if (typeof wpcButtonFilterSetError !== 'undefined') { |
| 2494 |
alert(wpcButtonFilterSetError); |
| 2495 |
} |
| 2496 |
if (typeof wpcButtonWidgetError !== 'undefined') { |
| 2497 |
if (typeof window.wpcFilterWidgetActive === 'undefined') { |
| 2498 |
alert(wpcButtonWidgetError); |
| 2499 |
} |
| 2500 |
} |
| 2501 |
}); |
| 2502 |
}); |
| 2503 |
</script> |
| 2504 |
<?php |
| 2505 |
} |
| 2506 |
} |
| 2507 |
}); |
| 2508 |
|
| 2509 |
function flrt_log( $message, $data = null ) { |
| 2510 |
if ( ! defined('WP_DEBUG_LOG') || ! WP_DEBUG_LOG ) { |
| 2511 |
return; |
| 2512 |
} |
| 2513 |
|
| 2514 |
$log = '[Filter Everything] ' . $message; |
| 2515 |
|
| 2516 |
if ( $data !== null ) { |
| 2517 |
$log .= ' | ' . wp_json_encode( $data ); |
| 2518 |
} |
| 2519 |
|
| 2520 |
error_log( $log ); |
| 2521 |
} |
| 2522 |
|
| 2523 |
function prepare_wpc_filter_set_json_data($postData) |
| 2524 |
{ |
| 2525 |
if(!empty($postData['wpc_filter_set_json_data'])){ |
| 2526 |
$postData = json_decode(stripslashes($postData['wpc_filter_set_json_data']), true); |
| 2527 |
$postData['wpc_set_fields']['wp_filter_query_vars'] = wp_slash($postData['wpc_set_fields']['wp_filter_query_vars']); |
| 2528 |
} |
| 2529 |
return $postData; |
| 2530 |
} |
| 2531 |
|
| 2532 |
function flrt_rating_slugs() |
| 2533 |
{ |
| 2534 |
return array( |
| 2535 |
'rated-1' => 1, |
| 2536 |
'rated-2' => 2, |
| 2537 |
'rated-3' => 3, |
| 2538 |
'rated-4' => 4, |
| 2539 |
'rated-5' => 5 |
| 2540 |
); |
| 2541 |
} |
| 2542 |
|
| 2543 |
/** |
| 2544 |
* Whether Apply button Sets recalculate counters instantly in the browser |
| 2545 |
* (the 1.9.3 client-side recount) instead of the legacy per-click AJAX |
| 2546 |
* request. Disabled by default, so existing Apply button users keep the |
| 2547 |
* pre-1.9.3 behaviour after the update until they opt in. |
| 2548 |
* |
| 2549 |
* The option is PRO-only: in the free version the preserved DB value stays |
| 2550 |
* inert and Apply button Sets always use the legacy AJAX recount. The whole |
| 2551 |
* client-side engine works in free too — this gate is the only thing to |
| 2552 |
* relax if instant recount ever ships in the free version. |
| 2553 |
*/ |
| 2554 |
function flrt_instant_recount() |
| 2555 |
{ |
| 2556 |
return defined('FLRT_FILTERS_PRO') && flrt_get_option('apply_button_instant_recount') === 'on'; |
| 2557 |
} |
| 2558 |
|
| 2559 |
function flrt_check_apply_buttom_mode($set) |
| 2560 |
{ |
| 2561 |
return ((isset($set['use_apply_button']['value']) && $set['use_apply_button']['value'] === 'yes') && flrt_instant_recount()); |
| 2562 |
} |
| 2563 |
|
| 2564 |
|
| 2565 |
function flrt_parent_filter_apply_button_data($filter, $args = []) |
| 2566 |
{ |
| 2567 |
$data = ''; |
| 2568 |
if($args['use_apply_button'] && (int) $filter['parent_filter'] > 0){ |
| 2569 |
$hide_until_parent = 0; |
| 2570 |
if($filter['hide_until_parent'] === 'yes'){ |
| 2571 |
$hide_until_parent = 1; |
| 2572 |
} |
| 2573 |
$data .= ' data-parent-filter-id="' . esc_attr($filter['parent_filter']) . '" data-hide-until-parent="' . esc_attr($hide_until_parent) .'"'; |
| 2574 |
} |
| 2575 |
return $data; |
| 2576 |
} |
| 2577 |
|
| 2578 |
function flrt_parent_filter_apply_class($filter, $args = [], $terms = []) |
| 2579 |
{ |
| 2580 |
$css_class = ''; |
| 2581 |
// '-1', the legacy 'no' placeholder and anything non-numeric all mean "no parent" |
| 2582 |
if( (int) $filter['parent_filter'] <= 0 ){ |
| 2583 |
return $css_class; |
| 2584 |
} |
| 2585 |
|
| 2586 |
$checked = false; |
| 2587 |
|
| 2588 |
$css_class = ' ' . esc_attr('wpc-has-parent-filter'); |
| 2589 |
|
| 2590 |
$is_parent_has_terms = false; |
| 2591 |
if(!empty($terms)){ |
| 2592 |
foreach ($terms as $term){ |
| 2593 |
if(isset($term->show_with_parent)){ |
| 2594 |
$is_parent_has_terms = true; |
| 2595 |
} |
| 2596 |
if( in_array( $term->slug, $filter['values'] ) ){ |
| 2597 |
$checked = true; |
| 2598 |
} |
| 2599 |
if($is_parent_has_terms && $checked){ |
| 2600 |
break; |
| 2601 |
} |
| 2602 |
} |
| 2603 |
} |
| 2604 |
|
| 2605 |
|
| 2606 |
if($args['use_apply_button'] && $is_parent_has_terms === false){ |
| 2607 |
$css_class .= ' ' . esc_attr('wpc-parent-filter-terms-unselected'); |
| 2608 |
} |
| 2609 |
|
| 2610 |
if($args['use_apply_button'] && $is_parent_has_terms === false && $checked){ |
| 2611 |
$css_class .= ' ' . esc_attr('wpc-child-selected-no-parent'); |
| 2612 |
} |
| 2613 |
|
| 2614 |
if($args['use_apply_button'] && $is_parent_has_terms === true){ |
| 2615 |
$css_class .= ' ' . esc_attr('wpc-parent-filter-terms-selected'); |
| 2616 |
} |
| 2617 |
|
| 2618 |
if(empty($filter['hide_until_parent']) || $filter['hide_until_parent'] !== 'yes'){ |
| 2619 |
return $css_class; |
| 2620 |
} |
| 2621 |
|
| 2622 |
if($args['use_apply_button'] && !empty($filter['hide_until_parent']) && $filter['hide_until_parent'] === 'yes' && $is_parent_has_terms === false){ |
| 2623 |
$css_class .= ' ' . esc_attr('wpc-hide-terms-until-parent-unselected'); |
| 2624 |
} |
| 2625 |
|
| 2626 |
return $css_class; |
| 2627 |
} |
| 2628 |
|
| 2629 |
function flrtIsMoreLess($filter) |
| 2630 |
{ |
| 2631 |
return (!empty($filter['more_less']) && $filter['more_less'] === 'yes') ? true : false; |
| 2632 |
} |
| 2633 |
|
| 2634 |
function flrtParentFilter($filter) |
| 2635 |
{ |
| 2636 |
// Positive filter ID only. '-1' means no parent, and single-filter sets used |
| 2637 |
// to save the 'no' select placeholder — on PHP 8 the string comparison |
| 2638 |
// 'no' > 0 is true, so a plain numeric check would treat it as a parent |
| 2639 |
return !empty($filter['parent_filter']) && (int) $filter['parent_filter'] > 0; |
| 2640 |
} |
| 2641 |
|
| 2642 |
function flrt_get_filtered_term_url( $term, $filter, $url_manager ) { |
| 2643 |
$exclude_from_url = []; |
| 2644 |
|
| 2645 |
if ( ! empty( $filter['has_child_filter'] ) ) { |
| 2646 |
if ( $filter['has_child_filter'] === true && count( $filter['values'] ) === 1 ) { |
| 2647 |
if ( $term->slug === $filter['values'][0] ) { |
| 2648 |
foreach ( $filter['child_values'] as $child_value ) { |
| 2649 |
$exclude_from_url[ $child_value ] = true; |
| 2650 |
} |
| 2651 |
} |
| 2652 |
} |
| 2653 |
} |
| 2654 |
|
| 2655 |
return $url_manager->getTermUrl( |
| 2656 |
$term->slug, |
| 2657 |
$filter['e_name'], |
| 2658 |
$filter['entity'], |
| 2659 |
'', |
| 2660 |
$exclude_from_url |
| 2661 |
); |
| 2662 |
} |
| 2663 |
function flrtDetectTimeComponents(string $format): array |
| 2664 |
{ |
| 2665 |
$hasHours = false; |
| 2666 |
$hasMinutes = false; |
| 2667 |
$hasSeconds = false; |
| 2668 |
|
| 2669 |
$len = strlen($format); |
| 2670 |
for ($i = 0; $i < $len; $i++) { |
| 2671 |
$char = $format[$i]; |
| 2672 |
|
| 2673 |
if ($char === '\\') { |
| 2674 |
$i++; |
| 2675 |
continue; |
| 2676 |
} |
| 2677 |
|
| 2678 |
if (in_array($char, ['g', 'G', 'h', 'H'], true)) { |
| 2679 |
$hasHours = true; |
| 2680 |
} elseif ($char === 'i') { |
| 2681 |
$hasMinutes = true; |
| 2682 |
} elseif ($char === 's') { |
| 2683 |
$hasSeconds = true; |
| 2684 |
} |
| 2685 |
} |
| 2686 |
|
| 2687 |
return [ |
| 2688 |
'hours' => $hasHours, |
| 2689 |
'minutes' => $hasMinutes, |
| 2690 |
'seconds' => $hasSeconds, |
| 2691 |
]; |
| 2692 |
} |
| 2693 |
|
| 2694 |
function flrtBuildDateTimeString(string $value, string $format): ?string |
| 2695 |
{ |
| 2696 |
$date = DateTime::createFromFormat($format, $value); |
| 2697 |
if ($date === false) { |
| 2698 |
return null; |
| 2699 |
} |
| 2700 |
|
| 2701 |
$components = flrtDetectTimeComponents($format); |
| 2702 |
|
| 2703 |
$hours = $components['hours'] ? $date->format('H') : '00'; |
| 2704 |
$minutes = $components['minutes'] ? $date->format('i') : '00'; |
| 2705 |
$seconds = $components['seconds'] ? $date->format('s') : '00'; |
| 2706 |
|
| 2707 |
return $date->format('Y-m-d') . " {$hours}:{$minutes}:{$seconds}"; |
| 2708 |
} |
| 2709 |
|