PluginProbe
Polylang / 3.8.6
Polylang v3.8.6
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 / src / install / upgrade.php

upgrade.php in Polylang 3.8.6, at src/install/upgrade.php

388 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 use WP_Syntex\Polylang\Options\Options;
7 /**
8 * Manages Polylang upgrades
9 *
10 * @since 1.2
11 */
12 class PLL_Upgrade {
13 /**
14 * Stores the plugin options.
15 *
16 * @var Options
17 */
18 public $options;
19
20 /**
21 * Constructor
22 *
23 * @since 1.2
24 * @since 3.7 The `$options` parameter is an instance of `Options`.
25 *
26 * @param Options $options Polylang options.
27 */
28 public function __construct( Options $options ) {
29 $this->options = $options;
30 }
31
32 /**
33 * Check if upgrade is possible otherwise die to avoid activation
34 *
35 * @since 1.2
36 *
37 * @return void
38 */
39 public function can_activate() {
40 if ( ! $this->can_upgrade() ) {
41 ob_start();
42 $this->admin_notices(); // FIXME the error message is displayed two times
43 die( ob_get_contents() ); // phpcs:ignore WordPress.Security.EscapeOutput
44 }
45 }
46
47 /**
48 * Upgrades if possible otherwise returns false to stop Polylang loading
49 *
50 * @since 1.2
51 *
52 * @return bool true if upgrade is possible, false otherwise
53 */
54 public function upgrade() {
55 if ( ! $this->can_upgrade() ) {
56 add_action( 'all_admin_notices', array( $this, 'admin_notices' ) );
57 return false;
58 }
59
60 add_action( 'admin_init', array( $this, '_upgrade' ) );
61 return true;
62 }
63
64
65 /**
66 * Check if we the previous version is not too old
67 * Upgrades if OK
68 * /!\ never start any upgrade before admin_init as it is likely to conflict with some other plugins
69 *
70 * @since 1.2
71 *
72 * @return bool true if upgrade is possible, false otherwise
73 */
74 public function can_upgrade() {
75 // Don't manage upgrade from version < 1.8
76 return version_compare( $this->options['version'], '1.8', '>=' );
77 }
78
79 /**
80 * Displays a notice when upgrading from a too old version
81 *
82 * @since 1.0
83 *
84 * @return void
85 */
86 public function admin_notices() {
87 load_plugin_textdomain( 'polylang' );
88 printf(
89 '<div class="error"><p>%s</p><p>%s</p></div>',
90 esc_html__( 'Polylang has been deactivated because you upgraded from a too old version.', 'polylang' ),
91 sprintf(
92 /* translators: %1$s and %2$s are Polylang version numbers */
93 esc_html__( 'Before upgrading to %2$s, please upgrade to %1$s.', 'polylang' ),
94 '<strong>2.9</strong>',
95 POLYLANG_VERSION // phpcs:ignore WordPress.Security.EscapeOutput
96 )
97 );
98 }
99
100 /**
101 * Upgrades the plugin depending on the previous version
102 *
103 * @since 1.2
104 *
105 * @return void
106 */
107 public function _upgrade() {
108 /*
109 * Delete the transient precisely at this point (`admin_init`)
110 * to ensure `Model\Languages` callbacks do their job.
111 * i.e. delete the transient from the options table when external object cache is used.
112 */
113 delete_transient( 'pll_languages_list' );
114
115 foreach ( array( '2.0.8', '2.1', '2.7', '3.4', '3.7', '3.8' ) as $version ) {
116 if ( version_compare( $this->options['version'], $version, '<' ) ) {
117 $method_to_call = array( $this, 'upgrade_' . str_replace( '.', '_', $version ) );
118 if ( is_callable( $method_to_call ) ) {
119 call_user_func( $method_to_call );
120 }
121 }
122 }
123
124 /**
125 * Fires after Polylang has been upgraded and before the new version is saved in options.
126 *
127 * @since 3.7
128 */
129 do_action( 'pll_upgrade' );
130
131 $this->options['previous_version'] = $this->options['version']; // Remember the previous version of Polylang since v1.7.7
132 $this->options['version'] = POLYLANG_VERSION;
133 }
134
135 /**
136 * Upgrades if the previous version is < 2.0.8
137 * Changes the user meta 'user_lang' to 'locale' to match WP 4.7 choice
138 *
139 * @since 2.0.8
140 *
141 * @return void
142 */
143 protected function upgrade_2_0_8() {
144 global $wpdb;
145 $wpdb->update( $wpdb->usermeta, array( 'meta_key' => 'locale' ), array( 'meta_key' => 'user_lang' ) );
146 }
147
148 /**
149 * Upgrades if the previous version is < 2.1.
150 * Moves strings translations from polylang_mo post_content to post meta _pll_strings_translations.
151 *
152 * @since 2.1
153 *
154 * @return void
155 */
156 protected function upgrade_2_1() {
157 $posts = get_posts(
158 array(
159 'post_type' => 'polylang_mo',
160 'post_status' => 'any',
161 'numberposts' => -1,
162 'nopaging' => true,
163 )
164 );
165
166 if ( is_array( $posts ) ) {
167 foreach ( $posts as $post ) {
168 $meta = get_post_meta( $post->ID, '_pll_strings_translations', true );
169
170 if ( empty( $meta ) ) {
171 $strings = maybe_unserialize( $post->post_content );
172 if ( is_array( $strings ) ) {
173 update_post_meta( $post->ID, '_pll_strings_translations', $strings );
174 }
175 }
176 }
177 }
178 }
179
180 /**
181 * Upgrades if the previous version is < 2.7
182 * Replace numeric keys by hashes in WPML registered strings
183 * Dismiss the wizard notice for existing sites
184 *
185 * @since 2.7
186 *
187 * @return void
188 */
189 protected function upgrade_2_7() {
190 $strings = get_option( 'polylang_wpml_strings' );
191 if ( is_array( $strings ) ) {
192 $new_strings = array();
193
194 foreach ( $strings as $string ) {
195 $context = $string['context'];
196 $name = $string['name'];
197
198 $key = md5( "$context | $name" );
199 $new_strings[ $key ] = $string;
200 }
201 update_option( 'polylang_wpml_strings', $new_strings );
202 }
203
204 PLL_Admin_Notices::dismiss( 'wizard' );
205 }
206
207 /**
208 * Upgrades if the previous version is < 3.4.0.
209 *
210 * @since 3.4
211 *
212 * @return void
213 */
214 protected function upgrade_3_4() {
215 $this->migrate_locale_fallback_to_language_description();
216
217 $this->migrate_strings_translations();
218 }
219
220 /**
221 * Upgrades if the previous version is < 3.7.
222 * Hides the "The language is set from content" option if it isn't the one selected.
223 * Cleans up strings translations so we don't store translations duplicated from the source.
224 *
225 * @since 3.7
226 *
227 * @return void
228 */
229 protected function upgrade_3_7() {
230 $this->allow_to_hide_language_from_content();
231 $this->empty_duplicated_strings_translations();
232 }
233
234 /**
235 * Upgrades if the previous version is < 3.8.
236 * Migrates language taxonomies from `polylang` option to `pll_language_taxonomies` option.
237 *
238 * @since 3.8
239 *
240 * @return void
241 */
242 protected function upgrade_3_8() {
243 $options = get_option( 'polylang' );
244
245 $language_taxonomies = array();
246 if ( is_array( $options ) && isset( $options['language_taxonomies'] ) && is_array( $options['language_taxonomies'] ) ) {
247 $language_taxonomies = $options['language_taxonomies'];
248 }
249
250 update_option( 'pll_language_taxonomies', $language_taxonomies );
251 }
252
253 /**
254 * Moves strings translations from post meta to term meta _pll_strings_translations.
255 *
256 * @since 3.4
257 *
258 * @return void
259 */
260 protected function migrate_strings_translations() {
261 $posts = get_posts(
262 array(
263 'post_type' => 'polylang_mo',
264 'post_status' => 'any',
265 'numberposts' => -1,
266 'nopaging' => true,
267 )
268 );
269
270 if ( ! is_array( $posts ) ) {
271 return;
272 }
273
274 foreach ( $posts as $post ) {
275 $meta = get_post_meta( $post->ID, '_pll_strings_translations', true );
276
277 $term_id = (int) substr( $post->post_title, 12 );
278
279 // Do not delete post metas in case a user needs to rollback to Polylang < 3.4.
280
281 if ( empty( $meta ) || ! is_array( $meta ) ) {
282 continue;
283 }
284
285 update_term_meta( $term_id, '_pll_strings_translations', wp_slash( $meta ) );
286 }
287 }
288
289 /**
290 * Migrate locale fallback to language term description.
291 *
292 * @since 3.4
293 *
294 * @return void
295 */
296 protected function migrate_locale_fallback_to_language_description() {
297 // Migrate locale fallbacks from term metas to language term description.
298 $terms = get_terms(
299 array(
300 'taxonomy' => 'language',
301 'hide_empty' => false,
302 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
303 array(
304 'key' => 'fallback',
305 'compare_key' => 'EXISTS',
306 ),
307 ),
308 )
309 );
310
311 if ( ! is_array( $terms ) ) {
312 return;
313 }
314
315 foreach ( $terms as $term ) {
316 $fallbacks = get_term_meta( $term->term_id, 'fallback', true );
317
318 delete_term_meta( $term->term_id, 'fallback' );
319
320 if ( empty( $fallbacks ) || ! is_array( $fallbacks ) ) {
321 // Empty or invalid value, should not happen.
322 continue;
323 }
324
325 $description = maybe_unserialize( $term->description );
326 $description = is_array( $description ) ? $description : array();
327
328 $description['fallbacks'] = $fallbacks;
329 /** @var string */
330 $description = maybe_serialize( $description );
331
332 wp_update_term( $term->term_id, 'language', array( 'description' => $description ) );
333 }
334 }
335
336 /**
337 * Hides the language from content option if it is not the one selected.
338 *
339 * @since 3.7
340 *
341 * @return void
342 */
343 private function allow_to_hide_language_from_content() {
344 update_option(
345 'pll_language_from_content_available',
346 0 === $this->options['force_lang'] ? 'yes' : 'no'
347 );
348 }
349
350 /**
351 * Cleans up strings translations so we don't store translations duplicated from the source.
352 *
353 * @since 3.7
354 *
355 * @return void
356 */
357 private function empty_duplicated_strings_translations() {
358 $terms = get_terms(
359 array(
360 'taxonomy' => 'language',
361 'hide_empty' => false,
362 )
363 );
364
365 if ( ! is_array( $terms ) ) {
366 return;
367 }
368
369 foreach ( $terms as $term ) {
370 $strings = get_term_meta( $term->term_id, '_pll_strings_translations', true );
371
372 if ( empty( $strings ) || ! is_array( $strings ) ) {
373 continue;
374 }
375
376 foreach ( $strings as $i => $tuple ) {
377 if ( $tuple[0] !== $tuple[1] ) {
378 continue;
379 }
380
381 $strings[ $i ][1] = '';
382 }
383
384 update_term_meta( $term->term_id, '_pll_strings_translations', $strings );
385 }
386 }
387 }
388