PluginProbe
Polylang / 0.5.1
Polylang v0.5.1
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.5.1, at polylang.php

336 lines 12.3 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.5.1
6 Author: F. Demarle
7 Description: Adds multilingual capability to Wordpress
8 */
9
10 /* Copyright 2011 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, version 2, as
14 published by the Free Software Foundation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 define('POLYLANG_VERSION', '0.5.1');
27
28 define('POLYLANG_DIR', dirname(__FILE__));
29 define('PLL_INC', POLYLANG_DIR.'/include');
30
31 if (!defined('PLL_DISPLAY_ALL'))
32 define('PLL_DISPLAY_ALL', false); // diplaying posts & terms with undefined language is disabled by default
33
34 require_once(PLL_INC.'/base.php');
35 require_once(PLL_INC.'/widget.php');
36 require_once(PLL_INC.'/calendar.php');
37
38 // controls the plugin, deals with activation, deactivation, upgrades, initialization as well as rewrite rules
39 class Polylang extends Polylang_Base {
40
41 function __construct() {
42 global $polylang;
43
44 // manages plugin activation and deactivation
45 register_activation_hook( __FILE__, array(&$this, 'activate') );
46 register_deactivation_hook( __FILE__, array(&$this, 'deactivate') );
47
48 // manages plugin upgrade
49 add_filter('upgrader_pre_install', array(&$this, 'pre_upgrade'));
50 add_filter('upgrader_post_install', array(&$this, 'post_upgrade'));
51 add_action('admin_init', array(&$this, 'admin_init'));
52
53 // plugin and widget initialization
54 add_action('init', array(&$this, 'init'));
55 add_action('widgets_init', array(&$this, 'widgets_init'));
56
57 // rewrite rules
58 add_filter('rewrite_rules_array', array(&$this, 'rewrite_rules_array' ));
59
60 if (is_admin()) {
61 require_once(PLL_INC.'/admin.php');
62 new Polylang_Admin();
63 }
64 else {
65 require_once(PLL_INC.'/core.php');
66 require_once(PLL_INC.'/api.php');
67 $polylang = new Polylang_Core();
68 }
69 }
70
71 // plugin activation for multisite
72 function activate() {
73 global $wpdb;
74
75 // check if it is a network activation - if so, run the activation function for each blog
76 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
77 foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
78 switch_to_blog($blog_id);
79 $this->_activate();
80 }
81 restore_current_blog();
82 }
83 else
84 $this->_activate();
85 }
86
87 // plugin activation
88 function _activate() {
89 // create the termmeta table - not provided by WP by default - if it does not already exists
90 // uses exactly the same model as other meta tables to be able to use access functions provided by WP
91 global $wpdb;
92 $charset_collate = '';
93 if ( ! empty($wpdb->charset) )
94 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
95 if ( ! empty($wpdb->collate) )
96 $charset_collate .= " COLLATE $wpdb->collate";
97
98 $table = $wpdb->prefix . 'termmeta';
99
100 $tables = $wpdb->get_results("show tables like '$table'");
101 if (!count($tables))
102 $wpdb->query("CREATE TABLE $table (
103 meta_id bigint(20) unsigned NOT NULL auto_increment,
104 term_id bigint(20) unsigned NOT NULL default '0',
105 meta_key varchar(255) default NULL,
106 meta_value longtext,
107 PRIMARY KEY (meta_id),
108 KEY term_id (term_id),
109 KEY meta_key (meta_key)
110 ) $charset_collate;");
111
112 // codex tells to use the init action to call register_taxonomy but I need it now for my rewrite rules
113 register_taxonomy('language', get_post_types(array('show_ui' => true)), array('label' => false, 'query_var'=>'lang'));
114
115 // defines default values for options in case this is the first installation
116 $options = get_option('polylang');
117 if (!$options) {
118 $options['browser'] = 1; // default language for the front page is set by browser preference
119 $options['rewrite'] = 0; // do not remove /language/ in permalinks
120 $options['hide_default'] = 0; // do not remove URL language information for default language
121 }
122 $options['version'] = POLYLANG_VERSION;
123 update_option('polylang', $options);
124
125 // add our rewrite rules
126 global $wp_rewrite;
127 $wp_rewrite->flush_rules();
128 }
129
130 // plugin deactivation for multisite
131 function deactivate() {
132 global $wpdb;
133
134 // check if it is a network deactivation - if so, run the deactivation function for each blog
135 if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
136 foreach ($wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")) as $blog_id) {
137 switch_to_blog($blog_id);
138 $this->_deactivate();
139 }
140 restore_current_blog();
141 }
142 else
143 $this->_deactivate();
144 }
145
146 // plugin deactivation
147 function _deactivate() {
148 global $wp_rewrite;
149
150 // delete our rewrite rules
151 remove_filter('rewrite_rules_array', array(&$this,'rewrite_rules_array' ));
152 $wp_rewrite->flush_rules();
153 }
154
155 // saves the local_flags directory before upgrade
156 function pre_upgrade() {
157 // nothing to backup
158 if (!@is_dir($flags_dir = POLYLANG_DIR . '/local_flags'))
159 return true;
160
161 $upgrade_dirs = array(
162 WP_CONTENT_DIR . '/upgrade',
163 WP_CONTENT_DIR . '/upgrade/polylang'
164 );
165
166 foreach ($upgrade_dirs as $dir) {
167 if (!@is_dir($dir) && !@mkdir($dir, 0755))
168 return new WP_Error('polylang_upgrade_error', sprintf('%s<br />%s <strong>%s</strong>',
169 __("Error: Upgrade directory doesn't exist!", 'polylang'),
170 __('Please create', 'polylang'),
171 esc_html($dir)
172 ));
173 }
174
175 if (!@rename($flags_dir, WP_CONTENT_DIR . '/upgrade/polylang/local_flags'))
176 return new WP_Error('polylang_backup_error', sprintf('%s<br />%s <strong>%s</strong>',
177 __('Error: Backup of local flags failed!', 'polylang'),
178 __('Please backup', 'polylang'),
179 esc_html($flags_dir)
180 ));
181
182 return true;
183 }
184
185 // restores the local_flags directory after upgrade
186 function post_upgrade() {
187 // nothing to restore
188 if (!@is_dir($upgrade_dir = WP_CONTENT_DIR . '/upgrade/polylang/local_flags'))
189 return true;
190
191 if (!@rename($upgrade_dir, POLYLANG_DIR . '/local_flags'))
192 return new WP_Error('polylang_restore_error', sprintf('%s<br />%s (<strong>%s</strong>)',
193 __('Error: Restore of local flags failed!', 'polylang'),
194 __('Please restore your local flags', 'polylang'),
195 esc_html($upgrade_dir)
196 ));
197
198 @rmdir(WP_CONTENT_DIR . '/upgrade/polylang');
199 return true;
200 }
201
202 // upgrades from old translation used up to V0.4.4 to new model used in V0.5+
203 function upgrade_translations($type, $ids) {
204 $listlanguages = $this->get_languages_list();
205 foreach ($ids as $id) {
206 $lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id);
207 if (!$lang)
208 continue;
209
210 $tr = array();
211 foreach ($listlanguages as $language) {
212 if ($meta = get_metadata($type, $id, '_lang-'.$language->slug, true))
213 $tr[$language->slug] = $meta;
214 }
215
216 if(!empty($tr)) {
217 $tr = serialize(array_merge(array($lang->slug => $id), $tr));
218 update_metadata($type, $id, '_translations', $tr);
219 }
220 }
221 }
222
223 // manage upgrade even when it is done manually
224 function admin_init() {
225 $options = get_option('polylang');
226 if (version_compare($options['version'], POLYLANG_VERSION, '<')) {
227
228 if (version_compare($options['version'], '0.4', '<'))
229 $options['hide_default'] = 0; // option introduced in 0.4
230
231 // translation model changed in 0.5
232 // FIXME will not delete old data before 0.6 (just in case...)
233 if (version_compare($options['version'], '0.5', '<')) {
234 $ids = get_posts(array('numberposts'=>-1, 'fields' => 'ids', 'post_type'=>'any', 'post_status'=>'any'));
235 $this->upgrade_translations('post', $ids);
236 $ids = get_terms(get_taxonomies(array('show_ui'=>true)), array('get'=>'all', 'fields'=>'ids'));
237 $this->upgrade_translations('term', $ids);
238 }
239
240 $options['version'] = POLYLANG_VERSION;
241 update_option('polylang', $options);
242 }
243 }
244
245 // some initialization
246 function init() {
247 global $wpdb;
248 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
249
250 // registers the language taxonomy
251 // codex: use the init action to call this function
252 register_taxonomy('language', get_post_types(array('show_ui' => true)), array(
253 'label' => false,
254 'public' => false, // avoid displaying the 'like post tags text box' in the quick edit
255 'query_var'=>'lang',
256 'update_count_callback' => '_update_post_term_count'));
257
258 // optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
259 // the simple line of code is inspired by the WP No Category Base plugin: http://wordpresssupplies.com/wordpress-plugins/no-category-base/
260 global $wp_rewrite;
261 $options = get_option('polylang');
262 if ($options['rewrite'] && $wp_rewrite->extra_permastructs)
263 $wp_rewrite->extra_permastructs['language'][0] = '%language%';
264
265 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages'); // plugin i18n
266 }
267
268 // registers our widgets
269 function widgets_init() {
270 register_widget('Polylang_Widget');
271
272 // overwrites the calendar widget to filter posts by language
273 unregister_widget('WP_Widget_Calendar');
274 register_widget('Polylang_Widget_Calendar');
275 }
276
277 // rewrites rules if pretty permalinks are used
278 function rewrite_rules_array($rules) {
279 $options = get_option('polylang');
280 $newrules = array();
281
282 $listlanguages = $this->get_languages_list();
283
284 // modifies the rules created by WordPress when '/language/' is removed in permalinks
285 if ($options['rewrite']) {
286 foreach ($listlanguages as $language) {
287 $slug = $options['default_lang'] == $language->slug && $options['hide_default'] ? '' : $language->slug . '/';
288 $newrules[$slug.'feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
289 $newrules[$slug.'(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]';
290 $newrules[$slug.'page/?([0-9]{1,})/?$'] = 'index.php?lang='.$language->slug.'&paged=$matches[1]';
291 if ($slug)
292 $newrules[$slug.'?$'] = 'index.php?lang='.$language->slug;
293 }
294 unset($rules['([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
295 unset($rules['([^/]+)/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?lang=$matches[1]&feed=$matches[2]
296 unset($rules['([^/]+)/page/?([0-9]{1,})/?$']); // => index.php?lang=$matches[1]&paged=$matches[2]
297 unset($rules['([^/]+)/?$']); // => index.php?lang=$matches[1]
298 }
299
300 $base = $options['rewrite'] ? '' : 'language/';
301
302 // rewrite rules for comments feed filtered by language
303 foreach ($listlanguages as $language) {
304 $slug = $options['default_lang'] == $language->slug && $options['hide_default'] ? '' : $base.$language->slug . '/';
305 $newrules[$slug.'comments/feed/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
306 $newrules[$slug.'comments/(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?lang='.$language->slug.'&feed=$matches[1]&withcomments=1';
307 }
308 unset($rules['comments/feed/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
309 unset($rules['comments/(feed|rdf|rss|rss2|atom)/?$']); // => index.php?&feed=$matches[1]&withcomments=1
310
311 // rewrite rules for archives filtered by language
312 foreach ($rules as $key => $rule) {
313 $is_archive = strpos($rule, 'author_name=') || strpos($rule, 'year=') && !(
314 strpos($rule, 'p=') ||
315 strpos($rule, 'name=') ||
316 strpos($rule, 'page=') ||
317 strpos($rule, 'cpage=') );
318
319 if ($is_archive) {
320 foreach ($listlanguages as $language) {
321 $slug = $options['default_lang'] == $language->slug && $options['hide_default'] ? '' : $base.$language->slug . '/';
322 $newrules[$slug.$key] = str_replace('?', '?lang='.$language->slug.'&', $rule);
323 }
324 unset($rules[$key]); // now useless
325 }
326 }
327 return $newrules + $rules;
328 }
329
330 } // class Polylang
331
332 if (class_exists("Polylang"))
333 new Polylang();
334
335 ?>
336