PLL_Model

Setups the language and translations model based on WordPress taxonomies.

Defined (1)

The class is defined in the following location(s).

/include/model.php  
  1. class PLL_Model { 
  2. public $cache; // our internal non persistent cache object 
  3. public $options; 
  4. public $post, $term; // translated objects models 
  5.  
  6. /** 
  7. * Constructor 
  8. * setups translated objects sub models 
  9. * setups filters and actions 
  10. * @since 1.2 
  11. * @param array $options Polylang options 
  12. */ 
  13. public function __construct( &$options ) { 
  14. $this->options = &$options; 
  15.  
  16. $this->cache = new PLL_Cache(); 
  17. $this->post = new PLL_Translated_Post( $this ); // translated post sub model 
  18. $this->term = new PLL_Translated_Term( $this ); // translated term sub model 
  19.  
  20. // we need to clean languages cache when editing a language and when modifying the permalink structure 
  21. add_action( 'edited_term_taxonomy', array( $this, 'clean_languages_cache' ), 10, 2 ); 
  22. add_action( 'update_option_permalink_structure', array( $this, 'clean_languages_cache' ) ); 
  23. add_action( 'update_option_siteurl', array( $this, 'clean_languages_cache' ) ); 
  24. add_action( 'update_option_home', array( $this, 'clean_languages_cache' ) ); 
  25.  
  26. // just in case someone would like to display the language description ;- ) 
  27. add_filter( 'language_description', '__return_empty_string' ); 
  28.  
  29. /** 
  30. * Returns the list of available languages 
  31. * caches the list in a db transient ( except flags ), unless PLL_CACHE_LANGUAGES is set to false 
  32. * caches the list ( with flags ) in the private property $languages 
  33. * list of parameters accepted in $args: 
  34. * hide_empty => hides languages with no posts if set to true ( defaults to false ) 
  35. * fields => return only that field if set ( see PLL_Language for a list of fields ) 
  36. * @since 0.1 
  37. * @param array $args 
  38. * @return array|string|int list of PLL_Language objects or PLL_Language object properties 
  39. */ 
  40. public function get_languages_list( $args = array() ) { 
  41. if ( false === $languages = $this->cache->get( 'languages' ) ) { 
  42.  
  43. // create the languages from taxonomies 
  44. if ( ( defined( 'PLL_CACHE_LANGUAGES' ) && ! PLL_CACHE_LANGUAGES ) || false === ( $languages = get_transient( 'pll_languages_list' ) ) ) { 
  45. $languages = get_terms( 'language', array( 'hide_empty' => false, 'orderby' => 'term_group' ) ); 
  46. $languages = empty( $languages ) || is_wp_error( $languages ) ? array() : $languages; 
  47.  
  48. $term_languages = get_terms( 'term_language', array( 'hide_empty' => false ) ); 
  49. $term_languages = empty( $term_languages ) || is_wp_error( $term_languages ) ? 
  50. array() : array_combine( wp_list_pluck( $term_languages, 'slug' ), $term_languages ); 
  51.  
  52. if ( ! empty( $languages ) && ! empty( $term_languages ) ) { 
  53. // don't use array_map + create_function to instantiate an autoloaded class as it breaks badly in old versions of PHP 
  54. foreach ( $languages as $k => $v ) { 
  55. $languages[ $k ] = new PLL_Language( $v, $term_languages[ 'pll_' . $v->slug ] ); 
  56.  
  57. // we will need the languages list to allow its access in the filter below 
  58. $this->cache->set( 'languages', $languages ); 
  59.  
  60. /** 
  61. * Filter the list of languages *before* it is stored in the persistent cache 
  62. * /!\ this filter is fired *before* the $polylang object is available 
  63. * @since 1.7.5 
  64. * @param array $languages the list of language objects 
  65. * @param object $model PLL_Model object 
  66. */ 
  67. $languages = apply_filters( 'pll_languages_list', $languages, $this ); 
  68.  
  69. // don't store directly objects as it badly break with some hosts ( GoDaddy ) due to race conditions when using object cache 
  70. // thanks to captin411 for catching this! 
  71. // see https://wordpress.org/support/topic/fatal-error-pll_model_languages_list?replies=8#post-6782255; 
  72. set_transient( 'pll_languages_list', array_map( 'get_object_vars', $languages ) ); 
  73. else { 
  74. $languages = array(); // in case something went wrong 
  75.  
  76. // create the languages directly from arrays stored in transients 
  77. else { 
  78. foreach ( $languages as $k => $v ) { 
  79. $languages[ $k ] = new PLL_Language( $v ); 
  80.  
  81. // custom flags 
  82. if ( ! PLL_ADMIN ) { 
  83. foreach ( $languages as $language ) { 
  84. $language->set_custom_flag(); 
  85.  
  86. /** 
  87. * Filter the list of languages *after* it is stored in the persistent cache 
  88. * /!\ this filter is fired *before* the $polylang object is available 
  89. * @since 1.8 
  90. * @param array $languages the list of language objects 
  91. */ 
  92. $languages = apply_filters( 'pll_after_languages_cache', $languages ); 
  93. $this->cache->set( 'languages', $languages ); 
  94.  
  95. $args = wp_parse_args( $args, array( 'hide_empty' => false ) ); 
  96.  
  97. // remove empty languages if requested 
  98. if ( $args['hide_empty'] ) { 
  99. $languages = wp_list_filter( $languages, array( 'count' => 0 ), 'NOT' ); 
  100.  
  101. return empty( $args['fields'] ) ? $languages : wp_list_pluck( $languages, $args['fields'] ); 
  102.  
  103. /** 
  104. * Cleans language cache 
  105. * can be called directly with no parameter 
  106. * called by the 'edited_term_taxonomy' filter with 2 parameters when count needs to be updated 
  107. * @since 1.2 
  108. * @param int $term not used 
  109. * @param string $taxonomy taxonomy name 
  110. */ 
  111. public function clean_languages_cache( $term = 0, $taxonomy = null ) { 
  112. if ( empty( $taxonomy ) || 'language' == $taxonomy ) { 
  113. delete_transient( 'pll_languages_list' ); 
  114. $this->cache->clean(); 
  115.  
  116. /** 
  117. * Returns the language by its term_id, tl_term_id, slug or locale 
  118. * @since 0.1 
  119. * @param int|string term_id, tl_term_id, slug or locale of the queried language 
  120. * @return object|bool PLL_Language object, false if no language found 
  121. */ 
  122. public function get_language( $value ) { 
  123. if ( is_object( $value ) ) { 
  124. return $value instanceof PLL_Language ? $value : $this->get_language( $value->term_id ); // will force cast to PLL_Language 
  125.  
  126. if ( false === $return = $this->cache->get( 'language:' . $value ) ) { 
  127. foreach ( $this->get_languages_list() as $lang ) { 
  128. $this->cache->set( 'language:' . $lang->term_id, $lang ); 
  129. $this->cache->set( 'language:' . $lang->tl_term_id, $lang ); 
  130. $this->cache->set( 'language:' . $lang->slug, $lang ); 
  131. $this->cache->set( 'language:' . $lang->locale, $lang ); 
  132. $return = $this->cache->get( 'language:' . $value ); 
  133.  
  134. return $return; 
  135.  
  136. /** 
  137. * Adds terms clauses to get_terms to filter them by languages - used in both frontend and admin 
  138. * @since 1.2 
  139. * @param array $clauses the list of sql clauses in terms query 
  140. * @param object $lang PLL_Language object 
  141. * @return array modifed list of clauses 
  142. */ 
  143. public function terms_clauses( $clauses, $lang ) { 
  144. if ( ! empty( $lang ) && false === strpos( $clauses['join'], 'pll_tr' ) ) { 
  145. $clauses['join'] .= $this->term->join_clause(); 
  146. $clauses['where'] .= $this->term->where_clause( $lang ); 
  147. return $clauses; 
  148.  
  149. /** 
  150. * Returns post types that need to be translated 
  151. * the post types list is cached for better better performance 
  152. * wait for 'after_setup_theme' to apply the cache to allow themes adding the filter in functions.php 
  153. * @since 1.2 
  154. * @param bool $filter true if we should return only valid registered post types 
  155. * @return array post type names for which Polylang manages languages and translations 
  156. */ 
  157. public function get_translated_post_types( $filter = true ) { 
  158. if ( false === $post_types = $this->cache->get( 'post_types' ) ) { 
  159. $post_types = array( 'post' => 'post', 'page' => 'page' ); 
  160.  
  161. if ( ! empty( $this->options['media_support'] ) ) { 
  162. $post_types['attachment'] = 'attachment'; 
  163.  
  164. if ( ! empty( $this->options['post_types'] ) && is_array( $this->options['post_types'] ) ) { 
  165. $post_types = array_merge( $post_types, array_combine( $this->options['post_types'], $this->options['post_types'] ) ); 
  166.  
  167. /** 
  168. * Filter the list of post types available for translation. 
  169. * The default are post types which have the parameter *public* set to true. 
  170. * The filter must be added soon in the WordPress loading process: 
  171. * in a function hooked to *plugins_loaded* or directly in functions.php for themes. 
  172. * @since 0.8 
  173. * @param array $post_types list of post type names 
  174. * @param bool $is_settings true when displaying the list of custom post types in Polylang settings 
  175. */ 
  176. $post_types = apply_filters( 'pll_get_post_types', $post_types, false ); 
  177.  
  178. if ( did_action( 'after_setup_theme' ) ) { 
  179. $this->cache->set( 'post_types', $post_types ); 
  180.  
  181. return $filter ? array_intersect( $post_types, get_post_types() ) : $post_types; 
  182.  
  183. /** 
  184. * Returns true if Polylang manages languages and translations for this post type 
  185. * @since 1.2 
  186. * @param string|array $post_type post type name or array of post type names 
  187. * @return bool 
  188. */ 
  189. public function is_translated_post_type( $post_type ) { 
  190. $post_types = $this->get_translated_post_types( false ); 
  191. return ( is_array( $post_type ) && array_intersect( $post_type, $post_types ) || in_array( $post_type, $post_types ) ); 
  192.  
  193. /** 
  194. * Return taxonomies that need to be translated 
  195. * @since 1.2 
  196. * @param bool $filter true if we should return only valid registered taxonmies 
  197. * @return array array of registered taxonomy names for which Polylang manages languages and translations 
  198. */ 
  199. public function get_translated_taxonomies( $filter = true ) { 
  200. if ( false === $taxonomies = $this->cache->get( 'taxonomies' ) ) { 
  201. $taxonomies = array( 'category' => 'category', 'post_tag' => 'post_tag' ); 
  202.  
  203. if ( ! empty( $this->options['taxonomies'] ) && is_array( $this->options['taxonomies'] ) ) { 
  204. $taxonomies = array_merge( $taxonomies, array_combine( $this->options['taxonomies'], $this->options['taxonomies'] ) ); 
  205.  
  206. /** 
  207. * Filter the list of taxonomies available for translation. 
  208. * The default are taxonomies which have the parameter *public* set to true. 
  209. * The filter must be added soon in the WordPress loading process: 
  210. * in a function hooked to *plugins_loaded* or directly in functions.php for themes. 
  211. * @since 0.8 
  212. * @param array $taxonomies list of taxonomy names 
  213. * @param bool $is_settings true when displaying the list of custom taxonomies in Polylang settings 
  214. */ 
  215. $taxonomies = apply_filters( 'pll_get_taxonomies', $taxonomies, false ); 
  216. if ( did_action( 'after_setup_theme' ) ) { 
  217. $this->cache->set( 'taxonomies', $taxonomies ); 
  218.  
  219. return $filter ? array_intersect( $taxonomies, get_taxonomies() ) : $taxonomies; 
  220.  
  221. /** 
  222. * Returns true if Polylang manages languages and translations for this taxonomy 
  223. * @since 1.2 
  224. * @param string|array $tax taxonomy name or array of taxonomy names 
  225. * @return bool 
  226. */ 
  227. public function is_translated_taxonomy( $tax ) { 
  228. $taxonomies = $this->get_translated_taxonomies( false ); 
  229. return ( is_array( $tax ) && array_intersect( $tax, $taxonomies ) || in_array( $tax, $taxonomies ) ); 
  230.  
  231. /** 
  232. * Check if translated taxonomy is queried 
  233. * Compatible with nested queries introduced in WP 4.1 
  234. * @see https://wordpress.org/support/topic/tax_query-bug 
  235. * @since 1.7 
  236. * @param array $tax_queries 
  237. * @return bool 
  238. */ 
  239. public function have_translated_taxonomy( $tax_queries ) { 
  240. foreach ( $tax_queries as $tax_query ) { 
  241. if ( isset( $tax_query['taxonomy'] ) && $this->is_translated_taxonomy( $tax_query['taxonomy'] ) && ! ( isset( $tax_query['operator'] ) && 'NOT IN' === $tax_query['operator'] ) ) { 
  242. return true; 
  243.  
  244. // Nested queries 
  245. elseif ( is_array( $tax_query ) && $this->have_translated_taxonomy( $tax_query ) ) { 
  246. return true; 
  247.  
  248. return false; 
  249.  
  250. /** 
  251. * Return taxonomies that need to be filtered ( post_format like ) 
  252. * @since 1.7 
  253. * @param bool $filter true if we should return only valid registered taxonomies 
  254. * @return array array of registered taxonomy names 
  255. */ 
  256. public function get_filtered_taxonomies( $filter = true ) { 
  257. if ( did_action( 'after_setup_theme' ) ) { 
  258. static $taxonomies = null; 
  259.  
  260. if ( empty( $taxonomies ) ) { 
  261. $taxonomies = array( 'post_format' => 'post_format' ); 
  262.  
  263. /** 
  264. * Filter the list of taxonomies not translatable but filtered by language. 
  265. * Includes only the post format by default 
  266. * The filter must be added soon in the WordPress loading process: 
  267. * in a function hooked to *plugins_loaded* or directly in functions.php for themes. 
  268. * @since 1.7 
  269. * @param array $taxonomies list of taxonomy names 
  270. * @param bool $is_settings true when displaying the list of custom taxonomies in Polylang settings 
  271. */ 
  272. $taxonomies = apply_filters( 'pll_filtered_taxonomies', $taxonomies, false ); 
  273.  
  274. return $filter ? array_intersect( $taxonomies, get_taxonomies() ) : $taxonomies; 
  275.  
  276. /** 
  277. * Returns true if Polylang filters this taxonomy per language 
  278. * @since 1.7 
  279. * @param string|array $tax taxonomy name or array of taxonomy names 
  280. * @return bool 
  281. */ 
  282. public function is_filtered_taxonomy( $tax ) { 
  283. $taxonomies = $this->get_filtered_taxonomies( false ); 
  284. return ( is_array( $tax ) && array_intersect( $tax, $taxonomies ) || in_array( $tax, $taxonomies ) ); 
  285.  
  286. /** 
  287. * Returns the query vars of all filtered taxonomies 
  288. * @since 1.7 
  289. * @return array 
  290. */ 
  291. public function get_filtered_taxonomies_query_vars() { 
  292. $query_vars = array(); 
  293. foreach ( $this->get_filtered_taxonomies() as $filtered_tax ) { 
  294. $tax = get_taxonomy( $filtered_tax ); 
  295. $query_vars[] = $tax->query_var; 
  296. return $query_vars; 
  297.  
  298. /** 
  299. * Create a default category for a language 
  300. * @since 1.2 
  301. * @param object|string|int $lang language 
  302. */ 
  303. public function create_default_category( $lang ) { 
  304. $lang = $this->get_language( $lang ); 
  305.  
  306. // create a new category 
  307. // FIXME this is translated in admin language when we would like it in $lang 
  308. $cat_name = __( 'Uncategorized' ); 
  309. $cat_slug = sanitize_title( $cat_name . '-' . $lang->slug ); 
  310. $cat = wp_insert_term( $cat_name, 'category', array( 'slug' => $cat_slug ) ); 
  311.  
  312. // check that the category was not previously created ( in case the language was deleted and recreated ) 
  313. $cat = isset( $cat->error_data['term_exists'] ) ? $cat->error_data['term_exists'] : $cat['term_id']; 
  314.  
  315. // set language 
  316. $this->term->set_language( (int) $cat, $lang ); 
  317.  
  318. // this is a translation of the default category 
  319. $default = (int) get_option( 'default_category' ); 
  320. $translations = $this->term->get_translations( $default ); 
  321. if ( empty( $translations ) ) { 
  322. if ( $lg = $this->term->get_language( $default ) ) { 
  323. $translations[ $lg->slug ] = $default; 
  324. else { 
  325. $translations = array(); 
  326.  
  327. $this->term->save_translations( (int) $cat, $translations ); 
  328.  
  329. /** 
  330. * It is possible to have several terms with the same name in the same taxonomy ( one per language ) 
  331. * but the native term_exists will return true even if only one exists 
  332. * so here the function adds the language parameter 
  333. * @since 1.4 
  334. * @param string $term_name the term name 
  335. * @param string $taxonomy taxonomy name 
  336. * @param int $parent parent term id 
  337. * @param string|object $language the language slug or object 
  338. * @return null|int the term_id of the found term 
  339. */ 
  340. public function term_exists( $term_name, $taxonomy, $parent, $language ) { 
  341. global $wpdb; 
  342.  
  343. $term_name = trim( wp_unslash( $term_name ) ); 
  344.  
  345. $select = "SELECT t.term_id FROM $wpdb->terms AS t"; 
  346. $join = " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"; 
  347. $join .= $this->term->join_clause(); 
  348. $where = $wpdb->prepare( ' WHERE tt.taxonomy = %s AND t.name = %s', $taxonomy, $term_name ); 
  349. $where .= $this->term->where_clause( $this->get_language( $language ) ); 
  350.  
  351. if ( $parent > 0 ) { 
  352. $where .= $wpdb->prepare( ' AND tt.parent = %d', $parent ); 
  353.  
  354. return $wpdb->get_var( $select . $join . $where ); 
  355.  
  356. /** 
  357. * Gets the number of posts per language in a date, author or post type archive 
  358. * @since 1.2 
  359. * @param object $lang 
  360. * @param array $q WP_Query arguments ( accepted: post_type, m, year, monthnum, day, author, author_name, post_format ) 
  361. * @return int 
  362. */ 
  363. public function count_posts( $lang, $q = array() ) { 
  364. global $wpdb; 
  365.  
  366. $q = wp_parse_args( $q, array( 'post_type' => 'post' ) ); 
  367.  
  368. if ( ! is_array( $q['post_type'] ) ) { 
  369. $q['post_type'] = array( $q['post_type'] ); 
  370.  
  371. foreach ( $q['post_type'] as $key => $type ) { 
  372. if ( ! post_type_exists( $type ) ) { 
  373. unset( $q['post_type'][ $key ] ); 
  374.  
  375. if ( empty( $q['post_type'] ) ) { 
  376. $q['post_type'] = array( 'post' ); // we *need* a post type 
  377.  
  378. $cache_key = md5( serialize( $q ) ); 
  379. $counts = wp_cache_get( $cache_key, 'pll_count_posts' ); 
  380.  
  381. if ( false === $counts ) { 
  382. $select = "SELECT pll_tr.term_taxonomy_id, COUNT( * ) AS num_posts FROM {$wpdb->posts}"; 
  383. $join = $this->post->join_clause(); 
  384. $where = " WHERE post_status = 'publish'"; 
  385. $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_type IN ( '%s' )", join( "', '", $q['post_type'] ) ); 
  386. $where .= $this->post->where_clause( $this->get_languages_list() ); 
  387. $groupby = ' GROUP BY pll_tr.term_taxonomy_id'; 
  388.  
  389. if ( ! empty( $q['m'] ) ) { 
  390. $q['m'] = '' . preg_replace( '|[^0-9]|', '', $q['m'] ); 
  391. $where .= $wpdb->prepare( " AND YEAR( {$wpdb->posts}.post_date ) = %d", substr( $q['m'], 0, 4 ) ); 
  392. if ( strlen( $q['m'] ) > 5 ) { 
  393. $where .= $wpdb->prepare( " AND MONTH( {$wpdb->posts}.post_date ) = %d", substr( $q['m'], 4, 2 ) ); 
  394. if ( strlen( $q['m'] ) > 7 ) { 
  395. $where .= $wpdb->prepare( " AND DAYOFMONTH( {$wpdb->posts}.post_date ) = %d", substr( $q['m'], 6, 2 ) ); 
  396.  
  397. if ( ! empty( $q['year'] ) ) { 
  398. $where .= $wpdb->prepare( " AND YEAR( {$wpdb->posts}.post_date ) = %d", $q['year'] ); 
  399.  
  400. if ( ! empty( $q['monthnum'] ) ) { 
  401. $where .= $wpdb->prepare( " AND MONTH( {$wpdb->posts}.post_date ) = %d", $q['monthnum'] ); 
  402.  
  403. if ( ! empty( $q['day'] ) ) { 
  404. $where .= $wpdb->prepare( " AND DAYOFMONTH( {$wpdb->posts}.post_date ) = %d", $q['day'] ); 
  405.  
  406. if ( ! empty( $q['author_name'] ) ) { 
  407. $author = get_user_by( 'slug', sanitize_title_for_query( $q['author_name'] ) ); 
  408. if ( $author ) { 
  409. $q['author'] = $author->ID; 
  410.  
  411. if ( ! empty( $q['author'] ) ) { 
  412. $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $q['author'] ); 
  413.  
  414. // filtered taxonomies ( post_format ) 
  415. foreach ( $this->get_filtered_taxonomies_query_vars() as $tax_qv ) { 
  416.  
  417. if ( ! empty( $q[ $tax_qv ] ) ) { 
  418. $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.object_id = {$wpdb->posts}.ID"; 
  419. $join .= " INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id"; 
  420. $join .= " INNER JOIN {$wpdb->terms} AS t ON t.term_id = tt.term_id"; 
  421. $where .= $wpdb->prepare( ' AND t.slug = %s', $q[ $tax_qv ] ); 
  422.  
  423. $res = $wpdb->get_results( $select . $join . $where . $groupby, ARRAY_A ); 
  424. foreach ( (array) $res as $row ) { 
  425. $counts[ $row['term_taxonomy_id'] ] = $row['num_posts']; 
  426.  
  427. wp_cache_set( $cache_key, $counts, 'pll_count_posts' ); 
  428.  
  429. return empty( $counts[ $lang->term_taxonomy_id ] ) ? 0 : $counts[ $lang->term_taxonomy_id ]; 
  430.  
  431. /** 
  432. * Setup the links model based on options 
  433. * @since 1.2 
  434. * @return object implementing "links_model interface" 
  435. */ 
  436. public function get_links_model() { 
  437. $c = array( 'Directory', 'Directory', 'Subdomain', 'Domain' ); 
  438. $class = get_option( 'permalink_structure' ) ? 'PLL_Links_' . $c[ $this->options['force_lang'] ] : 'PLL_Links_Default'; 
  439.  
  440. /** 
  441. * Filter the links model class to use 
  442. * /!\ this filter is fired *before* the $polylang object is available 
  443. * @since 2.1.1 
  444. * @param string $class A class name: PLL_Links_Default, PLL_Links_Directory, PLL_Links_Subdomain, PLL_Links_Domain 
  445. */ 
  446. $class = apply_filters( 'pll_links_model', $class ); 
  447.  
  448. return new $class( $this ); 
  449.  
  450. /** 
  451. * Some backward compatibility with Polylang < 1.8 
  452. * allows for example to call $polylang->model->get_post_languages( $post_id ) instead of $polylang->model->post->get_language( $post_id ) 
  453. * this works but should be slower than the direct call, thus an error is triggered in debug mode 
  454. * @since 1.8 
  455. * @param string $func function name 
  456. * @param array $args function arguments 
  457. */ 
  458. public function __call( $func, $args ) { 
  459. $f = $func; 
  460.  
  461. switch ( $func ) { 
  462. case 'get_object_term': 
  463. $o = false === strpos( $args[1], 'term' ) ? 'post' : 'term'; 
  464. break; 
  465.  
  466. case 'save_translations': 
  467. case 'delete_translation': 
  468. case 'get_translations': 
  469. case 'get_translation': 
  470. case 'join_clause': 
  471. $o = ( 'post' == $args[0] || $this->is_translated_post_type( $args[0] ) ) ? 'post' : ( 'term' == $args[0] || $this->is_translated_taxonomy( $args[0] ) ? 'term' : false ); 
  472. unset( $args[0] ); 
  473. break; 
  474.  
  475. case 'set_post_language': 
  476. case 'get_post_language': 
  477. case 'set_term_language': 
  478. case 'get_term_language': 
  479. case 'delete_term_language': 
  480. case 'get_post': 
  481. case 'get_term': 
  482. $str = explode( '_', $func ); 
  483. $f = empty( $str[2] ) ? $str[0] : $str[0] . '_' . $str[2]; 
  484. $o = $str[1]; 
  485. break; 
  486.  
  487. case 'where_clause': 
  488. case 'get_objects_in_language': 
  489. $o = $args[1]; 
  490. unset( $args[1] ); 
  491. break; 
  492.  
  493. if ( ! empty( $o ) && is_object( $this->$o ) && method_exists( $this->$o, $f ) ) { 
  494. if ( WP_DEBUG ) { 
  495. $debug = debug_backtrace(); 
  496. $i = 1 + empty( $debug[1]['line'] ); // the file and line are in $debug[2] if the function was called using call_user_func 
  497.  
  498. trigger_error( sprintf( 
  499. '%1$s was called incorrectly in %4$s on line %5$s: the call to $polylang->model->%1$s() has been deprecated in Polylang 1.8, use PLL()->model->%2$s->%3$s() instead.' . "\nError handler",  
  500. $func, $o, $f, $debug[ $i ]['file'], $debug[ $i ]['line'] 
  501. ) ); 
  502. return call_user_func_array( array( $this->$o, $f ), $args ); 
  503.  
  504. $debug = debug_backtrace(); 
  505. trigger_error( sprintf( 'Call to undefined function PLL()->model->%1$s() in %2$s on line %3$s' . "\nError handler", $func, $debug[0]['file'], $debug[0]['line'] ), E_USER_ERROR );