| @@ -1,169 +1,382 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -/** | |
| 4 | - * Base class for both admin and frontend | |
| 5 | - * | |
| 6 | - * @since 1.2 | |
| 7 | - */ | |
| 8 | -abstract class PLL_Base { | |
| 9 | - public $links_model, $model, $options; | |
| 3 | +// setups basic functions used for admin and frontend | |
| 4 | +abstract class Polylang_Base { | |
| 5 | + public $post_types; // post types to filter by language | |
| 6 | + public $taxonomies; // taxonomies to filter by language | |
| 7 | + public $is_ajax_on_front; | |
| 8 | + public $is_admin; | |
| 10 | 9 | |
| 11 | - /** | |
| 12 | - * Constructor | |
| 13 | - * | |
| 14 | - * @since 1.2 | |
| 15 | - * | |
| 16 | - * @param object $links_model | |
| 17 | - */ | |
| 18 | - public function __construct( &$links_model ) { | |
| 19 | - $this->links_model = &$links_model; | |
| 20 | - $this->model = &$links_model->model; | |
| 21 | - $this->options = &$this->model->options; | |
| 10 | + protected $options; | |
| 11 | + protected $home; | |
| 12 | + protected $using_permalinks; | |
| 13 | + protected $strings = array(); // strings to translate | |
| 22 | 14 | |
| 23 | - $GLOBALS['l10n_unloaded']['pll_string'] = true; // Short-circuit _load_textdomain_just_in_time() for 'pll_string' domain in WP 4.6+ | |
| 15 | + // used to cache results | |
| 16 | + // FIXME use wp_cache ? | |
| 17 | + private $languages_list = array(); | |
| 18 | + private $language = array(); | |
| 19 | + private $links = array(); | |
| 24 | 20 | |
| 25 | - add_action( 'widgets_init', array( $this, 'widgets_init' ) ); | |
| 21 | + function __construct() { | |
| 22 | + // avoid loading polylang admin filters for frontend ajax requests if 'pll_load_front' is set (thanks to g100g) | |
| 23 | + // FIXME should I permit plugins to overwrite this? | |
| 24 | + $this->is_ajax_on_front = defined('DOING_AJAX') && isset($_REQUEST['pll_load_front']); | |
| 25 | + $this->is_admin = defined('DOING_CRON') || (is_admin() && !$this->is_ajax_on_front); | |
| 26 | 26 | |
| 27 | - // User defined strings translations | |
| 28 | - add_action( 'pll_language_defined', array( $this, 'load_strings_translations' ), 5 ); | |
| 29 | - add_action( 'change_locale', array( $this, 'load_strings_translations' ) ); // Since WP 4.7 | |
| 27 | + // init options often needed | |
| 28 | + $this->options = get_option('polylang'); | |
| 29 | + $this->home = get_option('home'); | |
| 30 | + $this->using_permalinks = (bool) get_option('permalink_structure'); | |
| 30 | 31 | |
| 31 | - // Switch_to_blog | |
| 32 | - add_action( 'switch_blog', array( $this, 'switch_blog' ), 10, 2 ); | |
| 32 | + add_action('wp_loaded', array(&$this, 'add_post_types_taxonomies'), 1); // must come after 'init' to be sure that all post types and taxonomies are registered | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | - /** | |
| 36 | - * Instantiate classes always needed | |
| 37 | - * | |
| 38 | - * @since 2.6 | |
| 39 | - */ | |
| 40 | - public function init() { | |
| 41 | - // REST API | |
| 42 | - if ( class_exists( 'PLL_REST_API' ) ) { | |
| 43 | - $this->rest_api = new PLL_REST_API( $this ); | |
| 35 | + // init post types and taxonomies to filter by language | |
| 36 | + function add_post_types_taxonomies() { | |
| 37 | + $post_types = array('post', 'page'); | |
| 38 | + if (!empty($this->options['media_support'])) | |
| 39 | + $post_types[] = 'attachment'; | |
| 40 | + if (!empty($this->options['post_types'])) | |
| 41 | + $post_types = array_merge($post_types, $this->options['post_types']); | |
| 42 | + $this->post_types = apply_filters('pll_get_post_types', array_combine($post_types, $post_types), false); | |
| 43 | + | |
| 44 | + $taxonomies = array('category', 'post_tag', 'nav_menu'); | |
| 45 | + if (!empty($this->options['taxonomies'])) | |
| 46 | + $taxonomies = array_merge($taxonomies, $this->options['taxonomies']); | |
| 47 | + $this->taxonomies = apply_filters('pll_get_taxonomies', array_combine($taxonomies, $taxonomies), false); | |
| 48 | + } | |
| 49 | + | |
| 50 | + // returns the list of available languages | |
| 51 | + function get_languages_list($args = array()) { | |
| 52 | + // although get_terms is cached, it is efficient to add our own cache | |
| 53 | + // FIXME don't use on admin in case we modify the list of languages! | |
| 54 | + if (!$this->is_admin && isset($this->languages_list[$cache_key = md5(serialize($args))])) | |
| 55 | + return $this->languages_list[$cache_key]; | |
| 56 | + | |
| 57 | + $args = wp_parse_args($args, array('hide_empty' => false, 'orderby'=> 'term_group')); | |
| 58 | + $languages = get_terms('language', $args); | |
| 59 | + $languages = empty($languages) || is_wp_error($languages) ? array() : $languages; | |
| 60 | + return isset($cache_key) ? ($this->languages_list[$cache_key] = $languages) : $languages; | |
| 61 | + } | |
| 62 | + | |
| 63 | + // retrieves the dropdown list of the languages | |
| 64 | + function dropdown_languages($args = array()) { | |
| 65 | + $args = apply_filters('pll_dropdown_language_args', $args); | |
| 66 | + $defaults = array('name' => 'lang_choice', 'class' => '', 'add_options' => array(), 'hide_empty' => false, 'value' => 'slug', 'selected' => ''); | |
| 67 | + extract(wp_parse_args($args, $defaults)); | |
| 68 | + | |
| 69 | + // sort $add_options by value | |
| 70 | + uasort($add_options, create_function('$a, $b', "return \$a['value'] > \$b['value'];" )); | |
| 71 | + | |
| 72 | + $out = sprintf( | |
| 73 | + '<select name="%1$s" id="%1$s"%2$s>'."\n", | |
| 74 | + esc_attr($name), | |
| 75 | + $class ? ' class="'.esc_attr($class).'"' : '' | |
| 76 | + ); | |
| 77 | + | |
| 78 | + foreach ($add_options as $option) | |
| 79 | + $out .= sprintf( | |
| 80 | + '<option value="%s">%s</option>'."\n", | |
| 81 | + esc_attr($option['value']), | |
| 82 | + esc_html($option['text']) | |
| 83 | + ); | |
| 84 | + | |
| 85 | + foreach ($this->get_languages_list($args) as $language) { | |
| 86 | + $out .= sprintf( | |
| 87 | + '<option value="%s"%s>%s</option>'."\n", | |
| 88 | + esc_attr($language->$value), | |
| 89 | + $language->$value == $selected ? ' selected="selected"' : '', | |
| 90 | + esc_html($language->name) | |
| 91 | + ); | |
| 44 | 92 | } |
| 93 | + $out .= "</select>\n"; | |
| 94 | + return $out; | |
| 95 | + } | |
| 45 | 96 | |
| 46 | - if ( $this->model->get_languages_list() ) { | |
| 47 | - // Used by content duplicate and post synchronization | |
| 48 | - if ( class_exists( 'PLL_Sync_Content' ) ) { | |
| 49 | - $this->sync_content = new PLL_Sync_Content( $this ); | |
| 50 | - } | |
| 97 | + // returns the language by its id or its slug | |
| 98 | + // Note: it seems that get_term_by slug is not cached (3.2.1) | |
| 99 | + function get_language($value) { | |
| 100 | + if (is_object($value)) | |
| 101 | + return $value; | |
| 51 | 102 | |
| 52 | - // Active languages | |
| 53 | - if ( class_exists( 'PLL_Active_Languages' ) ) { | |
| 54 | - $this->active_languages = new PLL_Active_Languages( $this ); | |
| 55 | - } | |
| 103 | + if (isset($this->language[$value])) | |
| 104 | + return $this->language[$value]; | |
| 56 | 105 | |
| 57 | - // Share post slugs | |
| 58 | - if ( get_option( 'permalink_structure' ) && $this->options['force_lang'] && class_exists( 'PLL_Share_Post_Slug' ) ) { | |
| 59 | - $this->share_post_slug = new PLL_Share_Post_Slug( $this ); | |
| 60 | - } | |
| 106 | + $lang = (is_numeric($value) || (int) $value) ? get_term((int) $value, 'language') : | |
| 107 | + (is_string($value) ? get_term_by('slug', $value , 'language') : false); | |
| 108 | + | |
| 109 | + return !empty($lang) && !is_wp_error($lang) ? ($this->language[$value] = $lang) : false; | |
| 110 | + } | |
| 111 | + | |
| 112 | + // saves translations for posts or terms | |
| 113 | + // the underscore in '_lang' hides the post meta in the Custom Fields metabox in the Edit Post screen | |
| 114 | + // $type: either 'post' or 'term' | |
| 115 | + // $id: post id or term id | |
| 116 | + // $translations: an associative array of translations with language code as key and translation id as value | |
| 117 | + function save_translations($type, $id, $translations) { | |
| 118 | + $lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id); | |
| 119 | + if (!$lang) | |
| 120 | + return; | |
| 121 | + | |
| 122 | + if (isset($translations) && is_array($translations)) { | |
| 123 | + $translations = array_merge(array($lang->slug => $id), $translations); | |
| 124 | + foreach($translations as $p) | |
| 125 | + update_metadata($type, (int) $p, '_translations', $translations); | |
| 61 | 126 | } |
| 62 | 127 | } |
| 63 | 128 | |
| 64 | - /** | |
| 65 | - * Registers our widgets | |
| 66 | - * | |
| 67 | - * @since 0.1 | |
| 68 | - */ | |
| 69 | - public function widgets_init() { | |
| 70 | - register_widget( 'PLL_Widget_Languages' ); | |
| 129 | + // deletes a translation of a post or term | |
| 130 | + function delete_translation($type, $id) { | |
| 131 | + $translations = $this->get_translations($type, $id); | |
| 132 | + if (is_array($translations)) { | |
| 133 | + $slug = array_search($id, $translations); | |
| 134 | + unset($translations[$slug]); | |
| 135 | + foreach($translations as $p) | |
| 136 | + update_metadata($type, (int) $p, '_translations', $translations); | |
| 137 | + delete_metadata($type, $id, '_translations'); | |
| 138 | + } | |
| 139 | + } | |
| 71 | 140 | |
| 72 | - // Overwrites the calendar widget to filter posts by language | |
| 73 | - if ( ! defined( 'PLL_WIDGET_CALENDAR' ) || PLL_WIDGET_CALENDAR ) { | |
| 74 | - unregister_widget( 'WP_Widget_Calendar' ); | |
| 75 | - register_widget( 'PLL_Widget_Calendar' ); | |
| 141 | + // returns the id of the translation of a post or term | |
| 142 | + // $type: either 'post' or 'term' | |
| 143 | + // $id: post id or term id | |
| 144 | + // $lang: object or slug (in the order of preference latest to avoid) | |
| 145 | + function get_translation($type, $id, $lang) { | |
| 146 | + $translations = $this->get_translations($type, $id); | |
| 147 | + $slug = $this->get_language($lang)->slug; | |
| 148 | + return isset($translations[$slug]) ? (int) $translations[$slug] : false; | |
| 149 | + } | |
| 150 | + | |
| 151 | + // returns an array of translations of a post or term | |
| 152 | + function get_translations($type, $id) { | |
| 153 | + $type = ($type == 'post' || in_array($type, $this->post_types)) ? 'post' : (($type == 'term' || in_array($type, $this->taxonomies)) ? 'term' : false); | |
| 154 | + // maybe_unserialize due to useless serialization in versions < 0.9 | |
| 155 | + return $type && ($meta = get_metadata($type, $id, '_translations', true)) ? maybe_unserialize($meta) : array(); | |
| 156 | + } | |
| 157 | + | |
| 158 | + // store the post language in the database | |
| 159 | + function set_post_language($post_id, $lang) { | |
| 160 | + wp_set_post_terms($post_id, $lang ? $this->get_language($lang)->slug : '', 'language' ); | |
| 161 | + } | |
| 162 | + | |
| 163 | + // returns the language of a post | |
| 164 | + function get_post_language($post_id) { | |
| 165 | + $lang = get_the_terms($post_id, 'language' ); | |
| 166 | + return ($lang) ? reset($lang) : false; // there's only one language per post : first element of the array returned | |
| 167 | + } | |
| 168 | + | |
| 169 | + // among the post and its translations, returns the id of the post which is in $lang | |
| 170 | + function get_post($post_id, $lang) { | |
| 171 | + $post_lang = $this->get_post_language($post_id); | |
| 172 | + if (!$lang || !$post_lang) | |
| 173 | + return false; | |
| 174 | + | |
| 175 | + $lang = $this->get_language($lang); | |
| 176 | + return $post_lang->term_id == $lang->term_id ? $post_id : $this->get_translation('post', $post_id, $lang); | |
| 177 | + } | |
| 178 | + | |
| 179 | + // store the term language in the database | |
| 180 | + function set_term_language($term_id, $lang) { | |
| 181 | + update_metadata('term', $term_id, '_language', $lang ? $this->get_language($lang)->term_id : 0); | |
| 182 | + } | |
| 183 | + | |
| 184 | + // remove the term language in the database | |
| 185 | + function delete_term_language($term_id) { | |
| 186 | + delete_metadata('term', $term_id, '_language'); | |
| 187 | + } | |
| 188 | + | |
| 189 | + // returns the language of a term | |
| 190 | + function get_term_language($value, $taxonomy = '') { | |
| 191 | + if (is_numeric($value)) | |
| 192 | + $term_id = $value; | |
| 193 | + | |
| 194 | + elseif (is_string($value) && $taxonomy) | |
| 195 | + $term_id = get_term_by('slug', $value , $taxonomy)->term_id; | |
| 196 | + | |
| 197 | + return empty($term_id) ? false : $this->get_language(get_metadata('term', $term_id, '_language', true)); | |
| 198 | + } | |
| 199 | + | |
| 200 | + // among the term and its translations, returns the id of the term which is in $lang | |
| 201 | + function get_term($term_id, $lang) { | |
| 202 | + $lg = $this->get_term_language($term_id); | |
| 203 | + if (!$lang || !$lg) | |
| 204 | + return false; | |
| 205 | + | |
| 206 | + $lang = $this->get_language($lang); | |
| 207 | + return $lg->term_id == $lang->term_id ? $term_id : $this->get_translation('term', $term_id, $lang); | |
| 208 | + } | |
| 209 | + | |
| 210 | + // adds language information to a link when using pretty permalinks | |
| 211 | + function add_language_to_link($url, $lang) { | |
| 212 | + if (empty($lang)) | |
| 213 | + return $url; | |
| 214 | + | |
| 215 | + global $wp_rewrite; | |
| 216 | + if ($this->using_permalinks) { | |
| 217 | + $base = $this->options['rewrite'] ? '' : 'language/'; | |
| 218 | + $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base.$lang->slug.'/'; | |
| 219 | + return esc_url(str_replace($this->home.'/'.$wp_rewrite->root, $this->home.'/'.$wp_rewrite->root.$slug, $url)); | |
| 76 | 220 | } |
| 221 | + | |
| 222 | + // special case for pages which do not accept adding the lang parameter | |
| 223 | + elseif ('_get_page_link' != current_filter()) | |
| 224 | + return esc_url(add_query_arg( 'lang', $lang->slug, $url )); | |
| 225 | + | |
| 226 | + return $url; | |
| 77 | 227 | } |
| 78 | 228 | |
| 79 | - /** | |
| 80 | - * Loads user defined strings translations | |
| 81 | - * | |
| 82 | - * @since 1.2 | |
| 83 | - * @since 2.1.3 $locale parameter added. | |
| 84 | - * | |
| 85 | - * @param string $locale Locale. Defaults to current locale. | |
| 86 | - */ | |
| 87 | - public function load_strings_translations( $locale = '' ) { | |
| 88 | - if ( empty( $locale ) ) { | |
| 89 | - $locale = get_locale(); | |
| 229 | + // optionally rewrite posts, pages links to filter them by language | |
| 230 | + // rewrite post format (and optionally categories and post tags) archives links to filter them by language | |
| 231 | + function add_post_term_link_filters() { | |
| 232 | + if ($this->options['force_lang'] && $this->using_permalinks) { | |
| 233 | + foreach (array('post_link', '_get_page_link', 'post_type_link') as $filter) | |
| 234 | + add_filter($filter, array(&$this, 'post_link'), 10, 2); | |
| 90 | 235 | } |
| 91 | 236 | |
| 92 | - $language = $this->model->get_language( $locale ); | |
| 237 | + add_filter('term_link', array(&$this, 'term_link'), 10, 3); | |
| 238 | + } | |
| 93 | 239 | |
| 94 | - if ( ! empty( $language ) ) { | |
| 95 | - $mo = new PLL_MO(); | |
| 96 | - $mo->import_from_db( $language ); | |
| 97 | - $GLOBALS['l10n']['pll_string'] = &$mo; | |
| 98 | - } else { | |
| 99 | - unset( $GLOBALS['l10n']['pll_string'] ); | |
| 240 | + // modifies post & page links | |
| 241 | + function post_link($link, $post) { | |
| 242 | + if (isset($this->links[$link])) | |
| 243 | + return $this->links[$link]; | |
| 244 | + | |
| 245 | + if ('post_type_link' == current_filter() && !in_array($post->post_type, $this->post_types)) | |
| 246 | + return $this->links[$link] = $link; | |
| 247 | + | |
| 248 | + if ('_get_page_link' == current_filter()) // this filter uses the ID instead of the post object | |
| 249 | + $post = get_post($post); | |
| 250 | + | |
| 251 | + // /!\ when post_status in not "publish", WP does not use pretty permalinks | |
| 252 | + return $this->links[$link] = $post->post_status != 'publish' ? $link : $this->add_language_to_link($link, $this->get_post_language($post->ID)); | |
| 253 | + } | |
| 254 | + | |
| 255 | + // modifies term link | |
| 256 | + function term_link($link, $term, $tax) { | |
| 257 | + if (isset($this->links[$link])) | |
| 258 | + return $this->links[$link]; | |
| 259 | + | |
| 260 | + return $this->links[$link] = ($tax == 'post_format' || ($this->options['force_lang'] && $this->using_permalinks && in_array($tax, $this->taxonomies))) ? | |
| 261 | + $this->add_language_to_link($link, $this->get_term_language($term->term_id)) : $link; | |
| 262 | + } | |
| 263 | + | |
| 264 | + // returns the html link to the flag if exists | |
| 265 | + // $lang: object | |
| 266 | + function get_flag($lang, $url_only = false) { | |
| 267 | + if (file_exists(POLYLANG_DIR.($file = '/flags/'.$lang->description.'.png'))) | |
| 268 | + $url = POLYLANG_URL.$file; | |
| 269 | + | |
| 270 | + // overwrite with custom flags | |
| 271 | + // never use custom flags on admin side | |
| 272 | + if (!$this->is_admin && ( file_exists(PLL_LOCAL_DIR.($file = '/'.$lang->description.'.png')) || file_exists(PLL_LOCAL_DIR.($file = '/'.$lang->description.'.jpg')) )) | |
| 273 | + $url = PLL_LOCAL_URL.$file; | |
| 274 | + | |
| 275 | + return apply_filters('pll_get_flag', empty($url) ? '' : | |
| 276 | + ($url_only ? $url : | |
| 277 | + sprintf( | |
| 278 | + '<img src="%s" title="%s" alt="%s" />', | |
| 279 | + esc_url($url), | |
| 280 | + esc_attr(apply_filters('pll_flag_title', $lang->name, $lang->slug, $lang->description)), | |
| 281 | + esc_attr($lang->name) | |
| 282 | + ))); | |
| 283 | + } | |
| 284 | + | |
| 285 | + // get languages term_ids or term_taxonomy_ids for use in sql queries | |
| 286 | + function _get_languages_for_sql($lang, $field) { | |
| 287 | + global $wpdb; | |
| 288 | + // the query is coming from Polylang and the $lang is an object | |
| 289 | + if (is_object($lang)) | |
| 290 | + return $field == 'term_id' ? "'" . $lang->$field . "'" : $lang->$field; | |
| 291 | + | |
| 292 | + // the query is coming from outside with 'lang' parameter and $lang is a comma separated list of slugs (or an array of slugs) | |
| 293 | + $languages = is_array($lang) ? $lang : explode(',', $lang); | |
| 294 | + $languages = "'" . implode("','", array_map( 'sanitize_title_for_query', $languages)) . "'"; | |
| 295 | + $languages = $wpdb->get_col(" | |
| 296 | + SELECT $wpdb->term_taxonomy.$field FROM $wpdb->term_taxonomy | |
| 297 | + INNER JOIN $wpdb->terms USING (term_id) | |
| 298 | + WHERE taxonomy = 'language' AND $wpdb->terms.slug IN ($languages) | |
| 299 | + "); // get ids from slugs | |
| 300 | + | |
| 301 | + if ($field == 'term_id') | |
| 302 | + $languages = array_map(create_function('$v', 'return "\'" . $v . "\'";'), $languages); | |
| 303 | + | |
| 304 | + return implode(',', $languages); | |
| 305 | + } | |
| 306 | + | |
| 307 | + // adds clauses to comments query - used in both frontend and admin | |
| 308 | + function _comments_clauses($clauses, $lang) { | |
| 309 | + global $wpdb; | |
| 310 | + if (!empty($lang)) { | |
| 311 | + // if this clause is not already added by WP | |
| 312 | + if (!strpos($clauses['join'], '.ID')) | |
| 313 | + $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID"; | |
| 314 | + | |
| 315 | + $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = ID"; | |
| 316 | + $clauses['where'] .= " AND pll_tr.term_taxonomy_id IN (" . $this->_get_languages_for_sql($lang, 'term_taxonomy_id') . ")"; | |
| 100 | 317 | } |
| 318 | + return $clauses; | |
| 101 | 319 | } |
| 102 | 320 | |
| 103 | - /** | |
| 104 | - * Resets some variables when switching blog | |
| 105 | - * Applies only if Polylang is active on the new blog | |
| 106 | - * | |
| 107 | - * @since 1.5.1 | |
| 108 | - * | |
| 109 | - * @param int $new_blog | |
| 110 | - * @param int $old_blog | |
| 111 | - * @return bool not used by WP but by child class | |
| 112 | - */ | |
| 113 | - public function switch_blog( $new_blog, $old_blog ) { | |
| 114 | - $plugins = ( $sitewide_plugins = get_site_option( 'active_sitewide_plugins' ) ) && is_array( $sitewide_plugins ) ? array_keys( $sitewide_plugins ) : array(); | |
| 115 | - $plugins = array_merge( $plugins, get_option( 'active_plugins', array() ) ); | |
| 321 | + // adds terms clauses to get_terms - used in both frontend and admin | |
| 322 | + function _terms_clauses($clauses, $lang) { | |
| 323 | + global $wpdb; | |
| 324 | + if (!empty($lang)) { | |
| 325 | + $clauses['join'] .= " LEFT JOIN $wpdb->termmeta AS pll_tm ON t.term_id = pll_tm.term_id"; | |
| 326 | + $clauses['where'] .= " AND pll_tm.meta_key = '_language' AND pll_tm.meta_value IN (" . $this->_get_languages_for_sql($lang, 'term_id') . ")"; | |
| 327 | + } | |
| 328 | + return $clauses; | |
| 329 | + } | |
| 116 | 330 | |
| 117 | - // 2nd test needed when Polylang is not networked activated | |
| 118 | - // 3rd test needed when Polylang is networked activated and a new site is created | |
| 119 | - if ( $new_blog != $old_blog && in_array( POLYLANG_BASENAME, $plugins ) && get_option( 'polylang' ) ) { | |
| 120 | - $this->options = get_option( 'polylang' ); // Needed for menus | |
| 121 | - remove_action( 'pre_option_rewrite_rules', array( $this->links_model, 'prepare_rewrite_rules' ) ); | |
| 122 | - $this->links_model = $this->model->get_links_model(); | |
| 123 | - return true; | |
| 124 | - } | |
| 125 | - return false; | |
| 331 | + // returns all page ids *not in* language defined by $lang_id | |
| 332 | + function exclude_pages($lang_id) { | |
| 333 | + return get_posts(array( | |
| 334 | + 'lang' => 0, // so this query is not filtered by our pre_get_post filter in core.php | |
| 335 | + 'numberposts' => -1, | |
| 336 | + 'nopaging' => true, | |
| 337 | + 'post_type' => array_intersect(get_post_types(array('hierarchical' => 1)), $this->post_types), | |
| 338 | + 'fields' => 'ids', | |
| 339 | + 'tax_query' => array(array( | |
| 340 | + 'taxonomy' => 'language', | |
| 341 | + 'terms' => $lang_id, | |
| 342 | + 'operator' => 'NOT IN' | |
| 343 | + )) | |
| 344 | + )); | |
| 126 | 345 | } |
| 127 | 346 | |
| 128 | - /** | |
| 129 | - * Some backward compatibility with Polylang < 1.2 | |
| 130 | - * Allows for example to call $polylang->get_languages_list() instead of $polylang->model->get_languages_list() | |
| 131 | - * This works but should be slower than the direct call, thus an error is triggered in debug mode | |
| 132 | - * | |
| 133 | - * @since 1.2 | |
| 134 | - * | |
| 135 | - * @param string $func function name | |
| 136 | - * @param array $args function arguments | |
| 137 | - */ | |
| 138 | - public function __call( $func, $args ) { | |
| 139 | - foreach ( $this as $prop => &$obj ) { | |
| 140 | - if ( is_object( $obj ) && method_exists( $obj, $func ) ) { | |
| 141 | - if ( WP_DEBUG ) { | |
| 142 | - $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions | |
| 143 | - $i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func | |
| 144 | - trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions | |
| 145 | - sprintf( | |
| 146 | - '%1$s was called incorrectly in %3$s on line %4$s: the call to $polylang->%1$s() has been deprecated in Polylang 1.2, use PLL()->%2$s->%1$s() instead.' . "\nError handler", | |
| 147 | - esc_html( $func ), | |
| 148 | - esc_html( $prop ), | |
| 149 | - esc_html( $debug[ $i ]['file'] ), | |
| 150 | - absint( $debug[ $i ]['line'] ) | |
| 151 | - ) | |
| 152 | - ); | |
| 153 | - } | |
| 154 | - return call_user_func_array( array( $obj, $func ), $args ); | |
| 155 | - } | |
| 347 | + // export a mo object in options | |
| 348 | + function mo_export($mo, $lang) { | |
| 349 | + $strings = array(); | |
| 350 | + foreach ($mo->entries as $entry) | |
| 351 | + $strings[] = array($entry->singular, $mo->translate($entry->singular)); | |
| 352 | + update_option('polylang_mo'.$lang->term_id, $strings); | |
| 353 | + } | |
| 354 | + | |
| 355 | + // import a mo object from options | |
| 356 | + function mo_import($lang) { | |
| 357 | + $mo = new MO(); | |
| 358 | + if ($strings = get_option('polylang_mo'.$lang->term_id)) { | |
| 359 | + foreach ($strings as $msg) | |
| 360 | + $mo->add_entry($mo->make_entry($msg[0], $msg[1])); | |
| 156 | 361 | } |
| 362 | + return $mo; | |
| 363 | + } | |
| 157 | 364 | |
| 158 | - $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions | |
| 159 | - trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions | |
| 160 | - sprintf( | |
| 161 | - 'Call to undefined function PLL()->%1$s() in %2$s on line %3$s' . "\nError handler", | |
| 162 | - esc_html( $func ), | |
| 163 | - esc_html( $debug[0]['file'] ), | |
| 164 | - absint( $debug[0]['line'] ) | |
| 165 | - ), | |
| 166 | - E_USER_ERROR | |
| 365 | + // list the post metas to synchronize | |
| 366 | + static function list_metas_to_sync() { | |
| 367 | + return array( | |
| 368 | + 'taxonomies' => __('Taxonomies', 'polylang'), | |
| 369 | + 'post_meta' => __('Custom fields', 'polylang'), | |
| 370 | + 'comment_status' => __('Comment status', 'polylang'), | |
| 371 | + 'ping_status' => __('Ping status', 'polylang'), | |
| 372 | + 'sticky_posts' => __('Sticky posts', 'polylang'), | |
| 373 | + 'post_date' => __('Published date', 'polylang'), | |
| 374 | + 'post_format' => __('Post format', 'polylang'), | |
| 375 | + 'post_parent' => __('Page parent', 'polylang'), | |
| 376 | + '_wp_page_template' => __('Page template', 'polylang'), | |
| 377 | + 'menu_order' => __('Page order', 'polylang'), | |
| 378 | + '_thumbnail_id' => __('Featured image', 'polylang'), | |
| 167 | 379 | ); |
| 168 | 380 | } |
| 169 | -} | |
| 381 | + | |
| 382 | +} //class Polylang_Base | |