PluginProbe
Polylang / 1.3
Polylang v1.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
polylang / include / model.php

model.php in Polylang 1.3, at include/model.php

748 lines 24.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * setups the language and translations model based on WordPress taxonomies
5 *
6 * @since 1.2
7 */
8 class PLL_Model {
9 public $options;
10 public $post_types = array(), $taxonomies = array(); // post types & taxonomies to filter by language
11 private $languages; // used to cache the list of languages
12
13 /*
14 * constructor: registers custom taxonomies and setups filters and actions
15 *
16 * @since 1.2
17 *
18 * @param array $options Polylang options
19 */
20 public function __construct(&$options) {
21 $this->options = &$options;
22
23 // register our taxonomies as soon as possible
24 // this is early registration, not ready for rewrite rules as wp_rewrite will be setup later
25 // FIXME should I supply an 'update_count_callback' for taxonomies other than 'language' (currently not needed by PLL)?
26 foreach (array('language', 'term_language', 'post_translations', 'term_translations') as $tax) {
27 register_taxonomy($tax,
28 false !== strpos($tax, 'term_') ? 'term' : null ,
29 array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false, '_pll' => true)
30 );
31 }
32
33 add_filter('get_terms', array(&$this, '_prime_terms_cache'), 10, 2);
34 add_filter('wp_get_object_terms', array(&$this, 'wp_get_object_terms'), 10, 3);
35
36 // we need to clean languages cache when editing a language,
37 // when editing page of front or when modifying the permalink structure
38 add_action('edited_term_taxonomy', array(&$this, 'clean_languages_cache'), 10, 2);
39 add_action('update_option_page_on_front', array(&$this, 'clean_languages_cache'));
40 add_action('update_option_permalink_structure', array(&$this, 'clean_languages_cache'));
41
42 // registers completely the language taxonomy
43 add_action('setup_theme', array(&$this, 'register_taxonomy'), 1);
44
45 // setups post types and taxonomies to translate
46 add_action('registered_post_type', array(&$this, 'registered_post_type'));
47 add_action('registered_taxonomy', array(&$this, 'registered_taxonomy'));
48
49 // just in case someone would like to display the language description ;-)
50 add_filter('language_description', create_function('$v', "return '';"));
51
52 // adds cache domain when querying terms
53 add_filter('get_terms_args', array(&$this, 'get_terms_args'));
54 }
55
56 /*
57 * cache language and translations when terms are queried by get_terms
58 *
59 * @since 1.2
60 *
61 * @param array $terms queried terms
62 * @param array $taxonomies queried taxonomies
63 * @return array unmodified $terms
64 */
65 public function _prime_terms_cache($terms, $taxonomies) {
66 foreach ($terms as $term) {
67 if (is_object($term)) {
68 if (in_array($term->taxonomy, $this->taxonomies))
69 $term_ids[] = $term->term_id;
70 }
71 elseif (array_intersect($taxonomies, $this->taxonomies))
72 $term_ids[] = $term;
73 }
74
75 if (!empty($term_ids))
76 update_object_term_cache(array_unique($term_ids), 'term'); // adds language and translation of terms to cache
77 return $terms;
78 }
79
80 /*
81 * when terms are found for posts, add their language and translations to cache
82 *
83 * @since 1.2
84 *
85 * @param array $terms terms found
86 * @param array $object_ids not used
87 * @param array $taxonomies terms taxonomies
88 * @return array unmodified $terms
89 */
90 // FIXME is that useful? or even desirable?
91 public function wp_get_object_terms($terms, $object_ids, $taxonomies) {
92 $taxonomies = explode("', '", trim($taxonomies, "'"));
93 if (!in_array('term_translations', $taxonomies))
94 $this->_prime_terms_cache($terms, $taxonomies);
95 return $terms;
96 }
97
98 /*
99 * wrap wp_get_object_terms to cache it and return only one object
100 * inspired by the function get_the_terms
101 *
102 * @since 1.2
103 *
104 * @param int $object_id post_id or term_id
105 * @param string $taxonomy Polylang taxonomy depending if we are looking for a post (or term) language (or translation)
106 * @return bool|object the term associated to the object in the requested taxonomy if exists, false otherwise
107 */
108 protected function get_object_term($object_id, $taxonomy) {
109 $term = get_object_term_cache($object_id, $taxonomy);
110
111 if ( false === $term ) {
112 // query language and translations at the same time
113 $taxonomies = (false !== strpos($taxonomy, 'term_')) ?
114 array('term_language', 'term_translations') :
115 array('language', 'post_translations');
116
117 foreach (wp_get_object_terms($object_id, $taxonomies) as $t) {
118 wp_cache_add($object_id, array($t), $t->taxonomy . '_relationships'); // store it the way WP wants it
119 if ($t->taxonomy == $taxonomy)
120 $term = $t;
121 }
122 }
123 else {
124 $term = reset($term);
125 }
126
127 return empty($term) ? false : $term;
128 }
129
130 /*
131 * returns the list of available languages
132 * caches the list in a db transient (except flags)
133 * caches the list (with flags) in the private property $languages
134 *
135 * list of parameters accepted in $args:
136 *
137 * hide_empty => hides languages with no posts if set to true (defaults to false)
138 * fields => return only that field if set (see PLL_Language for a list of fields)
139 *
140 * @since 0.1
141 *
142 * @param array $args
143 * @return array|string|int list of PLL_Language objects or PLL_Language object properties
144 */
145 public function get_languages_list($args = array()) {
146 if (empty($this->languages)) {
147 if (false === ($languages = get_transient('pll_languages_list'))) {
148 $languages = get_terms('language', array('hide_empty' => false, 'orderby'=> 'term_group'));
149 $languages = empty($languages) || is_wp_error($languages) ? array() : $languages;
150
151 $term_languages = get_terms('term_language', array('hide_empty' => false));
152 $term_languages = empty($term_languages) || is_wp_error($term_languages) ?
153 array() : array_combine(wp_list_pluck($term_languages, 'name'), $term_languages);
154
155 if (!empty($languages) && !empty($term_languages)) {
156 array_walk($languages, create_function('&$v, $k, $term_languages', '$v = new PLL_Language($v, $term_languages[$v->name]);'), $term_languages);
157
158 // need to wait for $wp_rewrite availibility to set homepage urls
159 $this->_languages = $languages;
160 did_action('setup_theme') ? $this->_languages_urls() : add_action('setup_theme', array(&$this, '_languages_urls'));
161 }
162 else {
163 $languages = array(); // in case something went wrong
164 }
165 }
166
167 // add flags (not in db cache as they may be different on frontend and admin)
168 foreach ($languages as $lang)
169 $lang->set_flag();
170
171 $this->languages = $languages;
172 }
173
174 $args = wp_parse_args($args, array('hide_empty' => false));
175 extract($args);
176
177 // remove empty languages if requested
178 $languages = array_filter($this->languages, create_function('$v', sprintf('return $v->count || !%d;', $hide_empty)));
179
180 return empty($fields) ? $languages : wp_list_pluck($languages, $fields);
181 }
182
183 /*
184 * fills home urls in language list and set transient in db
185 * delayed to be sure we have access to $wp_rewrite
186 *
187 * @since 1.3
188 */
189 public function _languages_urls() {
190 foreach ($this->_languages as $language)
191 $language->set_home_url();
192
193 set_transient('pll_languages_list', $this->_languages);
194 unset($this->languages, $this->_languages); // in case flags were already set
195 }
196
197 /*
198 * cleans language cache
199 * can be called directly with no parameter
200 * called by the 'edited_term_taxonomy' filter with 2 parameters when count needs to be updated
201 *
202 * @since 1.2
203 *
204 * @param int $term not used
205 * @param string $taxonomy taxonomy name
206 */
207 public function clean_languages_cache($term = 0, $taxonomy = null) {
208 if (empty($taxonomy->name) || 'language' == $taxonomy->name) {
209 delete_transient('pll_languages_list');
210 $this->languages = array();
211 }
212 }
213
214 /*
215 * returns the language by its term_id, tl_term_id, slug or locale
216 *
217 * @since 0.1
218 *
219 * @param int|string term_id, tl_term_id, slug or locale of the queried language
220 * @return object|bool PLL_Language object, false if no language found
221 */
222 public function get_language($value) {
223 static $language;
224
225 if (is_object($value))
226 return $this->get_language($value->term_id); // will force cast to PLL_Language
227
228 if (empty($language[$value])) {
229 foreach ($this->get_languages_list() as $lang)
230 $language[$lang->term_id] = $language[$lang->tl_term_id] = $language[$lang->slug] = $language[$lang->locale] = $lang;
231 }
232
233 return empty($language[$value]) ? false : $language[$value];
234 }
235
236 /*
237 * saves translations for posts or terms
238 *
239 * @since 0.5
240
241 * @param string $type either 'post' or 'term'
242 * @param int $id post id or term id
243 * @param array $translations: an associative array of translations with language code as key and translation id as value
244 */
245 public function save_translations($type, $id, $translations) {
246 if (($lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id)) && isset($translations) && is_array($translations)) {
247 // first unlink this object
248 foreach ($this->get_translations($type, $id) as $object_id)
249 $this->delete_translation($type, $object_id);
250
251 $translations = array_merge(array($lang->slug => $id), $translations); // make sure this object is in tranlations
252 $translations = array_diff($translations, array(0)); // don't keep non translated languages
253
254 // don't create a translation group for untranslated posts as it is useless
255 // but we need one for terms to allow relationships remap when importing from a WXR file
256 if ('term' == $type || count($translations) > 1) {
257 $terms = wp_get_object_terms($translations, $type . '_translations');
258 $term = array_pop($terms);
259
260 // create a new term if necessary
261 empty($term) ?
262 wp_insert_term($group = uniqid('pll_'), $type . '_translations', array('description' => serialize($translations))) :
263 wp_update_term($group = (int) $term->term_id, $type . '_translations', array('description' => serialize($translations)));
264
265 // link all translations to the new term
266 foreach($translations as $p)
267 wp_set_object_terms($p, $group, $type . '_translations');
268 }
269 }
270 }
271
272 /*
273 * deletes a translation of a post or term
274 *
275 * @since 0.5
276 *
277 * @param string $type either 'post' or 'term'
278 * @param int $id post id or term id
279 */
280 public function delete_translation($type, $id) {
281 $term = $this->get_object_term($id, $type . '_translations');
282
283 if (!empty($term)) {
284 $translations = unserialize($term->description);
285
286 if (is_array($translations)) {
287 $slug = array_search($id, $translations);
288 unset($translations[$slug]);
289
290 empty($translations) || 1 == count($translations) ?
291 wp_delete_term((int) $term->term_id, $type . '_translations') :
292 wp_update_term((int) $term->term_id, $type . '_translations', array('description' => serialize($translations)));
293
294 wp_set_object_terms($id, null, $type . '_translations');
295 }
296 }
297 }
298
299 /*
300 * returns the id of the translation of a post or term
301 *
302 * @since 0.5
303 *
304 * @param string $type either 'post' or 'term'
305 * @param int $id post id or term id
306 * @param object|string $lang object or slug
307 * @return bool|int post id or term id of the translation, flase if there is none
308 */
309 public function get_translation($type, $id, $lang) {
310 if (!$lang = $this->get_language($lang))
311 return false;
312
313 $translations = $this->get_translations($type, $id);
314
315 return isset($translations[$lang->slug]) ? (int) $translations[$lang->slug] : false;
316 }
317
318 /*
319 * returns an array of translations of a post or term
320 *
321 * @since 0.5
322 *
323 * @param string $type either 'post' or 'term'
324 * @param int $id post id or term id
325 * @return array an associative array of translations with language code as key and translation id as value
326 */
327 public function get_translations($type, $id) {
328 $type = ($type == 'post' || in_array($type, $this->post_types)) ? 'post' : (($type == 'term' || in_array($type, $this->taxonomies)) ? 'term' : false);
329 return $type && ($term = $this->get_object_term($id, $type . '_translations')) && !empty($term) ? unserialize($term->description) : array();
330 }
331
332 /*
333 * store the post language in the database
334 *
335 * @since 0.6
336 *
337 * @param int $post_id post id
338 * @param int|string|object language (term_id or slug or object)
339 */
340 public function set_post_language($post_id, $lang) {
341 wp_set_post_terms($post_id, $lang ? $this->get_language($lang)->slug : '', 'language' );
342 }
343
344 /*
345 * returns the language of a post
346 *
347 * @since 0.1
348 *
349 * @param int $post_id post id
350 * @return bool|object PLL_Language object, false if no language is associated to that post
351 */
352 public function get_post_language($post_id) {
353 $lang = $this->get_object_term($post_id, 'language' );
354 return ($lang) ? $this->get_language($lang) : false;
355 }
356
357 /*
358 * among the post and its translations, returns the id of the post which is in $lang
359 *
360 * @since 0.1
361 *
362 * @param int $post_id post id
363 * @param int|string|object language (term_id or slug or object)
364 * @return bool|int the translation post id if exists, otherwise the post id, false if the post has no language
365 */
366 public function get_post($post_id, $lang) {
367 $post_lang = $this->get_post_language($post_id); // FIXME is this necessary?
368 if (!$lang || !$post_lang)
369 return false;
370
371 $lang = $this->get_language($lang);
372 return $post_lang->term_id == $lang->term_id ? $post_id : $this->get_translation('post', $post_id, $lang);
373 }
374
375 /*
376 * stores the term language in the database
377 *
378 * @since 0.6
379 *
380 * @param int $term_id term id
381 * @param int|string|object language (term_id or slug or object)
382 */
383 public function set_term_language($term_id, $lang) {
384 wp_set_object_terms($term_id, $lang ? $this->get_language($lang)->tl_term_id : '', 'term_language');
385 }
386
387 /*
388 * removes the term language in database
389 *
390 * @since 0.5
391 *
392 * @param int $term_id term id
393 */
394 public function delete_term_language($term_id) {
395 wp_delete_object_term_relationships($term_id, 'term_language');
396 }
397
398 /*
399 * returns the language of a term
400 *
401 * @since 0.1
402 *
403 * @param int|string $value term id or term slug
404 * @param string $taxonomy optional taxonomy needed when the term slug is passed as first parameter
405 * @return bool|object PLL_Language object, false if no language is associated to that term
406 */
407 public function get_term_language($value, $taxonomy = '') {
408 if (is_numeric($value))
409 $term_id = $value;
410
411 // get_term_by still not cached in WP 3.5.1 but internally, the function is always called by term_id
412 elseif (is_string($value) && $taxonomy)
413 $term_id = get_term_by('slug', $value , $taxonomy)->term_id;
414
415 $lang = $this->get_object_term($term_id, 'term_language');
416
417 // switch to PLL_Language
418 return ($lang) ? $this->get_language($lang->term_id) : false;
419 }
420
421 /*
422 * among the term and its translations, returns the id of the term which is in $lang
423 *
424 * @since 0.1
425 *
426 * @param int $term_id term id
427 * @param int|string|object language (term_id or slug or object)
428 * @return bool|int the translation term id if exists, otherwise the term id, false if the term has no language
429 */
430 public function get_term($term_id, $lang) {
431 $lg = $this->get_term_language($term_id); // FIXME is this necessary?
432 if (!$lang || !$lg)
433 return false;
434
435 $lang = $this->get_language($lang);
436 return $lg->term_id == $lang->term_id ? $term_id : $this->get_translation('term', $term_id, $lang);
437 }
438
439 /*
440 * a join clause to add to sql queries when filtering by language is needed directly in query
441 *
442 * @since 1.2
443 *
444 * @param string $type either 'post' or 'term'
445 * @return string join clause
446 */
447 public function join_clause($type) {
448 global $wpdb;
449 return " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = " . ('term' == $type ? "t.term_id" : "ID");
450 }
451
452 /*
453 * a where clause to add to sql queries when filtering by language is needed directly in query
454 *
455 * @since 1.2
456 *
457 * @param object|array|string $lang a PLL_Language object or a comma separated list of languag slug or an array of language slugs
458 * @param string $type either 'post' or 'term'
459 * @return string where clause
460 */
461 public function where_clause($lang, $type) {
462 global $wpdb;
463 $tt_id = 'term' == $type ? 'tl_term_taxonomy_id' : 'term_taxonomy_id';
464
465 // $lang is an object
466 // generally the case if the query is coming from Polylang
467 if (is_object($lang))
468 return $wpdb->prepare(" AND pll_tr.term_taxonomy_id = %d", $lang->$tt_id);
469
470 // $lang is a comma separated list of slugs (or an array of slugs)
471 // generally the case is the query is coming from outside with 'lang' parameter
472 $slugs = is_array($lang) ? $lang : explode(',', $lang);
473 foreach ($slugs as $slug)
474 $languages[] = (int) $this->get_language($slug)->$tt_id;
475
476 return " AND pll_tr.term_taxonomy_id IN (" . implode(',', $languages) . ")";
477 }
478
479 /*
480 * adds clauses to comments query to filter them by language - used in both frontend and admin
481 *
482 * @since 1.2
483 *
484 * @param array $clauses the list of sql clauses in comments query
485 * @param object $lang PLL_Language object
486 * @return array modifed list of clauses
487 */
488 public function comments_clauses($clauses, $lang) {
489 global $wpdb;
490 if (!empty($lang)) {
491 // if this clause is not already added by WP
492 if (!strpos($clauses['join'], '.ID'))
493 $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
494
495 $clauses['join'] .= $this->join_clause('post');
496 $clauses['where'] .= $this->where_clause($lang, 'post');
497 }
498 return $clauses;
499 }
500
501 /*
502 * adds terms clauses to get_terms to filter them by languages - used in both frontend and admin
503 *
504 * @since 1.2
505 *
506 * @param array $clauses the list of sql clauses in terms query
507 * @param object $lang PLL_Language object
508 * @return array modifed list of clauses
509 */
510 public function terms_clauses($clauses, $lang) {
511 if (!empty($lang)) {
512 $clauses['join'] .= $this->join_clause('term');
513 $clauses['where'] .= $this->where_clause($lang, 'term');
514 }
515 return $clauses;
516 }
517
518 /*
519 * register the language taxonomy
520 *
521 * @since 1.2
522 */
523 public function register_taxonomy() {
524 // registers the language taxonomy
525 // object types will be set later once all custom post types are registered
526 register_taxonomy('language', $this->post_types, array(
527 'labels' => array(
528 'name' => __('Languages', 'polylang'),
529 'singular_name' => __('Language', 'polylang'),
530 'all_items' => __('All languages', 'polylang'),
531 ),
532 'public' => false, // avoid displaying the 'like post tags text box' in the quick edit
533 'query_var' => 'lang',
534 '_pll' => true // polylang taxonomy
535 ));
536 }
537
538 /*
539 * post types that need to be translated
540 *
541 * @since 1.2
542 *
543 * @return array array of post types names for which Polylang manages languages and translations
544 */
545 protected function get_post_types() {
546 $post_types = array('post' => 'post', 'page' => 'page');
547 if (!empty($this->options['media_support']))
548 $post_types['attachement'] = 'attachment';
549
550 if (is_array($this->options['post_types']))
551 $post_types = array_merge($post_types, $this->options['post_types']);
552
553 return apply_filters('pll_get_post_types', $post_types , false);
554 }
555
556 /*
557 * returns valid registered post types that need to be translated
558 *
559 * @since 1.2
560 *
561 * @return array array of registered post type names for which Polylang manages languages and translations
562 */
563 public function get_translated_post_types() {
564 return $this->post_types = array_intersect($this->get_post_types(), get_post_types());
565 }
566
567 /*
568 * check if registered post type must be translated
569 *
570 * @since 1.2
571 *
572 * @param string $post_type post type name
573 */
574 public function registered_post_type($post_type) {
575 if (in_array($post_type, $this->get_post_types())) {
576 $this->post_types[$post_type] = $post_type;
577 register_taxonomy_for_object_type('language', $post_type);
578 register_taxonomy_for_object_type('post_translations', $post_type);
579 }
580 }
581
582 /*
583 * returns true if Polylang manages languages and translations for this post type
584 *
585 * @since 1.2
586 *
587 * @param string|array $post_type post type name or array of post type names
588 */
589 public function is_translated_post_type($post_type) {
590 return (is_array($post_type) && array_intersect($post_type, $this->post_types) || in_array($post_type, $this->post_types));
591 }
592
593 /*
594 * taxonomies that need to be translated
595 *
596 * @since 1.2
597 *
598 * @return array array of taxonomy names for which Polylang manages languages and translations
599 */
600 protected function get_taxonomies() {
601 $taxonomies = array('category' => 'category', 'post_tag' => 'post_tag');
602
603 if (is_array($this->options['taxonomies']))
604 $taxonomies = array_merge($taxonomies, $this->options['taxonomies']);
605
606 return apply_filters('pll_get_taxonomies', $taxonomies, false);
607 }
608
609 /*
610 * return valid registered taxonomies that need to be translated
611 *
612 * @since 1.2
613 *
614 * @return array array of registered taxonomy names for which Polylang manages languages and translations
615 */
616 public function get_translated_taxonomies() {
617 return $this->taxonomies = array_intersect($this->get_taxonomies(), get_taxonomies());
618 }
619
620 /*
621 * check if registered post type must be translated
622 *
623 * @since 1.2
624 *
625 * @param string $taxonomy taxonomy name
626 */
627 public function registered_taxonomy($taxonomy) {
628 if (in_array($taxonomy, $this->get_taxonomies()))
629 $this->taxonomies[$taxonomy] = $taxonomy;
630 }
631
632 /*
633 * returns true if Polylang manages languages and translations for this post type
634 *
635 * @since 1.2
636 *
637 * @param string|array $tax taxonomy name or array of taxonomy names
638 */
639 public function is_translated_taxonomy($tax) {
640 return (is_array($tax) && array_intersect($tax, $this->taxonomies) || in_array($tax, $this->taxonomies));
641 }
642
643 /*
644 * it is possible to have several terms with the same name in the same taxonomy (one per language)
645 * but the native get_term_by will return only one term
646 * so here the function adds the language parameter
647 *
648 * @since 1.2
649 *
650 * @param string $field currently the only possibility is 'name'
651 * @param string $value the term name
652 * @param string $taxonomy taxonomy name
653 * @param string|object $language the language slug or object
654 * @return null|int the term_id of the found term
655 */
656 public function get_term_by($field, $value, $taxonomy, $language) {
657 global $wpdb;
658
659 if ('name' != $field)
660 return NULL;
661
662 return $wpdb->get_row("SELECT t.*, tt.* FROM $wpdb->terms AS t"
663 . " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"
664 . $this->join_clause('term')
665 . $wpdb->prepare(" WHERE tt.taxonomy = %s AND t.name = %s", $taxonomy, $value)
666 . $this->where_clause($this->get_language($language), 'term')
667 );
668 }
669
670 /*
671 * gets the number of posts per language in a date, author or post type archive
672 *
673 * @since 1.2
674 *
675 * @param object lang
676 * @param array $args WP_Query arguments (accepted: post_type, m, year, monthnum, day, author, author_name)
677 * @return int
678 */
679 public function count_posts($lang, $args = array()) {
680 global $wpdb;
681
682 $q = wp_parse_args($args, array('post_type' => 'post'));
683
684 $cache_key = md5(serialize($q));
685 $counts = wp_cache_get($cache_key, 'pll_count_posts');
686
687 if (false === $counts) {
688 $where = " WHERE post_status = 'publish'";
689 $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_type = %s", $q['post_type']);
690
691 if (!empty($q['m'])) {
692 $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
693 $where .= $wpdb->prepare(" AND YEAR({$wpdb->posts}.post_date) = %d", substr($q['m'], 0, 4));
694 if ( strlen($q['m']) > 5 )
695 $where .= $wpdb->prepare(" AND MONTH({$wpdb->posts}.post_date) = %d", substr($q['m'], 4, 2));
696 if ( strlen($q['m']) > 7 )
697 $where .= $wpdb->prepare(" AND DAYOFMONTH({$wpdb->posts}.post_date) = %d", substr($q['m'], 6, 2));
698 }
699
700 if (!empty($q['year']))
701 $where .= $wpdb->prepare(" AND YEAR({$wpdb->posts}.post_date) = %d", $q['year']);
702
703 if (!empty($q['monthnum']))
704 $where .= $wpdb->prepare(" AND MONTH({$wpdb->posts}.post_date) = %d", $q['monthnum']);
705
706 if (!empty($q['day']))
707 $where .= $wpdb->prepare(" AND DAYOFMONTH({$wpdb->posts}.post_date) = %d", $q['day']);
708
709 if (!empty($q['author_name'])) {
710 $author = get_user_by('slug', sanitize_title_for_query($q['author_name']));
711 if ($author)
712 $q['author'] = $author->ID;
713 }
714
715 if (!empty($q['author']))
716 $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_author = %d", $q['author']);
717
718 $select = "SELECT pll_tr.term_taxonomy_id, COUNT(*) AS num_posts FROM {$wpdb->posts}";
719 $join = $this->join_clause('post');
720 $where .= $this->where_clause($this->get_languages_list(), 'post');
721 $groupby = " GROUP BY pll_tr.term_taxonomy_id";
722
723 $res = $wpdb->get_results($select . $join . $where . $groupby, ARRAY_A);
724 foreach ((array) $res as $row)
725 $counts[$row['term_taxonomy_id']] = $row['num_posts'];
726
727 wp_cache_set($cache_key, $counts, 'pll_count_posts');
728 }
729
730 return empty($counts[$lang->term_taxonomy_id]) ? 0 : $counts[$lang->term_taxonomy_id];
731 }
732
733 /*
734 * adds language dependent cache domain when explicitely querying terms per language
735 * useful as the 'lang' parameter is not included in cache key by WordPress
736 *
737 * @since 1.3
738 */
739 public function get_terms_args($args) {
740 if (isset($args['lang'])) {
741 $key = '_' . (is_array($lang) ? implode(',', $lang) : $lang);
742 $args['cache_domain'] = empty($args['cache_domain']) ? 'pll' . $key : $args['cache_domain'] . $key;
743 }
744
745 return $args;
746 }
747 }
748