�PNG  IHDR22?�� pHYs  �� OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, � ��!���������{�kּ������>���� �H3Q5� �B�������.@� $p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[ �b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|�� �J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN �(���~���)�)�4L�1e\k����X�H�Q�G�6������E�Y��A�J'\'Gg����S�Sݧ �M=:��.�k���Dw�n��^��Lo��y���}/�T�m���G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z���������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%� y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y- �B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I���?�������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��499�?r����C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h���SЧ��������c3-� cHRMz%������u0�`:�o�_�F5IDATx��ytUս�?�;���fN$$��@B�!�k��� -*�gE���j�O�kQ�ʠ`U�B_ �AÐ0%�Ȕ�@r3ޛ;߳��$�@��v����^�s����������$��ߢ !�W��5�̱'-٘������4�>�Rƫ$�G��0U�H}�_ _� #��k�MJ/=�9Du *ڲ�k�PQ;0��j|�*�$�^컂脛y���>�z×� B��� ��(�:$�ʔ_�6��C!B����MVx��a��ζyY����j��ƋY2�9�F�{r��r�딟F��Q��hY6��� x��[l��RC��������nt@��;P��3��� F�w��7��:�P���ɋ'���mj���Bƪ�$�Q�L��y��߷g��\���z����v5�p�v$�v櫻�`6~K �Y�X����,�:��"�o�e0II"(��,������l_�C���/4�+f�E�!q��:����u����c��樼.UE�@� �]K�W���$-�h]�JG���Dz)�`��.�A/ ���mᏣc�3jK� �!�>���$�Q�!�_�? \�C2(E �M$Z I{�U���s�ǣ���=��@Բe ޻��W�����@ �w����}�9v,)��.}*|"�s��di���,���G�]W�AC�������|<����[��ߕ������K�*�G nߴ!��‹��J�!��6(L�a)��Am��������;adf��:�xm��nh�;֦I��(���o�C~ډa?�=��s����h��E������xp����)���_���t��W�����´;8���`dz=(��@@�+,�;�`�fhl��XȌ�3,uI�~z(J����� �ZX�A����H'�À�㜦�82|��a�n�z2��I���� ���EY�h�ε<�0�q�{��C��v�˅��?"@��χ�x�WS+��N�~�KQ�J�8ل�� _.W��� !TU{�����,��"�� �;�������HI S� ��))�o�1�H�D� ���� (� ;����"Ҕ��,���� �F=���O��&�Ph>�`���y��߲ &S��P�<��'��1s�1cĂ�N����2)����@�u��tv��<�+�-&�����h��[!FSG���' � z z0��<����8d&�����E0�,��<��"!P�b4��� �{S�����X����.�囤���T��hEF��X�q0"-<����h���]�Py*����F⩍��@v�˂�Y08�� .q��a��s����(!<̫1�3�L�H��7sYW�`��qtu�\7��?�@�Y�� %Ka�x�GZ�*W�P��y�����N0r9��Z�c�%���q,��k�����!!,��>���IB��� �x1�Xu�Y���v-���ֺ��N������JP��a�2`�e5��w��u;�6�i���̃��(K���ťa��(l51��JL��O'%���]���ٖ뿉!��{*�p+f ���i8��D�ȑ���ܩ�M��V��ӟz��x�7Z�1i}�^͜���6e����x��)u�d�ˏ�V�eG�\�X1�����=n�U'�~Y����L�\,�(d!x ,�:�TW8� M`r���@��r+v�Q0��>^;˴�VbF��('����� �*O��i��j�Ӆ����^�S3&� ���{������.ی�� N;��NU%d0�Ce\r"�C�b��&t7N�7��� �ȪD�[%l�۪�$��'m?�A9tI�9>��NVL ��� 6v~M�����ъ�B���0����9$&=ώm��W�0���L���&��E���f�f��'+�9��hv��7,���M��6�D�&�^� �����8 D֮�����o��k^z��O��hP�8q�5d*��YVq3�{��������#LX4�?��jP=3�~�؅c�ݰ�̱�ұ��8̲��2�G�����j��έ�9��w7���U�X�w�85C��?!I&���o&����L���I#�^�eV�,�^t5�k� �xs˛\��U�8��."���{���ǵ�l4��ݼ�;��r"���G�/~���gJV�N糦��ZZ^k+NN�D��I$�=OE�z����|*�*{��%k���G��>�`9��b;�s���8,�qs��c��.b��q�%�>r��n�R�Ƨ�%�,�A��le#�8���}; 21�0�b�&�QX�f���q�00����$>�h�N�'�a3��A���/�r ��L5�8�GԲ'�����w;��c#�q1���h$*��V^�k��QĽ�b:i������� ����H F#�_���,��]g����Ը����`RUU���� ��"�qD���>-��ϤI�~��3�̴�����NZ[[555�eeek7�m����YF#[��Đ��R��i��L�H�r ��@��J-�Pŝ��_|�-��6y��ks�V�U~��6���w.����(��0A� 4��f��� /���C�xŊ�ٳ����z=6�����rg���mKo��o�/����a�g���?'9%9��P��斓��~���L{�� �H��{AW��B��$����v�1b�&Mb�ر��ر#�0`�`xMBp! )Z�Nmo�mZ�g�}�eذaWTVV ���'99��C5��&�&+5�bT>|8��PUUETT����&���t��~TE%��'������b�tEGG;RSS�S�N�v��ѯ��t����u1@�ޚ"f��͈���r'L�Ph��m��ƌ�74o��`�x�q�P���NRSS�X,�����l&&&��MFFA!-��`��ҷ�n��Yuu�����x<I�LB%����KԒ50�!�3�bz�����ʸKL���;---�l6[��`��������Ȏ;�����egg4��!D�T��jWujyZ��������K����%����p�^���X,6��sV=�ܖ����6�3�X ���4ҿ��A2�&����_k�;d�� �VfOIEND�B`�
Warning: session_start(): Session cannot be started after headers have already been sent in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 124

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 130

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 131

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 132

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 133

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 134

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 547

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 548

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 549

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 550

