PluginProbe
Polylang / 1.0.4
Polylang v1.0.4
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 1.0.4, at polylang.php

394 lines 15.6 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://polylang.wordpress.com/
5 Version: 1.0.4
6 Author: F. Demarle
7 Description: Adds multilingual capability to WordPress
8 Text Domain: polylang
9 Domain Path: /languages
10 */
11
12 /*
13 * Copyright 2011-2013 F. Demarle
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 * MA 02110-1301, USA.
29 *
30 */
31
32 define('POLYLANG_VERSION', '1.0.4');
33 define('PLL_MIN_WP_VERSION', '3.1');
34
35 define('POLYLANG_DIR', dirname(__FILE__)); // our directory
36 define('PLL_INC', POLYLANG_DIR.'/include');
37
38 if (!defined('PLL_LOCAL_DIR'))
39 define('PLL_LOCAL_DIR', WP_CONTENT_DIR.'/polylang'); // default directory to store user data such as custom flags
40
41 if (file_exists(PLL_LOCAL_DIR.'/pll-config.php'))
42 include_once(PLL_LOCAL_DIR.'/pll-config.php'); // includes local config file if exists
43
44 define('POLYLANG_URL', plugins_url('/'.basename(POLYLANG_DIR))); // our url. Don't use WP_PLUGIN_URL http://wordpress.org/support/topic/ssl-doesnt-work-properly
45
46 if (!defined('PLL_LOCAL_URL'))
47 define('PLL_LOCAL_URL', content_url('/polylang')); // default url to access user data such as custom flags
48
49 if (!defined('PLL_COOKIE'))
50 define('PLL_COOKIE', 'pll_language'); // cookie name. no cookie will be used if set to false
51
52 require_once(PLL_INC.'/base.php');
53
54 // controls the plugin, deals with activation, deactivation, upgrades, initialization as well as rewrite rules
55 class Polylang extends Polylang_Base {
56
57 function __construct() {
58 parent::__construct();
59 global $polylang; // globalize the variable to access it in the API
60
61 // manages plugin activation and deactivation
62 register_activation_hook( __FILE__, array(&$this, 'activate'));
63 register_deactivation_hook( __FILE__, array(&$this, 'deactivate'));
64
65 // stopping here if we upgraded from a too old version
66 if (($options = get_option('polylang')) && version_compare($options['version'], '0.8', '<')) {
67 add_action('all_admin_notices', array(&$this, 'admin_notices'));
68 return;
69 }
70
71 // stopping here if we are going to deactivate the plugin (avoids breaking rewrite rules)
72 if (isset($_GET['action']) && $_GET['action'] == 'deactivate' && isset($_GET['plugin']) && $_GET['plugin'] == 'polylang/polylang.php')
73 return;
74
75 // blog creation on multisite
76 add_action('wpmu_new_blog', array(&$this, 'wpmu_new_blog'));
77
78 // manages plugin upgrade
79 add_action('admin_init', array(&$this, 'admin_init'));
80
81 // plugin and widget initialization
82 add_action('setup_theme', array(&$this, 'init'), 1);
83 add_action('widgets_init', array(&$this, 'widgets_init'));
84 add_action('wp_loaded', array(&$this, 'prepare_rewrite_rules'), 5); // after Polylang_base::add_post_types_taxonomies
85
86 // separate admin and frontend
87 if (is_admin() && isset($_GET['page']) && $_GET['page'] == 'mlang') {
88 require_once(PLL_INC.'/admin-base.php');
89 require_once(PLL_INC.'/admin.php');
90 $polylang = new Polylang_Admin();
91 }
92
93 // avoid loading polylang admin filters for frontend ajax requests if 'pll_load_front' is set (thanks to g100g)
94 elseif (defined('DOING_CRON') || (is_admin() && !(defined('DOING_AJAX') && isset($_REQUEST['pll_load_front'])))) {
95 require_once(PLL_INC.'/admin-base.php');
96 require_once(PLL_INC.'/admin-filters.php');
97 $polylang = new Polylang_Admin_Filters();
98 }
99
100 else {
101 require_once(PLL_INC.'/core.php');
102 $polylang = new Polylang_Core();
103 }
104
105 // loads the API
106 require_once(PLL_INC.'/api.php');
107
108 // WPML API + wpml-config.xml
109 if (!defined('PLL_WPML_COMPAT') || PLL_WPML_COMPAT)
110 require_once(PLL_INC.'/wpml-compat.php');
111
112 // extra code for compatibility with some plugins
113 if (!defined('PLL_PLUGINS_COMPAT') || PLL_PLUGINS_COMPAT)
114 require_once(PLL_INC.'/plugins-compat.php');
115 }
116
117 // plugin activation for multisite
118 function activate() {
119 global $wp_version, $wpdb;
120 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages'); // plugin i18n
121
122 if (version_compare($wp_version, PLL_MIN_WP_VERSION , '<'))
123 die (sprintf('<p style = "font-family: sans-serif; font-size: 12px; color: #333; margin: -5px">%s</p>',
124 sprintf(__('You are using WordPress %s. Polylang requires at least WordPress %s.', 'polylang'),
125 esc_html($wp_version),
126 PLL_MIN_WP_VERSION
127 )
128 ));
129
130 // check if it is a network activation - if so, run the activation function for each blog
131 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
132 foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
133 switch_to_blog($blog_id);
134 $this->_activate();
135 }
136 restore_current_blog();
137 }
138 else
139 $this->_activate();
140 }
141
142 // plugin activation
143 function _activate() {
144 // create the termmeta table - not provided by WP by default - if it does not already exists
145 // uses exactly the same model as other meta tables to be able to use access functions provided by WP
146 global $wpdb;
147 $charset_collate = empty($wpdb->charset) ? '' : "DEFAULT CHARACTER SET $wpdb->charset";
148 $charset_collate .= empty($wpdb->collate) ? '' : " COLLATE $wpdb->collate";
149 $table = $wpdb->prefix . 'termmeta';
150
151 $r = $wpdb->query("
152 CREATE TABLE IF NOT EXISTS $table (
153 meta_id bigint(20) unsigned NOT NULL auto_increment,
154 term_id bigint(20) unsigned NOT NULL default '0',
155 meta_key varchar(255) default NULL,
156 meta_value longtext,
157 PRIMARY KEY (meta_id),
158 KEY term_id (term_id),
159 KEY meta_key (meta_key)
160 ) $charset_collate;");
161
162 if ($r === false)
163 die (sprintf(
164 '<p style = "font-family: sans-serif; font-size: 12px; color: #333; margin: -5px">%s</p>',
165 __('For some reasons, Polylang could not create a table in your database.', 'polylang')
166 ));
167
168 // codex tells to use the init action to call register_taxonomy but I need it now for my rewrite rules
169 register_taxonomy('language', null , array('label' => false, 'query_var'=>'lang'));
170
171 // defines default values for options in case this is the first installation
172 if (!get_option('polylang')) {
173 $options['browser'] = 1; // default language for the front page is set by browser preference
174 $options['rewrite'] = 1; // remove /language/ in permalinks (was the opposite before 0.7.2)
175 $options['hide_default'] = 0; // do not remove URL language information for default language
176 $options['force_lang'] = 0; // do not add URL language information when useless
177 $options['redirect_lang'] = 0; // do not redirect the language page to the homepage
178 $options['media_support'] = 1; // support languages and translation for media by default
179 $options['sync'] = array_keys($this->list_metas_to_sync()); // synchronisation is enabled by default
180 $options['post_types'] = array_values(get_post_types(array('_builtin' => false, 'show_ui => true')));
181 $options['taxonomies'] = array_values(get_taxonomies(array('_builtin' => false, 'show_ui => true')));
182 $options['version'] = POLYLANG_VERSION;
183
184 update_option('polylang', $options);
185 }
186
187 // add our rewrite rules
188 $this->add_post_types_taxonomies();
189 $this->prepare_rewrite_rules();
190 flush_rewrite_rules();
191 }
192
193 // plugin deactivation for multisite
194 function deactivate() {
195 global $wpdb;
196
197 // check if it is a network deactivation - if so, run the deactivation function for each blog
198 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
199 foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
200 switch_to_blog($blog_id);
201 $this->_deactivate();
202 }
203 restore_current_blog();
204 }
205 else
206 $this->_deactivate();
207 }
208
209 // plugin deactivation
210 function _deactivate() {
211 flush_rewrite_rules();
212 }
213
214 // blog creation on multisite
215 function wpmu_new_blog($blog_id) {
216 switch_to_blog($blog_id);
217 $r = $this->_activate();
218 restore_current_blog();
219 }
220
221 // displays a notice when ugrading from a too old version
222 function admin_notices() {
223 printf(
224 '<div class="error"><p>%s</p><p>%s</p></div>',
225 __('Polylang has been deactivated because you upgraded from a too old version.', 'polylang'),
226 sprintf(
227 __('Please upgrade first to %s before ugrading to %s.', 'polylang'),
228 '<strong>0.9.8</strong>',
229 POLYLANG_VERSION
230 )
231 );
232 }
233
234 // manage upgrade even when it is done manually
235 function admin_init() {
236 $options = get_option('polylang');
237 if (version_compare($options['version'], POLYLANG_VERSION, '<')) {
238
239 if (version_compare($options['version'], '0.9', '<'))
240 $options['sync'] = defined('PLL_SYNC') && !PLL_SYNC ? 0 : 1; // the option replaces PLL_SYNC in 0.9
241
242 if (version_compare($options['version'], '1.0', '<')) {
243 // the option replaces PLL_MEDIA_SUPPORT in 1.0
244 $options['media_support'] = defined('PLL_MEDIA_SUPPORT') && !PLL_MEDIA_SUPPORT ? 0 : 1;
245
246 // split the synchronization options in 1.0
247 $options['sync'] = empty($options['sync']) ? array() : array_keys($this->list_metas_to_sync());
248
249 // set default values for post types and taxonomies to translate
250 $options['post_types'] = array_values(get_post_types(array('_builtin' => false, 'show_ui => true')));
251 $options['taxonomies'] = array_values(get_taxonomies(array('_builtin' => false, 'show_ui => true')));
252
253 flush_rewrite_rules(); // rewrite rules have been modified in 1.0
254 }
255
256 if (version_compare($options['version'], '1.0.2', '<'))
257 // set the option again in case it was not in 1.0
258 if (!isset($options['media_support']))
259 $options['media_support'] = defined('PLL_MEDIA_SUPPORT') && !PLL_MEDIA_SUPPORT ? 0 : 1;
260
261 $options['version'] = POLYLANG_VERSION;
262 update_option('polylang', $options);
263 }
264 }
265
266 // some initialization
267 function init() {
268 global $wpdb;
269 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
270 $options = get_option('polylang');
271
272 if (is_admin())
273 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages'); // plugin i18n, only needed for backend
274
275 // registers the language taxonomy
276 // codex: use the init action to call this function
277 // object types will be set later once all custom post types are registered
278 register_taxonomy('language', null, array(
279 'labels' => array(
280 'name' => __('Languages', 'polylang'),
281 'singular_name' => __('Language', 'polylang'),
282 'all_items' => __('All languages', 'polylang'),
283 ),
284 'public' => false, // avoid displaying the 'like post tags text box' in the quick edit
285 'query_var' => 'lang',
286 'update_count_callback' => '_update_post_term_count'
287 ));
288
289 // optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
290 // language information always in front of the uri ('with_front' => false)
291 // the 3rd parameter structure has been modified in WP 3.4
292 add_permastruct('language', $options['rewrite'] ? '%language%' : 'language/%language%',
293 version_compare($GLOBALS['wp_version'], '3.4' , '<') ? false : array('with_front' => false));
294 }
295
296 // registers our widgets
297 function widgets_init() {
298 require_once(PLL_INC.'/widget.php');
299 register_widget('Polylang_Widget');
300
301 // overwrites the calendar widget to filter posts by language
302 if (!defined('PLL_WIDGET_CALENDAR') || PLL_WIDGET_CALENDAR) {
303 require_once(PLL_INC.'/calendar.php'); // loads this only now otherwise it breaks widgets not registered in a widgets_init hook
304 unregister_widget('WP_Widget_Calendar');
305 register_widget('Polylang_Widget_Calendar');
306 }
307 }
308
309 // complete our taxonomy and add rewrite rules filters once custom post types and taxonomies are registered (normally in init)
310 function prepare_rewrite_rules() {
311 foreach ($this->post_types as $post_type)
312 register_taxonomy_for_object_type('language', $post_type);
313
314 // don't modify the rules if there is no languages created yet
315 if (!$this->get_languages_list())
316 return;
317
318 $types = array_values(array_merge($this->post_types, $this->taxonomies)); // supported post types and taxonomies
319 $types = array_merge(array('date', 'root', 'comments', 'search', 'author', 'language', 'post_format'), $types);
320 $types = apply_filters('pll_rewrite_rules', $types); // allow plugins to add rewrite rules to the language filter
321
322 foreach ($types as $type)
323 add_filter($type . '_rewrite_rules', array(&$this, 'rewrite_rules'));
324
325 add_filter('rewrite_rules_array', array(&$this, 'rewrite_rules')); // needed for post type archives
326 }
327
328 // the rewrite rules !
329 // always make sure the default language is at the end in case the language information is hidden for default language
330 // thanks to brbrbr http://wordpress.org/support/topic/plugin-polylang-rewrite-rules-not-correct
331 function rewrite_rules($rules) {
332 $filter = str_replace('_rewrite_rules', '', current_filter());
333
334 // suppress the rules created by WordPress for our taxonomy
335 if ($filter == 'language')
336 return array();
337
338 global $wp_rewrite;
339 $options = get_option('polylang');
340 $always_rewrite = in_array($filter, array('date', 'root', 'comments', 'author', 'post_format'));
341 $newrules = array();
342
343 foreach ($this->get_languages_list() as $language)
344 if (!$options['hide_default'] || $options['default_lang'] != $language->slug)
345 $languages[] = $language->slug;
346
347 if (isset($languages))
348 $slug = $wp_rewrite->root . ($options['rewrite'] ? '' : 'language/') . '('.implode('|', $languages).')/';
349
350 foreach ($rules as $key => $rule) {
351 // we don't need the lang parameter for post types and taxonomies
352 // moreover adding it would create issues for pages and taxonomies
353 if ($options['force_lang'] && in_array($filter, array_merge($this->post_types, $this->taxonomies))) {
354 if (isset($slug))
355 $newrules[$slug.str_replace($wp_rewrite->root, '', $key)] = str_replace(
356 array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]'),
357 array('[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]'),
358 $rule
359 ); // hopefully it is sufficient!
360
361 if ($options['hide_default']) {
362 $newrules[$key] = $rules[$key];
363 // unset only if we hide the code for the default language as check_language_code_in_url will do its job in other cases
364 unset($rules[$key]);
365 }
366 }
367
368 // rewrite rules filtered by language
369 elseif ($always_rewrite || (strpos($rule, 'post_type=') && !strpos($rule, 'name=')) || ($filter != 'rewrite_rules_array' && $options['force_lang'])) {
370 if (isset($slug))
371 $newrules[$slug.str_replace($wp_rewrite->root, '', $key)] = str_replace(
372 array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?'),
373 array('[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&'),
374 $rule
375 ); // should be enough!
376
377 if ($options['hide_default'])
378 $newrules[$key] = str_replace('?', '?lang='.$options['default_lang'].'&', $rule);
379
380 unset($rules[$key]); // now useless
381 }
382 }
383
384 // the home rewrite rule
385 if ($filter == 'root' && isset($slug))
386 $newrules[$slug.'?$'] = $wp_rewrite->index.'?lang=$matches[1]';
387
388 return $newrules + $rules;
389 }
390
391 } // class Polylang
392
393 new Polylang();
394