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

upgrade.php in Polylang 3.7.1, at install/upgrade.php

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