y_vars(); $config['loopFilter'] = [ 'mainQueryPostType' => $current_query_vars['post_type'] ?? 'post', 'nonce' => wp_create_nonce( 'wp_rest' ), ]; return $config; } private function get_current_query_vars() { $current_query_vars = $GLOBALS['wp_query']->query_vars; /** * Current query variables. * * Filters the query variables for the current query. This hook allows * developers to alter those variables. * * @param array $current_query_vars Current query variables. */ return apply_filters( 'elementor/query/get_query_args/current_query', $current_query_vars ); } private function parse_query_string( $param_key ) { // Check if the query param is a filter. match a regex for `e-filter-14f9e1d-post_tag` where `14f9e1d` is the widget ID and must be 7 characters long and have only letters and numbers, then followed by a string that can only have letters, numbers, dashes and underscores. if ( ! preg_match( '/^e-filter-[a-z0-9]{7}-[a-z0-9_\-]+$/', $param_key ) ) { return []; } // Remove the 'filter_' prefix from the query param $filter = str_replace( 'e-filter-', '', $param_key ); // Split the filter into an array of widget ID and filter type $filter = explode( '-', $filter ); if ( count( $filter ) !== 2 ) { return []; } // Get the widget ID $widget_id = $filter[0]; // Get the taxonomy $taxonomy = $filter[1]; return [ 'taxonomy' => $taxonomy, 'widget_id' => $widget_id, ]; } private function maybe_populate_filters_from_query_string() { if ( ! isset( $_SERVER['QUERY_STRING'] ) ) { return; } $query_params = []; wp_parse_str( htmlspecialchars_decode( Utils::_unstable_get_super_global_value( $_SERVER, 'QUERY_STRING' ) ), $query_params ); foreach ( $query_params as $param_key => $param_value ) { // TODO: This part is not generic - it only supports taxonomy filters. It should be refactored to allow for multiple types of filters. $parsed_query_string = $this->parse_query_string( $param_key ); if ( empty( $parsed_query_string ) || empty( $parsed_query_string['taxonomy'] ) || empty( $parsed_query_string['widget_id'] ) ) { continue; } $terms = $this->get_terms_array_from_params( $param_value ); $logical_join = $this->get_logical_join_from_params( $param_value ); if ( empty( $terms ) ) { continue; } $filter_data = [ 'taxonomy' => [ $parsed_query_string['taxonomy'] => [ 'terms' => $terms, 'logicalJoin' => $logical_join, ], ], ]; $this->register_widget_filter( $parsed_query_string['widget_id'], $filter_data ); } } private function get_seperator_from_params( $param_value ) { $separator = $this->query['AND']['separator']['from-browser']; // The web browser automatically replaces the plus sign with a space character before sending the data to the server. if ( strstr( $param_value, $this->query['OR']['separator']['from-browser'] ) ) { $separator = $this->query['OR']['separator']['from-browser']; $this->operator = $this->query['OR']['operator']; } return $separator; } private function get_terms_array_from_params( $param_value ) { $separator = $this->get_seperator_from_params( $param_value ); return explode( $separator, $param_value ); } private function get_logical_join_from_params( $param_value ) { $separator = $this->get_seperator_from_params( $param_value ); foreach ( $this->query as $index => $data ) { if ( $data['separator']['decoded'] === $separator ) { return $index; // Return the index when the decoded separator is found } } return 'AND'; // Default logical join } /** * @return array */ public function get_query_string_filters() { return $this->filters; } public function remove_rest_route_parameter( $link ) { return remove_query_arg( 'rest_route', $link ); } /** * @return boolean */ public function is_term_not_selected_for_inclusion( $loop_widget_settings, $term, $skin ) { return ! empty( $loop_widget_settings[ $skin . '_query_include' ] ) && in_array( 'terms', $loop_widget_settings[ $skin . '_query_include' ] ) && isset( $loop_widget_settings[ $skin . '_query_include_term_ids' ] ) && ! in_array( $term->term_id, $loop_widget_settings[ $skin . '_query_include_term_ids' ] ); } /** * @return boolean */ public function is_term_selected_for_exclusion( $loop_widget_settings, $term, $skin ) { return ! empty( $loop_widget_settings[ $skin . '_query_exclude' ] ) && in_array( 'terms', $loop_widget_settings[ $skin . '_query_exclude' ] ) && isset( $loop_widget_settings[ $skin . '_query_exclude_term_ids' ] ) && in_array( $term->term_id, $loop_widget_settings[ $skin . '_query_exclude_term_ids' ] ); } /** * @return boolean */ public function should_exclude_term_by_manual_selection( $loop_widget_settings, $term, $user_selected_taxonomy, $skin ) { if ( ! $this->loop_widget_has_manual_selection( $loop_widget_settings, $skin ) ) { return false; } $terms_to_exclude_by_manual_selection = $this->get_terms_to_exclude_by_manual_selection( $loop_widget_settings[ $skin . '_query_exclude_ids' ] ?? [], $user_selected_taxonomy ); if ( in_array( $term->term_id, $terms_to_exclude_by_manual_selection ) ) { return true; } return false; } /** * @return boolean */ private function loop_widget_has_manual_selection( $loop_widget_settings, $skin ) { return ! empty( $loop_widget_settings[ $skin . '_query_exclude' ] ) && in_array( 'manual_selection', $loop_widget_settings[ $skin . '_query_exclude' ] ) && ! empty( $loop_widget_settings[ $skin . '_query_exclude_ids' ] ); } /** * @return array */ private function get_terms_to_exclude_by_manual_selection( $selected_posts, $user_selected_taxonomy ) { $terms_to_exclude = []; $term_exclude_counts = []; $term_actual_counts = []; foreach ( $selected_posts as $post_id ) { $this->calculate_post_terms_counts( $post_id, $user_selected_taxonomy, $term_exclude_counts, $term_actual_counts ); } foreach ( $term_exclude_counts as $term_id => $selected_count ) { $this->maybe_add_term_to_exclusion( $term_id, $selected_count, $term_actual_counts, $terms_to_exclude ); } return $terms_to_exclude; } /** * @return void */ private function calculate_post_terms_counts( $post_id, $user_selected_taxonomy, &$term_exclude_counts, &$term_actual_counts ) { $post_terms = wp_get_post_terms( $post_id, $user_selected_taxonomy ); foreach ( $post_terms as $term ) { $this->calculate_term_counts( $term, $term_exclude_counts, $term_actual_counts ); } } /** * @return void */ private function calculate_term_counts( $term, &$term_exclude_counts, &$term_actual_counts ) { if ( empty( $term_exclude_counts[ $term->term_id ] ) ) { $term_exclude_counts[ $term->term_id ] = 0; } $term_exclude_counts[ $term->term_id ] = (int) $term_exclude_counts[ $term->term_id ] + 1; $term_actual_counts[ $term->term_id ] = (int) $term->count; } /** * @return void */ private function maybe_add_term_to_exclusion( $term_id, $selected_count, $term_actual_counts, &$terms_to_exclude ) { $user_selected_all_the_posts_for_this_term = $selected_count >= $term_actual_counts[ $term_id ]; if ( $user_selected_all_the_posts_for_this_term ) { $terms_to_exclude[] = $term_id; } } public function __construct() { parent::__construct(); $this->query = Query_Constants::DATA; if ( ! empty( $_SERVER['QUERY_STRING'] ) ) { $this->maybe_populate_filters_from_query_string(); } // Register the controller. new Controller(); add_filter( 'elementor/query/query_args', [ $this, 'filter_loop_query' ], 10, 2 ); add_filter( 'elementor_pro/editor/localize_settings', [ $this, 'add_localize_data' ] ); add_filter( 'paginate_links', [ $this, 'remove_rest_route_parameter' ] ); add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_styles' ] ); } }
Fatal error: Uncaught Error: Class "\ElementorPro\Modules\LoopFilter\Module" not found in /htdocs/wp-content/plugins/elementor-pro/core/modules-manager.php:87 Stack trace: #0 /htdocs/wp-content/plugins/elementor-pro/plugin.php(366): ElementorPro\Core\Modules_Manager->__construct() #1 /htdocs/wp-includes/class-wp-hook.php(324): ElementorPro\Plugin->on_elementor_init('') #2 /htdocs/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #3 /htdocs/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #4 /htdocs/wp-content/plugins/elementor/includes/plugin.php(685): do_action('elementor/init') #5 /htdocs/wp-includes/class-wp-hook.php(324): Elementor\Plugin->init('') #6 /htdocs/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #7 /htdocs/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #8 /htdocs/wp-settings.php(700): do_action('init') #9 /htdocs/wp-config.php(95): require_once('/htdocs/wp-sett...') #10 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #11 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #12 /htdocs/index.php(17): require('/htdocs/wp-blog...') #13 {main} thrown in /htdocs/wp-content/plugins/elementor-pro/core/modules-manager.php on line 87