PluginProbe
Polylang / 2.7.2
Polylang v2.7.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 / modules / wizard / wizard.php

wizard.php in Polylang 2.7.2, at modules/wizard/wizard.php

785 lines 23.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main class for Polylang wizard.
4 *
5 * @since 2.7
6 */
7 class PLL_Wizard {
8 /**
9 * Reference to PLL_Model object
10 *
11 * @var object $model
12 */
13 protected $model;
14
15 /**
16 * Reference to Polylang options array
17 *
18 * @var array $options
19 */
20 protected $options;
21
22 /**
23 * List of steps
24 *
25 * @var array $steps
26 */
27 protected $steps = array();
28
29 /**
30 * List of WordPress CSS file handles
31 *
32 * @var array $styles
33 */
34 protected $styles = array();
35
36 /**
37 * Constructor
38 *
39 * @param object $polylang Reference to Polylang global object.
40 * @since 2.7
41 */
42 public function __construct( &$polylang ) {
43 $this->options = &$polylang->options;
44 $this->model = &$polylang->model;
45
46 // Display Wizard page before any other action to ensure displaying it outside the WordPress admin context.
47 // Hooked on admin_init with priority 40 to ensure PLL_Wizard_Pro is corretly initialized.
48 add_action( 'admin_init', array( $this, 'setup_wizard_page' ), 40 );
49 // Add Wizard submenu.
50 add_filter( 'pll_settings_tabs', array( $this, 'settings_tabs' ), 10, 1 );
51 // Add filter to select screens where to display the notice.
52 add_filter( 'pll_can_display_notice', array( $this, 'can_display_notice' ), 10, 2 );
53
54 // Default steps.
55 add_filter( 'pll_wizard_steps', array( $this, 'add_step_licenses' ), 100 );
56 add_filter( 'pll_wizard_steps', array( $this, 'add_step_languages' ), 200 );
57 add_filter( 'pll_wizard_steps', array( $this, 'add_step_media' ), 300 );
58 add_filter( 'pll_wizard_steps', array( $this, 'add_step_untranslated_contents' ), 400 );
59 add_filter( 'pll_wizard_steps', array( $this, 'add_step_home_page' ), 500 );
60 add_filter( 'pll_wizard_steps', array( $this, 'add_step_last' ), 999 );
61 }
62
63 /**
64 * Save an activation transient when Polylang is activating to redirect to the wizard
65 *
66 * @param bool $network_wide if activated for all sites in the network.
67 * @since 2.7
68 */
69 public static function start_wizard( $network_wide ) {
70 $options = get_option( 'polylang' );
71
72 if ( wp_doing_ajax() || $network_wide || ! empty( $options ) ) {
73 return;
74 }
75 set_transient( 'pll_activation_redirect', 1, 30 );
76 }
77
78 /**
79 * Redirect to the wizard depending on the context
80 *
81 * @since 2.7
82 */
83 public function redirect_to_wizard() {
84 if ( get_transient( 'pll_activation_redirect' ) ) {
85 $do_redirect = true;
86 if ( ( isset( $_GET['page'] ) && 'mlang_wizard' === sanitize_key( $_GET['page'] ) || isset( $_GET['activate-multi'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
87 delete_transient( 'pll_activation_redirect' );
88 $do_redirect = false;
89 }
90
91 if ( $do_redirect ) {
92 wp_safe_redirect(
93 esc_url_raw(
94 add_query_arg(
95 array(
96 'page' => 'mlang_wizard',
97 ),
98 admin_url( 'admin.php' )
99 )
100 )
101 );
102 exit;
103 }
104 }
105 }
106
107 /**
108 * Add an admin Polylang submenu to access the wizard
109 *
110 * @param array $tabs Submenus list.
111 * @return array Submenus list updated.
112 * @since 2.7
113 */
114 public function settings_tabs( $tabs ) {
115 $tabs['wizard'] = __( 'Setup', 'polylang' );
116 return $tabs;
117 }
118
119 /**
120 * Return if the media step is displayable
121 *
122 * @param array $languages List of language objects.
123 * @return bool
124 * @since 2.7
125 */
126 public function is_media_step_displayable( $languages ) {
127 $media = array();
128 // If there is no language or only one the media step is displayable.
129 if ( ! $languages || count( $languages ) < 2 ) {
130 return true;
131 }
132 foreach ( $languages as $language ) {
133 $media[ $language->slug ] = $this->model->count_posts(
134 $language,
135 array(
136 'post_type' => array( 'attachment' ),
137 'post_status' => 'inherit',
138 )
139 );
140 }
141 return count( array_filter( $media ) ) === 0;
142 }
143
144 /**
145 * Check if the licenses step is displayable
146 *
147 * @return bool
148 * @since 2.7
149 */
150 public function is_licenses_step_displayable() {
151 $licenses = apply_filters( 'pll_settings_licenses', array() );
152 return count( $licenses ) > 0;
153 }
154
155 /**
156 * Setup the wizard page
157 *
158 * @since 2.7
159 */
160 public function setup_wizard_page() {
161
162 PLL_Admin_Notices::add_notice( 'wizard', $this->wizard_notice() );
163
164 $this->redirect_to_wizard();
165 if ( ! Polylang::is_wizard() ) {
166 return;
167 }
168 if ( ! current_user_can( 'manage_options' ) ) {
169 wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'polylang' ) );
170 }
171
172 // Enqueue scripts and styles especially for the wizard.
173 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
174
175 $this->steps = apply_filters( 'pll_wizard_steps', $this->steps );
176 $step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
177
178 $this->step = $step && array_key_exists( $step, $this->steps ) ? $step : current( array_keys( $this->steps ) );
179
180 $languages = $this->model->get_languages_list();
181
182 if ( count( $languages ) === 0 && ! in_array( $this->step, array( 'licenses', 'languages' ) ) ) {
183 wp_safe_redirect( esc_url_raw( $this->get_step_link( 'languages' ) ) );
184 exit;
185 }
186
187 if ( count( $languages ) > 0 && $this->model->get_objects_with_no_lang( 1 ) && ! in_array( $this->step, array( 'licenses', 'languages', 'media', 'untranslated-contents' ) ) ) {
188 wp_safe_redirect( esc_url_raw( $this->get_step_link( 'untranslated-contents' ) ) );
189 exit;
190 }
191
192 // Call the handler of the step for going to the next step.
193 // Be careful nonce verification with check_admin_referer must be done in each handler.
194 if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->step ]['handler'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
195 call_user_func( $this->steps[ $this->step ]['handler'] );
196 }
197
198 $this->display_wizard_page();
199 // Ensure nothing is done after including the page.
200 exit;
201 }
202
203 /**
204 * Adds some admin screens where to display the wizard notice
205 *
206 * @param bool $can_display_notice Whether the notice can be displayed.
207 * @param string $notice The notice name.
208 * @return bool
209 * @since 2.7
210 */
211 public function can_display_notice( $can_display_notice, $notice ) {
212 if ( ! $can_display_notice && 'wizard' === $notice ) {
213 $screen = get_current_screen();
214 $can_display_notice = in_array(
215 $screen->base,
216 array(
217 'edit',
218 'upload',
219 'options-general',
220 )
221 );
222 }
223 return $can_display_notice;
224 }
225
226 /**
227 * Return html code of the wizard notice
228 *
229 * @since 2.7
230 */
231 public function wizard_notice() {
232 ob_start();
233 include PLL_MODULES_INC . '/wizard/html-wizard-notice.php';
234 return ob_get_clean();
235 }
236
237 /**
238 * Display the wizard page
239 *
240 * @since 2.7
241 */
242 public function display_wizard_page() {
243 set_current_screen();
244 include PLL_MODULES_INC . '/wizard/view-wizard-page.php';
245 }
246
247 /**
248 * Enqueue scripts and styles for the wizard
249 *
250 * @since 2.7
251 */
252 public function enqueue_scripts() {
253 wp_enqueue_style( 'polylang_admin', plugins_url( '/css/admin' . $this->get_suffix() . '.css', POLYLANG_FILE ), array(), POLYLANG_VERSION );
254 wp_enqueue_style( 'pll-wizard', plugins_url( '/modules/wizard/css/wizard' . $this->get_suffix() . '.css', POLYLANG_FILE ), array( 'dashicons', 'install', 'common', 'forms' ), POLYLANG_VERSION );
255
256 $this->styles = array( 'polylang_admin', 'pll-wizard' );
257 }
258
259 /**
260 * Get the suffix to enqueue non minified files in a Debug context
261 *
262 * @return string Empty when SCRIPT_DEBUG equal to true
263 * otherwise .min
264 * @since 2.7
265 */
266 public function get_suffix() {
267 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
268 }
269
270 /**
271 * Get the URL for the step's screen.
272 *
273 * @param string $step slug (default: current step).
274 * @return string URL for the step if it exists.
275 * Empty string on failure.
276 * @since 2.7
277 */
278 public function get_step_link( $step = '' ) {
279 if ( ! $step ) {
280 $step = $this->step;
281 }
282
283 $keys = array_keys( $this->steps );
284
285 $step_index = array_search( $step, $keys, true );
286 if ( false === $step_index ) {
287 return '';
288 }
289
290 return add_query_arg( 'step', $keys[ $step_index ], remove_query_arg( 'activate_error' ) );
291 }
292
293 /**
294 * Get the URL for the next step's screen.
295 *
296 * @param string $step slug (default: current step).
297 * @return string URL for next step if a next step exists.
298 * Admin URL if it's the last step.
299 * Empty string on failure.
300 * @since 2.7
301 */
302 public function get_next_step_link( $step = '' ) {
303 if ( ! $step ) {
304 $step = $this->step;
305 }
306
307 $keys = array_keys( $this->steps );
308 if ( end( $keys ) === $step ) {
309 return admin_url();
310 }
311
312 $step_index = array_search( $step, $keys, true );
313 if ( false === $step_index ) {
314 return '';
315 }
316
317 return add_query_arg( 'step', $keys[ $step_index + 1 ], remove_query_arg( 'activate_error' ) );
318 }
319
320 /**
321 * Add licenses step to the wizard
322 *
323 * @param array $steps List of steps.
324 * @return array List of steps updated.
325 * @since 2.7
326 */
327 public function add_step_licenses( $steps ) {
328 // Add ajax action on deactivate button in licenses step.
329 add_action( 'wp_ajax_pll_deactivate_license', array( $this, 'deactivate_license' ) );
330
331 wp_enqueue_script( 'pll_admin', plugins_url( '/js/admin' . $this->get_suffix() . '.js', POLYLANG_FILE ), array( 'jquery', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
332 if ( $this->is_licenses_step_displayable() ) {
333 $steps['licenses'] = array(
334 'name' => __( 'Licenses', 'polylang' ),
335 'view' => array( $this, 'display_step_licenses' ),
336 'handler' => array( $this, 'save_step_licenses' ),
337 'scripts' => array( 'pll_admin' ), // Polylang admin script used by deactivate license button.
338 'styles' => array(),
339 );
340 }
341 return $steps;
342 }
343
344 /**
345 * Display the languages step form
346 *
347 * @since 2.7
348 */
349 public function display_step_licenses() {
350 include PLL_MODULES_INC . '/wizard/view-wizard-step-licenses.php';
351 }
352
353 /**
354 * Execute the languages step
355 *
356 * @since 2.7
357 */
358 public function save_step_licenses() {
359 check_admin_referer( 'pll-wizard', '_pll_nonce' );
360
361 $redirect = $this->get_next_step_link();
362 $licenses = apply_filters( 'pll_settings_licenses', array() );
363
364 foreach ( $licenses as $license ) {
365 if ( ! empty( $_POST['licenses'][ $license->id ] ) ) {
366 $updated_license = $license->activate_license( sanitize_key( $_POST['licenses'][ $license->id ] ) );
367 if ( ! empty( $updated_license->license_data ) && false === $updated_license->license_data->success ) {
368 // Stay on this step with an error.
369 $redirect = add_query_arg(
370 array(
371 'step' => $this->step,
372 'activate_error' => 'i18n_license_key_error',
373 )
374 );
375 }
376 }
377 }
378
379 wp_safe_redirect( esc_url_raw( $redirect ) );
380 exit;
381 }
382
383 /**
384 * Ajax method to deactivate a license
385 *
386 * @since 2.7
387 */
388 public function deactivate_license() {
389 check_ajax_referer( 'pll-wizard', '_pll_nonce' );
390
391 if ( ! current_user_can( 'manage_options' ) ) {
392 wp_die( -1 );
393 }
394
395 if ( ! isset( $_POST['id'] ) ) {
396 wp_die( 0 );
397 }
398
399 $id = substr( sanitize_text_field( wp_unslash( $_POST['id'] ) ), 11 );
400 $licenses = apply_filters( 'pll_settings_licenses', array() );
401 $license = $licenses[ $id ];
402 $license->deactivate_license();
403
404 wp_send_json(
405 array(
406 'id' => $id,
407 'html' => $license->get_form_field(),
408 )
409 );
410 }
411
412 /**
413 * Add languages step to the wizard
414 *
415 * @param array $steps List of steps.
416 * @return array List of steps updated.
417 * @since 2.7
418 */
419 public function add_step_languages( $steps ) {
420 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 );
421 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 );
422 wp_localize_script(
423 'pll-wizard-languages',
424 'pll_wizard_params',
425 array(
426 'i18n_no_language_selected' => __( 'You need to select a language to be added.', 'polylang' ),
427 'i18n_language_already_added' => __( 'You already added this language.', 'polylang' ),
428 'i18n_no_language_added' => __( 'You need to add at least one language.', 'polylang' ),
429 'i18n_add_language_needed' => __( 'You selected a language, however, to be able to continue, you need to add it.', 'polylang' ),
430 'i18n_pll_add_language' => __( 'Impossible to add the language.', 'polylang' ),
431 'i18n_pll_invalid_locale' => __( 'Enter a valid WordPress locale', 'polylang' ),
432 'i18n_pll_invalid_slug' => __( 'The language code contains invalid characters', 'polylang' ),
433 'i18n_pll_non_unique_slug' => __( 'The language code must be unique', 'polylang' ),
434 'i18n_pll_invalid_name' => __( 'The language must have a name', 'polylang' ),
435 'i18n_pll_invalid_flag' => __( 'The flag does not exist', 'polylang' ),
436 'i18n_dialog_title' => __( "A language wasn't added.", 'polylang' ),
437 'i18n_dialog_yes_button' => __( 'Yes', 'polylang' ),
438 'i18n_dialog_no_button' => __( 'No', 'polylang' ),
439 'i18n_dialog_ignore_button' => __( 'Ignore', 'polylang' ),
440 'i18n_remove_language_icon' => __( 'Remove this language', 'polylang' ),
441 )
442 );
443 wp_enqueue_script( 'pll-wizard-languages' );
444 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 );
445 $steps['languages'] = array(
446 'name' => __( 'Languages', 'polylang' ),
447 'view' => array( $this, 'display_step_languages' ),
448 'handler' => array( $this, 'save_step_languages' ),
449 'scripts' => array( 'pll-wizard-languages', 'pll-wizard-language-choice' ),
450 'styles' => array( 'pll-wizard-selectmenu' ),
451 );
452 return $steps;
453 }
454
455 /**
456 * Display the languages step form
457 *
458 * @since 2.7
459 */
460 public function display_step_languages() {
461 include PLL_MODULES_INC . '/wizard/view-wizard-step-languages.php';
462 }
463
464 /**
465 * Execute the languages step
466 *
467 * @since 2.7
468 */
469 public function save_step_languages() {
470 check_admin_referer( 'pll-wizard', '_pll_nonce' );
471
472 $existing_languages = $this->model->get_languages_list();
473
474 $all_languages = include PLL_SETTINGS_INC . '/languages.php';
475 $languages = isset( $_POST['languages'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['languages'] ) ) : false;
476 $saved_languages = array();
477
478 // If there is no language added or defined.
479 if ( empty( $languages ) && empty( $existing_languages ) ) {
480 // Stay on this step with an error.
481 wp_safe_redirect(
482 esc_url_raw(
483 add_query_arg(
484 array(
485 'step' => $this->step,
486 'activate_error' => 'i18n_no_language_added',
487 )
488 )
489 )
490 );
491 exit;
492 }
493
494 // Otherwise process the languages to add or skip the step if no language has been added.
495 if ( ! empty( $languages ) ) {
496 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
497 // Remove duplicate values.
498 $languages = array_unique( $languages );
499 // For each language add it in Polylang settings.
500 foreach ( $languages as $locale ) {
501 $saved_languages = $all_languages[ $locale ];
502
503 $saved_languages['slug'] = $saved_languages['code'];
504 $saved_languages['rtl'] = (int) ( 'rtl' === $saved_languages['dir'] );
505 $saved_languages['term_group'] = 0; // Default term_group.
506
507 $language_added = $this->model->add_language( $saved_languages );
508
509 if ( $language_added instanceof WP_Error && array_key_exists( 'pll_non_unique_slug', $language_added->errors ) ) {
510 // Get the slug from the locale : lowercase and dash instead of underscore.
511 $saved_languages['slug'] = strtolower( str_replace( '_', '-', $saved_languages['locale'] ) );
512 $language_added = $this->model->add_language( $saved_languages );
513 }
514
515 if ( $language_added instanceof WP_Error ) {
516 // Stay on this step with an error.
517 $error_keys = array_keys( $language_added->errors );
518 wp_safe_redirect(
519 esc_url_raw(
520 add_query_arg(
521 array(
522 'step' => $this->step,
523 'activate_error' => 'i18n_' . reset( $error_keys ),
524 )
525 )
526 )
527 );
528 exit;
529 }
530 if ( 'en_US' !== $locale ) {
531 wp_download_language_pack( $locale );
532 }
533 }
534 }
535 wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
536 exit;
537 }
538
539 /**
540 * Add media step to the wizard
541 * Add media step to the wizard
542 *
543 * @param array $steps List of steps.
544 * @return array List of steps updated.
545 * @since 2.7
546 */
547 public function add_step_media( $steps ) {
548 $languages = $this->model->get_languages_list();
549
550 if ( $this->is_media_step_displayable( $languages ) ) {
551 $steps['media'] = array(
552 'name' => __( 'Media', 'polylang' ),
553 'view' => array( $this, 'display_step_media' ),
554 'handler' => array( $this, 'save_step_media' ),
555 'scripts' => array(),
556 'styles' => array(),
557 );
558 }
559 return $steps;
560 }
561
562 /**
563 * Display the media step form
564 *
565 * @since 2.7
566 */
567 public function display_step_media() {
568 include PLL_MODULES_INC . '/wizard/view-wizard-step-media.php';
569 }
570
571 /**
572 * Execute the media step
573 *
574 * @since 2.7
575 */
576 public function save_step_media() {
577 check_admin_referer( 'pll-wizard', '_pll_nonce' );
578
579 $media_support = isset( $_POST['media_support'] ) ? sanitize_key( $_POST['media_support'] ) === 'yes' : false;
580
581 $this->options['media_support'] = $media_support;
582
583 update_option( 'polylang', $this->options );
584
585 wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
586 exit;
587 }
588
589 /**
590 * Add untranslated contents step to the wizard
591 *
592 * @param array $steps List of steps.
593 * @return array List of steps updated.
594 * @since 2.7
595 */
596 public function add_step_untranslated_contents( $steps ) {
597 if ( ! $this->model->get_languages_list() || $this->model->get_objects_with_no_lang( 1 ) ) {
598 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 );
599 wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/selectmenu' . $this->get_suffix() . '.css', POLYLANG_FILE ), array( 'dashicons', 'install', 'common' ), POLYLANG_VERSION );
600 $steps['untranslated-contents'] = array(
601 'name' => __( 'Content', 'polylang' ),
602 'view' => array( $this, 'display_step_untranslated_contents' ),
603 'handler' => array( $this, 'save_step_untranslated_contents' ),
604 'scripts' => array( 'pll-wizard-language-choice' ),
605 'styles' => array( 'pll-wizard-selectmenu' ),
606 );
607 }
608 return $steps;
609 }
610
611 /**
612 * Display the untranslated contents step form
613 *
614 * @since 2.7
615 */
616 public function display_step_untranslated_contents() {
617 include PLL_MODULES_INC . '/wizard/view-wizard-step-untranslated-contents.php';
618 }
619
620 /**
621 * Execute the untranslated contents step
622 *
623 * @since 2.7
624 */
625 public function save_step_untranslated_contents() {
626 check_admin_referer( 'pll-wizard', '_pll_nonce' );
627
628 $lang = isset( $_POST['language'] ) ? sanitize_text_field( wp_unslash( $_POST['language'] ) ) : false;
629
630 if ( empty( $lang ) ) {
631 $lang = $this->options['default_lang'];
632 }
633
634 $language = $this->model->get_language( $lang );
635
636 while ( $nolang = $this->model->get_objects_with_no_lang( 1000 ) ) {
637 if ( ! empty( $nolang['posts'] ) ) {
638 $this->model->set_language_in_mass( 'post', $nolang['posts'], $language->slug );
639 }
640 if ( ! empty( $nolang['terms'] ) ) {
641 $this->model->set_language_in_mass( 'term', $nolang['terms'], $language->slug );
642 }
643 }
644
645 wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
646 exit;
647 }
648
649 /**
650 * Add home page step to the wizard
651 *
652 * @param array $steps List of steps.
653 * @return array List of steps updated.
654 * @since 2.7
655 */
656 public function add_step_home_page( $steps ) {
657 $languages = $this->model->get_languages_list();
658 $home_page_id = get_option( 'page_on_front' );
659
660 $translations = $this->model->post->get_translations( $home_page_id );
661
662 if ( $home_page_id > 0 && ( ! $languages || count( $languages ) === 1 || count( $translations ) !== count( $languages ) ) ) {
663 $steps['home-page'] = array(
664 'name' => __( 'Homepage', 'polylang' ),
665 'view' => array( $this, 'display_step_home_page' ),
666 'handler' => array( $this, 'save_step_home_page' ),
667 'scripts' => array(),
668 'styles' => array(),
669 );
670 }
671 return $steps;
672 }
673
674 /**
675 * Display the home page step form
676 *
677 * @since 2.7
678 */
679 public function display_step_home_page() {
680 include PLL_MODULES_INC . '/wizard/view-wizard-step-home-page.php';
681 }
682
683 /**
684 * Execute the home page step
685 *
686 * @since 2.7
687 */
688 public function save_step_home_page() {
689 check_admin_referer( 'pll-wizard', '_pll_nonce' );
690
691 $languages = $this->model->get_languages_list();
692
693 $default_language = count( $languages ) > 0 ? $this->options['default_lang'] : null;
694 $home_page = isset( $_POST['home_page'] ) ? sanitize_key( $_POST['home_page'] ) : false;
695 $home_page_title = isset( $_POST['home_page_title'] ) ? sanitize_text_field( wp_unslash( $_POST['home_page_title'] ) ) : esc_html__( 'Homepage', 'polylang' );
696 $home_page_language = isset( $_POST['home_page_language'] ) ? sanitize_key( $_POST['home_page_language'] ) : false;
697
698 $untranslated_languages = isset( $_POST['untranslated_languages'] ) ? array_map( 'sanitize_key', $_POST['untranslated_languages'] ) : array();
699
700 call_user_func(
701 apply_filters( 'pll_wizard_create_home_page_translations', array( $this, 'create_home_page_translations' ) ),
702 $default_language,
703 $home_page,
704 $home_page_title,
705 $home_page_language,
706 $untranslated_languages
707 );
708
709 $this->model->clean_languages_cache();
710
711 wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
712 exit;
713 }
714
715 /**
716 * Create home page translations for each language defined.
717 *
718 * @since 2.7
719 *
720 * @param string $default_language slug of the default language; null if no default language is defined.
721 * @param int $home_page post_id of the home page if it's defined, false otherwise.
722 * @param string $home_page_title home page title if it's defined, 'Homepage' otherwise.
723 * @param string $home_page_language slug of the home page if it's defined, false otherwise.
724 * @param array $untranslated_languages array of languages which needs to have a home page translated.
725 */
726 public function create_home_page_translations( $default_language, $home_page, $home_page_title, $home_page_language, $untranslated_languages ) {
727 $translations = $this->model->post->get_translations( $home_page );
728
729 foreach ( $untranslated_languages as $language ) {
730 $language_properties = $this->model->get_language( $language );
731 $id = wp_insert_post(
732 array(
733 'post_title' => $home_page_title . ' - ' . $language_properties->name,
734 'post_type' => 'page',
735 'post_status' => 'publish',
736 )
737 );
738 $translations[ $language ] = $id;
739 pll_set_post_language( $id, $language );
740 }
741 pll_save_post_translations( $translations );
742 }
743
744 /**
745 * Add last step to the wizard
746 *
747 * @param array $steps List of steps.
748 * @return array List of steps updated.
749 * @since 2.7
750 */
751 public function add_step_last( $steps ) {
752 $steps['last'] = array(
753 'name' => __( 'Ready!', 'polylang' ),
754 'view' => array( $this, 'display_step_last' ),
755 'handler' => array( $this, 'save_step_last' ),
756 'scripts' => array(),
757 'styles' => array(),
758 );
759 return $steps;
760 }
761
762 /**
763 * Display the last step form
764 *
765 * @since 2.7
766 */
767 public function display_step_last() {
768 // We ran the wizard once. So we can dismiss its notice.
769 PLL_Admin_Notices::dismiss( 'wizard' );
770 include PLL_MODULES_INC . '/wizard/view-wizard-step-last.php';
771 }
772
773 /**
774 * Execute the last step
775 *
776 * @since 2.7
777 */
778 public function save_step_last() {
779 check_admin_referer( 'pll-wizard', '_pll_nonce' );
780
781 wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
782 exit;
783 }
784 }
785