PluginProbe
Polylang / 0.9.2
Polylang v0.9.2
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 / base.php

base.php in Polylang 0.9.2, at include/base.php

289 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // setups basic functions used for admin and frontend
4 abstract class Polylang_Base {
5 protected $options;
6 protected $home;
7 protected $strings = array(); // strings to translate
8 protected $post_types; // post types to filter by language
9 protected $taxonomies; // taxonomies to filter by language
10
11 // used to cache results
12 private $languages_list = array();
13 private $links = array();
14
15 function __construct() {
16 // init options often needed
17 $this->options = get_option('polylang');
18 $this->home = get_option('home');
19
20 add_action('wp_loaded', array(&$this, 'add_post_types_taxonomies')); // must come late to be sure that all post types and taxonomies are registered
21 }
22
23 // init post types and taxonomies to filter by language
24 function add_post_types_taxonomies() {
25 $post_types = array_merge(PLL_MEDIA_SUPPORT ? array('attachment' => 'attachment') : array(), get_post_types(array('show_ui' => true)));
26 $this->post_types = apply_filters('pll_get_post_types', $post_types);
27 $this->taxonomies = apply_filters('pll_get_taxonomies', get_taxonomies(array('show_ui'=>true)));
28 }
29
30 // returns the list of available languages
31 function get_languages_list($args = array()) {
32 // although get_terms is cached, it is efficient to add our own cache
33 if (isset($this->languages_list[$cache_key = md5(serialize($args))]))
34 return $this->languages_list[$cache_key];
35
36 $defaults = array('hide_empty' => false, 'orderby'=> 'term_group');
37 $args = wp_parse_args($args, $defaults);
38 return $this->languages_list[$cache_key] = get_terms('language', $args);
39 }
40
41 // retrieves the dropdown list of the languages
42 function dropdown_languages($args = array()) {
43 $args = apply_filters('pll_dropdown_language_args', $args);
44 $defaults = array('name' => 'lang_choice', 'class' => '', 'add_option' => false, 'hide_empty' => false, 'value' => 'slug', 'selected' => '');
45 extract(wp_parse_args($args, $defaults));
46
47 $out = sprintf('<select name="%1$s" id="%1$s"%2$s>'."\n", esc_attr($name), $class ? ' class="'.esc_attr($class).'"' : '');
48 $out .= $add_option !== false ? "<option value='0'>$add_option</option>\n" : '';
49 foreach ($this->get_languages_list($args) as $language) {
50 $out .= sprintf("<option value='%s'%s>%s</option>\n",
51 esc_attr($language->$value),
52 $language->$value == $selected ? ' selected="selected"' : '',
53 esc_html($language->name)
54 );
55 }
56 $out .= "</select>\n";
57 return $out;
58 }
59
60 // returns the language by its id or its slug
61 // Note: it seems that a numeric value is better for performance (3.2.1)
62 function get_language($value) {
63 $lang = is_object($value) ? $value :
64 ((is_numeric($value) || (int) $value) ? get_term((int) $value, 'language') :
65 (is_string($value) ? get_term_by('slug', $value , 'language') : // seems it is not cached in 3.2.1
66 false));
67 return isset($lang) && $lang && !is_wp_error($lang) ? $lang : false;
68 }
69
70 // saves translations for posts or terms
71 // the underscore in '_lang' hides the post meta in the Custom Fields metabox in the Edit Post screen
72 // $type: either 'post' or 'term'
73 // $id: post id or term id
74 // $translations: an associative array of translations with language code as key and translation id as value
75 function save_translations($type, $id, $translations) {
76 $lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id);
77 if (!$lang)
78 return;
79
80 if (isset($translations) && is_array($translations)) {
81 $translations = array_merge(array($lang->slug => $id), $translations);
82 foreach($translations as $key=>$p)
83 update_metadata($type, (int) $p, '_translations', $translations);
84 }
85 }
86
87 // deletes a translation of a post or term
88 function delete_translation($type, $id) {
89 $translations = $this->get_translations($type, $id);
90 if (is_array($translations)) {
91 $slug = array_search($id, $translations);
92 unset($translations[$slug]);
93 foreach($translations as $p)
94 update_metadata($type, (int) $p, '_translations', $translations);
95 delete_metadata($type, $id, '_translations');
96 }
97 }
98
99 // returns the id of the translation of a post or term
100 // $type: either 'post' or 'term'
101 // $id: post id or term id
102 // $lang: object or slug (in the order of preference latest to avoid)
103 function get_translation($type, $id, $lang) {
104 $translations = $this->get_translations($type, $id);
105 $slug = $this->get_language($lang)->slug;
106 return isset($translations[$slug]) ? (int) $translations[$slug] : false;
107 }
108
109 // returns an array of translations of a post or term
110 function get_translations($type, $id) {
111 // maybe_unserialize due to useless serialization in versions < 0.9
112 return maybe_unserialize(get_metadata($type, $id, '_translations', true));
113 }
114
115 // store the post language in the database
116 function set_post_language($post_id, $lang) {
117 wp_set_post_terms($post_id, $lang ? $this->get_language($lang)->slug : '', 'language' );
118 }
119
120 // returns the language of a post
121 function get_post_language($post_id) {
122 $lang = get_the_terms($post_id, 'language' );
123 return ($lang) ? reset($lang) : false; // there's only one language per post : first element of the array returned
124 }
125
126 // among the post and its translations, returns the id of the post which is in $lang
127 function get_post($post_id, $lang) {
128 $post_lang = $this->get_post_language($post_id);
129 if (!$lang || !$post_lang)
130 return false;
131
132 $lang = $this->get_language($lang);
133 return $post_lang->term_id == $lang->term_id ? $post_id : $this->get_translation('post', $post_id, $lang);
134 }
135
136 // store the term language in the database
137 function set_term_language($term_id, $lang) {
138 update_metadata('term', $term_id, '_language', $lang ? $this->get_language($lang)->term_id : 0);
139 }
140
141 // remove the term language in the database
142 function delete_term_language($term_id) {
143 delete_metadata('term', $term_id, '_language');
144 }
145
146 // returns the language of a term
147 function get_term_language($value, $taxonomy = '') {
148 if (is_numeric($value))
149 $term_id = $value;
150 elseif (is_string($value) && $taxonomy)
151 $term_id = get_term_by('slug', $value , $taxonomy)->term_id;
152 return $term_id ? $this->get_language(get_metadata('term', $term_id, '_language', true)) : false;
153 }
154
155 // among the term and its translations, returns the id of the term which is in $lang
156 function get_term($term_id, $lang) {
157 $lg = $this->get_term_language($term_id);
158 if (!$lang || !$lg)
159 return false;
160
161 $lang = $this->get_language($lang);
162 return $lg->term_id == $lang->term_id ? $term_id : $this->get_translation('term', $term_id, $lang);
163 }
164
165 // adds language information to a link when using pretty permalinks
166 function add_language_to_link($url, $lang) {
167 if (!isset($lang) || !$lang)
168 return $url;
169
170 global $wp_rewrite;
171 if ($wp_rewrite->using_permalinks()) {
172 $base = $this->options['rewrite'] ? '' : 'language/';
173 $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base.$lang->slug.'/';
174 return esc_url(str_replace($this->home.'/'.$wp_rewrite->root, $this->home.'/'.$wp_rewrite->root.$slug, $url));
175 }
176
177 // special case for pages which do not accept adding the lang parameter
178 elseif ('_get_page_link' != current_filter())
179 return add_query_arg( 'lang', $lang->slug, $url );
180
181 return $url;
182 }
183
184 // optionally rewrite posts, pages links to filter them by language
185 // rewrite post format (and optionally categories and post tags) archives links to filter them by language
186 function add_post_term_link_filters() {
187 if ($this->options['force_lang'] && $GLOBALS['wp_rewrite']->using_permalinks()) {
188 foreach (array('post_link', '_get_page_link', 'post_type_link') as $filter)
189 add_filter($filter, array(&$this, 'post_link'), 10, 2);
190 }
191
192 add_filter('term_link', array(&$this, 'term_link'), 10, 3);
193 }
194
195 // modifies post & page links
196 function post_link($link, $post) {
197 if (isset($this->links[$link]))
198 return $this->links[$link];
199
200 return $this->links[$link] = ('post_type_link' == current_filter() && !in_array($post->post_type, $this->post_types)) ?
201 $link : $this->add_language_to_link($link, $this->get_post_language('_get_page_link' == current_filter() ? $post : $post->ID));
202 }
203
204 // modifies term link
205 function term_link($link, $term, $tax) {
206 if (isset($this->links[$link]))
207 return $this->links[$link];
208
209 $ok = $tax == 'post_format' || ($this->options['force_lang'] && $GLOBALS['wp_rewrite']->using_permalinks() && in_array($tax, $this->taxonomies));
210 return $this->links[$link] = $ok ? $this->add_language_to_link($link, $this->get_term_language($term->term_id)) : $link;
211 }
212
213 // returns the html link to the flag if exists
214 // $lang: object
215 function get_flag($lang) {
216 if (file_exists(POLYLANG_DIR.($file = '/flags/'.$lang->description.'.png')))
217 $url = POLYLANG_URL.$file;
218
219 // overwrite with custom flags
220 if (!is_admin() && ( // never use custom flags on admin side
221 file_exists(PLL_LOCAL_DIR.($file = '/'.$lang->description.'.png')) ||
222 file_exists(PLL_LOCAL_DIR.($file = '/'.$lang->description.'.jpg')) ))
223 $url = PLL_LOCAL_URL.$file;
224
225 $title = apply_filters('pll_flag_title', $lang->name, $lang->slug, $lang->description);
226 return isset($url) ? '<img src="'.esc_url($url).'" title="'.esc_attr($title).'" alt="'.esc_attr($lang->name).'" />' : '';
227 }
228
229 // adds clauses to comments query - used in both frontend and admin
230 function _comments_clauses($clauses, $lang) {
231 global $wpdb;
232
233 // if this clause is not already added by WP
234 if (!strpos($clauses['join'], '.ID'))
235 $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
236
237 $clauses['join'] .= " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = ID";
238 $clauses['where'] .= $wpdb->prepare(" AND pll_tr.term_taxonomy_id = %d", $lang->term_taxonomy_id);
239
240 return $clauses;
241 }
242
243 // adds terms clauses to get_terms - used in both frontend and admin
244 function _terms_clauses($clauses, $lang) {
245 global $wpdb;
246 if (isset($lang) && $lang) {
247 $clauses['join'] .= $wpdb->prepare(" LEFT JOIN $wpdb->termmeta AS pll_tm ON t.term_id = pll_tm.term_id");
248 $clauses['where'] .= $wpdb->prepare(" AND pll_tm.meta_key = '_language' AND pll_tm.meta_value IN ($lang->term_id)");
249 }
250 return $clauses;
251 }
252
253 // returns all page ids *not in* language defined by $lang_id
254 function exclude_pages($lang_id) {
255 $q = array(
256 'numberposts' => -1,
257 'post_type' => array_intersect(get_post_types(array('hierarchical' => 1)), $this->post_types),
258 'fields' => 'ids',
259 'tax_query' => array(array(
260 'taxonomy' => 'language',
261 'fields' => 'id',
262 'terms' => $lang_id,
263 'operator' => 'NOT IN'
264 ))
265 );
266 return get_posts($q);
267 }
268
269 // export a mo object in options
270 function mo_export($mo, $lang) {
271 $strings = array();
272 foreach ($mo->entries as $entry)
273 $strings[] = array($entry->singular, $mo->translate($entry->singular));
274 update_option('polylang_mo'.$lang->term_id, $strings);
275 }
276
277 // import a mo object from options
278 function mo_import($lang) {
279 $mo = new MO();
280 if ($strings = get_option('polylang_mo'.$lang->term_id)) {
281 foreach ($strings as $msg)
282 $mo->add_entry($mo->make_entry($msg[0], $msg[1]));
283 }
284 return $mo;
285 }
286
287 } //class Polylang_Base
288 ?>
289