PluginProbe
Polylang / 0.9.5
Polylang v0.9.5
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.5, at include/base.php

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