PluginProbe
Polylang / 0.7.2
Polylang v0.7.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 / polylang.php

polylang.php in Polylang 0.7.2, at polylang.php

362 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Polylang
4 Plugin URI: http://wordpress.org/extend/plugins/polylang/
5 Version: 0.7.2
6 Author: F. Demarle
7 Description: Adds multilingual capability to Wordpress
8 */
9
10 /* Copyright 2011-2012 F. Demarle
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License, published by
14 the Free Software Foundation, either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 */
26
27 define('POLYLANG_VERSION', '0.7.2');
28 define('PLL_MIN_WP_VERSION', '3.1');
29
30 define('POLYLANG_DIR', dirname(__FILE__)); // our directory
31 define('PLL_INC', POLYLANG_DIR.'/include');
32
33 define('POLYLANG_URL', WP_PLUGIN_URL.'/'.basename(POLYLANG_DIR)); // our url
34
35 if (!defined('PLL_LOCAL_DIR'))
36 define('PLL_LOCAL_DIR', WP_CONTENT_DIR.'/polylang'); // default directory to store user data such as custom flags
37
38 if (!defined('PLL_LOCAL_URL'))
39 define('PLL_LOCAL_URL', WP_CONTENT_URL.'/polylang'); // default url to access user data such as custom flags
40
41 if (!defined('PLL_DISPLAY_ALL'))
42 define('PLL_DISPLAY_ALL', false); // diplaying posts & terms with undefined language is disabled by default
43
44 require_once(PLL_INC.'/base.php');
45 require_once(PLL_INC.'/widget.php');
46 require_once(PLL_INC.'/calendar.php');
47
48 // controls the plugin, deals with activation, deactivation, upgrades, initialization as well as rewrite rules
49 class Polylang extends Polylang_Base {
50
51 function __construct() {
52 global $polylang; // globalize the variable to access it in the API
53
54 // manages plugin activation and deactivation
55 register_activation_hook( __FILE__, array(&$this, 'activate') );
56 register_deactivation_hook( __FILE__, array(&$this, 'deactivate') );
57
58 // stopping here if we are going to deactivate the plugin avoids breaking rewrite rules
59 if (isset($_GET['action']) && $_GET['action'] == 'deactivate' && isset($_GET['plugin']) && $_GET['plugin'] == 'polylang/polylang.php')
60 return;
61
62 // manages plugin upgrade
63 add_filter('upgrader_post_install', array(&$this, 'post_upgrade'));
64 add_action('admin_init', array(&$this, 'admin_init'));
65
66 // plugin and widget initialization
67 add_action('init', array(&$this, 'init'));
68 add_action('widgets_init', array(&$this, 'widgets_init'));
69
70 // rewrite rules
71 add_filter('rewrite_rules_array', array(&$this, 'rewrite_rules_array' ));
72
73 // separate admin and frontend
74 if (is_admin()) {
75 require_once(PLL_INC.'/admin.php');
76 $polylang = new Polylang_Admin();
77 }
78 else {
79 require_once(PLL_INC.'/core.php');
80 $polylang = new Polylang_Core();
81 }
82
83 // loads the API
84 require_once(PLL_INC.'/api.php');
85 }
86
87 // plugin activation for multisite
88 function activate() {
89 global $wp_version, $wpdb;
90
91 if (version_compare($wp_version, PLL_MIN_WP_VERSION , '<'))
92 die (sprintf('<p style = "font-family: sans-serif; font-size: 12px; color: #333; margin: -5px">%s</p>',
93 sprintf(__('You are using WordPress %s. Polylang requires at least WordPress %s.', 'polylang'), $wp_version, PLL_MIN_WP_VERSION)));
94
95 // check if it is a network activation - if so, run the activation function for each blog
96 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
97 foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
98 switch_to_blog($blog_id);
99 $this->_activate();
100 }
101 restore_current_blog();
102 }
103 else
104 $this->_activate();
105 }
106
107 // plugin activation
108 function _activate() {
109 // create the termmeta table - not provided by WP by default - if it does not already exists
110 // uses exactly the same model as other meta tables to be able to use access functions provided by WP
111 global $wpdb;
112 $charset_collate = '';
113 if ( ! empty($wpdb->charset) )
114 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
115 if ( ! empty($wpdb->collate) )
116 $charset_collate .= " COLLATE $wpdb->collate";
117
118 $table = $wpdb->prefix . 'termmeta';
119
120 $wpdb->query("CREATE TABLE IF NOT EXISTS $table (
121 meta_id bigint(20) unsigned NOT NULL auto_increment,
122 term_id bigint(20) unsigned NOT NULL default '0',
123 meta_key varchar(255) default NULL,
124 meta_value longtext,
125 PRIMARY KEY (meta_id),
126 KEY term_id (term_id),
127 KEY meta_key (meta_key)
128 ) $charset_collate;");
129
130 // codex tells to use the init action to call register_taxonomy but I need it now for my rewrite rules
131 register_taxonomy('language', get_post_types(array('show_ui' => true)), array('label' => false, 'query_var'=>'lang'));
132
133 // defines default values for options in case this is the first installation
134 $options = get_option('polylang');
135 if (!$options) {
136 $options['browser'] = 1; // default language for the front page is set by browser preference
137 $options['rewrite'] = 1; // remove /language/ in permalinks (was the opposite before 0.7.2)
138 $options['hide_default'] = 0; // do not remove URL language information for default language
139 $options['force_lang'] = 0; // do not add URL language information when useless
140 }
141 $options['version'] = POLYLANG_VERSION;
142 update_option('polylang', $options);
143
144 // add our rewrite rules
145 global $wp_rewrite;
146 $wp_rewrite->flush_rules();
147 }
148
149 // plugin deactivation for multisite
150 function deactivate() {
151 global $wpdb;
152
153 // check if it is a network deactivation - if so, run the deactivation function for each blog
154 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
155 foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
156 switch_to_blog($blog_id);
157 $this->_deactivate();
158 }
159 restore_current_blog();
160 }
161 else
162 $this->_deactivate();
163 }
164
165 // plugin deactivation
166 function _deactivate() {
167 global $wp_rewrite;
168 $wp_rewrite->flush_rules();
169 }
170
171 // restores the local_flags directory after upgrade from version 0.5.1 or older
172 function post_upgrade() {
173 // nothing to restore
174 if (!@is_dir($upgrade_dir = WP_CONTENT_DIR . '/upgrade/polylang/local_flags'))
175 return true;
176
177 // don't move if the directory is empty
178 $contents = @scandir($upgrade_dir);
179 if (is_array($contents) && ($files = array_diff($contents, array(".", "..", ".DS_Store", "_notes", "Thumbs.db"))) && empty($files))
180 return true;
181
182 // move the directory to wp-content
183 if (!@rename($upgrade_dir, PLL_LOCAL_DIR))
184 return new WP_Error('polylang_restore_error', sprintf('%s<br />%s',
185 __('Error: Restore of local flags failed!', 'polylang'),
186 sprintf(__('Please move your local flags from %s to %s', 'polylang'), esc_html($upgrade_dir), '<strong>'.esc_html(PLL_LOCAL_DIR).'</strong>')
187 ));
188
189 @rmdir(WP_CONTENT_DIR . '/upgrade/polylang');
190 return true;
191 }
192
193 // upgrades from old translation used up to V0.4.4 to new model used in V0.5+
194 function upgrade_translations($type, $ids) {
195 $listlanguages = $this->get_languages_list();
196 foreach ($ids as $id) {
197 $lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id);
198 if (!$lang)
199 continue;
200
201 $tr = array();
202 foreach ($listlanguages as $language) {
203 if ($meta = get_metadata($type, $id, '_lang-'.$language->slug, true))
204 $tr[$language->slug] = $meta;
205 }
206
207 if (!empty($tr)) {
208 $tr = serialize(array_merge(array($lang->slug => $id), $tr));
209 update_metadata($type, $id, '_translations', $tr);
210 }
211 }
212 }
213
214 // manage upgrade even when it is done manually
215 function admin_init() {
216 $options = get_option('polylang');
217 if (version_compare($options['version'], POLYLANG_VERSION, '<')) {
218
219 if (version_compare($options['version'], '0.4', '<'))
220 $options['hide_default'] = 0; // option introduced in 0.4
221
222 // translation model changed in V0.5
223 if (version_compare($options['version'], '0.5', '<')) {
224 $ids = get_posts(array('numberposts'=>-1, 'fields' => 'ids', 'post_type'=>'any', 'post_status'=>'any'));
225 $this->upgrade_translations('post', $ids);
226 $ids = get_terms(get_taxonomies(array('show_ui'=>true)), array('get'=>'all', 'fields'=>'ids'));
227 $this->upgrade_translations('term', $ids);
228 }
229
230 // translation model changed in V0.5
231 // deleting the old one has been delayed in V0.6 (just in case...)
232 if (version_compare($options['version'], '0.6', '<')) {
233 $listlanguages = $this->get_languages_list();
234
235 $ids = get_posts(array('numberposts'=> -1, 'fields' => 'ids', 'post_type'=>'any', 'post_status'=>'any'));
236 foreach ($ids as $id) {
237 foreach ($listlanguages as $lang)
238 delete_post_meta($id, '_lang-'.$lang->slug);
239 }
240
241 $ids = get_terms(get_taxonomies(array('show_ui'=>true)), array('get'=>'all', 'fields'=>'ids'));
242 foreach ($ids as $id) {
243 foreach ($listlanguages as $lang)
244 delete_metadata('term', $id, '_lang-'.$lang->slug);
245 }
246 }
247
248 if (version_compare($options['version'], '0.7', '<'))
249 $options['force_lang'] = 0; // option introduced in 0.7
250
251 if (version_compare($options['version'], '0.7.2', '<'))
252 $GLOBALS['wp_rewrite']->flush_rules(); // rewrite rules have been modified in 0.7.1 & 0.7.2
253
254 $options['version'] = POLYLANG_VERSION;
255 update_option('polylang', $options);
256 }
257 }
258
259 // some initialization
260 function init() {
261 global $wpdb;
262 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
263
264 // registers the language taxonomy
265 // codex: use the init action to call this function
266 register_taxonomy('language', get_post_types(array('show_ui' => true)), array(
267 'label' => false,
268 'public' => false, // avoid displaying the 'like post tags text box' in the quick edit
269 'query_var'=>'lang',
270 'update_count_callback' => '_update_post_term_count'));
271
272 // optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
273 // the simple line of code is inspired by the WP No Category Base plugin: http://wordpresssupplies.com/wordpress-plugins/no-category-base/
274 global $wp_rewrite;
275 $options = get_option('polylang');
276 if ($options['rewrite'] && $wp_rewrite->extra_permastructs)
277 $wp_rewrite->extra_permastructs['language'][0] = '%language%';
278
279 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages'); // plugin i18n
280 }
281
282 // registers our widgets
283 function widgets_init() {
284 register_widget('Polylang_Widget');
285
286 // overwrites the calendar widget to filter posts by language
287 unregister_widget('WP_Widget_Calendar');
288 register_widget('Polylang_Widget_Calendar');
289 }
290
291 // rewrites rules if pretty permalinks are used
292 // always make sure the default language is at the end in case the language information is hidden for default language
293 // thanks to brbrbr http://wordpress.org/support/topic/plugin-polylang-rewrite-rules-not-correct
294 function rewrite_rules_array($rules) {
295 $options = get_option('polylang');
296 $newrules = array();
297
298 // don't modify the rules if there is no languages created
299 if (!($listlanguages = $this->get_languages_list()))
300 return $rules;
301
302 $languages = array();
303 foreach ($listlanguages as $language)
304 if (!$options['hide_default'] || $options['default_lang'] != $language->slug)
305 $languages[] = $language->slug;
306
307 if ($languages) {
308 $slug = '('.implode('|', $languages).')/';
309 $slug = $options['rewrite'] ? $slug : 'language/'.$slug;
310 }
311
312 foreach ($rules as $key => $rule) {
313 $is_archive = strpos($rule, 'post_format=') || strpos($rule, 'author_name=') || strpos($rule, 'post_type=') || strpos($rule, 'year=') &&
314 !(strpos($rule, 'p=') || strpos($rule, 'name=') || strpos($rule, 'page=') || strpos($rule, 'cpage='));
315
316 $is_comment_feed = strpos($rule, 'withcomments=1');
317
318 // modifies the rules created by WordPress for our taxonomy
319 if (strpos($rule, 'lang=')) {
320 $newkey = $options['rewrite'] ? str_replace('([^/]+)/', '', $key) : str_replace('language/([^/]+)/', '', $key);
321 if (isset($slug))
322 $newrules[$slug.$newkey] = $rule;
323
324 // take care not to create the rule [?$] => index.php?lang=$matches[1] !
325 if ($options['hide_default'] && $newkey != '?$')
326 $newrules[$newkey] = str_replace('lang=$matches[1]', 'lang='.$options['default_lang'], $rule);
327
328 unset($rules[$key]);
329 }
330
331 // special case for pages which do not accept adding the lang parameter
332 // FIXME check if it's still the case for WP3.4
333 elseif ($options['force_lang'] && strpos($rule, 'pagename')) {
334 if (isset($slug))
335 $newrules[$slug.$key] = str_replace(array('[4]', '[3]', '[2]', '[1]'), array('[5]', '[4]', '[3]', '[2]'), $rule); // hopefully it is sufficient !
336
337 if (!$options['hide_default'])
338 unset($rules[$key]); // now useless
339 }
340
341 // rewrite rules filtered by language
342 elseif ($is_archive || $is_comment_feed || $options['force_lang']) {
343 if (isset($slug))
344 $newrules[$slug.$key] = str_replace(array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?'),
345 array('[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&'), $rule); // hopefully it is sufficient !
346
347 if ($options['hide_default'])
348 $newrules[$key] = str_replace('?', '?lang='.$options['default_lang'].'&', $rule);
349
350 unset($rules[$key]); // now useless
351 }
352 }
353
354 return $newrules + $rules;
355 }
356
357 } // class Polylang
358
359 if (class_exists("Polylang"))
360 new Polylang();
361 ?>
362