PluginProbe
Polylang / 1.3
Polylang v1.3
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 / upgrade.php

upgrade.php in Polylang 1.3, at include/upgrade.php

413 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * manages Polylang upgrades
5 *
6 * @since 1.2
7 */
8 class PLL_Upgrade {
9 public $options;
10
11 /*
12 * constructor
13 *
14 * @since 1.2
15 */
16 public function __construct(&$options) {
17 $this->options = &$options;
18 }
19
20 /*
21 * upgrades if possible otherwise die to avoid activation
22 *
23 * @since 1.2
24 */
25 public function upgrade_at_activation() {
26 if (!$this->can_upgrade()) {
27 ob_start();
28 $this->admin_notices();
29 die(ob_get_contents());
30 }
31 }
32
33 /*
34 * upgrades if possible otherwise returns false to stop Polylang loading
35 *
36 * @since 1.2
37 *
38 * @return bool true if upgrade is possible, false otherwise
39 */
40 public function upgrade() {
41 if (!$this->can_upgrade()) {
42 add_action('all_admin_notices', array(&$this, 'admin_notices'));
43 return false;
44 }
45 return true;
46 }
47
48
49 /*
50 * check if we the previous version is not too old
51 * upgrades if OK
52 * /!\ never start any upgrade before admin_init as it is likely to conflict with some other plugins
53 *
54 * @since 1.2
55 *
56 * @return bool true if upgrade is possible, false otherwise
57 */
58 public function can_upgrade() {
59 // don't manage upgrade from version < 0.8
60 if (version_compare($this->options['version'], '0.8', '<'))
61 return false;
62
63 add_action('admin_init', array(&$this, '_upgrade'));
64 return true;
65 }
66
67 /*
68 * displays a notice when ugrading from a too old version
69 *
70 * @since 1.0
71 */
72 public function admin_notices() {
73 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages');
74 printf(
75 '<div class="error"><p>%s</p><p>%s</p></div>',
76 __('Polylang has been deactivated because you upgraded from a too old version.', 'polylang'),
77 sprintf(
78 __('Please upgrade first to %s before ugrading to %s.', 'polylang'),
79 '<strong>0.9.8</strong>',
80 POLYLANG_VERSION
81 )
82 );
83 }
84
85 /*
86 * upgrades the plugin depending on the previous version
87 *
88 * @since 1.2
89 */
90 public function _upgrade() {
91 foreach (array('0.9', '1.0', '1.1', '1.2', '1.2.1', '1.2.3', '1.3') as $version)
92 if (version_compare($this->options['version'], $version, '<'))
93 call_user_func(array(&$this, 'upgrade_' . str_replace('.', '_', $version)));
94
95 $this->options['version'] = POLYLANG_VERSION;
96 update_option('polylang', $this->options);
97 }
98
99 /*
100 * upgrades if the previous version is < 0.9
101 *
102 * @since 1.2
103 */
104 protected function upgrade_0_9() {
105 $this->options['sync'] = defined('PLL_SYNC') && !PLL_SYNC ? 0 : 1; // the option replaces PLL_SYNC in 0.9
106 }
107
108 /*
109 * upgrades if the previous version is < 1.0
110 *
111 * @since 1.2
112 */
113 protected function upgrade_1_0() {
114 // the option replaces PLL_MEDIA_SUPPORT in 1.0
115 $this->options['media_support'] = defined('PLL_MEDIA_SUPPORT') && !PLL_MEDIA_SUPPORT ? 0 : 1;
116
117 // split the synchronization options in 1.0
118 $this->options['sync'] = empty($this->options['sync']) ? array() : array_keys(PLL_Settings::list_metas_to_sync());
119
120 // set default values for post types and taxonomies to translate
121 $this->options['post_types'] = array_values(get_post_types(array('_builtin' => false, 'show_ui => true')));
122 $this->options['taxonomies'] = array_values(get_taxonomies(array('_builtin' => false, 'show_ui => true')));
123 update_option('polylang', $this->options);
124
125 flush_rewrite_rules(); // rewrite rules have been modified in 1.0
126 }
127
128 /*
129 * upgrades if the previous version is < 1.1
130 *
131 * @since 1.2
132 */
133 protected function upgrade_1_1() {
134 // update strings register with icl_register_string
135 $strings = get_option('polylang_wpml_strings');
136 if ($strings) {
137 foreach ($strings as $key => $string)
138 $strings[$key]['icl'] = 1;
139 update_option('polylang_wpml_strings', $strings);
140 }
141
142 // move polylang_widgets options
143 if ($widgets = get_option('polylang_widgets')) {
144 $this->options['widgets'] = $widgets;
145 delete_option('polylang_widgets');
146 }
147 }
148
149 /*
150 * upgrades if the previous version is < 1.2
151 *
152 * @since 1.2
153 */
154 protected function upgrade_1_2() {
155 $this->options['domains'] = array(); // option added in 1.2
156
157 // need to register the taxonomies
158 foreach (array('language', 'term_language', 'post_translations', 'term_translations') as $taxonomy)
159 register_taxonomy($taxonomy, null , array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false));
160
161 // abort if the db upgrade has already been done previously
162 if (get_terms('term_language', array('hide_empty' => 0)))
163 return;
164
165 set_time_limit(0); // in case we upgrade a huge site
166
167 // upgrade old model based on metas to new model based on taxonomies
168 global $wpdb;
169 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
170 $languages = get_terms('language', array('hide_empty' => 0)); // don't use get_languages_list which can't work with the old model
171
172 foreach($languages as $lang) {
173 // first update language with new storage for locale and text direction
174 $text_direction = get_metadata('term', $lang->term_id, '_rtl', true);
175 $desc = serialize(array('locale' => $lang->description, 'rtl' => $text_direction));
176 wp_update_term((int) $lang->term_id, 'language', array('description' => $desc));
177
178 // add language to new 'term_language' taxonomy
179 $term_lang = wp_insert_term($lang->name, 'term_language', array('slug' => 'pll_' . $lang->slug));
180 $lang_tt_ids[$lang->term_id] = $term_lang['term_taxonomy_id']; // keep the term taxonomy id for future
181 }
182
183 // get all terms with a language defined
184 $terms = $wpdb->get_results("SELECT term_id, meta_value FROM $wpdb->termmeta WHERE meta_key = '_language'");
185 foreach ($terms as $key => $term)
186 $terms[$key] = $wpdb->prepare('(%d, %d)', $term->term_id, $lang_tt_ids[$term->meta_value]);
187
188 $terms = array_unique($terms);
189
190 // assign language to each term
191 if (!empty($terms))
192 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $terms));
193
194 // translations
195 foreach (array('post', 'term') as $type) {
196 $table = $type . 'meta';
197 $terms = $slugs = $tts = $trs = array();
198
199 // get all translated objects
200 $objects = $wpdb->get_col("SELECT DISTINCT meta_value FROM {$wpdb->$table} WHERE meta_key = '_translations'");
201
202 if (empty($objects))
203 continue;
204
205 foreach ($objects as $obj) {
206 $term = uniqid('pll_'); // the term name
207 $terms[] = $wpdb->prepare('("%1$s", "%1$s")', $term);
208 $slugs[] = $wpdb->prepare('"%s"', $term);
209 $translations = maybe_unserialize(maybe_unserialize($obj)); // 2 unserialize due to an old storage bug
210 $description[$term] = serialize($translations);
211 }
212
213 $terms = array_unique($terms);
214
215 // insert terms
216 if (!empty($terms))
217 $wpdb->query("INSERT INTO $wpdb->terms (slug, name) VALUES " . implode(',', $terms));
218
219 // get all terms with their term_id
220 $terms = $wpdb->get_results("SELECT term_id, slug FROM $wpdb->terms WHERE slug IN (" . implode(',', $slugs) . ")");
221
222 // prepare terms taxonomy relationship
223 foreach ($terms as $term)
224 $tts[] = $wpdb->prepare('(%d, "%s", "%s")', $term->term_id, $type . '_translations', $description[$term->slug]);
225
226 $tts = array_unique($tts);
227
228 // insert term_taxonomy
229 if (!empty($tts))
230 $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description) VALUES " . implode(',', $tts));
231
232 // get all terms with term_taxonomy_id
233 $terms = get_terms($type . '_translations', array('hide_empty' => false));
234
235 // prepare objects relationships
236 foreach ($terms as $term) {
237 $translations = unserialize($term->description);
238 foreach ($translations as $object_id)
239 if (!empty($object_id))
240 $trs[] = $wpdb->prepare('(%d, %d)', $object_id, $term->term_taxonomy_id);
241 }
242
243 $trs = array_unique($trs);
244
245 // insert term_relationships
246 if (!empty($trs))
247 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $trs));
248 }
249
250 // upgrade of string translations is now in upgrade_1_2_1
251 // upgrade of nav menus is now in upgrade_1_2_3
252 }
253
254 /*
255 * upgrades if the previous version is < 1.2.1
256 *
257 * @since 1.2.1
258 */
259 protected function upgrade_1_2_1() {
260 // strings translations
261 foreach(get_terms('language', array('hide_empty' => 0)) as $lang) {
262 if ($strings = get_option('polylang_mo'.$lang->term_id)) {
263 $mo = new PLL_MO();
264 foreach ($strings as $msg)
265 $mo->add_entry($mo->make_entry($msg[0], $msg[1]));
266 $mo->export_to_db($lang);
267 }
268 }
269 }
270
271 /*
272 * upgrades if the previous version is < 1.2.3
273 * uprades multilingual menus depending on the old version due to multiple changes in menus management
274 *
275 * @since 1.2.3
276 */
277 public function upgrade_1_2_3() {
278 // old version < 1.1
279 // multilingal locations and switcher item were stored in a dedicated option
280 if (version_compare($this->options['version'], '1.1', '<')) {
281 if ($menu_lang = get_option('polylang_nav_menus')) {
282 foreach ($menu_lang as $location => $arr) {
283 if (!in_array($location, array_keys(get_registered_nav_menus())))
284 continue;
285
286 $switch_options = array_slice($arr, -5, 5);
287 $translations = array_diff_key($arr, $switch_options);
288 $has_switcher = array_shift($switch_options);
289
290 foreach (get_terms('language', array('hide_empty' => 0)) as $lang) {
291 // move nav menus locations
292 if (!empty($translations[$lang->slug]))
293 $locations[$location][$lang->slug] = $translations[$lang->slug];
294
295 // create the menu items for the language switcher
296 if (!empty($has_switcher)) {
297 $menu_item_db_id = wp_update_nav_menu_item($translations[$lang->slug], 0, array(
298 'menu-item-title' => __('Language switcher', 'polylang'),
299 'menu-item-url' => '#pll_switcher',
300 'menu-item-status' => 'publish'
301 ));
302
303 update_post_meta($menu_item_db_id, '_pll_menu_item', $switch_options);
304 }
305 }
306 }
307
308 if (!empty($locations))
309 $this->options['nav_menus'][get_option('stylesheet')] = $locations;
310
311 delete_option('polylang_nav_menus');
312 }
313
314 }
315
316 elseif (empty($this->options['nav_menus'])) {
317 $menus = get_theme_mod('nav_menu_locations');
318
319 if (is_array($menus)) {
320 // if old version < 1.2
321 // clean the WP option as it was a bad idea to pollute it
322 if (version_compare($this->options['version'], '1.2', '<')) {
323 foreach ($menus as $loc => $menu) {
324 if ($pos = strpos($loc, '#'))
325 unset($menus[$loc]);
326 }
327
328 set_theme_mod('nav_menu_locations', $menus);
329 }
330
331 // get the multilingual locations
332 foreach ($menus as $loc => $menu) {
333 foreach (get_terms('language', array('hide_empty' => 0)) as $lang) {
334 $arr[$loc][$lang->slug] = pll_get_term($menu, $lang);
335 }
336 }
337
338 if (!empty($arr))
339 $this->options['nav_menus'][get_option('stylesheet')] = $arr;
340 }
341 }
342 }
343
344 /*
345 * upgrades if the previous version is < 1.3
346 * moves the user biographies in default language to the 'description' user meta
347 * multisite compatible
348 *
349 * @since 1.3
350 */
351 protected function upgrade_1_3() {
352 if (is_multisite()) {
353 foreach ($GLOBALS['wpdb']->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
354 switch_to_blog($blog_id);
355 $this->_upgrade_1_3();
356 }
357 restore_current_blog();
358 }
359 else {
360 $this->_upgrade_1_3();
361 }
362 }
363
364 /*
365 * cleans language cache as new properties have been added in PLL_Language
366 * moves the user biographies in default language to the 'description' user meta
367 *
368 * @since 1.3
369 */
370 protected function _upgrade_1_3() {
371 global $polylang;
372 $polylang->model->clean_languages_cache();
373
374 $usermeta = 'description_' . $this->options['default_lang'];
375 $query = new WP_User_Query(array('blog_id' => $GLOBALS['blog_id'], 'meta_key' => $usermeta));
376
377 foreach ($query->get_results() as $user) {
378 $desc = get_user_meta($user->ID, $usermeta, true);
379 if (!empty($desc)) {
380 update_user_meta($user->ID, 'description', $desc);
381 delete_user_meta($user->ID, $usermeta);
382 }
383 }
384 }
385
386 /*
387 * FIXME don't delete old data in 1.2, just in case...
388 * ready for a next version
389 */
390 protected function upgrade_1_4() {
391 // suppress data of the old model < 1.2
392 global $wpdb;
393 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
394
395 // do nothing if the termmeta table does not exists
396 if (count($wpdb->get_results("SHOW TABLES LIKE '$wpdb->termmeta'"))) {
397 $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = '_translations'");
398 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_language'");
399 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_rtl'");
400 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_translations'");
401
402 // delete the termmeta table only if it is empty as other plugins may use it
403 if (!$wpdb->get_var("SELECT COUNT(*) FROM $wpdb->termmeta;"))
404 $wpdb->query("DROP TABLE $wpdb->termmeta;");
405 }
406
407 // delete the strings translations
408 $languages = get_terms('language', array('hide_empty'=>false));
409 foreach ($languages as $lang)
410 delete_option('polylang_mo'.$lang->term_id);
411 }
412 }
413