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

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

386 lines 11.9 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 *
53 * @since 1.2
54 *
55 * @return bool true if upgrade is possible, false otherwise
56 */
57 public function can_upgrade() {
58 // don't manage upgrade from version < 0.8
59 if (version_compare($this->options['version'], '0.8', '<'))
60 return false;
61
62 $this->_upgrade();
63 return true;
64 }
65
66 /*
67 * displays a notice when ugrading from a too old version
68 *
69 * @since 1.0
70 */
71 public function admin_notices() {
72 load_plugin_textdomain('polylang', false, basename(POLYLANG_DIR).'/languages');
73 printf(
74 '<div class="error"><p>%s</p><p>%s</p></div>',
75 __('Polylang has been deactivated because you upgraded from a too old version.', 'polylang'),
76 sprintf(
77 __('Please upgrade first to %s before ugrading to %s.', 'polylang'),
78 '<strong>0.9.8</strong>',
79 POLYLANG_VERSION
80 )
81 );
82 }
83
84 /*
85 * upgrades the plugin depending on the previous version
86 *
87 * @since 1.2
88 */
89 protected function _upgrade() {
90 foreach (array('0.9', '1.0', '1.1', '1.2', '1.2.1') as $version)
91 if (version_compare($this->options['version'], $version, '<'))
92 call_user_func(array(&$this, 'upgrade_' . str_replace('.', '_', $version)));
93
94 $this->options['version'] = POLYLANG_VERSION;
95 update_option('polylang', $this->options);
96 }
97
98 /*
99 * upgrades if the previous version is < 0.9
100 *
101 * @since 1.2
102 */
103 protected function upgrade_0_9() {
104 $this->options['sync'] = defined('PLL_SYNC') && !PLL_SYNC ? 0 : 1; // the option replaces PLL_SYNC in 0.9
105 }
106
107 /*
108 * upgrades if the previous version is < 1.0
109 *
110 * @since 1.2
111 */
112 protected function upgrade_1_0() {
113 // the option replaces PLL_MEDIA_SUPPORT in 1.0
114 $this->options['media_support'] = defined('PLL_MEDIA_SUPPORT') && !PLL_MEDIA_SUPPORT ? 0 : 1;
115
116 // split the synchronization options in 1.0
117 $this->options['sync'] = empty($this->options['sync']) ? array() : array_keys(PLL_Settings::list_metas_to_sync());
118
119 add_action('wp_loaded', array(&$this, 'wp_loaded_upgrade_1_0')); // once post types and taxonomies are set
120
121 if (did_action('wp_loaded'))
122 $this->wp_loaded_upgrade_1_0();
123 }
124
125 /*
126 * upgrades if the previous version is < 1.0
127 * actions that need to be taken after all post types and taxonomies are known
128 *
129 * @since 1.2
130 */
131 public function wp_loaded_upgrade_1_0() {
132 // set default values for post types and taxonomies to translate
133 $this->options['post_types'] = array_values(get_post_types(array('_builtin' => false, 'show_ui => true')));
134 $this->options['taxonomies'] = array_values(get_taxonomies(array('_builtin' => false, 'show_ui => true')));
135 update_option('polylang', $this->options);
136
137 flush_rewrite_rules(); // rewrite rules have been modified in 1.0
138 }
139
140 /*
141 * upgrades if the previous version is < 1.1
142 *
143 * @since 1.2
144 */
145 protected function upgrade_1_1() {
146 // update strings register with icl_register_string
147 $strings = get_option('polylang_wpml_strings');
148 if ($strings) {
149 foreach ($strings as $key => $string)
150 $strings[$key]['icl'] = 1;
151 update_option('polylang_wpml_strings', $strings);
152 }
153
154 // move polylang_widgets options
155 if ($widgets = get_option('polylang_widgets')) {
156 $this->options['widgets'] = $widgets;
157 delete_option('polylang_widgets');
158 }
159
160 // update nav menus
161 if ($menu_lang = get_option('polylang_nav_menus')) {
162
163 foreach ($menu_lang as $location => $arr) {
164 if (!in_array($location, array_keys(get_registered_nav_menus())))
165 continue;
166
167 $switch_options = array_slice($arr, -5, 5);
168 $translations = array_diff_key($arr, $switch_options);
169 $has_switcher = array_shift($switch_options);
170
171 $languages = get_terms('language', array('hide_empty' => 0)); // don't use get_languages_list which can't work with the old model
172 foreach ($languages as $lang) {
173 $menu_locations[$location.(pll_default_language() == $lang->slug ? '' : '#' . $lang->slug)] = empty($translations[$lang->slug]) ? 0 : $translations[$lang->slug];
174
175 // create the menu items
176 if (!empty($has_switcher)) {
177 $menu_item_db_id = wp_update_nav_menu_item($translations[$lang->slug], 0, array(
178 'menu-item-title' => __('Language switcher', 'polylang'),
179 'menu-item-url' => '#pll_switcher',
180 'menu-item-status' => 'publish'
181 ));
182
183 update_post_meta($menu_item_db_id, '_pll_menu_item', $switch_options);
184 }
185 }
186 }
187
188 if (!empty($menu_locations))
189 set_theme_mod('nav_menu_locations', $menu_locations);
190
191 delete_option('polylang_nav_menus');
192 }
193 }
194
195 /*
196 * upgrades if the previous version is < 1.2
197 *
198 * @since 1.2
199 */
200 protected function upgrade_1_2() {
201 $this->options['domains'] = array(); // option added in 1.2
202
203 // need to register the taxonomies
204 foreach (array('language', 'term_language', 'post_translations', 'term_translations') as $taxonomy)
205 register_taxonomy($taxonomy, null , array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false));
206
207 // abort if the db upgrade has already been done previously
208 if (get_terms('term_language', array('hide_empty' => 0)))
209 return;
210
211 set_time_limit(0); // in case we upgrade a huge site
212
213 // upgrade old model based on metas to new model based on taxonomies
214 global $wpdb;
215 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
216 $languages = get_terms('language', array('hide_empty' => 0)); // don't use get_languages_list which can't work with the old model
217
218 foreach($languages as $lang) {
219 // first update language with new storage for locale and text direction
220 $text_direction = get_metadata('term', $lang->term_id, '_rtl', true);
221 $desc = serialize(array('locale' => $lang->description, 'rtl' => $text_direction));
222 wp_update_term((int) $lang->term_id, 'language', array('description' => $desc));
223
224 // add language to new 'term_language' taxonomy
225 $term_lang = wp_insert_term($lang->name, 'term_language', array('slug' => 'pll_' . $lang->slug));
226 $lang_tt_ids[$lang->term_id] = $term_lang['term_taxonomy_id']; // keep the term taxonomy id for future
227 }
228
229 // get all terms with a language defined
230 $terms = $wpdb->get_results("SELECT term_id, meta_value FROM $wpdb->termmeta WHERE meta_key = '_language'");
231 foreach ($terms as $key => $term)
232 $terms[$key] = $wpdb->prepare('(%d, %d)', $term->term_id, $lang_tt_ids[$term->meta_value]);
233
234 $terms = array_unique($terms);
235
236 // assign language to each term
237 if (!empty($terms))
238 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $terms));
239
240 // translations
241 foreach (array('post', 'term') as $type) {
242 $table = $type . 'meta';
243 $terms = $slugs = $tts = $trs = array();
244
245 // get all translated objects
246 $objects = $wpdb->get_col("SELECT DISTINCT meta_value FROM {$wpdb->$table} WHERE meta_key = '_translations'");
247
248 if (empty($objects))
249 continue;
250
251 foreach ($objects as $obj) {
252 $term = uniqid('pll_'); // the term name
253 $terms[] = $wpdb->prepare('("%1$s", "%1$s")', $term);
254 $slugs[] = $wpdb->prepare('"%s"', $term);
255 $translations = maybe_unserialize(maybe_unserialize($obj)); // 2 unserialize due to an old storage bug
256 $description[$term] = serialize($translations);
257 }
258
259 $terms = array_unique($terms);
260
261 // insert terms
262 if (!empty($terms))
263 $wpdb->query("INSERT INTO $wpdb->terms (slug, name) VALUES " . implode(',', $terms));
264
265 // get all terms with their term_id
266 $terms = $wpdb->get_results("SELECT term_id, slug FROM $wpdb->terms WHERE slug IN (" . implode(',', $slugs) . ")");
267
268 // prepare terms taxonomy relationship
269 foreach ($terms as $term)
270 $tts[] = $wpdb->prepare('(%d, "%s", "%s")', $term->term_id, $type . '_translations', $description[$term->slug]);
271
272 $tts = array_unique($tts);
273
274 // insert term_taxonomy
275 if (!empty($tts))
276 $wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description) VALUES " . implode(',', $tts));
277
278 // get all terms with term_taxonomy_id
279 $terms = get_terms($type . '_translations', array('hide_empty' => false));
280
281 // prepare objects relationships
282 foreach ($terms as $term) {
283 $translations = unserialize($term->description);
284 foreach ($translations as $object_id)
285 if (!empty($object_id))
286 $trs[] = $wpdb->prepare('(%d, %d)', $object_id, $term->term_taxonomy_id);
287 }
288
289 $trs = array_unique($trs);
290
291 // insert term_relationships
292 if (!empty($trs))
293 $wpdb->query("INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) VALUES " . implode(',', $trs));
294 }
295
296 // it was a bad idea to pollute WP option with our custom nav menu locations
297 $menus = get_theme_mod('nav_menu_locations');
298 if (is_array($menus)) {
299 $default = $this->options['default_lang'];
300 $arr = array();
301
302 foreach ($menus as $loc => $menu) {
303 if ($pos = strpos($loc, '#')) {
304 $arr[substr($loc, 0, $pos)][substr($loc, $pos+1)] = $menu;
305 unset($menus[$loc]);
306 }
307 else
308 $arr[$loc][$default] = $menu;
309 }
310
311 $model = new PLL_Admin_Model($this->options);
312 $model->clean_languages_cache();
313
314 // assign menus language and translations
315 foreach ($arr as $loc => $translations) {
316 foreach ($translations as $lang=>$menu) {
317 $model->set_term_language($menu, $lang);
318 $model->save_translations('term', $menu, $translations);
319 }
320 }
321
322 set_theme_mod('nav_menu_locations', $menus);
323 }
324 }
325
326 /*
327 * upgrades if the previous version is < 1.2.1
328 *
329 * @since 1.2.1
330 */
331 protected function upgrade_1_2_1() {
332 $action = is_admin() ? 'admin_init' : 'wp_loaded'; // admin_init for wp-ecommerce
333
334 add_action($action, array(&$this, 'wp_loaded_upgrade_1_2_1')); // once wp-rewrite is available
335
336 if (did_action($action))
337 $this->wp_loaded_upgrade_1_2_1();
338 }
339
340 /*
341 * upgrades if the previous version is < 1.2.1
342 * actions that need to be taken after $wp_rewrite is available
343 *
344 * @since 1.2.1
345 */
346 public function wp_loaded_upgrade_1_2_1() {
347 // strings translations
348 foreach(get_terms('language', array('hide_empty' => 0)) as $lang) {
349 if ($strings = get_option('polylang_mo'.$lang->term_id)) {
350 $mo = new PLL_MO();
351 foreach ($strings as $msg)
352 $mo->add_entry($mo->make_entry($msg[0], $msg[1]));
353 $mo->export_to_db($lang);
354 }
355 }
356 }
357
358 /*
359 * upgrades if the previous version is < 1.3
360 * FIXME don't delete old data in 1.2, just in case...
361 * ready for the next version
362 */
363 protected function upgrade_1_3() {
364 // suppress data of the old model < 1.2
365 global $wpdb;
366 $wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
367
368 // do nothing if the termmeta table does not exists
369 if (count($wpdb->get_results("SHOW TABLES LIKE '$wpdb->termmeta'"))) {
370 $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = '_translations'");
371 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_language'");
372 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_rtl'");
373 $wpdb->query("DELETE FROM $wpdb->termmeta WHERE meta_key = '_translations'");
374
375 // delete the termmeta table only if it is empty as other plugins may use it
376 if (!$wpdb->get_var("SELECT COUNT(*) FROM $wpdb->termmeta;"))
377 $wpdb->query("DROP TABLE $wpdb->termmeta;");
378 }
379
380 // delete the strings translations
381 $languages = get_terms('language', array('hide_empty'=>false));
382 foreach ($languages as $lang)
383 delete_option('polylang_mo'.$lang->term_id);
384 }
385 }
386