run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄class-wp-meta-query.php
1<?php
2/**
3 * Meta API: WP_Meta_Query class
4 *
5 * @package WordPress
6 * @subpackage Meta
7 * @since 4.4.0
8 */
9
10/**
11 * Core class used to implement meta queries for the Meta API.
12 *
13 * Used for generating SQL clauses that filter a primary query according to metadata keys and values.
14 *
15 * WP_Meta_Query is a helper that allows primary query classes, such as WP_Query and WP_User_Query,
16 *
17 * to filter their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be attached
18 * to the primary SQL query string.
19 *
20 * @since 3.2.0
21 */
22#[AllowDynamicProperties]
23class WP_Meta_Query {
24 /**
25 * Array of metadata queries.
26 *
27 * See WP_Meta_Query::__construct() for information on meta query arguments.
28 *
29 * @since 3.2.0
30 * @var array
31 */
32 public $queries = array();
33
34 /**
35 * The relation between the queries. Can be one of 'AND' or 'OR'.
36 *
37 * @since 3.2.0
38 * @var string
39 */
40 public $relation;
41
42 /**
43 * Database table to query for the metadata.
44 *
45 * @since 4.1.0
46 * @var string
47 */
48 public $meta_table;
49
50 /**
51 * Column in meta_table that represents the ID of the object the metadata belongs to.
52 *
53 * @since 4.1.0
54 * @var string
55 */
56 public $meta_id_column;
57
58 /**
59 * Database table that where the metadata's objects are stored (eg $wpdb->users).
60 *
61 * @since 4.1.0
62 * @var string
63 */
64 public $primary_table;
65
66 /**
67 * Column in primary_table that represents the ID of the object.
68 *
69 * @since 4.1.0
70 * @var string
71 */
72 public $primary_id_column;
73
74 /**
75 * A flat list of table aliases used in JOIN clauses.
76 *
77 * @since 4.1.0
78 * @var array
79 */
80 protected $table_aliases = array();
81
82 /**
83 * A flat list of clauses, keyed by clause 'name'.
84 *
85 * @since 4.2.0
86 * @var array
87 */
88 protected $clauses = array();
89
90 /**
91 * Whether the query contains any OR relations.
92 *
93 * @since 4.3.0
94 * @var bool
95 */
96 protected $has_or_relation = false;
97
98 /**
99 * Constructor.
100 *
101 * @since 3.2.0
102 * @since 4.2.0 Introduced support for naming query clauses by associative array keys.
103 * @since 5.1.0 Introduced `$compare_key` clause parameter, which enables LIKE key matches.
104 * @since 5.3.0 Increased the number of operators available to `$compare_key`. Introduced `$type_key`,
105 * which enables the `$key` to be cast to a new data type for comparisons.
106 *
107 * @param array $meta_query {
108 * Array of meta query clauses. When first-order clauses or sub-clauses use strings as
109 * their array keys, they may be referenced in the 'orderby' parameter of the parent query.
110 *
111 * @type string $relation Optional. The MySQL keyword used to join the clauses of the query.
112 * Accepts 'AND' or 'OR'. Default 'AND'.
113 * @type array ...$0 {
114 * Optional. An array of first-order clause parameters, or another fully-formed meta query.
115 *
116 * @type string|string[] $key Meta key or keys to filter by.
117 * @type string $compare_key MySQL operator used for comparing the $key. Accepts:
118 * - '='
119 * - '!='
120 * - 'LIKE'
121 * - 'NOT LIKE'
122 * - 'IN'
123 * - 'NOT IN'
124 * - 'REGEXP'
125 * - 'NOT REGEXP'
126 * - 'RLIKE'
127 * - 'EXISTS' (alias of '=')
128 * - 'NOT EXISTS' (alias of '!=')
129 * Default is 'IN' when `$key` is an array, '=' otherwise.
130 * @type string $type_key MySQL data type that the meta_key column will be CAST to for
131 * comparisons. Accepts 'BINARY' for case-sensitive regular expression
132 * comparisons. Default is ''.
133 * @type string|string[] $value Meta value or values to filter by.
134 * @type string $compare MySQL operator used for comparing the $value. Accepts:
135 * - '='
136 * - '!='
137 * - '>'
138 * - '>='
139 * - '<'
140 * - '<='
141 * - 'LIKE'
142 * - 'NOT LIKE'
143 * - 'IN'
144 * - 'NOT IN'
145 * - 'BETWEEN'
146 * - 'NOT BETWEEN'
147 * - 'REGEXP'
148 * - 'NOT REGEXP'
149 * - 'RLIKE'
150 * - 'EXISTS'
151 * - 'NOT EXISTS'
152 * Default is 'IN' when `$value` is an array, '=' otherwise.
153 * @type string $type MySQL data type that the meta_value column will be CAST to for
154 * comparisons. Accepts:
155 * - 'NUMERIC'
156 * - 'BINARY'
157 * - 'CHAR'
158 * - 'DATE'
159 * - 'DATETIME'
160 * - 'DECIMAL'
161 * - 'SIGNED'
162 * - 'TIME'
163 * - 'UNSIGNED'
164 * Default is 'CHAR'.
165 * }
166 * }
167 */
168 public function __construct( $meta_query = array() ) {
169 if ( ! $meta_query ) {
170 return;
171 }
172
173 if ( isset( $meta_query['relation'] ) && 'OR' === strtoupper( $meta_query['relation'] ) ) {
174 $this->relation = 'OR';
175 } else {
176 $this->relation = 'AND';
177 }
178
179 $this->queries = $this->sanitize_query( $meta_query );
180 }
181
182 /**
183 * Ensures the 'meta_query' argument passed to the class constructor is well-formed.
184 *
185 * Eliminates empty items and ensures that a 'relation' is set.
186 *
187 * @since 4.1.0
188 *
189 * @param array $queries Array of query clauses.
190 * @return array Sanitized array of query clauses.
191 */
192 public function sanitize_query( $queries ) {
193 $clean_queries = array();
194
195 if ( ! is_array( $queries ) ) {
196 return $clean_queries;
197 }
198
199 foreach ( $queries as $key => $query ) {
200 if ( 'relation' === $key ) {
201 $relation = $query;
202
203 } elseif ( ! is_array( $query ) ) {
204 continue;
205
206 // First-order clause.
207 } elseif ( $this->is_first_order_clause( $query ) ) {
208 if ( isset( $query['value'] ) && array() === $query['value'] ) {
209 unset( $query['value'] );
210 }
211
212 $clean_queries[ $key ] = $query;
213
214 // Otherwise, it's a nested query, so we recurse.
215 } else {
216 $cleaned_query = $this->sanitize_query( $query );
217
218 if ( ! empty( $cleaned_query ) ) {
219 $clean_queries[ $key ] = $cleaned_query;
220 }
221 }
222 }
223
224 if ( empty( $clean_queries ) ) {
225 return $clean_queries;
226 }
227
228 // Sanitize the 'relation' key provided in the query.
229 if ( isset( $relation ) && 'OR' === strtoupper( $relation ) ) {
230 $clean_queries['relation'] = 'OR';
231 $this->has_or_relation = true;
232
233 /*
234 * If there is only a single clause, call the relation 'OR'.
235 * This value will not actually be used to join clauses, but it
236 * simplifies the logic around combining key-only queries.
237 */
238 } elseif ( 1 === count( $clean_queries ) ) {
239 $clean_queries['relation'] = 'OR';
240
241 // Default to AND.
242 } else {
243 $clean_queries['relation'] = 'AND';
244 }
245
246 return $clean_queries;
247 }
248
249 /**
250 * Determines whether a query clause is first-order.
251 *
252 * A first-order meta query clause is one that has either a 'key' or
253 * a 'value' array key.
254 *
255 * @since 4.1.0
256 *
257 * @param array $query Meta query arguments.
258 * @return bool Whether the query clause is a first-order clause.
259 */
260 protected function is_first_order_clause( $query ) {
261 return isset( $query['key'] ) || isset( $query['value'] );
262 }
263
264 /**
265 * Constructs a meta query based on 'meta_*' query vars
266 *
267 * @since 3.2.0
268 *
269 * @param array $qv The query variables.
270 */
271 public function parse_query_vars( $qv ) {
272 $meta_query = array();
273
274 /*
275 * For orderby=meta_value to work correctly, simple query needs to be
276 * first (so that its table join is against an unaliased meta table) and
277 * needs to be its own clause (so it doesn't interfere with the logic of
278 * the rest of the meta_query).
279 */
280 $primary_meta_query = array();
281 foreach ( array( 'key', 'compare', 'type', 'compare_key', 'type_key' ) as $key ) {
282 if ( ! empty( $qv[ "meta_$key" ] ) ) {
283 $primary_meta_query[ $key ] = $qv[ "meta_$key" ];
284 }
285 }
286
287 // WP_Query sets 'meta_value' = '' by default.
288 if ( isset( $qv['meta_value'] ) && '' !== $qv['meta_value'] && ( ! is_array( $qv['meta_value'] ) || $qv['meta_value'] ) ) {
289 $primary_meta_query['value'] = $qv['meta_value'];
290 }
291
292 $existing_meta_query = isset( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ? $qv['meta_query'] : array();
293
294 if ( ! empty( $primary_meta_query ) && ! empty( $existing_meta_query ) ) {
295 $meta_query = array(
296 'relation' => 'AND',
297 $primary_meta_query,
298 $existing_meta_query,
299 );
300 } elseif ( ! empty( $primary_meta_query ) ) {
301 $meta_query = array(
302 $primary_meta_query,
303 );
304 } elseif ( ! empty( $existing_meta_query ) ) {
305 $meta_query = $existing_meta_query;
306 }
307
308 $this->__construct( $meta_query );
309 }
310
311 /**
312 * Returns the appropriate alias for the given meta type if applicable.
313 *
314 * @since 3.7.0
315 *
316 * @param string $type MySQL type to cast meta_value.
317 * @return string MySQL type.
318 */
319 public function get_cast_for_type( $type = '' ) {
320 if ( empty( $type ) ) {
321 return 'CHAR';
322 }
323
324 $meta_type = strtoupper( $type );
325
326 if ( ! preg_match( '/^(?:BINARY|CHAR|DATE|DATETIME|SIGNED|UNSIGNED|TIME|NUMERIC(?:\(\d+(?:,\s?\d+)?\))?|DECIMAL(?:\(\d+(?:,\s?\d+)?\))?)$/', $meta_type ) ) {
327 return 'CHAR';
328 }
329
330 if ( 'NUMERIC' === $meta_type ) {
331 $meta_type = 'SIGNED';
332 }
333
334 return $meta_type;
335 }
336
337 /**
338 * Generates SQL clauses to be appended to a main query.
339 *
340 * @since 3.2.0
341 *
342 * @param string $type Type of meta. Possible values include but are not limited
343 * to 'post', 'comment', 'blog', 'term', and 'user'.
344 * @param string $primary_table Database table where the object being filtered is stored (eg wp_users).
345 * @param string $primary_id_column ID column for the filtered object in $primary_table.
346 * @param object $context Optional. The main query object that corresponds to the type, for
347 * example a `WP_Query`, `WP_User_Query`, or `WP_Site_Query`.
348 * Default null.
349 * @return string[]|false {
350 * Array containing JOIN and WHERE SQL clauses to append to the main query,
351 * or false if no table exists for the requested meta type.
352 *
353 * @type string $join SQL fragment to append to the main JOIN clause.
354 * @type string $where SQL fragment to append to the main WHERE clause.
355 * }
356 */
357 public function get_sql( $type, $primary_table, $primary_id_column, $context = null ) {
358 $meta_table = _get_meta_table( $type );
359 if ( ! $meta_table ) {
360 return false;
361 }
362
363 $this->table_aliases = array();
364
365 $this->meta_table = $meta_table;
366 $this->meta_id_column = sanitize_key( $type . '_id' );
367
368 $this->primary_table = $primary_table;
369 $this->primary_id_column = $primary_id_column;
370
371 $sql = $this->get_sql_clauses();
372
373 /*
374 * If any JOINs are LEFT JOINs (as in the case of NOT EXISTS), then all JOINs should
375 * be LEFT. Otherwise posts with no metadata will be excluded from results.
376 */
377 if ( str_contains( $sql['join'], 'LEFT JOIN' ) ) {
378 $sql['join'] = str_replace( 'INNER JOIN', 'LEFT JOIN', $sql['join'] );
379 }
380
381 /**
382 * Filters the meta query's generated SQL.
383 *
384 * @since 3.1.0
385 *
386 * @param string[] $sql Array containing the query's JOIN and WHERE clauses.
387 * @param array $queries Array of meta queries.
388 * @param string $type Type of meta. Possible values include but are not limited
389 * to 'post', 'comment', 'blog', 'term', and 'user'.
390 * @param string $primary_table Primary table.
391 * @param string $primary_id_column Primary column ID.
392 * @param object $context The main query object that corresponds to the type, for
393 * example a `WP_Query`, `WP_User_Query`, or `WP_Site_Query`.
394 */
395 return apply_filters_ref_array( 'get_meta_sql', array( $sql, $this->queries, $type, $primary_table, $primary_id_column, $context ) );
396 }
397
398 /**
399 * Generates SQL clauses to be appended to a main query.
400 *
401 * Called by the public WP_Meta_Query::get_sql(), this method is abstracted
402 * out to maintain parity with the other Query classes.
403 *
404 * @since 4.1.0
405 *
406 * @return string[] {
407 * Array containing JOIN and WHERE SQL clauses to append to the main query.
408 *
409 * @type string $join SQL fragment to append to the main JOIN clause.
410 * @type string $where SQL fragment to append to the main WHERE clause.
411 * }
412 */
413 protected function get_sql_clauses() {
414 /*
415 * $queries are passed by reference to get_sql_for_query() for recursion.
416 * To keep $this->queries unaltered, pass a copy.
417 */
418 $queries = $this->queries;
419 $sql = $this->get_sql_for_query( $queries );
420
421 if ( ! empty( $sql['where'] ) ) {
422 $sql['where'] = ' AND ' . $sql['where'];
423 }
424
425 return $sql;
426 }
427
428 /**
429 * Generates SQL clauses for a single query array.
430 *
431 * If nested subqueries are found, this method recurses the tree to
432 * produce the properly nested SQL.
433 *
434 * @since 4.1.0
435 *
436 * @param array $query Query to parse (passed by reference).
437 * @param int $depth Optional. Number of tree levels deep we currently are.
438 * Used to calculate indentation. Default 0.
439 * @return string[] {
440 * Array containing JOIN and WHERE SQL clauses to append to a single query array.
441 *
442 * @type string $join SQL fragment to append to the main JOIN clause.
443 * @type string $where SQL fragment to append to the main WHERE clause.
444 * }
445 */
446 protected function get_sql_for_query( &$query, $depth = 0 ) {
447 $sql_chunks = array(
448 'join' => array(),
449 'where' => array(),
450 );
451
452 $sql = array(
453 'join' => '',
454 'where' => '',
455 );
456
457 $indent = '';
458 for ( $i = 0; $i < $depth; $i++ ) {
459 $indent .= ' ';
460 }
461
462 foreach ( $query as $key => &$clause ) {
463 if ( 'relation' === $key ) {
464 $relation = $query['relation'];
465 } elseif ( is_array( $clause ) ) {
466
467 // This is a first-order clause.
468 if ( $this->is_first_order_clause( $clause ) ) {
469 $clause_sql = $this->get_sql_for_clause( $clause, $query, $key );
470
471 $where_count = count( $clause_sql['where'] );
472 if ( ! $where_count ) {
473 $sql_chunks['where'][] = '';
474 } elseif ( 1 === $where_count ) {
475 $sql_chunks['where'][] = $clause_sql['where'][0];
476 } else {
477 $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )';
478 }
479
480 $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] );
481 // This is a subquery, so we recurse.
482 } else {
483 $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 );
484
485 $sql_chunks['where'][] = $clause_sql['where'];
486 $sql_chunks['join'][] = $clause_sql['join'];
487 }
488 }
489 }
490
491 // Filter to remove empties.
492 $sql_chunks['join'] = array_filter( $sql_chunks['join'] );
493 $sql_chunks['where'] = array_filter( $sql_chunks['where'] );
494
495 if ( empty( $relation ) ) {
496 $relation = 'AND';
497 }
498
499 // Filter duplicate JOIN clauses and combine into a single string.
500 if ( ! empty( $sql_chunks['join'] ) ) {
501 $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) );
502 }
503
504 // Generate a single WHERE clause with proper brackets and indentation.
505 if ( ! empty( $sql_chunks['where'] ) ) {
506 $sql['where'] = '( ' . "\n " . $indent . implode( ' ' . "\n " . $indent . $relation . ' ' . "\n " . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')';
507 }
508
509 return $sql;
510 }
511
512 /**
513 * Generates SQL JOIN and WHERE clauses for a first-order query clause.
514 *
515 * "First-order" means that it's an array with a 'key' or 'value'.
516 *
517 * @since 4.1.0
518 *
519 * @global wpdb $wpdb WordPress database abstraction object.
520 *
521 * @param array $clause Query clause (passed by reference).
522 * @param array $parent_query Parent query array.
523 * @param string $clause_key Optional. The array key used to name the clause in the original `$meta_query`
524 * parameters. If not provided, a key will be generated automatically.
525 * Default empty string.
526 * @return array {
527 * Array containing JOIN and WHERE SQL clauses to append to a first-order query.
528 *
529 * @type string[] $join Array of SQL fragments to append to the main JOIN clause.
530 * @type string[] $where Array of SQL fragments to append to the main WHERE clause.
531 * }
532 */
533 public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) {
534 global $wpdb;
535
536 $sql_chunks = array(
537 'where' => array(),
538 'join' => array(),
539 );
540
541 if ( isset( $clause['compare'] ) ) {
542 $clause['compare'] = strtoupper( $clause['compare'] );
543 } else {
544 $clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
545 }
546
547 $non_numeric_operators = array(
548 '=',
549 '!=',
550 'LIKE',
551 'NOT LIKE',
552 'IN',
553 'NOT IN',
554 'EXISTS',
555 'NOT EXISTS',
556 'RLIKE',
557 'REGEXP',
558 'NOT REGEXP',
559 );
560
561 $numeric_operators = array(
562 '>',
563 '>=',
564 '<',
565 '<=',
566 'BETWEEN',
567 'NOT BETWEEN',
568 );
569
570 if ( ! in_array( $clause['compare'], $non_numeric_operators, true ) && ! in_array( $clause['compare'], $numeric_operators, true ) ) {
571 $clause['compare'] = '=';
572 }
573
574 if ( isset( $clause['compare_key'] ) ) {
575 $clause['compare_key'] = strtoupper( $clause['compare_key'] );
576 } else {
577 $clause['compare_key'] = isset( $clause['key'] ) && is_array( $clause['key'] ) ? 'IN' : '=';
578 }
579
580 if ( ! in_array( $clause['compare_key'], $non_numeric_operators, true ) ) {
581 $clause['compare_key'] = '=';
582 }
583
584 $meta_compare = $clause['compare'];
585 $meta_compare_key = $clause['compare_key'];
586
587 // First build the JOIN clause, if one is required.
588 $join = '';
589
590 // We prefer to avoid joins if possible. Look for an existing join compatible with this clause.
591 $alias = $this->find_compatible_table_alias( $clause, $parent_query );
592 if ( false === $alias ) {
593 $i = count( $this->table_aliases );
594 $alias = $i ? 'mt' . $i : $this->meta_table;
595
596 // JOIN clauses for NOT EXISTS have their own syntax.
597 if ( 'NOT EXISTS' === $meta_compare ) {
598 $join .= " LEFT JOIN $this->meta_table";
599 $join .= $i ? " AS $alias" : '';
600
601 if ( 'LIKE' === $meta_compare_key ) {
602 $join .= $wpdb->prepare( " ON ( $this->primary_table.$this->primary_id_column = $alias.$this->meta_id_column AND $alias.meta_key LIKE %s )", '%' . $wpdb->esc_like( $clause['key'] ) . '%' );
603 } else {
604 $join .= $wpdb->prepare( " ON ( $this->primary_table.$this->primary_id_column = $alias.$this->meta_id_column AND $alias.meta_key = %s )", $clause['key'] );
605 }
606
607 // All other JOIN clauses.
608 } else {
609 $join .= " INNER JOIN $this->meta_table";
610 $join .= $i ? " AS $alias" : '';
611 $join .= " ON ( $this->primary_table.$this->primary_id_column = $alias.$this->meta_id_column )";
612 }
613
614 $this->table_aliases[] = $alias;
615 $sql_chunks['join'][] = $join;
616 }
617
618 // Save the alias to this clause, for future siblings to find.
619 $clause['alias'] = $alias;
620
621 // Determine the data type.
622 $_meta_type = isset( $clause['type'] ) ? $clause['type'] : '';
623 $meta_type = $this->get_cast_for_type( $_meta_type );
624 $clause['cast'] = $meta_type;
625
626 // Fallback for clause keys is the table alias. Key must be a string.
627 if ( is_int( $clause_key ) || ! $clause_key ) {
628 $clause_key = $clause['alias'];
629 }
630
631 // Ensure unique clause keys, so none are overwritten.
632 $iterator = 1;
633 $clause_key_base = $clause_key;
634 while ( isset( $this->clauses[ $clause_key ] ) ) {
635 $clause_key = $clause_key_base . '-' . $iterator;
636 ++$iterator;
637 }
638
639 // Store the clause in our flat array.
640 $this->clauses[ $clause_key ] =& $clause;
641
642 // Next, build the WHERE clause.
643
644 // meta_key.
645 if ( array_key_exists( 'key', $clause ) ) {
646 if ( 'NOT EXISTS' === $meta_compare ) {
647 $sql_chunks['where'][] = $alias . '.' . $this->meta_id_column . ' IS NULL';
648 } else {
649 /**
650 * In joined clauses negative operators have to be nested into a
651 * NOT EXISTS clause and flipped, to avoid returning records with
652 * matching post IDs but different meta keys. Here we prepare the
653 * nested clause.
654 */
655 if ( in_array( $meta_compare_key, array( '!=', 'NOT IN', 'NOT LIKE', 'NOT EXISTS', 'NOT REGEXP' ), true ) ) {
656 // Negative clauses may be reused.
657 $i = count( $this->table_aliases );
658 $subquery_alias = $i ? 'mt' . $i : $this->meta_table;
659 $this->table_aliases[] = $subquery_alias;
660
661 $meta_compare_string_start = 'NOT EXISTS (';
662 $meta_compare_string_start .= "SELECT 1 FROM $wpdb->postmeta $subquery_alias ";
663 $meta_compare_string_start .= "WHERE $subquery_alias.post_ID = $alias.post_ID ";
664 $meta_compare_string_end = 'LIMIT 1';
665 $meta_compare_string_end .= ')';
666 }
667
668 switch ( $meta_compare_key ) {
669 case '=':
670 case 'EXISTS':
671 $where = $wpdb->prepare( "$alias.meta_key = %s", trim( $clause['key'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
672 break;
673 case 'LIKE':
674 $meta_compare_value = '%' . $wpdb->esc_like( trim( $clause['key'] ) ) . '%';
675 $where = $wpdb->prepare( "$alias.meta_key LIKE %s", $meta_compare_value ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
676 break;
677 case 'IN':
678 $meta_compare_string = "$alias.meta_key IN (" . substr( str_repeat( ',%s', count( $clause['key'] ) ), 1 ) . ')';
679 $where = $wpdb->prepare( $meta_compare_string, $clause['key'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
680 break;
681 case 'RLIKE':
682 case 'REGEXP':
683 $operator = $meta_compare_key;
684 if ( isset( $clause['type_key'] ) && 'BINARY' === strtoupper( $clause['type_key'] ) ) {
685 $cast = 'BINARY';
686 $meta_key = "CAST($alias.meta_key AS BINARY)";
687 } else {
688 $cast = '';
689 $meta_key = "$alias.meta_key";
690 }
691 $where = $wpdb->prepare( "$meta_key $operator $cast %s", trim( $clause['key'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
692 break;
693
694 case '!=':
695 case 'NOT EXISTS':
696 $meta_compare_string = $meta_compare_string_start . "AND $subquery_alias.meta_key = %s " . $meta_compare_string_end;
697 $where = $wpdb->prepare( $meta_compare_string, $clause['key'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
698 break;
699 case 'NOT LIKE':
700 $meta_compare_string = $meta_compare_string_start . "AND $subquery_alias.meta_key LIKE %s " . $meta_compare_string_end;
701
702 $meta_compare_value = '%' . $wpdb->esc_like( trim( $clause['key'] ) ) . '%';
703 $where = $wpdb->prepare( $meta_compare_string, $meta_compare_value ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
704 break;
705 case 'NOT IN':
706 $array_subclause = '(' . substr( str_repeat( ',%s', count( $clause['key'] ) ), 1 ) . ') ';
707 $meta_compare_string = $meta_compare_string_start . "AND $subquery_alias.meta_key IN " . $array_subclause . $meta_compare_string_end;
708 $where = $wpdb->prepare( $meta_compare_string, $clause['key'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
709 break;
710 case 'NOT REGEXP':
711 $operator = $meta_compare_key;
712 if ( isset( $clause['type_key'] ) && 'BINARY' === strtoupper( $clause['type_key'] ) ) {
713 $cast = 'BINARY';
714 $meta_key = "CAST($subquery_alias.meta_key AS BINARY)";
715 } else {
716 $cast = '';
717 $meta_key = "$subquery_alias.meta_key";
718 }
719
720 $meta_compare_string = $meta_compare_string_start . "AND $meta_key REGEXP $cast %s " . $meta_compare_string_end;
721 $where = $wpdb->prepare( $meta_compare_string, $clause['key'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
722 break;
723 }
724
725 $sql_chunks['where'][] = $where;
726 }
727 }
728
729 // meta_value.
730 if ( array_key_exists( 'value', $clause ) ) {
731 $meta_value = $clause['value'];
732
733 if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ), true ) ) {
734 if ( ! is_array( $meta_value ) ) {
735 $meta_value = preg_split( '/[,\s]+/', $meta_value );
736 }
737 } elseif ( is_string( $meta_value ) ) {
738 $meta_value = trim( $meta_value );
739 }
740
741 switch ( $meta_compare ) {
742 case 'IN':
743 case 'NOT IN':
744 $meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')';
745 $where = $wpdb->prepare( $meta_compare_string, $meta_value );
746 break;
747
748 case 'BETWEEN':
749 case 'NOT BETWEEN':
750 $where = $wpdb->prepare( '%s AND %s', $meta_value[0], $meta_value[1] );
751 break;
752
753 case 'LIKE':
754 case 'NOT LIKE':
755 $meta_value = '%' . $wpdb->esc_like( $meta_value ) . '%';
756 $where = $wpdb->prepare( '%s', $meta_value );
757 break;
758
759 // EXISTS with a value is interpreted as '='.
760 case 'EXISTS':
761 $meta_compare = '=';
762 $where = $wpdb->prepare( '%s', $meta_value );
763 break;
764
765 // 'value' is ignored for NOT EXISTS.
766 case 'NOT EXISTS':
767 $where = '';
768 break;
769
770 default:
771 $where = $wpdb->prepare( '%s', $meta_value );
772 break;
773
774 }
775
776 if ( $where ) {
777 if ( 'CHAR' === $meta_type ) {
778 $sql_chunks['where'][] = "$alias.meta_value {$meta_compare} {$where}";
779 } else {
780 $sql_chunks['where'][] = "CAST($alias.meta_value AS {$meta_type}) {$meta_compare} {$where}";
781 }
782 }
783 }
784
785 /*
786 * Multiple WHERE clauses (for meta_key and meta_value) should
787 * be joined in parentheses.
788 */
789 if ( 1 < count( $sql_chunks['where'] ) ) {
790 $sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
791 }
792
793 return $sql_chunks;
794 }
795
796 /**
797 * Gets a flattened list of sanitized meta clauses.
798 *
799 * This array should be used for clause lookup, as when the table alias and CAST type must be determined for
800 * a value of 'orderby' corresponding to a meta clause.
801 *
802 * @since 4.2.0
803 *
804 * @return array Meta clauses.
805 */
806 public function get_clauses() {
807 return $this->clauses;
808 }
809
810 /**
811 * Identifies an existing table alias that is compatible with the current
812 * query clause.
813 *
814 * We avoid unnecessary table joins by allowing each clause to look for
815 * an existing table alias that is compatible with the query that it
816 * needs to perform.
817 *
818 * An existing alias is compatible if (a) it is a sibling of `$clause`
819 * (ie, it's under the scope of the same relation), and (b) the combination
820 * of operator and relation between the clauses allows for a shared table join.
821 * In the case of WP_Meta_Query, this only applies to 'IN' clauses that are
822 * connected by the relation 'OR'.
823 *
824 * @since 4.1.0
825 *
826 * @param array $clause Query clause.
827 * @param array $parent_query Parent query of $clause.
828 * @return string|false Table alias if found, otherwise false.
829 */
830 protected function find_compatible_table_alias( $clause, $parent_query ) {
831 $alias = false;
832
833 foreach ( $parent_query as $sibling ) {
834 // If the sibling has no alias yet, there's nothing to check.
835 if ( empty( $sibling['alias'] ) ) {
836 continue;
837 }
838
839 // We're only interested in siblings that are first-order clauses.
840 if ( ! is_array( $sibling ) || ! $this->is_first_order_clause( $sibling ) ) {
841 continue;
842 }
843
844 $compatible_compares = array();
845
846 // Clauses connected by OR can share joins as long as they have "positive" operators.
847 if ( 'OR' === $parent_query['relation'] ) {
848 $compatible_compares = array( '=', 'IN', 'BETWEEN', 'LIKE', 'REGEXP', 'RLIKE', '>', '>=', '<', '<=' );
849
850 // Clauses joined by AND with "negative" operators share a join only if they also share a key.
851 } elseif ( isset( $sibling['key'] ) && isset( $clause['key'] ) && $sibling['key'] === $clause['key'] ) {
852 $compatible_compares = array( '!=', 'NOT IN', 'NOT LIKE' );
853 }
854
855 $clause_compare = strtoupper( $clause['compare'] );
856 $sibling_compare = strtoupper( $sibling['compare'] );
857 if ( in_array( $clause_compare, $compatible_compares, true ) && in_array( $sibling_compare, $compatible_compares, true ) ) {
858 $alias = preg_replace( '/\W/', '_', $sibling['alias'] );
859 break;
860 }
861 }
862
863 /**
864 * Filters the table alias identified as compatible with the current clause.
865 *
866 * @since 4.1.0
867 *
868 * @param string|false $alias Table alias, or false if none was found.
869 * @param array $clause First-order query clause.
870 * @param array $parent_query Parent of $clause.
871 * @param WP_Meta_Query $query WP_Meta_Query object.
872 */
873 return apply_filters( 'meta_query_find_compatible_table_alias', $alias, $clause, $parent_query, $this );
874 }
875
876 /**
877 * Checks whether the current query has any OR relations.
878 *
879 * In some cases, the presence of an OR relation somewhere in the query will require
880 * the use of a `DISTINCT` or `GROUP BY` keyword in the `SELECT` clause. The current
881 * method can be used in these cases to determine whether such a clause is necessary.
882 *
883 * @since 4.3.0
884 *
885 * @return bool True if the query contains any `OR` relations, otherwise false.
886 */
887 public function has_or_relation() {
888 return $this->has_or_relation;
889 }
890}
891
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1