PluginProbe
Polylang / 3.3
Polylang v3.3
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
← All changes | include/query.php +94 -16 2.93.3 View file →
@@ -9,14 +9,24 @@
9 9 * @since 2.2
10 10 */
11 11 class PLL_Query {
12 12 /**
13 + * @var PLL_Model
14 + */
15 + public $model;
16 +
17 + /**
18 + * @var WP_Query
19 + */
20 + public $query;
21 +
22 + /**
13 23 * Constructor
14 24 *
15 25 * @since 2.2
16 26 *
17 - * @param array $query Reference to the WP_Query object
18 - * @param object $model
27 + * @param WP_Query $query Reference to the WP_Query object.
28 + * @param PLL_Model $model Instance of PLL_Model.
19 29 */
20 30 public function __construct( &$query, &$model ) {
21 31 $this->query = &$query;
22 32 $this->model = &$model;
@@ -22,8 +32,32 @@
22 32 $this->model = &$model;
23 33 }
24 34
25 35 /**
36 + * Checks if the query already includes a language taxonomy.
37 + *
38 + * @since 3.0
39 + *
40 + * @param array $qvars WP_Query query vars.
41 + * @return bool
42 + */
43 + protected function is_already_filtered( $qvars ) {
44 + if ( isset( $qvars['lang'] ) ) {
45 + return true;
46 + }
47 +
48 + if ( ! empty( $qvars['tax_query'] ) && is_array( $qvars['tax_query'] ) ) {
49 + foreach ( $qvars['tax_query'] as $tax_query ) {
50 + if ( isset( $tax_query['taxonomy'] ) && 'language' === $tax_query['taxonomy'] ) {
51 + return true;
52 + }
53 + }
54 + }
55 +
56 + return false;
57 + }
58 +
59 + /**
26 60 * Check if translated taxonomy is queried
27 61 * Compatible with nested queries introduced in WP 4.1
28 62 *
29 63 * @see https://wordpress.org/support/topic/tax_query-bug
@@ -57,25 +91,32 @@
57 91 *
58 92 * @return array queried taxonomies
59 93 */
60 94 public function get_queried_taxonomies() {
61 - return isset( $this->query->tax_query->queried_terms ) ? array_keys( wp_list_filter( $this->query->tax_query->queried_terms, array( 'operator' => 'NOT IN' ), 'NOT' ) ) : array();
95 + return ! empty( $this->query->tax_query->queried_terms ) ? array_keys( wp_list_filter( $this->query->tax_query->queried_terms, array( 'operator' => 'NOT IN' ), 'NOT' ) ) : array();
62 96 }
63 97
64 98 /**
65 - * Sets the language in query
66 - * Optimized for ( needs ) WP 3.5+
99 + * Sets the language in query.
100 + * Optimized for (and requires) WP 3.5+.
67 101 *
68 102 * @since 2.2
103 + * @since 3.3 Accepts now an array of languages.
69 104 *
70 - * @param object $lang
105 + * @param PLL_Language|PLL_Language[] $languages Language object(s).
106 + * @return void
71 107 */
72 - public function set_language( $lang ) {
73 - // Defining directly the tax_query ( rather than setting 'lang' avoids transforming the query by WP )
108 + public function set_language( $languages ) {
109 + if ( ! is_array( $languages ) ) {
110 + $languages = array( $languages );
111 + }
112 + $tt_ids = wp_list_pluck( $languages, 'term_taxonomy_id' );
113 +
114 + // Defining directly the tax_query (rather than setting 'lang' avoids transforming the query by WP).
74 115 $lang_query = array(
75 116 'taxonomy' => 'language',
76 117 'field' => 'term_taxonomy_id', // Since WP 3.5
77 - 'terms' => $lang->term_taxonomy_id,
118 + 'terms' => $tt_ids,
78 119 'operator' => 'IN',
79 120 );
80 121
81 122 $tax_query = &$this->query->query_vars['tax_query'];
@@ -82,9 +123,9 @@
82 123
83 124 if ( isset( $tax_query['relation'] ) && 'OR' === $tax_query['relation'] ) {
84 125 $tax_query = array(
85 126 $lang_query,
86 - array( $tax_query ),
127 + $tax_query,
87 128 'relation' => 'AND',
88 129 );
89 130 } elseif ( is_array( $tax_query ) ) {
90 131 // The tax query is expected to be *always* an array, but it seems that 3rd parties fill it with a string
@@ -97,23 +138,24 @@
97 138 }
98 139 }
99 140
100 141 /**
101 - * Add the language in query after it has checked that it won't conflict with other query vars
142 + * Adds the language in the query after it has checked that it won't conflict with other query vars.
102 143 *
103 144 * @since 2.2
104 145 *
105 - * @param object $lang Language
146 + * @param PLL_Language|false $lang Language.
147 + * @return void
106 148 */
107 149 public function filter_query( $lang ) {
108 150 $qvars = &$this->query->query_vars;
109 151
110 - if ( ! isset( $qvars['lang'] ) ) {
152 + if ( ! $this->is_already_filtered( $qvars ) ) {
111 153 $taxonomies = array_intersect( $this->model->get_translated_taxonomies(), get_taxonomies( array( '_builtin' => false ) ) );
112 154
113 155 foreach ( $taxonomies as $tax ) {
114 - $tax = get_taxonomy( $tax );
115 - if ( ! empty( $qvars[ $tax->query_var ] ) ) {
156 + $tax_object = get_taxonomy( $tax );
157 + if ( ! empty( $tax_object ) && ! empty( $qvars[ $tax_object->query_var ] ) ) {
116 158 return;
117 159 }
118 160 }
119 161
@@ -127,9 +169,9 @@
127 169
128 170 if ( $taxonomies && ( empty( $qvars['post_type'] ) || 'any' === $qvars['post_type'] ) ) {
129 171 foreach ( $taxonomies as $taxonomy ) {
130 172 $tax_object = get_taxonomy( $taxonomy );
131 - if ( $this->model->is_translated_post_type( $tax_object->object_type ) ) {
173 + if ( ! empty( $tax_object ) && $this->model->is_translated_post_type( $tax_object->object_type ) ) {
132 174 $this->set_language( $lang );
133 175 break;
134 176 }
135 177 }
@@ -137,8 +179,10 @@
137 179 $this->set_language( $lang );
138 180 }
139 181 }
140 182 } else {
183 + $this->maybe_set_language_for_or_relation();
184 +
141 185 // Do not filter untranslatable post types such as nav_menu_item
142 186 if ( isset( $qvars['post_type'] ) && ! $this->model->is_translated_post_type( $qvars['post_type'] ) && ( empty( $qvars['tax_query'] ) || ! $this->have_translated_taxonomy( $qvars['tax_query'] ) ) ) {
143 187 unset( $qvars['lang'] );
144 188 }
@@ -146,7 +190,41 @@
146 190 // Unset 'all' query var (mainly for admin language filter).
147 191 if ( isset( $qvars['lang'] ) && 'all' === $qvars['lang'] ) {
148 192 unset( $qvars['lang'] );
149 193 }
194 + }
195 + }
196 +
197 + /**
198 + * Sets the language correctly if the current query is a 'OR' relation,
199 + * since WordPress merges the language with the other query vars when the relation is OR.
200 + *
201 + * @since 3.3
202 + *
203 + * @return void
204 + */
205 + protected function maybe_set_language_for_or_relation() {
206 + if ( ! $this->query->tax_query instanceof WP_Tax_Query ) {
207 + return;
208 + }
209 +
210 + if ( 'OR' !== $this->query->tax_query->relation ) {
211 + return;
212 + }
213 +
214 + if ( ! isset( $this->query->tax_query->queried_terms['language'] ) ) {
215 + return;
216 + }
217 +
218 + $langs = $this->query->tax_query->queried_terms['language']['terms'];
219 + if ( is_string( $langs ) ) {
220 + $langs = explode( ',', $langs );
221 + }
222 + $langs = array_map( array( $this->model, 'get_language' ), $langs );
223 + $langs = array_filter( $langs );
224 +
225 + if ( ! empty( $langs ) ) {
226 + $this->set_language( $langs );
227 + unset( $this->query->query_vars['lang'] ); // Unset the language query var otherwise WordPress would add the language query by slug in WP_Query::parse_tax_query().
150 228 }
151 229 }
152 230 }