PluginProbe
Polylang / 1.5.1
Polylang v1.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 / include / upgrade.php

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

451 lines 14.0 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', '1.4', '1.4.1', '1.4.4', '1.5') as $version)
92 if (version_compare($this->options['version'], $version, '<'))
93 call_user_func(array(&$this, 'upgrade_' . str_replace('.', '_', $version)));
94
95 if (absint(get_transient('pll_upgrade_1_4')) < time())
96 $this->delete_pre_1_2_data();
97
98 $this->options['version'] = POLYLANG_VERSION;
99 update_option('polylang', $this->options);
100 }
101
102 /*
103 * upgrades if the previous version is < 0.9
104 *
105 * @since 1.2
106 */
107 protected function upgrade_0_9() {
108 $this->options['sync'] = defined('PLL_SYNC') && !PLL_SYNC ? 0 : 1; // the option replaces PLL_SYNC in 0.9
109 }
110
111 /*
112 * upgrades if the previous version is < 1.0
113 *
114 * @since 1.2
115 */
116 protected function upgrade_1_0() {
117 // the option replaces PLL_MEDIA_SUPPORT in 1.0
118 $this->options['media_support'] = defined('PLL_MEDIA_SUPPORT') && !PLL_MEDIA_SUPPORT ? 0 : 1;
119
120 // split the synchronization options in 1.0
121 $this->options['sync'] = empty($this->options['sync']) ? array() : array_keys(PLL_Settings::list_metas_to_sync());
122
123 // set default values for post types and taxonomies to translate
124 $this->options['post_types'] = array_values(get_post_types(array('_builtin' => false, 'show_ui => true')));
125 $this->options['taxonomies'] = array_values(get_taxonomies(array('_builtin' => false, 'show_ui => true')));
126 update_option('polylang', $this->options);
127
128 flush_rewrite_rules(); // rewrite rules have been modified in 1.0
129 }
130
131 /*
132 * upgrades if the previous version is < 1.1
133 *
134 * @since 1.2
135 */
136 protected function upgrade_1_1() {
137 // update strings register with icl_register_string
138 $strings = get_option('polylang_wpml_strings');
139 if ($strings) {
140 foreach ($strings as $key => $string)
141 $strings[$key]['icl'] = 1;
142 update_option('polylang_wpml_strings', $strings);
143 }
144
145 // move polylang_widgets options
146 if ($widgets = get_option('polylang_widgets')) {
147 $this->options['widgets'] = $widgets;
148 delete_option('polylang_widgets');
149 }
150 }
151
152 /*
153 * upgrades if the previous version is < 1.2
154 *
155 * @since 1.2
156 */
157 protected function upgrade_1_2() {
158 $this->options['domains'] = array(); // option added in 1.2
159
160 // need to register the taxonomies
161 foreach (array('language', 'term_language', 'post_translations', 'term_translations') as $taxonomy)
162 register_taxonomy($taxonomy, null , array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false));
163
164 // abort if the db upgrade has already been done previously
165 if (get_terms('term_language', array('hide_empty' => 0)))
166 return;
167
168 set_time_limit(0); // in case we upgrade a huge site
169
170 // upgrade old model based on metas to new model based on taxonomies
171 global $wpdb;
172 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
173 $languages = get_terms('language', array('hide_empty' => 0)); // don't use get_languages_list which can't work with the old model
174
175 foreach($languages as $lang) {
176 // first update language with new storage for locale and text direction
177 $text_direction = get_metadata('term', $lang->term_id, '_rtl', true);
178 $desc = serialize(array('locale' => $lang->description, 'rtl' => $text_direction));
179 wp_update_term((int) $lang->term_id, 'language', array('description' => $desc));
180
181 // add language to new 'term_language' taxonomy
182 $term_lang = wp_insert_term($lang->name, 'term_language', array('slug' => 'pll_' . $lang->slug));
183 $lang_tt_ids[$lang->term_id] = $term_lang['term_taxonomy_id']; // keep the term taxonomy id for future
184 }
185
186 // get all terms with a language defined
187 $terms = $wpdb->get_results("SELECT term_id, meta_value FROM $wpdb->termmeta WHERE meta_key = '_language'");
188 foreach ($terms as $key => $term)
189 $terms[$key] = $wpdb->prepare('(%d, %d)', $term->term_id, $lang_tt_ids[$term->meta_value]);
190
191 $terms = array_unique($terms);
192
193 // assign language to each term
194 if (!empty($terms))
195 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $terms));
196
197 // translations
198 foreach (array('post', 'term') as $type) {
199 $table = $type . 'meta';
200 $terms = $slugs = $tts = $trs = array();
201
202 // get all translated objects
203 $objects = $wpdb->get_col("SELECT DISTINCT meta_value FROM {$wpdb->$table} WHERE meta_key = '_translations'");
204
205 if (empty($objects))
206 continue;
207
208 foreach ($objects as $obj) {
209 $term = uniqid('pll_'); // the term name
210 $terms[] = $wpdb->prepare('("%1$s", "%1$s")', $term);
211 $slugs[] = $wpdb->prepare('"%s"', $term);
212 $translations = maybe_unserialize(maybe_unserialize($obj)); // 2 unserialize due to an old storage bug
213 $description[$term] = serialize($translations);
214 }
215
216 $terms = array_unique($terms);
217
218 // insert terms
219 if (!empty($terms))
220 $wpdb->query("INSERT INTO $wpdb->terms (slug, name) VALUES " . implode(',', $terms));
221
222 // get all terms with their term_id
223 $terms = $wpdb->get_results("SELECT term_id, slug FROM $wpdb->terms WHERE slug IN (" . implode(',', $slugs) . ")");
224
225 // prepare terms taxonomy relationship
226 foreach ($terms as $term)
227 $tts[] = $wpdb->prepare('(%d, "%s", "%s")', $term->term_id, $type . '_translations', $description[$term->slug]);
228
229 $tts = array_unique($tts);
230
231 // insert term_taxonomy
232 if (!empty($tts))
233 $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description) VALUES " . implode(',', $tts));
234
235 // get all terms with term_taxonomy_id
236 $terms = get_terms($type . '_translations', array('hide_empty' => false));
237
238 // prepare objects relationships
239 foreach ($terms as $term) {
240 $translations = unserialize($term->description);
241 foreach ($translations as $object_id)
242 if (!empty($object_id))
243 $trs[] = $wpdb->prepare('(%d, %d)', $object_id, $term->term_taxonomy_id);
244 }
245
246 $trs = array_unique($trs);
247
248 // insert term_relationships
249 if (!empty($trs))
250 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $trs));
251 }
252
253 // upgrade of string translations is now in upgrade_1_2_1
254 // upgrade of nav menus is now in upgrade_1_2_3
255 }
256
257 /*
258 * upgrades if the previous version is < 1.2.1
259 *
260 * @since 1.2.1
261 */
262 protected function upgrade_1_2_1() {
263 // strings translations
264 foreach(get_terms('language', array('hide_empty' => 0)) as $lang) {
265 if ($strings = get_option('polylang_mo'.$lang->term_id)) {
266 $mo = new PLL_MO();
267 foreach ($strings as $msg)
268 $mo->add_entry($mo->make_entry($msg[0], $msg[1]));
269 $mo->export_to_db($lang);
270 }
271 }
272 }
273
274 /*
275 * upgrades if the previous version is < 1.2.3
276 * uprades multilingual menus depending on the old version due to multiple changes in menus management
277 *
278 * @since 1.2.3
279 */
280 public function upgrade_1_2_3() {
281 // old version < 1.1
282 // multilingal locations and switcher item were stored in a dedicated option
283 if (version_compare($this->options['version'], '1.1', '<')) {
284 if ($menu_lang = get_option('polylang_nav_menus')) {
285 foreach ($menu_lang as $location => $arr) {
286 if (!in_array($location, array_keys(get_registered_nav_menus())))
287 continue;
288
289 $switch_options = array_slice($arr, -5, 5);
290 $translations = array_diff_key($arr, $switch_options);
291 $has_switcher = array_shift($switch_options);
292
293 foreach (get_terms('language', array('hide_empty' => 0)) as $lang) {
294 // move nav menus locations
295 if (!empty($translations[$lang->slug]))
296 $locations[$location][$lang->slug] = $translations[$lang->slug];
297
298 // create the menu items for the language switcher
299 if (!empty($has_switcher)) {
300 $menu_item_db_id = wp_update_nav_menu_item($translations[$lang->slug], 0, array(
301 'menu-item-title' => __('Language switcher', 'polylang'),
302 'menu-item-url' => '#pll_switcher',
303 'menu-item-status' => 'publish'
304 ));
305
306 update_post_meta($menu_item_db_id, '_pll_menu_item', $switch_options);
307 }
308 }
309 }
310
311 if (!empty($locations))
312 $this->options['nav_menus'][get_option('stylesheet')] = $locations;
313
314 delete_option('polylang_nav_menus');
315 }
316
317 }
318
319 elseif (empty($this->options['nav_menus'])) {
320 $menus = get_theme_mod('nav_menu_locations');
321
322 if (is_array($menus)) {
323 // if old version < 1.2
324 // clean the WP option as it was a bad idea to pollute it
325 if (version_compare($this->options['version'], '1.2', '<')) {
326 foreach ($menus as $loc => $menu) {
327 if ($pos = strpos($loc, '#'))
328 unset($menus[$loc]);
329 }
330
331 set_theme_mod('nav_menu_locations', $menus);
332 }
333
334 // get the multilingual locations
335 foreach ($menus as $loc => $menu) {
336 foreach (get_terms('language', array('hide_empty' => 0)) as $lang) {
337 $arr[$loc][$lang->slug] = pll_get_term($menu, $lang);
338 }
339 }
340
341 if (!empty($arr))
342 $this->options['nav_menus'][get_option('stylesheet')] = $arr;
343 }
344 }
345 }
346
347 /*
348 * upgrades if the previous version is < 1.3
349 * moves the user biographies in default language to the 'description' user meta
350 *
351 * @since 1.3
352 */
353 protected function upgrade_1_3() {
354 $usermeta = 'description_' . $this->options['default_lang'];
355 $query = new WP_User_Query(array('blog_id' => $GLOBALS['blog_id'], 'meta_key' => $usermeta));
356
357 foreach ($query->get_results() as $user) {
358 $desc = get_user_meta($user->ID, $usermeta, true);
359 if (!empty($desc)) {
360 update_user_meta($user->ID, 'description', $desc);
361 delete_user_meta($user->ID, $usermeta);
362 }
363 }
364 }
365
366 /*
367 * upgrades if the previous version is < 1.4
368 * sets a transient to delete old model data
369 * deletes language cache (due to bug correction in home urls in 1.3.1 and added mo_id in 1.4)
370 *
371 * @since 1.4
372 */
373 protected function upgrade_1_4() {
374 set_transient('pll_upgrade_1_4', time() + 60 * 24 * 60 * 60); // 60 days
375 delete_transient('pll_languages_list');
376 }
377
378 /*
379 * old data were not deleted in 1.2, just in case...
380 * delete them at first upgrade at least 60 days after upgrade to 1.4
381 *
382 * @since 1.4
383 */
384 protected function delete_pre_1_2_data() {
385 // suppress data of the old model < 1.2
386 global $wpdb;
387 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
388
389 // do nothing if the termmeta table does not exists
390 if (count($wpdb->get_results("SHOW TABLES LIKE '$wpdb->termmeta'"))) {
391 $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = '_translations'");
392 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_language'");
393 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_rtl'");
394 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_translations'");
395
396 // delete the termmeta table only if it is empty as other plugins may use it
397 if (!$wpdb->get_var("SELECT COUNT(*) FROM $wpdb->termmeta;"))
398 $wpdb->query("DROP TABLE $wpdb->termmeta;");
399 }
400
401 // delete the strings translations
402 $languages = get_terms('language', array('hide_empty'=>false));
403 foreach ($languages as $lang)
404 delete_option('polylang_mo'.$lang->term_id);
405
406 delete_transient('pll_upgrade_1_4');
407 }
408
409 /*
410 * upgrades if the previous version is < 1.4.1
411 * disables the browser detection when using multiple domains
412 *
413 * @since 1.4.1
414 */
415 protected function upgrade_1_4_1() {
416 if (3 == $this->options['force_lang'])
417 $this->options['browser'] = $this->options['hide_default'] = 0;
418 }
419
420 /*
421 * upgrades if the previous version is < 1.4.4
422 * uprades widgets options for language filter
423 *
424 * @since 1.4.4
425 */
426 protected function upgrade_1_4_4() {
427 foreach ($GLOBALS['wp_registered_widgets'] as $widget) {
428 if (!empty($this->options['widgets'][$widget['id']]) && !empty($widget['callback'][0]) && !empty($widget['params'][0]['number'])) {
429 $obj = $widget['callback'][0];
430 if (is_object($obj) && method_exists($obj, 'get_settings') && method_exists($obj, 'save_settings')) {
431 $settings = $obj->get_settings();
432 $settings[$widget['params'][0]['number']]['pll_lang'] = $this->options['widgets'][$widget['id']];
433 $obj->save_settings($settings);
434 }
435 }
436 }
437 unset($this->options['widgets']);
438 }
439
440 /*
441 * upgrades if the previous version is < 1.5
442 * deletes language cache (due to host property added and bug on search url)
443 *
444 * @since 1.5
445 */
446 protected function upgrade_1_5() {
447 delete_transient('pll_languages_list');
448 }
449
450 }
451