PluginProbe
Polylang / 3.7.7
Polylang v3.7.7
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
← All changes | modules/wizard/wizard.php +188 -97 2.8.23.7.7 View file →
@@ -2,8 +2,12 @@
2 2 /**
3 3 * @package Polylang
4 4 */
5 5
6 +defined( 'ABSPATH' ) || exit;
7 +
8 +use WP_Syntex\Polylang\Options\Options;
9 +
6 10 /**
7 11 * Main class for Polylang wizard.
8 12 *
9 13 * @since 2.7
@@ -9,39 +13,50 @@
9 13 * @since 2.7
10 14 */
11 15 class PLL_Wizard {
12 16 /**
13 - * Reference to PLL_Model object
17 + * Reference to the model object
14 18 *
15 - * @var object $model
19 + * @var PLL_Admin_Model
16 20 */
17 21 protected $model;
18 22
19 23 /**
20 - * Reference to Polylang options array
24 + * Reference to the Polylang options array.
21 25 *
22 - * @var array $options
26 + * @var array
23 27 */
24 28 protected $options;
25 29
26 30 /**
27 - * List of steps
31 + * List of steps.
28 32 *
29 - * @var array $steps {
30 - * @type string $name i18n string which names the step.
31 - * @type callable $view The callback function use to display the step content.
32 - * @type callable $handler The callback function use to process the step after it is submitted.
33 - * @type array $scripts List of scripts handle needed by the step.
34 - * @type array $styles The list of styles handle needed by the step.
33 + * @var array[] $steps {
34 + * @type array {
35 + * List of step properties.
36 + *
37 + * @type string $name I18n string which names the step.
38 + * @type callable $view The callback function use to display the step content.
39 + * @type callable $handler The callback function use to process the step after it is submitted.
40 + * @type array $scripts List of scripts handle needed by the step.
41 + * @type array $styles The list of styles handle needed by the step.
42 + * }
35 43 * }
36 44 */
37 45 protected $steps = array();
38 46
39 47 /**
40 - * List of WordPress CSS file handles
48 + * The current step.
41 49 *
42 - * @var array $styles
50 + * @var string|null
43 51 */
52 + protected $current_step;
53 +
54 + /**
55 + * List of WordPress CSS file handles.
56 + *
57 + * @var string[]
58 + */
44 59 protected $styles = array();
45 60
46 61 /**
47 62 * Constructor
@@ -53,9 +68,9 @@
53 68 $this->options = &$polylang->options;
54 69 $this->model = &$polylang->model;
55 70
56 71 // Display Wizard page before any other action to ensure displaying it outside the WordPress admin context.
57 - // Hooked on admin_init with priority 40 to ensure PLL_Wizard_Pro is corretly initialized.
72 + // Hooked on admin_init with priority 40 to ensure PLL_Wizard_Pro is correctly initialized.
58 73 add_action( 'admin_init', array( $this, 'setup_wizard_page' ), 40 );
59 74 // Add Wizard submenu.
60 75 add_filter( 'pll_settings_tabs', array( $this, 'settings_tabs' ), 10, 1 );
61 76 // Add filter to select screens where to display the notice.
@@ -72,15 +87,17 @@
72 87
73 88 /**
74 89 * Save an activation transient when Polylang is activating to redirect to the wizard
75 90 *
91 + * @since 2.7
92 + *
76 93 * @param bool $network_wide if activated for all sites in the network.
77 - * @since 2.7
94 + * @return void
78 95 */
79 96 public static function start_wizard( $network_wide ) {
80 - $options = get_option( 'polylang' );
97 + $options = (array) get_option( Options::OPTION_NAME, array() );
81 98
82 - if ( wp_doing_ajax() || $network_wide || ! empty( $options ) ) {
99 + if ( wp_doing_ajax() || $network_wide || ! empty( $options['version'] ) ) {
83 100 return;
84 101 }
85 102 set_transient( 'pll_activation_redirect', 1, 30 );
86 103 }
@@ -88,13 +105,15 @@
88 105 /**
89 106 * Redirect to the wizard depending on the context
90 107 *
91 108 * @since 2.7
109 + *
110 + * @return void
92 111 */
93 112 public function redirect_to_wizard() {
94 113 if ( get_transient( 'pll_activation_redirect' ) ) {
95 114 $do_redirect = true;
96 - if ( ( isset( $_GET['page'] ) && 'mlang_wizard' === sanitize_key( $_GET['page'] ) || isset( $_GET['activate-multi'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
115 + if ( ( isset( $_GET['page'] ) && 'mlang_wizard' === sanitize_key( $_GET['page'] ) ) || isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
97 116 delete_transient( 'pll_activation_redirect' );
98 117 $do_redirect = false;
99 118 }
100 119
@@ -99,9 +118,9 @@
99 118 }
100 119
101 120 if ( $do_redirect ) {
102 121 wp_safe_redirect(
103 - esc_url_raw(
122 + sanitize_url(
104 123 add_query_arg(
105 124 array(
106 125 'page' => 'mlang_wizard',
107 126 ),
@@ -116,11 +135,12 @@
116 135
117 136 /**
118 137 * Add an admin Polylang submenu to access the wizard
119 138 *
120 - * @param array $tabs Submenus list.
121 - * @return array Submenus list updated.
122 139 * @since 2.7
140 + *
141 + * @param string[] $tabs Submenus list.
142 + * @return string[] Submenus list updated.
123 143 */
124 144 public function settings_tabs( $tabs ) {
125 145 $tabs['wizard'] = esc_html__( 'Setup', 'polylang' );
126 146 return $tabs;
@@ -126,13 +146,14 @@
126 146 return $tabs;
127 147 }
128 148
129 149 /**
130 - * Return if the media step is displayable
150 + * Returns true if the media step is displayable, false otherwise.
131 151 *
132 - * @param array $languages List of language objects.
152 + * @since 2.7
153 + *
154 + * @param PLL_Language[] $languages List of language objects.
133 155 * @return bool
134 - * @since 2.7
135 156 */
136 157 public function is_media_step_displayable( $languages ) {
137 158 $media = array();
138 159 // If there is no language or only one the media step is displayable.
@@ -153,10 +174,11 @@
153 174
154 175 /**
155 176 * Check if the licenses step is displayable
156 177 *
178 + * @since 2.7
179 + *
157 180 * @return bool
158 - * @since 2.7
159 181 */
160 182 public function is_licenses_step_displayable() {
161 183 $licenses = apply_filters( 'pll_settings_licenses', array() );
162 184 return count( $licenses ) > 0;
@@ -165,8 +187,10 @@
165 187 /**
166 188 * Setup the wizard page
167 189 *
168 190 * @since 2.7
191 + *
192 + * @return void
169 193 */
170 194 public function setup_wizard_page() {
171 195
172 196 PLL_Admin_Notices::add_notice( 'wizard', $this->wizard_notice() );
@@ -184,26 +208,26 @@
184 208
185 209 $this->steps = apply_filters( 'pll_wizard_steps', $this->steps );
186 210 $step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
187 211
188 - $this->step = $step && array_key_exists( $step, $this->steps ) ? $step : current( array_keys( $this->steps ) );
212 + $this->current_step = $step && array_key_exists( $step, $this->steps ) ? $step : current( array_keys( $this->steps ) );
189 213
190 - $languages = $this->model->get_languages_list();
214 + $has_languages = $this->model->has_languages();
191 215
192 - if ( count( $languages ) === 0 && ! in_array( $this->step, array( 'licenses', 'languages' ) ) ) {
193 - wp_safe_redirect( esc_url_raw( $this->get_step_link( 'languages' ) ) );
216 + if ( ! $has_languages && ! in_array( $this->current_step, array( 'licenses', 'languages' ) ) ) {
217 + wp_safe_redirect( sanitize_url( $this->get_step_link( 'languages' ) ) );
194 218 exit;
195 219 }
196 220
197 - if ( count( $languages ) > 0 && $this->model->get_objects_with_no_lang( 1 ) && ! in_array( $this->step, array( 'licenses', 'languages', 'media', 'untranslated-contents' ) ) ) {
198 - wp_safe_redirect( esc_url_raw( $this->get_step_link( 'untranslated-contents' ) ) );
221 + if ( $has_languages && $this->model->get_objects_with_no_lang( 1 ) && ! in_array( $this->current_step, array( 'licenses', 'languages', 'media', 'untranslated-contents' ) ) ) {
222 + wp_safe_redirect( sanitize_url( $this->get_step_link( 'untranslated-contents' ) ) );
199 223 exit;
200 224 }
201 225
202 226 // Call the handler of the step for going to the next step.
203 227 // Be careful nonce verification with check_admin_referer must be done in each handler.
204 - if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->step ]['handler'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
205 - call_user_func( $this->steps[ $this->step ]['handler'] );
228 + if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->current_step ]['handler'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
229 + call_user_func( $this->steps[ $this->current_step ]['handler'] );
206 230 }
207 231
208 232 $this->display_wizard_page();
209 233 // Ensure nothing is done after including the page.
@@ -212,17 +236,18 @@
212 236
213 237 /**
214 238 * Adds some admin screens where to display the wizard notice
215 239 *
240 + * @since 2.7
241 + *
216 242 * @param bool $can_display_notice Whether the notice can be displayed.
217 243 * @param string $notice The notice name.
218 244 * @return bool
219 - * @since 2.7
220 245 */
221 246 public function can_display_notice( $can_display_notice, $notice ) {
222 247 if ( ! $can_display_notice && 'wizard' === $notice ) {
223 248 $screen = get_current_screen();
224 - $can_display_notice = in_array(
249 + $can_display_notice = ! empty( $screen ) && in_array(
225 250 $screen->base,
226 251 array(
227 252 'edit',
228 253 'upload',
@@ -236,8 +261,10 @@
236 261 /**
237 262 * Return html code of the wizard notice
238 263 *
239 264 * @since 2.7
265 + *
266 + * @return string
240 267 */
241 268 public function wizard_notice() {
242 269 ob_start();
243 270 include __DIR__ . '/html-wizard-notice.php';
@@ -247,11 +274,17 @@
247 274 /**
248 275 * Display the wizard page
249 276 *
250 277 * @since 2.7
278 + *
279 + * @return void
251 280 */
252 281 public function display_wizard_page() {
253 - set_current_screen();
282 + set_current_screen( 'pll-wizard' );
283 + do_action( 'admin_enqueue_scripts' );
284 + $steps = $this->steps;
285 + $current_step = $this->current_step;
286 + $styles = $this->styles;
254 287 include __DIR__ . '/view-wizard-page.php';
255 288 }
256 289
257 290 /**
@@ -257,12 +290,14 @@
257 290 /**
258 291 * Enqueue scripts and styles for the wizard
259 292 *
260 293 * @since 2.7
294 + *
295 + * @return void
261 296 */
262 297 public function enqueue_scripts() {
263 - wp_enqueue_style( 'polylang_admin', plugins_url( '/css/admin' . $this->get_suffix() . '.css', POLYLANG_FILE ), array(), POLYLANG_VERSION );
264 - wp_enqueue_style( 'pll-wizard', plugins_url( '/modules/wizard/css/wizard' . $this->get_suffix() . '.css', POLYLANG_FILE ), array( 'dashicons', 'install', 'common', 'forms' ), POLYLANG_VERSION );
298 + wp_enqueue_style( 'polylang_admin', plugins_url( '/css/build/admin' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array(), POLYLANG_VERSION );
299 + wp_enqueue_style( 'pll-wizard', plugins_url( '/css/build/wizard' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array( 'dashicons', 'install', 'common', 'forms' ), POLYLANG_VERSION );
265 300
266 301 $this->styles = array( 'polylang_admin', 'pll-wizard' );
267 302 }
268 303
@@ -268,11 +303,12 @@
268 303
269 304 /**
270 305 * Get the suffix to enqueue non minified files in a Debug context
271 306 *
307 + * @since 2.7
308 + *
272 309 * @return string Empty when SCRIPT_DEBUG equal to true
273 310 * otherwise .min
274 - * @since 2.7
275 311 */
276 312 public function get_suffix() {
277 313 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
278 314 }
@@ -279,16 +315,17 @@
279 315
280 316 /**
281 317 * Get the URL for the step's screen.
282 318 *
319 + * @since 2.7
320 + *
283 321 * @param string $step slug (default: current step).
284 322 * @return string URL for the step if it exists.
285 323 * Empty string on failure.
286 - * @since 2.7
287 324 */
288 325 public function get_step_link( $step = '' ) {
289 326 if ( ! $step ) {
290 - $step = $this->step;
327 + $step = $this->current_step;
291 328 }
292 329
293 330 $keys = array_keys( $this->steps );
294 331
@@ -302,17 +339,18 @@
302 339
303 340 /**
304 341 * Get the URL for the next step's screen.
305 342 *
343 + * @since 2.7
344 + *
306 345 * @param string $step slug (default: current step).
307 346 * @return string URL for next step if a next step exists.
308 347 * Admin URL if it's the last step.
309 348 * Empty string on failure.
310 - * @since 2.7
311 349 */
312 350 public function get_next_step_link( $step = '' ) {
313 351 if ( ! $step ) {
314 - $step = $this->step;
352 + $step = $this->current_step;
315 353 }
316 354
317 355 $keys = array_keys( $this->steps );
318 356 if ( end( $keys ) === $step ) {
@@ -329,24 +367,28 @@
329 367
330 368 /**
331 369 * Add licenses step to the wizard
332 370 *
371 + * @since 2.7
372 + *
333 373 * @param array $steps List of steps.
334 374 * @return array List of steps updated.
335 - * @since 2.7
336 375 */
337 376 public function add_step_licenses( $steps ) {
338 377 // Add ajax action on deactivate button in licenses step.
339 378 add_action( 'wp_ajax_pll_deactivate_license', array( $this, 'deactivate_license' ) );
340 379
341 - wp_enqueue_script( 'pll_admin', plugins_url( '/js/admin' . $this->get_suffix() . '.js', POLYLANG_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
342 - wp_localize_script( 'pll_admin', 'pll_dismiss_notice', esc_html__( 'Dismiss this notice.', 'polylang' ) );
380 + // Be careful `settings` script is enqueued here without dependency except jquery because only code useful for deactivate license button is needed.
381 + // To be really loaded the script needs to be passed to the `$steps['licenses']['scripts']` array below with the same handle than in `wp_enqueue_script()`.
382 + wp_enqueue_script( 'pll_settings', plugins_url( '/js/build/settings' . $this->get_suffix() . '.js', POLYLANG_ROOT_FILE ), array( 'jquery' ), POLYLANG_VERSION, true );
383 + wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) );
384 +
343 385 if ( $this->is_licenses_step_displayable() ) {
344 386 $steps['licenses'] = array(
345 387 'name' => esc_html__( 'Licenses', 'polylang' ),
346 388 'view' => array( $this, 'display_step_licenses' ),
347 389 'handler' => array( $this, 'save_step_licenses' ),
348 - 'scripts' => array( 'pll_admin' ), // Polylang admin script used by deactivate license button.
390 + 'scripts' => array( 'pll_settings' ), // Polylang admin script used by deactivate license button.
349 391 'styles' => array(),
350 392 );
351 393 }
352 394 return $steps;
@@ -355,8 +397,10 @@
355 397 /**
356 398 * Display the languages step form
357 399 *
358 400 * @since 2.7
401 + *
402 + * @return void
359 403 */
360 404 public function display_step_licenses() {
361 405 include __DIR__ . '/view-wizard-step-licenses.php';
362 406 }
@@ -364,8 +408,10 @@
364 408 /**
365 409 * Execute the languages step
366 410 *
367 411 * @since 2.7
412 + *
413 + * @return void
368 414 */
369 415 public function save_step_licenses() {
370 416 check_admin_referer( 'pll-wizard', '_pll_nonce' );
371 417
@@ -378,9 +424,9 @@
378 424 if ( ! empty( $updated_license->license_data ) && false === $updated_license->license_data->success ) {
379 425 // Stay on this step with an error.
380 426 $redirect = add_query_arg(
381 427 array(
382 - 'step' => $this->step,
428 + 'step' => $this->current_step,
383 429 'activate_error' => 'i18n_license_key_error',
384 430 )
385 431 );
386 432 }
@@ -386,9 +432,9 @@
386 432 }
387 433 }
388 434 }
389 435
390 - wp_safe_redirect( esc_url_raw( $redirect ) );
436 + wp_safe_redirect( sanitize_url( $redirect ) );
391 437 exit;
392 438 }
393 439
394 440 /**
@@ -394,8 +440,10 @@
394 440 /**
395 441 * Ajax method to deactivate a license
396 442 *
397 443 * @since 2.7
444 + *
445 + * @return void
398 446 */
399 447 public function deactivate_license() {
400 448 check_ajax_referer( 'pll-wizard', '_pll_nonce' );
401 449
@@ -422,16 +470,20 @@
422 470
423 471 /**
424 472 * Add languages step to the wizard
425 473 *
474 + * @since 2.7
475 + *
426 476 * @param array $steps List of steps.
427 477 * @return array List of steps updated.
428 - * @since 2.7
429 478 */
430 479 public function add_step_languages( $steps ) {
431 - wp_enqueue_script( 'pll-wizard-language-choice', plugins_url( '/js/admin' . $this->get_suffix() . '.js', POLYLANG_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
432 - wp_localize_script( 'pll-wizard-language-choice', 'pll_dismiss_notice', esc_html__( 'Dismiss this notice.', 'polylang' ) );
433 - wp_register_script( 'pll-wizard-languages', plugins_url( '/modules/wizard/js/languages-step' . $this->get_suffix() . '.js', POLYLANG_FILE ), array( 'jquery', 'jquery-ui-dialog' ), POLYLANG_VERSION, true );
480 + wp_deregister_script( 'pll_settings' ); // Deregister after the licenses step enqueue to update jquery-ui-selectmenu dependency.
481 + // The wp-ajax-response and postbox dependencies is useless in wizard steps especially postbox which triggers a javascript error otherwise.
482 + // To be really loaded the script needs to be passed to the `$steps['languages']['scripts']` array below with the same handle than in `wp_enqueue_script()`.
483 + wp_enqueue_script( 'pll_settings', plugins_url( '/js/build/settings' . $this->get_suffix() . '.js', POLYLANG_ROOT_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
484 + wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) );
485 + wp_register_script( 'pll-wizard-languages', plugins_url( '/js/build/languages-step' . $this->get_suffix() . '.js', POLYLANG_ROOT_FILE ), array( 'jquery', 'jquery-ui-dialog' ), POLYLANG_VERSION, true );
434 486 wp_localize_script(
435 487 'pll-wizard-languages',
436 488 'pll_wizard_params',
437 489 array(
@@ -452,14 +504,14 @@
452 504 'i18n_remove_language_icon' => esc_html__( 'Remove this language', 'polylang' ),
453 505 )
454 506 );
455 507 wp_enqueue_script( 'pll-wizard-languages' );
456 - wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/selectmenu' . $this->get_suffix() . '.css', POLYLANG_FILE ), array( 'dashicons', 'install', 'common', 'wp-jquery-ui-dialog' ), POLYLANG_VERSION );
508 + wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/build/selectmenu' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array( 'dashicons', 'install', 'common', 'wp-jquery-ui-dialog' ), POLYLANG_VERSION );
457 509 $steps['languages'] = array(
458 510 'name' => esc_html__( 'Languages', 'polylang' ),
459 511 'view' => array( $this, 'display_step_languages' ),
460 512 'handler' => array( $this, 'save_step_languages' ),
461 - 'scripts' => array( 'pll-wizard-languages', 'pll-wizard-language-choice' ),
513 + 'scripts' => array( 'pll-wizard-languages', 'pll_settings' ),
462 514 'styles' => array( 'pll-wizard-selectmenu' ),
463 515 );
464 516 return $steps;
465 517 }
@@ -467,10 +519,13 @@
467 519 /**
468 520 * Display the languages step form
469 521 *
470 522 * @since 2.7
523 + *
524 + * @return void
471 525 */
472 526 public function display_step_languages() {
527 + $model = $this->model;
473 528 include __DIR__ . '/view-wizard-step-languages.php';
474 529 }
475 530
476 531 /**
@@ -476,26 +531,26 @@
476 531 /**
477 532 * Execute the languages step
478 533 *
479 534 * @since 2.7
535 + *
536 + * @return void
480 537 */
481 538 public function save_step_languages() {
482 539 check_admin_referer( 'pll-wizard', '_pll_nonce' );
483 540
484 - $existing_languages = $this->model->get_languages_list();
485 -
486 - $all_languages = include POLYLANG_DIR . '/settings/languages.php';
487 - $languages = isset( $_POST['languages'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['languages'] ) ) : false;
541 + $all_languages = include POLYLANG_DIR . '/settings/languages.php';
542 + $languages = isset( $_POST['languages'] ) && is_array( $_POST['languages'] ) ? array_map( 'sanitize_locale_name', $_POST['languages'] ) : false;
488 543 $saved_languages = array();
489 544
490 545 // If there is no language added or defined.
491 - if ( empty( $languages ) && empty( $existing_languages ) ) {
546 + if ( empty( $languages ) && ! $this->model->has_languages() ) {
492 547 // Stay on this step with an error.
493 548 wp_safe_redirect(
494 - esc_url_raw(
549 + sanitize_url(
495 550 add_query_arg(
496 551 array(
497 - 'step' => $this->step,
552 + 'step' => $this->current_step,
498 553 'activate_error' => 'i18n_no_language_added',
499 554 )
500 555 )
501 556 )
@@ -527,12 +582,12 @@
527 582 if ( $language_added instanceof WP_Error ) {
528 583 // Stay on this step with an error.
529 584 $error_keys = array_keys( $language_added->errors );
530 585 wp_safe_redirect(
531 - esc_url_raw(
586 + sanitize_url(
532 587 add_query_arg(
533 588 array(
534 - 'step' => $this->step,
589 + 'step' => $this->current_step,
535 590 'activate_error' => 'i18n_' . reset( $error_keys ),
536 591 )
537 592 )
538 593 )
@@ -538,24 +593,25 @@
538 593 )
539 594 );
540 595 exit;
541 596 }
542 - if ( 'en_US' !== $locale ) {
597 +
598 + if ( 'en_US' !== $locale && current_user_can( 'install_languages' ) ) {
543 599 wp_download_language_pack( $locale );
544 600 }
545 601 }
546 602 }
547 - wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
603 + wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) );
548 604 exit;
549 605 }
550 606
551 607 /**
552 - * Add media step to the wizard
553 - * Add media step to the wizard
608 + * Add the media step to the wizard.
554 609 *
610 + * @since 2.7
611 + *
555 612 * @param array $steps List of steps.
556 613 * @return array List of steps updated.
557 - * @since 2.7
558 614 */
559 615 public function add_step_media( $steps ) {
560 616 $languages = $this->model->get_languages_list();
561 617
@@ -574,10 +630,13 @@
574 630 /**
575 631 * Display the media step form
576 632 *
577 633 * @since 2.7
634 + *
635 + * @return void
578 636 */
579 637 public function display_step_media() {
638 + $options = $this->options;
580 639 include __DIR__ . '/view-wizard-step-media.php';
581 640 }
582 641
583 642 /**
@@ -583,8 +642,10 @@
583 642 /**
584 643 * Execute the media step
585 644 *
586 645 * @since 2.7
646 + *
647 + * @return void
587 648 */
588 649 public function save_step_media() {
589 650 check_admin_referer( 'pll-wizard', '_pll_nonce' );
590 651
@@ -593,9 +654,9 @@
593 654 $this->options['media_support'] = $media_support;
594 655
595 656 update_option( 'polylang', $this->options );
596 657
597 - wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
658 + wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) );
598 659 exit;
599 660 }
600 661
601 662 /**
@@ -600,22 +661,25 @@
600 661
601 662 /**
602 663 * Add untranslated contents step to the wizard
603 664 *
665 + * @since 2.7
666 + *
604 667 * @param array $steps List of steps.
605 668 * @return array List of steps updated.
606 - * @since 2.7
607 669 */
608 670 public function add_step_untranslated_contents( $steps ) {
609 - if ( ! $this->model->get_languages_list() || $this->model->get_objects_with_no_lang( 1 ) ) {
610 - wp_enqueue_script( 'pll-wizard-language-choice', plugins_url( '/js/admin' . $this->get_suffix() . '.js', POLYLANG_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
611 - wp_localize_script( 'pll-wizard-language-choice', 'pll_dismiss_notice', esc_html__( 'Dismiss this notice.', 'polylang' ) );
612 - wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/selectmenu' . $this->get_suffix() . '.css', POLYLANG_FILE ), array( 'dashicons', 'install', 'common' ), POLYLANG_VERSION );
671 + if ( ! $this->model->has_languages() || $this->model->get_objects_with_no_lang( 1 ) ) {
672 + // Even if `pll_settings` is already enqueued with the same dependencies by the languages step, it is interesting to keep that it's also useful for the untranslated-contents step.
673 + // To be really loaded the script needs to be passed to the `$steps['untranslated-contents']['scripts']` array below with the same handle than in `wp_enqueue_script()`.
674 + wp_enqueue_script( 'pll_settings', plugins_url( '/js/build/settings' . $this->get_suffix() . '.js', POLYLANG_ROOT_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
675 + wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) );
676 + wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/build/selectmenu' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array( 'dashicons', 'install', 'common' ), POLYLANG_VERSION );
613 677 $steps['untranslated-contents'] = array(
614 678 'name' => esc_html__( 'Content', 'polylang' ),
615 679 'view' => array( $this, 'display_step_untranslated_contents' ),
616 680 'handler' => array( $this, 'save_step_untranslated_contents' ),
617 - 'scripts' => array( 'pll-wizard-language-choice' ),
681 + 'scripts' => array( 'pll_settings' ),
618 682 'styles' => array( 'pll-wizard-selectmenu' ),
619 683 );
620 684 }
621 685 return $steps;
@@ -624,10 +688,13 @@
624 688 /**
625 689 * Display the untranslated contents step form
626 690 *
627 691 * @since 2.7
692 + *
693 + * @return void
628 694 */
629 695 public function display_step_untranslated_contents() {
696 + $model = $this->model;
630 697 include __DIR__ . '/view-wizard-step-untranslated-contents.php';
631 698 }
632 699
633 700 /**
@@ -633,13 +700,15 @@
633 700 /**
634 701 * Execute the untranslated contents step
635 702 *
636 703 * @since 2.7
704 + *
705 + * @return void
637 706 */
638 707 public function save_step_untranslated_contents() {
639 708 check_admin_referer( 'pll-wizard', '_pll_nonce' );
640 709
641 - $lang = isset( $_POST['language'] ) ? sanitize_text_field( wp_unslash( $_POST['language'] ) ) : false;
710 + $lang = ! empty( $_POST['language'] ) && is_string( $_POST['language'] ) ? sanitize_locale_name( $_POST['language'] ) : false;
642 711
643 712 if ( empty( $lang ) ) {
644 713 $lang = $this->options['default_lang'];
645 714 }
@@ -645,18 +714,13 @@
645 714 }
646 715
647 716 $language = $this->model->get_language( $lang );
648 717
649 - while ( $nolang = $this->model->get_objects_with_no_lang( 1000 ) ) {
650 - if ( ! empty( $nolang['posts'] ) ) {
651 - $this->model->set_language_in_mass( 'post', $nolang['posts'], $language->slug );
652 - }
653 - if ( ! empty( $nolang['terms'] ) ) {
654 - $this->model->set_language_in_mass( 'term', $nolang['terms'], $language->slug );
655 - }
718 + if ( $language instanceof PLL_Language ) {
719 + $this->model->set_language_in_mass( $language );
656 720 }
657 721
658 - wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
722 + wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) );
659 723 exit;
660 724 }
661 725
662 726 /**
@@ -661,11 +725,12 @@
661 725
662 726 /**
663 727 * Add home page step to the wizard
664 728 *
729 + * @since 2.7
730 + *
665 731 * @param array $steps List of steps.
666 732 * @return array List of steps updated.
667 - * @since 2.7
668 733 */
669 734 public function add_step_home_page( $steps ) {
670 735 $languages = $this->model->get_languages_list();
671 736 $home_page_id = get_option( 'page_on_front' );
@@ -687,10 +752,30 @@
687 752 /**
688 753 * Display the home page step form
689 754 *
690 755 * @since 2.7
756 + *
757 + * @return void
691 758 */
692 759 public function display_step_home_page() {
760 + $model = $this->model;
761 + $languages = $model->languages->get_list();
762 + $home_page_id = get_option( 'page_on_front' );
763 + $home_page_id = is_numeric( $home_page_id ) ? (int) $home_page_id : 0;
764 + $translations = $model->post->get_translations( $home_page_id );
765 + $home_page = $home_page_id > 0 ? get_post( $home_page_id ) : null;
766 + $home_page_language = $model->post->get_language( $home_page_id );
767 + $untranslated_languages = array();
768 +
769 + if ( empty( $home_page ) ) {
770 + return;
771 + }
772 +
773 + foreach ( $languages as $language ) {
774 + if ( ! $model->post->get( $home_page_id, $language ) ) {
775 + $untranslated_languages[] = $language;
776 + }
777 + }
693 778 include __DIR__ . '/view-wizard-step-home-page.php';
694 779 }
695 780
696 781 /**
@@ -696,15 +781,15 @@
696 781 /**
697 782 * Execute the home page step
698 783 *
699 784 * @since 2.7
785 + *
786 + * @return void
700 787 */
701 788 public function save_step_home_page() {
702 789 check_admin_referer( 'pll-wizard', '_pll_nonce' );
703 790
704 - $languages = $this->model->get_languages_list();
705 -
706 - $default_language = count( $languages ) > 0 ? $this->options['default_lang'] : null;
791 + $default_language = $this->model->has_languages() ? $this->options['default_lang'] : null;
707 792 $home_page = isset( $_POST['home_page'] ) ? sanitize_key( $_POST['home_page'] ) : false;
708 793 $home_page_title = isset( $_POST['home_page_title'] ) ? sanitize_text_field( wp_unslash( $_POST['home_page_title'] ) ) : esc_html__( 'Homepage', 'polylang' );
709 794 $home_page_language = isset( $_POST['home_page_language'] ) ? sanitize_key( $_POST['home_page_language'] ) : false;
710 795
@@ -720,9 +805,9 @@
720 805 );
721 806
722 807 $this->model->clean_languages_cache();
723 808
724 - wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
809 + wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) );
725 810 exit;
726 811 }
727 812
728 813 /**
@@ -729,13 +814,14 @@
729 814 * Create home page translations for each language defined.
730 815 *
731 816 * @since 2.7
732 817 *
733 - * @param string $default_language slug of the default language; null if no default language is defined.
734 - * @param int $home_page post_id of the home page if it's defined, false otherwise.
735 - * @param string $home_page_title home page title if it's defined, 'Homepage' otherwise.
736 - * @param string $home_page_language slug of the home page if it's defined, false otherwise.
737 - * @param array $untranslated_languages array of languages which needs to have a home page translated.
818 + * @param string $default_language Slug of the default language; null if no default language is defined.
819 + * @param int $home_page Post ID of the home page if it's defined, false otherwise.
820 + * @param string $home_page_title Home page title if it's defined, 'Homepage' otherwise.
821 + * @param string $home_page_language Slug of the home page if it's defined, false otherwise.
822 + * @param string[] $untranslated_languages Array of languages which needs to have a home page translated.
823 + * @return void
738 824 */
739 825 public function create_home_page_translations( $default_language, $home_page, $home_page_title, $home_page_language, $untranslated_languages ) {
740 826 $translations = $this->model->post->get_translations( $home_page );
741 827
@@ -756,11 +842,12 @@
756 842
757 843 /**
758 844 * Add last step to the wizard
759 845 *
846 + * @since 2.7
847 + *
760 848 * @param array $steps List of steps.
761 849 * @return array List of steps updated.
762 - * @since 2.7
763 850 */
764 851 public function add_step_last( $steps ) {
765 852 $steps['last'] = array(
766 853 'name' => esc_html__( 'Ready!', 'polylang' ),
@@ -775,8 +862,10 @@
775 862 /**
776 863 * Display the last step form
777 864 *
778 865 * @since 2.7
866 + *
867 + * @return void
779 868 */
780 869 public function display_step_last() {
781 870 // We ran the wizard once. So we can dismiss its notice.
782 871 PLL_Admin_Notices::dismiss( 'wizard' );
@@ -786,12 +875,14 @@
786 875 /**
787 876 * Execute the last step
788 877 *
789 878 * @since 2.7
879 + *
880 + * @return void
790 881 */
791 882 public function save_step_last() {
792 883 check_admin_referer( 'pll-wizard', '_pll_nonce' );
793 884
794 - wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
885 + wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) );
795 886 exit;
796 887 }
797 888 }