Warning: Cannot modify header information - headers already sent by (output started at /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php:1) in /home/mciraet/www/wp-includes/php-ai-client/src/Providers/Enums/Documentsoliders.php on line 551
options = $polylang->options; $this->model = &$polylang->model; // Display Wizard page before any other action to ensure displaying it outside the WordPress admin context. // Hooked on admin_init with priority 40 to ensure PLL_Wizard_Pro is correctly initialized. add_action( 'admin_init', array( $this, 'setup_wizard_page' ), 40 ); // Add Wizard submenu. add_filter( 'pll_settings_tabs', array( $this, 'settings_tabs' ), 10, 1 ); // Add filter to select screens where to display the notice. add_filter( 'pll_can_display_notice', array( $this, 'can_display_notice' ), 10, 2 ); // Default steps. add_filter( 'pll_wizard_steps', array( $this, 'add_step_licenses' ), 100 ); add_filter( 'pll_wizard_steps', array( $this, 'add_step_languages' ), 200 ); add_filter( 'pll_wizard_steps', array( $this, 'add_step_media' ), 300 ); add_filter( 'pll_wizard_steps', array( $this, 'add_step_untranslated_contents' ), 400 ); add_filter( 'pll_wizard_steps', array( $this, 'add_step_home_page' ), 500 ); add_filter( 'pll_wizard_steps', array( $this, 'add_step_last' ), 999 ); } /** * Save an activation transient when Polylang is activating to redirect to the wizard * * @since 2.7 * * @param bool $network_wide if activated for all sites in the network. * @return void */ public static function start_wizard( $network_wide ) { $options = (array) get_option( Options::OPTION_NAME, array() ); if ( wp_doing_ajax() || $network_wide || ! empty( $options['version'] ) ) { return; } set_transient( 'pll_activation_redirect', 1, 30 ); } /** * Redirect to the wizard depending on the context * * @since 2.7 * * @return void */ public function redirect_to_wizard() { if ( get_transient( 'pll_activation_redirect' ) ) { $do_redirect = true; if ( ( isset( $_GET['page'] ) && 'mlang_wizard' === sanitize_key( $_GET['page'] ) ) || isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended delete_transient( 'pll_activation_redirect' ); $do_redirect = false; } if ( $do_redirect ) { wp_safe_redirect( sanitize_url( add_query_arg( array( 'page' => 'mlang_wizard', ), admin_url( 'admin.php' ) ) ) ); exit; } } } /** * Add an admin Polylang submenu to access the wizard * * @since 2.7 * * @param string[] $tabs Submenus list. * @return string[] Submenus list updated. */ public function settings_tabs( $tabs ) { $tabs['wizard'] = esc_html__( 'Setup', 'polylang' ); return $tabs; } /** * Returns true if the media step is displayable, false otherwise. * * @since 2.7 * * @param PLL_Language[] $languages List of language objects. * @return bool */ public function is_media_step_displayable( $languages ) { $media = array(); // If there is no language or only one the media step is displayable. if ( ! $languages || count( $languages ) < 2 ) { return true; } foreach ( $languages as $language ) { $media[ $language->slug ] = $this->model->count_posts( $language, array( 'post_type' => array( 'attachment' ), 'post_status' => 'inherit', ) ); } return count( array_filter( $media ) ) === 0; } /** * Check if the licenses step is displayable * * @since 2.7 * * @return bool */ public function is_licenses_step_displayable() { $licenses = apply_filters( 'pll_settings_licenses', array() ); return count( $licenses ) > 0; } /** * Setup the wizard page * * @since 2.7 * * @return void */ public function setup_wizard_page() { PLL_Admin_Notices::add_notice( 'wizard', $this->wizard_notice() ); $this->redirect_to_wizard(); if ( ! Polylang::is_wizard() ) { return; } if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'polylang' ) ); } // Enqueue scripts and styles especially for the wizard. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); $this->steps = apply_filters( 'pll_wizard_steps', $this->steps ); $step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification $this->current_step = $step && array_key_exists( $step, $this->steps ) ? $step : current( array_keys( $this->steps ) ); $has_languages = $this->model->has_languages(); if ( ! $has_languages && ! in_array( $this->current_step, array( 'licenses', 'languages' ) ) ) { wp_safe_redirect( sanitize_url( $this->get_step_link( 'languages' ) ) ); exit; } if ( $has_languages && $this->model->get_objects_with_no_lang( 1 ) && ! in_array( $this->current_step, array( 'licenses', 'languages', 'media', 'untranslated-contents' ) ) ) { wp_safe_redirect( sanitize_url( $this->get_step_link( 'untranslated-contents' ) ) ); exit; } // Call the handler of the step for going to the next step. // Be careful nonce verification with check_admin_referer must be done in each handler. if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->current_step ]['handler'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing call_user_func( $this->steps[ $this->current_step ]['handler'] ); } $this->display_wizard_page(); // Ensure nothing is done after including the page. exit; } /** * Adds some admin screens where to display the wizard notice * * @since 2.7 * * @param bool $can_display_notice Whether the notice can be displayed. * @param string $notice The notice name. * @return bool */ public function can_display_notice( $can_display_notice, $notice ) { if ( ! $can_display_notice && 'wizard' === $notice ) { $screen = get_current_screen(); $can_display_notice = ! empty( $screen ) && in_array( $screen->base, array( 'edit', 'upload', 'options-general', ) ); } return $can_display_notice; } /** * Return html code of the wizard notice * * @since 2.7 * * @return string */ public function wizard_notice() { ob_start(); include __DIR__ . '/html-wizard-notice.php'; return ob_get_clean(); } /** * Display the wizard page * * @since 2.7 * * @return void */ public function display_wizard_page() { set_current_screen( 'pll-wizard' ); do_action( 'admin_enqueue_scripts' ); $steps = $this->steps; $current_step = $this->current_step; $styles = $this->styles; include __DIR__ . '/view-wizard-page.php'; } /** * Enqueue scripts and styles for the wizard * * @since 2.7 * * @return void */ public function enqueue_scripts() { wp_enqueue_style( 'polylang_admin', plugins_url( '/css/build/admin' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array(), POLYLANG_VERSION ); wp_enqueue_style( 'pll-wizard', plugins_url( '/css/build/wizard' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array( 'dashicons', 'install', 'common', 'forms' ), POLYLANG_VERSION ); $this->styles = array( 'polylang_admin', 'pll-wizard' ); } /** * Get the suffix to enqueue non minified files in a Debug context * * @since 2.7 * * @return string Empty when SCRIPT_DEBUG equal to true * otherwise .min */ public function get_suffix() { return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; } /** * Get the URL for the step's screen. * * @since 2.7 * * @param string $step slug (default: current step). * @return string URL for the step if it exists. * Empty string on failure. */ public function get_step_link( $step = '' ) { if ( ! $step ) { $step = $this->current_step; } $keys = array_keys( $this->steps ); $step_index = array_search( $step, $keys, true ); if ( false === $step_index ) { return ''; } return add_query_arg( 'step', $keys[ $step_index ], remove_query_arg( 'activate_error' ) ); } /** * Get the URL for the next step's screen. * * @since 2.7 * * @param string $step slug (default: current step). * @return string URL for next step if a next step exists. * Admin URL if it's the last step. * Empty string on failure. */ public function get_next_step_link( $step = '' ) { if ( ! $step ) { $step = $this->current_step; } $keys = array_keys( $this->steps ); if ( end( $keys ) === $step ) { return admin_url(); } $step_index = array_search( $step, $keys, true ); if ( false === $step_index ) { return ''; } return add_query_arg( 'step', $keys[ $step_index + 1 ], remove_query_arg( 'activate_error' ) ); } /** * Add licenses step to the wizard * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_licenses( $steps ) { // Add ajax action on deactivate button in licenses step. add_action( 'wp_ajax_pll_deactivate_license', array( $this, 'deactivate_license' ) ); // Be careful `settings` script is enqueued here without dependency except jquery because only code useful for deactivate license button is needed. // 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()`. wp_enqueue_script( 'pll_settings', plugins_url( '/js/build/settings' . $this->get_suffix() . '.js', POLYLANG_ROOT_FILE ), array( 'jquery' ), POLYLANG_VERSION, true ); wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) ); if ( $this->is_licenses_step_displayable() ) { $steps['licenses'] = array( 'name' => esc_html__( 'Licenses', 'polylang' ), 'view' => array( $this, 'display_step_licenses' ), 'handler' => array( $this, 'save_step_licenses' ), 'scripts' => array( 'pll_settings' ), // Polylang admin script used by deactivate license button. 'styles' => array(), ); } return $steps; } /** * Display the languages step form * * @since 2.7 * * @return void */ public function display_step_licenses() { include __DIR__ . '/view-wizard-step-licenses.php'; } /** * Execute the languages step * * @since 2.7 * * @return void */ public function save_step_licenses() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); $redirect = $this->get_next_step_link(); $licenses = apply_filters( 'pll_settings_licenses', array() ); foreach ( $licenses as $license ) { if ( ! empty( $_POST['licenses'][ $license->id ] ) ) { $updated_license = $license->activate_license( sanitize_key( $_POST['licenses'][ $license->id ] ) ); if ( ! empty( $updated_license->license_data ) && false === $updated_license->license_data->success ) { // Stay on this step with an error. $redirect = add_query_arg( array( 'step' => $this->current_step, 'activate_error' => 'i18n_license_key_error', ) ); } } } wp_safe_redirect( sanitize_url( $redirect ) ); exit; } /** * Ajax method to deactivate a license * * @since 2.7 * * @return void */ public function deactivate_license() { check_ajax_referer( 'pll-wizard', '_pll_nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( -1 ); } if ( ! isset( $_POST['id'] ) ) { wp_die( 0 ); } $id = substr( sanitize_text_field( wp_unslash( $_POST['id'] ) ), 11 ); $licenses = apply_filters( 'pll_settings_licenses', array() ); $license = $licenses[ $id ]; $license->deactivate_license(); wp_send_json( array( 'id' => $id, 'html' => $license->get_form_field(), ) ); } /** * Add languages step to the wizard * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_languages( $steps ) { wp_deregister_script( 'pll_settings' ); // Deregister after the licenses step enqueue to update jquery-ui-selectmenu dependency. // The wp-ajax-response and postbox dependencies is useless in wizard steps especially postbox which triggers a javascript error otherwise. // 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()`. 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 ); wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) ); 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 ); wp_localize_script( 'pll-wizard-languages', 'pll_wizard_params', array( 'i18n_no_language_selected' => esc_html__( 'You need to select a language to be added.', 'polylang' ), 'i18n_language_already_added' => esc_html__( 'You already added this language.', 'polylang' ), 'i18n_no_language_added' => esc_html__( 'You need to add at least one language.', 'polylang' ), 'i18n_add_language_needed' => esc_html__( 'You selected a language, however, to be able to continue, you need to add it.', 'polylang' ), 'i18n_pll_add_language' => esc_html__( 'Impossible to add the language.', 'polylang' ), 'i18n_pll_invalid_locale' => esc_html__( 'Enter a valid WordPress locale', 'polylang' ), 'i18n_pll_invalid_slug' => esc_html__( 'The language code contains invalid characters', 'polylang' ), 'i18n_pll_non_unique_slug' => esc_html__( 'The language code must be unique', 'polylang' ), 'i18n_pll_invalid_name' => esc_html__( 'The language must have a name', 'polylang' ), 'i18n_pll_invalid_flag' => esc_html__( 'The flag does not exist', 'polylang' ), 'i18n_dialog_title' => esc_html__( "A language wasn't added.", 'polylang' ), 'i18n_dialog_yes_button' => esc_html__( 'Yes', 'polylang' ), 'i18n_dialog_no_button' => esc_html__( 'No', 'polylang' ), 'i18n_dialog_ignore_button' => esc_html__( 'Ignore', 'polylang' ), 'i18n_remove_language_icon' => esc_html__( 'Remove this language', 'polylang' ), ) ); wp_enqueue_script( 'pll-wizard-languages' ); 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 ); $steps['languages'] = array( 'name' => esc_html__( 'Languages', 'polylang' ), 'view' => array( $this, 'display_step_languages' ), 'handler' => array( $this, 'save_step_languages' ), 'scripts' => array( 'pll-wizard-languages', 'pll_settings' ), 'styles' => array( 'pll-wizard-selectmenu' ), ); return $steps; } /** * Display the languages step form * * @since 2.7 * * @return void */ public function display_step_languages() { $model = $this->model; include __DIR__ . '/view-wizard-step-languages.php'; } /** * Execute the languages step * * @since 2.7 * * @return void */ public function save_step_languages() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); $all_languages = include POLYLANG_DIR . '/src/settings/languages.php'; $languages = isset( $_POST['languages'] ) && is_array( $_POST['languages'] ) ? array_map( 'sanitize_locale_name', $_POST['languages'] ) : false; $saved_languages = array(); // If there is no language added or defined. if ( empty( $languages ) && ! $this->model->has_languages() ) { // Stay on this step with an error. wp_safe_redirect( sanitize_url( add_query_arg( array( 'step' => $this->current_step, 'activate_error' => 'i18n_no_language_added', ) ) ) ); exit; } // Otherwise process the languages to add or skip the step if no language has been added. if ( ! empty( $languages ) ) { require_once ABSPATH . 'wp-admin/includes/translation-install.php'; // Remove duplicate values. $languages = array_unique( $languages ); // For each language add it in Polylang settings. foreach ( $languages as $locale ) { $saved_languages = $all_languages[ $locale ]; $saved_languages['slug'] = $saved_languages['code']; $saved_languages['rtl'] = (int) ( 'rtl' === $saved_languages['dir'] ); $saved_languages['term_group'] = 0; // Default term_group. $language_added = $this->model->add_language( $saved_languages ); if ( $language_added instanceof WP_Error && array_key_exists( 'pll_non_unique_slug', $language_added->errors ) ) { // Get the slug from the locale : lowercase and dash instead of underscore. $saved_languages['slug'] = strtolower( str_replace( '_', '-', $saved_languages['locale'] ) ); $language_added = $this->model->add_language( $saved_languages ); } if ( $language_added instanceof WP_Error ) { // Stay on this step with an error. $error_keys = array_keys( $language_added->errors ); wp_safe_redirect( sanitize_url( add_query_arg( array( 'step' => $this->current_step, 'activate_error' => 'i18n_' . reset( $error_keys ), ) ) ) ); exit; } if ( 'en_US' !== $locale && current_user_can( 'install_languages' ) ) { wp_download_language_pack( $locale ); } } } wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) ); exit; } /** * Add the media step to the wizard. * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_media( $steps ) { $languages = $this->model->get_languages_list(); if ( $this->is_media_step_displayable( $languages ) ) { $steps['media'] = array( 'name' => esc_html__( 'Media', 'polylang' ), 'view' => array( $this, 'display_step_media' ), 'handler' => array( $this, 'save_step_media' ), 'scripts' => array(), 'styles' => array(), ); } return $steps; } /** * Display the media step form * * @since 2.7 * * @return void */ public function display_step_media() { $options = $this->options; include __DIR__ . '/view-wizard-step-media.php'; } /** * Execute the media step * * @since 2.7 * * @return void */ public function save_step_media() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); $media_support = isset( $_POST['media_support'] ) ? sanitize_key( $_POST['media_support'] ) === 'yes' : false; $this->options['media_support'] = $media_support; update_option( 'polylang', $this->options ); wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) ); exit; } /** * Add untranslated contents step to the wizard * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_untranslated_contents( $steps ) { if ( ! $this->model->has_languages() || $this->model->get_objects_with_no_lang( 1 ) ) { // 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. // 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()`. 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 ); wp_localize_script( 'pll_settings', 'pll_settings', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) ); wp_enqueue_style( 'pll-wizard-selectmenu', plugins_url( '/css/build/selectmenu' . $this->get_suffix() . '.css', POLYLANG_ROOT_FILE ), array( 'dashicons', 'install', 'common' ), POLYLANG_VERSION ); $steps['untranslated-contents'] = array( 'name' => esc_html__( 'Content', 'polylang' ), 'view' => array( $this, 'display_step_untranslated_contents' ), 'handler' => array( $this, 'save_step_untranslated_contents' ), 'scripts' => array( 'pll_settings' ), 'styles' => array( 'pll-wizard-selectmenu' ), ); } return $steps; } /** * Display the untranslated contents step form * * @since 2.7 * * @return void */ public function display_step_untranslated_contents() { $model = $this->model; include __DIR__ . '/view-wizard-step-untranslated-contents.php'; } /** * Execute the untranslated contents step * * @since 2.7 * * @return void */ public function save_step_untranslated_contents() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); $lang = ! empty( $_POST['language'] ) && is_string( $_POST['language'] ) ? sanitize_locale_name( $_POST['language'] ) : false; if ( empty( $lang ) ) { $lang = $this->options['default_lang']; } $language = $this->model->get_language( $lang ); if ( $language instanceof PLL_Language ) { $this->model->set_language_in_mass( $language ); } wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) ); exit; } /** * Add home page step to the wizard * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_home_page( $steps ) { $languages = $this->model->get_languages_list(); $home_page_id = get_option( 'page_on_front' ); $translations = $this->model->post->get_translations( $home_page_id ); if ( $home_page_id > 0 && ( ! $languages || count( $languages ) === 1 || count( $translations ) !== count( $languages ) ) ) { $steps['home-page'] = array( 'name' => esc_html__( 'Homepage', 'polylang' ), 'view' => array( $this, 'display_step_home_page' ), 'handler' => array( $this, 'save_step_home_page' ), 'scripts' => array(), 'styles' => array(), ); } return $steps; } /** * Display the home page step form * * @since 2.7 * * @return void */ public function display_step_home_page() { $model = $this->model; $languages = $model->languages->get_list(); $home_page_id = get_option( 'page_on_front' ); $home_page_id = is_numeric( $home_page_id ) ? (int) $home_page_id : 0; $translations = $model->post->get_translations( $home_page_id ); $home_page = $home_page_id > 0 ? get_post( $home_page_id ) : null; $home_page_language = $model->post->get_language( $home_page_id ); $untranslated_languages = array(); if ( empty( $home_page ) ) { return; } foreach ( $languages as $language ) { if ( ! $model->post->get( $home_page_id, $language ) ) { $untranslated_languages[] = $language; } } include __DIR__ . '/view-wizard-step-home-page.php'; } /** * Execute the home page step * * @since 2.7 * * @return void */ public function save_step_home_page() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); $default_language = $this->model->has_languages() ? $this->options['default_lang'] : null; $home_page = isset( $_POST['home_page'] ) ? sanitize_key( $_POST['home_page'] ) : false; $home_page_title = isset( $_POST['home_page_title'] ) ? sanitize_text_field( wp_unslash( $_POST['home_page_title'] ) ) : esc_html__( 'Homepage', 'polylang' ); $home_page_language = isset( $_POST['home_page_language'] ) ? sanitize_key( $_POST['home_page_language'] ) : false; $untranslated_languages = isset( $_POST['untranslated_languages'] ) ? array_map( 'sanitize_key', $_POST['untranslated_languages'] ) : array(); call_user_func( apply_filters( 'pll_wizard_create_home_page_translations', array( $this, 'create_home_page_translations' ) ), $default_language, $home_page, $home_page_title, $home_page_language, $untranslated_languages ); $this->model->clean_languages_cache(); wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) ); exit; } /** * Create home page translations for each language defined. * * @since 2.7 * * @param string $default_language Slug of the default language; null if no default language is defined. * @param int $home_page Post ID of the home page if it's defined, false otherwise. * @param string $home_page_title Home page title if it's defined, 'Homepage' otherwise. * @param string $home_page_language Slug of the home page if it's defined, false otherwise. * @param string[] $untranslated_languages Array of languages which needs to have a home page translated. * @return void */ public function create_home_page_translations( $default_language, $home_page, $home_page_title, $home_page_language, $untranslated_languages ) { $translations = $this->model->post->get_translations( $home_page ); foreach ( $untranslated_languages as $language ) { $language_properties = $this->model->get_language( $language ); $id = wp_insert_post( array( 'post_title' => $home_page_title . ' - ' . $language_properties->name, 'post_type' => 'page', 'post_status' => 'publish', ) ); $translations[ $language ] = $id; pll_set_post_language( $id, $language ); } pll_save_post_translations( $translations ); } /** * Add last step to the wizard * * @since 2.7 * * @param array $steps List of steps. * @return array List of steps updated. */ public function add_step_last( $steps ) { $steps['last'] = array( 'name' => esc_html__( 'Ready!', 'polylang' ), 'view' => array( $this, 'display_step_last' ), 'handler' => array( $this, 'save_step_last' ), 'scripts' => array(), 'styles' => array(), ); return $steps; } /** * Display the last step form * * @since 2.7 * * @return void */ public function display_step_last() { // We ran the wizard once. So we can dismiss its notice. PLL_Admin_Notices::dismiss( 'wizard' ); include __DIR__ . '/view-wizard-step-last.php'; } /** * Execute the last step * * @since 2.7 * * @return void */ public function save_step_last() { check_admin_referer( 'pll-wizard', '_pll_nonce' ); wp_safe_redirect( sanitize_url( $this->get_next_step_link() ) ); exit; } }