Plugin Directory

Changeset 3462372


Ignore:
Timestamp:
02/16/2026 10:09:24 AM (3 weeks ago)
Author:
daext
Message:

Committing and tagging 1.14

Location:
hreflang-manager-lite
Files:
34 added
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • hreflang-manager-lite/tags/1.14/admin/class-daexthrmal-admin.php

    r3379980 r3462372  
    6767        // Add the admin menu.
    6868        add_action( 'admin_menu', array( $this, 'me_add_admin_menu' ) );
     69
     70        // Add the meta box.
     71        add_action( 'add_meta_boxes', array( $this, 'create_meta_box' ) );
     72
     73        // Save the meta box.
     74        add_action( 'save_post', array( $this, 'save_meta_box' ) );
    6975
    7076        // This hook is triggered during the creation of a new blog.
     
    232238
    233239        }
     240
     241        $meta_box_post_types_a = $this->shared->get_post_types_with_ui();
     242
     243        if ( in_array( $screen->id, $meta_box_post_types_a, true ) ) {
     244            wp_enqueue_style( $this->shared->get( 'slug' ) . '-meta-box', $this->shared->get( 'url' ) . 'admin/assets/css/meta-box.css', array(), $this->shared->get( 'ver' ) );
     245
     246            // Select2.
     247            wp_enqueue_style(
     248                $this->shared->get( 'slug' ) . '-select2',
     249                $this->shared->get( 'url' ) . 'admin/assets/inc/select2/css/select2.min.css',
     250                array(),
     251                $this->shared->get( 'ver' )
     252            );
     253
     254            wp_enqueue_style( $this->shared->get( 'slug' ) . '-select2-custom', $this->shared->get( 'url' ) . 'admin/assets/css/select2-custom.css', array(), $this->shared->get( 'ver' ) );
     255
     256        }
    234257    }
    235258
     
    295318            wp_enqueue_script( $this->shared->get( 'slug' ) . '-menu', $this->shared->get( 'url' ) . 'admin/assets/js/framework-menu/menu.js', array( 'jquery' ), $this->shared->get( 'ver' ), true );
    296319
     320        }
     321
     322        $meta_box_post_types_a = $this->shared->get_post_types_with_ui();
     323
     324        if ( in_array( $screen->id, $meta_box_post_types_a, true ) ) {
     325
     326            wp_enqueue_script(
     327                $this->shared->get( 'slug' ) . '-select2',
     328                $this->shared->get( 'url' ) . 'admin/assets/inc/select2/js/select2.min.js',
     329                array( 'jquery' ),
     330                $this->shared->get( 'ver' ),
     331                true
     332            );
     333
     334            wp_enqueue_script( $this->shared->get( 'slug' ) . '-meta-box', $this->shared->get( 'url' ) . 'admin/assets/js/meta-box.js', array( 'jquery', $this->shared->get( 'slug' ) . '-select2' ), $this->shared->get( 'ver' ), true );
    297335        }
    298336    }
     
    572610    }
    573611
     612    // meta box -----------------------------------------------------------------.
     613
     614    /**
     615     * The add_meta_boxes hook callback.
     616     *
     617     * @return void
     618     */
     619    public function create_meta_box() {
     620
     621        // Verify the capability.
     622        if ( current_user_can( 'edit_others_posts' ) ) {
     623
     624            $post_types_a = $this->shared->get_post_types_with_ui();
     625
     626            foreach ( $post_types_a as $key => $post_type ) {
     627                $post_type = trim( $post_type );
     628                add_meta_box(
     629                    'daexthrmal-meta',
     630                    'Hreflang Manager',
     631                    array( $this, 'meta_box_callback' ),
     632                    $post_type,
     633                    'normal',
     634                    'high',
     635                    // Ref: https://make.wordpress.org/core/2018/11/07/meta-box-compatibility-flags/ .
     636                    array(
     637
     638                        /*
     639                         * It's not confirmed that this meta box works in the block editor.
     640                         */
     641                        '__block_editor_compatible_meta_box' => false,
     642
     643                        /*
     644                         * This meta box should only be loaded in the classic editor interface, and the block editor
     645                         * should not display it.
     646                         */
     647                        '__back_compat_meta_box' => true,
     648
     649                    )
     650                );
     651            }
     652        }
     653    }
     654
     655    /**
     656     * Display the Hreflang Manager meta box content.
     657     *
     658     * @return void
     659     */
     660    public function meta_box_callback() {
     661
     662        ?>
     663
     664        <table class="form-table daexthrmal-table-hreflang-manager">
     665
     666            <tbody>
     667
     668            <?php
     669
     670            /**
     671             * Activate the 'disabled="disabled"' attribute when the post status is not:
     672             *  - publish
     673             *  - future
     674             *  - pending
     675             *  - private
     676             */
     677            $post_status = get_post_status();
     678            if ( 'publish' !== $post_status && 'future' !== $post_status && 'pending' !== $post_status && 'private' !== $post_status ) {
     679                $input_disabled = 'disabled';
     680            } else {
     681                $input_disabled = '';
     682            }
     683
     684            /**
     685             * Look for a connection that has as a url_to_connect value the permalink value of this post
     686             *
     687             *  If there is already a connection:
     688             *  - show the form with the field already filled with the value from the database
     689             *  If there is no connection:
     690             *  - show the form with empty fields
     691             */
     692
     693            // Get the number of connections that should be displayed in the menu.
     694            $connections_in_menu = 10;
     695
     696            $permalink = $this->shared->get_permalink( get_the_ID(), true );
     697
     698            // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     699            global $wpdb;
     700
     701            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     702            $permalink_connections = $wpdb->get_row(
     703                $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     704            );
     705
     706            if ( null === $permalink_connections ) {
     707
     708                // Default empty form.
     709                for ( $i = 1; $i <= $connections_in_menu; $i++ ) {
     710
     711                    ?>
     712
     713                    <!-- url -->
     714                    <tr valign="top">
     715                        <th scope="row"><label for="url<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     716                        <td><input autocomplete="off" <?php echo esc_attr( $input_disabled ); ?> type="text" id="url<?php echo esc_attr( $i ); ?>" maxlength="2083" name="url<?php echo esc_attr( $i ); ?>" class="regular-text daexthrmal-url"/></td>
     717                    </tr>
     718
     719                    <!-- Language -->
     720                    <tr valign="top">
     721                        <th scope="row"><label for="language<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Language', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     722                        <td>
     723                            <select <?php echo esc_attr( $input_disabled ); ?> id="language<?php echo esc_attr( $i ); ?>" class="daexthrmal-language" name="language<?php echo esc_attr( $i ); ?>">
     724                                <?php
     725
     726                                $array_language = get_option( 'daexthrmal_language' );
     727                                foreach ( $array_language as $key => $value ) {
     728                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_language_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     729                                }
     730
     731                                ?>
     732                            </select>
     733                        </td>
     734                    </tr>
     735
     736                    <!-- Script -->
     737                    <tr valign="top">
     738                        <th scope="row"><label for="script<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Script', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     739                        <td>
     740                            <select <?php echo esc_attr( $input_disabled ); ?> id="script<?php echo esc_attr( $i ); ?>" class="daexthrmal-script" name="script<?php echo esc_attr( $i ); ?>">
     741                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     742                                <?php
     743
     744                                $array_language = get_option( 'daexthrmal_script' );
     745                                foreach ( $array_language as $key => $value ) {
     746                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_script_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     747                                }
     748
     749                                ?>
     750                            </select>
     751                        </td>
     752                    </tr>
     753
     754                    <!-- Locale -->
     755                    <tr valign="top">
     756                        <th scope="row"><label for="locale<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Locale', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     757                        <td>
     758                            <select <?php echo esc_attr( $input_disabled ); ?> id="locale<?php echo esc_attr( $i ); ?>" class="daexthrmal-locale" name="locale<?php echo esc_attr( $i ); ?>">
     759                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     760                                <?php
     761
     762                                $array_locale = get_option( 'daexthrmal_locale' );
     763                                foreach ( $array_locale as $key => $value ) {
     764                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_locale_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     765                                }
     766
     767                                ?>
     768                            </select>
     769                        </td>
     770                    </tr>
     771
     772                    <?php
     773
     774                }
     775            } else {
     776               
     777                // Form with data retrieved form the database.
     778                for ( $i = 1; $i <= $connections_in_menu; $i++ ) {
     779
     780                    ?>
     781
     782                    <!-- url -->
     783                    <tr valign="top">
     784                        <th scope="row"><label for="url<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     785                        <td><input autocomplete="off" type="text" value="<?php echo esc_attr( stripslashes( $permalink_connections->{'url' .$i} ) ); ?>" id="url<?php echo esc_attr( $i ); ?>" maxlength="2083" name="url<?php echo esc_attr( $i ); ?>" class="regular-text daexthrmal-url"/></td>
     786
     787                    </tr>
     788
     789                    <!-- Language <?php echo intval( $i, 10 ); ?> -->
     790                    <tr valign="top">
     791                        <th scope="row"><label for="language<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Language', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     792                        <td>
     793                            <select id="language<?php echo esc_attr( $i ); ?>" class="daexthrmal-language" name="language<?php echo esc_attr( $i ); ?>">
     794                                <?php
     795
     796                                $array_language = get_option( 'daexthrmal_language' );
     797                                foreach ( $array_language as $key => $value ) {
     798                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'language' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     799                                }
     800
     801                                ?>
     802                            </select>
     803                        </td>
     804                    </tr>
     805
     806                    <!-- Script <?php echo intval( $i, 10 ); ?> -->
     807                    <tr valign="top">
     808                        <th scope="row"><label for="script<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Script', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     809                        <td>
     810                            <select id="script<?php echo esc_attr( $i ); ?>" class="daexthrmal-script" name="script<?php echo esc_attr( $i ); ?>">
     811                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     812                                <?php
     813
     814                                $array_script = get_option( 'daexthrmal_script' );
     815                                foreach ( $array_script as $key => $value ) {
     816                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'script' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     817                                }
     818
     819                                ?>
     820                            </select>
     821                        </td>
     822                    </tr>
     823
     824                    <!-- Locale <?php echo intval( $i, 10 ); ?> -->
     825                    <tr valign="top">
     826                        <th scope="row"><label for="locale<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Locale', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     827                        <td>
     828                            <select id="locale<?php echo esc_attr( $i ); ?>" class="daexthrmal-locale" name="locale<?php echo esc_attr( $i ); ?>">
     829                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     830                                <?php
     831
     832                                $array_locale = get_option( 'daexthrmal_locale' );
     833                                foreach ( $array_locale as $key => $value ) {
     834                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'locale' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     835                                }
     836
     837                                ?>
     838                            </select>
     839                        </td>
     840                    </tr>
     841
     842                    <?php
     843
     844                }
     845            }
     846
     847        ?>
     848
     849        </tbody>
     850
     851        </table>
     852
     853        <?php
     854
     855        // Store the original permalink to detect changes when the form is saved.
     856        echo '<input type="hidden" name="daexthrmal_original_permalink" value="' . esc_attr( $permalink ) . '" />';
     857
     858        // Use nonce for verification.
     859        wp_nonce_field( plugin_basename( __FILE__ ), 'daexthrmal_nonce' );
     860    }
     861
     862    /**
     863     * Save the meta box data.
     864     *
     865     * @return void
     866     */
     867    public function save_meta_box() {
     868
     869        // Verify the capability.
     870        if ( ! current_user_can( 'edit_others_posts' ) ) {
     871            return;
     872        }
     873
     874        // Security verification.
     875
     876        // Verify if this is an auto save routine. If our form has not been submitted, we don't want to do anything.
     877        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
     878            return;
     879        }
     880
     881        /**
     882         * Verify this came from our screen and with proper authorization, because save_post can be triggered at other
     883         * times.
     884         */
     885        if ( isset( $_POST['daexthrmal_nonce'] ) ) {
     886            $nonce = sanitize_text_field( wp_unslash( $_POST['daexthrmal_nonce'] ) );
     887            if ( ! wp_verify_nonce( $nonce, plugin_basename( __FILE__ ) ) ) {
     888                return;
     889            }
     890        } else {
     891            return;
     892        }
     893
     894        /* - end security verification - */
     895
     896        /*
     897         * Return ( do not save ) if the post status is not:
     898         * - publish
     899         * - future
     900         * - pending
     901         * - private
     902         */
     903        $post_status = get_post_status();
     904        if ( 'publish' !== $post_status && 'future' !== $post_status && 'pending' !== $post_status && 'private' !== $post_status ) {
     905            return;}
     906
     907        // Init vars.
     908        $url      = array();
     909        $language = array();
     910        $script   = array();
     911        $locale   = array();
     912
     913        // Initialize the variables that include the URLs, the languages and the locale.
     914        for ( $i = 1;$i <= 10;$i++ ) {
     915
     916            if ( isset( $_POST[ 'url' . $i ] ) && strlen( trim( esc_url_raw( wp_unslash( $_POST[ 'url' . $i ] ) ) ) ) > 0 ) {
     917                $url[ $i ]        = esc_url_raw( wp_unslash( $_POST[ 'url' . $i ] ) );
     918                $at_least_one_url = true;
     919            } else {
     920                $url[ $i ] = '';
     921            }
     922
     923            if ( isset( $_POST[ 'language' . $i ] ) && strlen( trim( sanitize_text_field( wp_unslash( $_POST[ 'language' . $i ] ) ) ) ) > 0 ) {
     924                $language[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'language' . $i ] ) );
     925            } else {
     926                $language[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_language_' . $i );
     927            }
     928
     929            if ( isset( $_POST[ 'script' . $i ] ) ) {
     930                $script[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'script' . $i ] ) );
     931            } else {
     932                $script[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_script_' . $i );
     933            }
     934
     935            if ( isset( $_POST[ 'locale' . $i ] ) ) {
     936                $locale[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'locale' . $i ] ) );
     937            } else {
     938                $locale[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_locale_' . $i );
     939            }
     940        }
     941
     942        /*
     943         * save the fields in the daexthrmal_connection database table:
     944         *
     945         * - if a row with the daexthrmal_connection equal to the current permalink already exists update the row
     946         *
     947         * - if a row with the daexthrmal_connection equal to the current permalink doesn't exists create a new row
     948         */
     949        $permalink = $this->shared->get_permalink( get_the_ID(), true );
     950
     951        // Retrieve the original permalink from the hidden form field.
     952        $original_permalink = isset( $_POST['daexthrmal_original_permalink'] ) ? esc_url_raw( wp_unslash( $_POST['daexthrmal_original_permalink'] ) ) : '';
     953
     954        // Update url_to_connect when a permalink change is detected.
     955        global $wpdb;
     956        if ( ! empty( $original_permalink ) && ! empty( $permalink ) && $original_permalink !== $permalink ) {
     957            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     958            $wpdb->query(
     959                $wpdb->prepare(
     960                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     961                    . 'url_to_connect = %s WHERE url_to_connect = %s ',
     962                    $permalink,
     963                    $original_permalink
     964                )
     965            );
     966        }
     967
     968        // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     969        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     970        $permalink_connections = $wpdb->get_row(
     971            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     972        );
     973
     974        if ( null !== $permalink_connections ) {
     975
     976            // Update an existing connection.
     977
     978            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     979            $query_result = $wpdb->query(
     980                $wpdb->prepare(
     981                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     982                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     983                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     984                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     985                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     986                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     987                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     988                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     989                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     990                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     991                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s WHERE url_to_connect = %s ',
     992                    $url[1],
     993                    $language[1],
     994                    $script[1],
     995                    $locale[1],
     996                    $url[2],
     997                    $language[2],
     998                    $script[2],
     999                    $locale[2],
     1000                    $url[3],
     1001                    $language[3],
     1002                    $script[3],
     1003                    $locale[3],
     1004                    $url[4],
     1005                    $language[4],
     1006                    $script[4],
     1007                    $locale[4],
     1008                    $url[5],
     1009                    $language[5],
     1010                    $script[5],
     1011                    $locale[5],
     1012                    $url[6],
     1013                    $language[6],
     1014                    $script[6],
     1015                    $locale[6],
     1016                    $url[7],
     1017                    $language[7],
     1018                    $script[7],
     1019                    $locale[7],
     1020                    $url[8],
     1021                    $language[8],
     1022                    $script[8],
     1023                    $locale[8],
     1024                    $url[9],
     1025                    $language[9],
     1026                    $script[9],
     1027                    $locale[9],
     1028                    $url[10],
     1029                    $language[10],
     1030                    $script[10],
     1031                    $locale[10],
     1032                    $permalink
     1033                )
     1034            );
     1035
     1036        } else {
     1037
     1038            // Return ( do not create a new connection ) if there are not a single url defined.
     1039            if ( ! isset( $at_least_one_url ) ) {
     1040                return;}
     1041
     1042            // Add a new connection into the database.
     1043
     1044            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     1045            $query_result = $wpdb->query(
     1046                $wpdb->prepare(
     1047                    "INSERT INTO {$wpdb->prefix}daexthrmal_connection SET url_to_connect = %s ,"
     1048                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     1049                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     1050                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     1051                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     1052                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     1053                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     1054                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     1055                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     1056                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     1057                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s',
     1058                    $permalink,
     1059                    $url[1],
     1060                    $language[1],
     1061                    $script[1],
     1062                    $locale[1],
     1063                    $url[2],
     1064                    $language[2],
     1065                    $script[2],
     1066                    $locale[2],
     1067                    $url[3],
     1068                    $language[3],
     1069                    $script[3],
     1070                    $locale[3],
     1071                    $url[4],
     1072                    $language[4],
     1073                    $script[4],
     1074                    $locale[4],
     1075                    $url[5],
     1076                    $language[5],
     1077                    $script[5],
     1078                    $locale[5],
     1079                    $url[6],
     1080                    $language[6],
     1081                    $script[6],
     1082                    $locale[6],
     1083                    $url[7],
     1084                    $language[7],
     1085                    $script[7],
     1086                    $locale[7],
     1087                    $url[8],
     1088                    $language[8],
     1089                    $script[8],
     1090                    $locale[8],
     1091                    $url[9],
     1092                    $language[9],
     1093                    $script[9],
     1094                    $locale[9],
     1095                    $url[10],
     1096                    $language[10],
     1097                    $script[10],
     1098                    $locale[10]
     1099                )
     1100            );
     1101
     1102        }
     1103    }
     1104
    5741105    /**
    5751106     * Register the admin menu.
  • hreflang-manager-lite/tags/1.14/admin/inc/class-daexthrmal-pagination.php

    r3379980 r3462372  
    184184                esc_html( $this->current_page ) .
    185185                '&nbsp' .
    186                 esc_html__( 'of' ) .
     186                esc_html__( 'of', 'hreflang-manager-lite' ) .
    187187                '&nbsp' .
    188188                esc_html( $last_page ) .
  • hreflang-manager-lite/tags/1.14/admin/inc/menu/class-daexthrmal-menu-elements.php

    r3379980 r3462372  
    966966                            <?php
    967967                            esc_html_e(
    968                                 'Sync hreflang data across multiple websites, bulk import entries from a spreadsheet, unlock advanced tools like the Locale Selector and Hreflang Checker, add hreflang directly in the post editor, and more!',
     968                                'Sync hreflang data across multiple websites, bulk import entries from spreadsheets, unlock advanced tools like the Locale Selector and Hreflang Checker, implement hreflang in XML sitemaps, and more!',
    969969                                'hreflang-manager-lite'
    970970                            );
  • hreflang-manager-lite/tags/1.14/inc/class-daexthrmal-rest.php

    r3379980 r3462372  
    5959     */
    6060    public function rest_api_register_route() {
     61
     62        // Add the GET 'hreflang-manager-lite/v1/post' endpoint to the Rest API.
     63        register_rest_route(
     64            'hreflang-manager-lite/v1',
     65            '/post/(?P<id>\d+)',
     66            array(
     67                'methods'             => 'GET',
     68                'callback'            => array( $this, 'rest_api_daext_hreflang_manager_read_connections_callback' ),
     69                'permission_callback' => array( $this, 'rest_api_daext_hreflang_manager_read_connections_callback_permission_check' ),
     70            )
     71        );
     72
     73        // Add the POST 'hreflang-manager-lite/v1/post' endpoint to the Rest API.
     74        register_rest_route(
     75            'hreflang-manager-lite/v1',
     76            '/post/',
     77            array(
     78                'methods'             => 'POST',
     79                'callback'            => array( $this, 'rest_api_daext_hreflang_manager_post_connection_callback' ),
     80                'permission_callback' => array( $this, 'rest_api_daext_hreflang_manager_post_connection_callback_permission_check' ),
     81            )
     82        );
    6183
    6284        // Add the GET 'hreflang-manager-lite/v1/options' endpoint to the Rest API.
     
    87109     * Callback for the GET 'hreflang-manager-lite/v1/options' endpoint of the Rest API.
    88110     *
     111     * @param array $data Data received from the request.
     112     *
     113     * @return false|WP_REST_Response
     114     */
     115    public function rest_api_daext_hreflang_manager_read_connections_callback( $data ) {
     116
     117        // Generate the response.
     118
     119        $url_to_connect = $this->shared->get_permalink( $data['id'], true );
     120
     121        global $wpdb;
     122        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     123        $row = $wpdb->get_row(
     124            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $url_to_connect ),
     125            ARRAY_A
     126        );
     127
     128        if ( $wpdb->num_rows > 0 ) {
     129
     130            // Prepare the response.
     131            $response = new WP_REST_Response( $row );
     132
     133        } else {
     134
     135            return false;
     136        }
     137
     138        return $response;
     139    }
     140
     141    /**
     142     * Check the user capability.
     143     *
     144     * @return true|WP_Error
     145     */
     146    public function rest_api_daext_hreflang_manager_read_connections_callback_permission_check() {
     147
     148        // Check the capability.
     149        if ( ! current_user_can( 'edit_others_posts' ) ) {
     150            return new WP_Error(
     151                'rest_read_error',
     152                'Sorry, you are not allowed to view the Hreflang Manager connections.',
     153                array( 'status' => 403 )
     154            );
     155        }
     156
     157        return true;
     158    }
     159
     160    /**
     161     * Callback for the POST 'hreflang-manager-lite/v1/post/' endpoint of the Rest API.
     162     *
     163     *  This method is in the following contexts:
     164     *  - To save the connection when the "Update" button of the Gutenberg editor is clicked.
     165     *
     166     * @param array $data Data received from the request.
     167     *
     168     * @return void|WP_REST_Response
     169     */
     170    public function rest_api_daext_hreflang_manager_post_connection_callback( $data ) {
     171
     172        $data    = json_decode( $data->get_body() );
     173        $post_id = $data->post_id;
     174        $old_permalink = isset( $data->old_permalink ) ? esc_url_raw( $data->old_permalink ) : '';
     175        $new_permalink = isset( $data->new_permalink ) ? esc_url_raw( $data->new_permalink ) : '';
     176        $data    = $data->connection_data;
     177
     178        // Init vars.
     179        $url      = array();
     180        $language = array();
     181        $script   = array();
     182        $locale   = array();
     183
     184        // Initialize the variables that include the URLs, the languages, the script and the locale.
     185        for ( $i = 1;$i <= 10;$i++ ) {
     186
     187            if ( isset( $data->{'url' . $i} ) && strlen( trim( $data->{'url' . $i} ) ) > 0 ) {
     188                $url[ $i ]        = esc_url_raw( $data->{'url' . $i} );
     189                $at_least_one_url = true;
     190            } else {
     191                $url[ $i ] = '';
     192            }
     193
     194            if ( isset( $data->{'language' . $i} ) && strlen( trim( $data->{'language' . $i} ) ) > 0 ) {
     195                $language[ $i ] = sanitize_text_field( $data->{'language' . $i} );
     196            } else {
     197                $language[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_language_' . $i );
     198            }
     199
     200            if ( isset( $data->{'script' . $i} ) ) {
     201                $script[ $i ] = sanitize_text_field( $data->{'script' . $i} );
     202            } else {
     203                $script[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_script_' . $i );
     204            }
     205
     206            if ( isset( $data->{'locale' . $i} ) ) {
     207                $locale[ $i ] = sanitize_text_field( $data->{'locale' . $i} );
     208            } else {
     209                $locale[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_locale_' . $i );
     210            }
     211        }
     212
     213        /*
     214         * Save the fields in the daexthrmal_connection database table:
     215         *
     216         * - if a row with the url_to_connect equal to the current permalink already exists update the row
     217         * - if a row with the url_to_connect equal to the current permalink doesn't exist create a new row
     218         */
     219        $permalink = $this->shared->get_permalink( $post_id, true );
     220
     221        if ( ! empty( $new_permalink ) ) {
     222            $permalink = $new_permalink;
     223        }
     224
     225        // Update url_to_connect when a permalink change is detected.
     226        global $wpdb;
     227        if ( ! empty( $old_permalink ) && ! empty( $new_permalink ) && $old_permalink !== $new_permalink ) {
     228            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     229            $query_result = $wpdb->query(
     230                $wpdb->prepare(
     231                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     232                    . 'url_to_connect = %s WHERE url_to_connect = %s ',
     233                    $new_permalink,
     234                    $old_permalink
     235                )
     236            );
     237        }
     238
     239        // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     240        global $wpdb;
     241        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     242        $permalink_connections = $wpdb->get_row(
     243            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     244        );
     245
     246        if ( null !== $permalink_connections ) {
     247
     248            // Update an existing connection.
     249
     250            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     251            $query_result = $wpdb->query(
     252                $wpdb->prepare(
     253                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     254                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     255                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     256                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     257                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     258                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     259                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     260                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     261                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     262                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     263                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s WHERE url_to_connect = %s ',
     264                    $url[1],
     265                    $language[1],
     266                    $script[1],
     267                    $locale[1],
     268                    $url[2],
     269                    $language[2],
     270                    $script[2],
     271                    $locale[2],
     272                    $url[3],
     273                    $language[3],
     274                    $script[3],
     275                    $locale[3],
     276                    $url[4],
     277                    $language[4],
     278                    $script[4],
     279                    $locale[4],
     280                    $url[5],
     281                    $language[5],
     282                    $script[5],
     283                    $locale[5],
     284                    $url[6],
     285                    $language[6],
     286                    $script[6],
     287                    $locale[6],
     288                    $url[7],
     289                    $language[7],
     290                    $script[7],
     291                    $locale[7],
     292                    $url[8],
     293                    $language[8],
     294                    $script[8],
     295                    $locale[8],
     296                    $url[9],
     297                    $language[9],
     298                    $script[9],
     299                    $locale[9],
     300                    $url[10],
     301                    $language[10],
     302                    $script[10],
     303                    $locale[10],
     304                    $permalink
     305                )
     306            );
     307
     308        } else {
     309
     310            // Return ( do not create a new connection ) if there are not a single url defined.
     311            if ( ! isset( $at_least_one_url ) ) {
     312                return new WP_REST_Response( array( 'message' => 'No URLs provided' ), 200 );
     313            }
     314
     315            // Add a new connection into the database.
     316
     317            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     318            $query_result = $wpdb->query(
     319                $wpdb->prepare(
     320                    "INSERT INTO {$wpdb->prefix}daexthrmal_connection SET url_to_connect = %s ,"
     321                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     322                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     323                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     324                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     325                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     326                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     327                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     328                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     329                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     330                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s',
     331                    $permalink,
     332                    $url[1],
     333                    $language[1],
     334                    $script[1],
     335                    $locale[1],
     336                    $url[2],
     337                    $language[2],
     338                    $script[2],
     339                    $locale[2],
     340                    $url[3],
     341                    $language[3],
     342                    $script[3],
     343                    $locale[3],
     344                    $url[4],
     345                    $language[4],
     346                    $script[4],
     347                    $locale[4],
     348                    $url[5],
     349                    $language[5],
     350                    $script[5],
     351                    $locale[5],
     352                    $url[6],
     353                    $language[6],
     354                    $script[6],
     355                    $locale[6],
     356                    $url[7],
     357                    $language[7],
     358                    $script[7],
     359                    $locale[7],
     360                    $url[8],
     361                    $language[8],
     362                    $script[8],
     363                    $locale[8],
     364                    $url[9],
     365                    $language[9],
     366                    $script[9],
     367                    $locale[9],
     368                    $url[10],
     369                    $language[10],
     370                    $script[10],
     371                    $locale[10]
     372                )
     373            );
     374
     375        }
     376
     377        // Generate the response.
     378        $response = new WP_REST_Response( $data );
     379
     380        return $response;
     381    }
     382
     383    /**
     384     * Check the user capability.
     385     *
     386     * @return true|WP_Error
     387     */
     388    public function rest_api_daext_hreflang_manager_post_connection_callback_permission_check() {
     389
     390        // Check the capability.
     391        if ( ! current_user_can( 'edit_others_posts' ) ) {
     392            return new WP_Error(
     393                'rest_read_error',
     394                'Sorry, you are not allowed to add a connection.',
     395                array( 'status' => 403 )
     396            );
     397        }
     398
     399        return true;
     400    }
     401
     402
     403    /**
     404     * Callback for the GET 'hreflang-manager-lite/v1/options' endpoint of the Rest API.
     405     *
    89406     * @return WP_REST_Response
    90407     */
     
    110427    public function rest_api_daext_hreflang_manager_read_options_callback_permission_check() {
    111428
    112         if ( ! current_user_can( 'manage_options' ) ) {
     429        if ( ! current_user_can( 'edit_others_posts' ) ) {
    113430            return new WP_Error(
    114431                'rest_read_error',
  • hreflang-manager-lite/tags/1.14/init.php

    r3379980 r3462372  
    33 * Plugin Name: Hreflang Manager
    44 * Description: Set language and regional URL for better SEO performance. (Lite Version)
    5  * Version: 1.13
     5 * Version: 1.14
    66 * Author: DAEXT
    77 * Author URI: https://daext.com
     
    3030require_once plugin_dir_path( __FILE__ ) . 'public/class-daexthrmal-public.php';
    3131add_action( 'plugins_loaded', array( 'Daexthrmal_Public', 'get_instance' ) );
     32
     33// Perform the Gutenberg related activities only if Gutenberg is present.
     34if ( function_exists( 'register_block_type' ) ) {
     35    require_once plugin_dir_path( __FILE__ ) . 'blocks/src/init.php';
     36}
    3237
    3338// Admin.
  • hreflang-manager-lite/tags/1.14/public/class-daexthrmal-public.php

    r3379980 r3462372  
    8282         * Don't show the tag inspector if:
    8383         *
    84          * - The current user has no edit_posts capabilities
     84         * - The current user has no edit_others_posts capabilities
    8585         * - The Tag Inspector is not enabled.
    8686         */
    87         if ( ! current_user_can( 'manage_options' ) ||
     87        if ( ! current_user_can( 'edit_others_posts' ) ||
    8888             ( 1 !== intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ||
    8989             ! $this->shared->has_valid_hreflang_tags()
     
    101101                    <div class="daexthrmal-tag-inspector__header-wrapper-left">
    102102                        <?php $this->shared->echo_icon_svg( 'drag-handle' ); ?>
    103                         <div class="daexthrmal-tag-inspector__title"><?php esc_html_e('Tag Inspector', 'hreflang-manager'); ?></div>
     103                        <div class="daexthrmal-tag-inspector__title"><?php esc_html_e('Tag Inspector', 'hreflang-manager-lite'); ?></div>
    104104                    </div>
    105105                    <div class="daexthrmal-tag-inspector__header-wrapper-right">
     
    118118                        <thead>
    119119                        <tr>
    120                             <th><?php esc_html_e( 'Language/Locale', 'hreflang-manager' ); ?></th>
    121                             <th><?php esc_html_e( 'URL', 'hreflang-manager' ); ?></th>
     120                            <th><?php esc_html_e( 'Language/Locale', 'hreflang-manager-lite' ); ?></th>
     121                            <th><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?></th>
    122122                        </tr>
    123123                        </thead>
     
    135135            <div id="daexthrmal-tag-inspector__footer" class="daexthrmal-tag-inspector__footer">
    136136                <div class="daexthrmal-tag-inspector__controls">
    137                     <button id="daexthrmal-tag-inspector__table-view-btn" class="daexthrmal-tag-inspector__table-view-btn daexthrmal-tag-inspector__table-view-btn-active"><?php esc_html_e('Table View', 'hreflang-manager'); ?></button>
    138                     <button id="daexthrmal-tag-inspector__tag-view-btn" class="daexthrmal-tag-inspector__tag-view-btn"><?php esc_html_e('Tag View', 'hreflang-manager'); ?></button>
     137                    <button id="daexthrmal-tag-inspector__table-view-btn" class="daexthrmal-tag-inspector__table-view-btn daexthrmal-tag-inspector__table-view-btn-active"><?php esc_html_e('Table View', 'hreflang-manager-lite'); ?></button>
     138                    <button id="daexthrmal-tag-inspector__tag-view-btn" class="daexthrmal-tag-inspector__tag-view-btn"><?php esc_html_e('Tag View', 'hreflang-manager-lite'); ?></button>
    139139                </div>
    140140            </div>
     
    151151    public function enqueue_styles() {
    152152
    153         // Enqueue the style used to show the log if the current user has the edit_posts capability and if the log is enabled.
    154         if ( current_user_can( 'manage_options' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
     153        // Enqueue the style used to show the log if the current user has the edit_others_posts capability and if the log is enabled.
     154        if ( current_user_can( 'edit_others_posts' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
    155155
    156156            wp_enqueue_style(
     
    169169    public function enqueue_scripts() {
    170170
    171         // Enqueue the script used to handle the tag inspector if the current user has the edit_posts capability and if the tag inspector is enabled.
    172         if ( current_user_can( 'manage_options' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
     171        // Enqueue the script used to handle the tag inspector if the current user has the edit_others_posts capability and if the tag inspector is enabled.
     172        if ( current_user_can( 'edit_others_posts' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
    173173            wp_enqueue_script(
    174174                $this->shared->get( 'slug' ) . '-tag-inspector',
  • hreflang-manager-lite/tags/1.14/readme.txt

    r3379980 r3462372  
    44Donate link: https://daext.com
    55Requires at least: 4.0
    6 Tested up to: 6.8.3
     6Tested up to: 6.9.1
    77Requires PHP: 5.2
    8 Stable tag: 1.13
     8Stable tag: 1.14
    99License: GPLv3
    1010
     
    6464
    6565== Changelog ==
     66
     67= 1.14 =
     68
     69*February 16, 2026*
     70
     71* Added new interfaces for adding and managing Hreflang data in both the Block Editor (via a dedicated sidebar) and the Classic or non-standard editors (via a dedicated meta box).
    6672
    6773= 1.13 =
  • hreflang-manager-lite/tags/1.14/shared/class-daexthrmal-shared.php

    r3379980 r3462372  
    4141
    4242        $this->data['slug'] = 'daexthrmal';
    43         $this->data['ver']  = '1.13';
     43        $this->data['ver']  = '1.14';
    4444        $this->data['dir']  = substr( plugin_dir_path( __FILE__ ), 0, -7 );
    4545        $this->data['url']  = substr( plugin_dir_url( __FILE__ ), 0, -7 );
     
    21512151    }
    21522152
     2153    /**
     2154     * Get the post types with UI.
     2155     *
     2156     * @return array|string[]|WP_Post_Type[]
     2157     */
     2158    public function get_post_types_with_ui() {
     2159
     2160        // Load the assets for the post editor.
     2161        $available_post_types_a = get_post_types(
     2162                array(
     2163                        'public'  => true,
     2164                        'show_ui' => true,
     2165                )
     2166        );
     2167
     2168        // Remove the "attachment" post type.
     2169        $available_post_types_a = array_diff( $available_post_types_a, array( 'attachment' ) );
     2170
     2171        return $available_post_types_a;
     2172    }
     2173
    21532174}
  • hreflang-manager-lite/trunk/admin/class-daexthrmal-admin.php

    r3379980 r3462372  
    6767        // Add the admin menu.
    6868        add_action( 'admin_menu', array( $this, 'me_add_admin_menu' ) );
     69
     70        // Add the meta box.
     71        add_action( 'add_meta_boxes', array( $this, 'create_meta_box' ) );
     72
     73        // Save the meta box.
     74        add_action( 'save_post', array( $this, 'save_meta_box' ) );
    6975
    7076        // This hook is triggered during the creation of a new blog.
     
    232238
    233239        }
     240
     241        $meta_box_post_types_a = $this->shared->get_post_types_with_ui();
     242
     243        if ( in_array( $screen->id, $meta_box_post_types_a, true ) ) {
     244            wp_enqueue_style( $this->shared->get( 'slug' ) . '-meta-box', $this->shared->get( 'url' ) . 'admin/assets/css/meta-box.css', array(), $this->shared->get( 'ver' ) );
     245
     246            // Select2.
     247            wp_enqueue_style(
     248                $this->shared->get( 'slug' ) . '-select2',
     249                $this->shared->get( 'url' ) . 'admin/assets/inc/select2/css/select2.min.css',
     250                array(),
     251                $this->shared->get( 'ver' )
     252            );
     253
     254            wp_enqueue_style( $this->shared->get( 'slug' ) . '-select2-custom', $this->shared->get( 'url' ) . 'admin/assets/css/select2-custom.css', array(), $this->shared->get( 'ver' ) );
     255
     256        }
    234257    }
    235258
     
    295318            wp_enqueue_script( $this->shared->get( 'slug' ) . '-menu', $this->shared->get( 'url' ) . 'admin/assets/js/framework-menu/menu.js', array( 'jquery' ), $this->shared->get( 'ver' ), true );
    296319
     320        }
     321
     322        $meta_box_post_types_a = $this->shared->get_post_types_with_ui();
     323
     324        if ( in_array( $screen->id, $meta_box_post_types_a, true ) ) {
     325
     326            wp_enqueue_script(
     327                $this->shared->get( 'slug' ) . '-select2',
     328                $this->shared->get( 'url' ) . 'admin/assets/inc/select2/js/select2.min.js',
     329                array( 'jquery' ),
     330                $this->shared->get( 'ver' ),
     331                true
     332            );
     333
     334            wp_enqueue_script( $this->shared->get( 'slug' ) . '-meta-box', $this->shared->get( 'url' ) . 'admin/assets/js/meta-box.js', array( 'jquery', $this->shared->get( 'slug' ) . '-select2' ), $this->shared->get( 'ver' ), true );
    297335        }
    298336    }
     
    572610    }
    573611
     612    // meta box -----------------------------------------------------------------.
     613
     614    /**
     615     * The add_meta_boxes hook callback.
     616     *
     617     * @return void
     618     */
     619    public function create_meta_box() {
     620
     621        // Verify the capability.
     622        if ( current_user_can( 'edit_others_posts' ) ) {
     623
     624            $post_types_a = $this->shared->get_post_types_with_ui();
     625
     626            foreach ( $post_types_a as $key => $post_type ) {
     627                $post_type = trim( $post_type );
     628                add_meta_box(
     629                    'daexthrmal-meta',
     630                    'Hreflang Manager',
     631                    array( $this, 'meta_box_callback' ),
     632                    $post_type,
     633                    'normal',
     634                    'high',
     635                    // Ref: https://make.wordpress.org/core/2018/11/07/meta-box-compatibility-flags/ .
     636                    array(
     637
     638                        /*
     639                         * It's not confirmed that this meta box works in the block editor.
     640                         */
     641                        '__block_editor_compatible_meta_box' => false,
     642
     643                        /*
     644                         * This meta box should only be loaded in the classic editor interface, and the block editor
     645                         * should not display it.
     646                         */
     647                        '__back_compat_meta_box' => true,
     648
     649                    )
     650                );
     651            }
     652        }
     653    }
     654
     655    /**
     656     * Display the Hreflang Manager meta box content.
     657     *
     658     * @return void
     659     */
     660    public function meta_box_callback() {
     661
     662        ?>
     663
     664        <table class="form-table daexthrmal-table-hreflang-manager">
     665
     666            <tbody>
     667
     668            <?php
     669
     670            /**
     671             * Activate the 'disabled="disabled"' attribute when the post status is not:
     672             *  - publish
     673             *  - future
     674             *  - pending
     675             *  - private
     676             */
     677            $post_status = get_post_status();
     678            if ( 'publish' !== $post_status && 'future' !== $post_status && 'pending' !== $post_status && 'private' !== $post_status ) {
     679                $input_disabled = 'disabled';
     680            } else {
     681                $input_disabled = '';
     682            }
     683
     684            /**
     685             * Look for a connection that has as a url_to_connect value the permalink value of this post
     686             *
     687             *  If there is already a connection:
     688             *  - show the form with the field already filled with the value from the database
     689             *  If there is no connection:
     690             *  - show the form with empty fields
     691             */
     692
     693            // Get the number of connections that should be displayed in the menu.
     694            $connections_in_menu = 10;
     695
     696            $permalink = $this->shared->get_permalink( get_the_ID(), true );
     697
     698            // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     699            global $wpdb;
     700
     701            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     702            $permalink_connections = $wpdb->get_row(
     703                $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     704            );
     705
     706            if ( null === $permalink_connections ) {
     707
     708                // Default empty form.
     709                for ( $i = 1; $i <= $connections_in_menu; $i++ ) {
     710
     711                    ?>
     712
     713                    <!-- url -->
     714                    <tr valign="top">
     715                        <th scope="row"><label for="url<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     716                        <td><input autocomplete="off" <?php echo esc_attr( $input_disabled ); ?> type="text" id="url<?php echo esc_attr( $i ); ?>" maxlength="2083" name="url<?php echo esc_attr( $i ); ?>" class="regular-text daexthrmal-url"/></td>
     717                    </tr>
     718
     719                    <!-- Language -->
     720                    <tr valign="top">
     721                        <th scope="row"><label for="language<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Language', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     722                        <td>
     723                            <select <?php echo esc_attr( $input_disabled ); ?> id="language<?php echo esc_attr( $i ); ?>" class="daexthrmal-language" name="language<?php echo esc_attr( $i ); ?>">
     724                                <?php
     725
     726                                $array_language = get_option( 'daexthrmal_language' );
     727                                foreach ( $array_language as $key => $value ) {
     728                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_language_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     729                                }
     730
     731                                ?>
     732                            </select>
     733                        </td>
     734                    </tr>
     735
     736                    <!-- Script -->
     737                    <tr valign="top">
     738                        <th scope="row"><label for="script<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Script', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     739                        <td>
     740                            <select <?php echo esc_attr( $input_disabled ); ?> id="script<?php echo esc_attr( $i ); ?>" class="daexthrmal-script" name="script<?php echo esc_attr( $i ); ?>">
     741                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     742                                <?php
     743
     744                                $array_language = get_option( 'daexthrmal_script' );
     745                                foreach ( $array_language as $key => $value ) {
     746                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_script_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     747                                }
     748
     749                                ?>
     750                            </select>
     751                        </td>
     752                    </tr>
     753
     754                    <!-- Locale -->
     755                    <tr valign="top">
     756                        <th scope="row"><label for="locale<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Locale', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     757                        <td>
     758                            <select <?php echo esc_attr( $input_disabled ); ?> id="locale<?php echo esc_attr( $i ); ?>" class="daexthrmal-locale" name="locale<?php echo esc_attr( $i ); ?>">
     759                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     760                                <?php
     761
     762                                $array_locale = get_option( 'daexthrmal_locale' );
     763                                foreach ( $array_locale as $key => $value ) {
     764                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( get_option( 'daexthrmal_default_locale_' . $i ), $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     765                                }
     766
     767                                ?>
     768                            </select>
     769                        </td>
     770                    </tr>
     771
     772                    <?php
     773
     774                }
     775            } else {
     776               
     777                // Form with data retrieved form the database.
     778                for ( $i = 1; $i <= $connections_in_menu; $i++ ) {
     779
     780                    ?>
     781
     782                    <!-- url -->
     783                    <tr valign="top">
     784                        <th scope="row"><label for="url<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     785                        <td><input autocomplete="off" type="text" value="<?php echo esc_attr( stripslashes( $permalink_connections->{'url' .$i} ) ); ?>" id="url<?php echo esc_attr( $i ); ?>" maxlength="2083" name="url<?php echo esc_attr( $i ); ?>" class="regular-text daexthrmal-url"/></td>
     786
     787                    </tr>
     788
     789                    <!-- Language <?php echo intval( $i, 10 ); ?> -->
     790                    <tr valign="top">
     791                        <th scope="row"><label for="language<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Language', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     792                        <td>
     793                            <select id="language<?php echo esc_attr( $i ); ?>" class="daexthrmal-language" name="language<?php echo esc_attr( $i ); ?>">
     794                                <?php
     795
     796                                $array_language = get_option( 'daexthrmal_language' );
     797                                foreach ( $array_language as $key => $value ) {
     798                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'language' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     799                                }
     800
     801                                ?>
     802                            </select>
     803                        </td>
     804                    </tr>
     805
     806                    <!-- Script <?php echo intval( $i, 10 ); ?> -->
     807                    <tr valign="top">
     808                        <th scope="row"><label for="script<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Script', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     809                        <td>
     810                            <select id="script<?php echo esc_attr( $i ); ?>" class="daexthrmal-script" name="script<?php echo esc_attr( $i ); ?>">
     811                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     812                                <?php
     813
     814                                $array_script = get_option( 'daexthrmal_script' );
     815                                foreach ( $array_script as $key => $value ) {
     816                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'script' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     817                                }
     818
     819                                ?>
     820                            </select>
     821                        </td>
     822                    </tr>
     823
     824                    <!-- Locale <?php echo intval( $i, 10 ); ?> -->
     825                    <tr valign="top">
     826                        <th scope="row"><label for="locale<?php echo esc_attr( $i ); ?>"><?php esc_html_e( 'Locale', 'hreflang-manager-lite' ); ?> <?php echo esc_html( $i ); ?></label></th>
     827                        <td>
     828                            <select id="locale<?php echo esc_attr( $i ); ?>" class="daexthrmal-locale" name="locale<?php echo esc_attr( $i ); ?>">
     829                                <option value=""><?php esc_html_e( 'Not Assigned', 'hreflang-manager-lite' ); ?></option>
     830                                <?php
     831
     832                                $array_locale = get_option( 'daexthrmal_locale' );
     833                                foreach ( $array_locale as $key => $value ) {
     834                                    echo '<option value="' . esc_attr( $value ) . '" ' . selected( $permalink_connections->{'locale' . $i}, $value, false ) . '>' . esc_html( $value ) . ' - ' . esc_html( $key ) . '</option>';
     835                                }
     836
     837                                ?>
     838                            </select>
     839                        </td>
     840                    </tr>
     841
     842                    <?php
     843
     844                }
     845            }
     846
     847        ?>
     848
     849        </tbody>
     850
     851        </table>
     852
     853        <?php
     854
     855        // Store the original permalink to detect changes when the form is saved.
     856        echo '<input type="hidden" name="daexthrmal_original_permalink" value="' . esc_attr( $permalink ) . '" />';
     857
     858        // Use nonce for verification.
     859        wp_nonce_field( plugin_basename( __FILE__ ), 'daexthrmal_nonce' );
     860    }
     861
     862    /**
     863     * Save the meta box data.
     864     *
     865     * @return void
     866     */
     867    public function save_meta_box() {
     868
     869        // Verify the capability.
     870        if ( ! current_user_can( 'edit_others_posts' ) ) {
     871            return;
     872        }
     873
     874        // Security verification.
     875
     876        // Verify if this is an auto save routine. If our form has not been submitted, we don't want to do anything.
     877        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
     878            return;
     879        }
     880
     881        /**
     882         * Verify this came from our screen and with proper authorization, because save_post can be triggered at other
     883         * times.
     884         */
     885        if ( isset( $_POST['daexthrmal_nonce'] ) ) {
     886            $nonce = sanitize_text_field( wp_unslash( $_POST['daexthrmal_nonce'] ) );
     887            if ( ! wp_verify_nonce( $nonce, plugin_basename( __FILE__ ) ) ) {
     888                return;
     889            }
     890        } else {
     891            return;
     892        }
     893
     894        /* - end security verification - */
     895
     896        /*
     897         * Return ( do not save ) if the post status is not:
     898         * - publish
     899         * - future
     900         * - pending
     901         * - private
     902         */
     903        $post_status = get_post_status();
     904        if ( 'publish' !== $post_status && 'future' !== $post_status && 'pending' !== $post_status && 'private' !== $post_status ) {
     905            return;}
     906
     907        // Init vars.
     908        $url      = array();
     909        $language = array();
     910        $script   = array();
     911        $locale   = array();
     912
     913        // Initialize the variables that include the URLs, the languages and the locale.
     914        for ( $i = 1;$i <= 10;$i++ ) {
     915
     916            if ( isset( $_POST[ 'url' . $i ] ) && strlen( trim( esc_url_raw( wp_unslash( $_POST[ 'url' . $i ] ) ) ) ) > 0 ) {
     917                $url[ $i ]        = esc_url_raw( wp_unslash( $_POST[ 'url' . $i ] ) );
     918                $at_least_one_url = true;
     919            } else {
     920                $url[ $i ] = '';
     921            }
     922
     923            if ( isset( $_POST[ 'language' . $i ] ) && strlen( trim( sanitize_text_field( wp_unslash( $_POST[ 'language' . $i ] ) ) ) ) > 0 ) {
     924                $language[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'language' . $i ] ) );
     925            } else {
     926                $language[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_language_' . $i );
     927            }
     928
     929            if ( isset( $_POST[ 'script' . $i ] ) ) {
     930                $script[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'script' . $i ] ) );
     931            } else {
     932                $script[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_script_' . $i );
     933            }
     934
     935            if ( isset( $_POST[ 'locale' . $i ] ) ) {
     936                $locale[ $i ] = sanitize_text_field( wp_unslash( $_POST[ 'locale' . $i ] ) );
     937            } else {
     938                $locale[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_locale_' . $i );
     939            }
     940        }
     941
     942        /*
     943         * save the fields in the daexthrmal_connection database table:
     944         *
     945         * - if a row with the daexthrmal_connection equal to the current permalink already exists update the row
     946         *
     947         * - if a row with the daexthrmal_connection equal to the current permalink doesn't exists create a new row
     948         */
     949        $permalink = $this->shared->get_permalink( get_the_ID(), true );
     950
     951        // Retrieve the original permalink from the hidden form field.
     952        $original_permalink = isset( $_POST['daexthrmal_original_permalink'] ) ? esc_url_raw( wp_unslash( $_POST['daexthrmal_original_permalink'] ) ) : '';
     953
     954        // Update url_to_connect when a permalink change is detected.
     955        global $wpdb;
     956        if ( ! empty( $original_permalink ) && ! empty( $permalink ) && $original_permalink !== $permalink ) {
     957            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     958            $wpdb->query(
     959                $wpdb->prepare(
     960                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     961                    . 'url_to_connect = %s WHERE url_to_connect = %s ',
     962                    $permalink,
     963                    $original_permalink
     964                )
     965            );
     966        }
     967
     968        // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     969        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     970        $permalink_connections = $wpdb->get_row(
     971            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     972        );
     973
     974        if ( null !== $permalink_connections ) {
     975
     976            // Update an existing connection.
     977
     978            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     979            $query_result = $wpdb->query(
     980                $wpdb->prepare(
     981                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     982                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     983                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     984                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     985                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     986                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     987                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     988                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     989                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     990                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     991                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s WHERE url_to_connect = %s ',
     992                    $url[1],
     993                    $language[1],
     994                    $script[1],
     995                    $locale[1],
     996                    $url[2],
     997                    $language[2],
     998                    $script[2],
     999                    $locale[2],
     1000                    $url[3],
     1001                    $language[3],
     1002                    $script[3],
     1003                    $locale[3],
     1004                    $url[4],
     1005                    $language[4],
     1006                    $script[4],
     1007                    $locale[4],
     1008                    $url[5],
     1009                    $language[5],
     1010                    $script[5],
     1011                    $locale[5],
     1012                    $url[6],
     1013                    $language[6],
     1014                    $script[6],
     1015                    $locale[6],
     1016                    $url[7],
     1017                    $language[7],
     1018                    $script[7],
     1019                    $locale[7],
     1020                    $url[8],
     1021                    $language[8],
     1022                    $script[8],
     1023                    $locale[8],
     1024                    $url[9],
     1025                    $language[9],
     1026                    $script[9],
     1027                    $locale[9],
     1028                    $url[10],
     1029                    $language[10],
     1030                    $script[10],
     1031                    $locale[10],
     1032                    $permalink
     1033                )
     1034            );
     1035
     1036        } else {
     1037
     1038            // Return ( do not create a new connection ) if there are not a single url defined.
     1039            if ( ! isset( $at_least_one_url ) ) {
     1040                return;}
     1041
     1042            // Add a new connection into the database.
     1043
     1044            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     1045            $query_result = $wpdb->query(
     1046                $wpdb->prepare(
     1047                    "INSERT INTO {$wpdb->prefix}daexthrmal_connection SET url_to_connect = %s ,"
     1048                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     1049                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     1050                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     1051                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     1052                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     1053                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     1054                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     1055                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     1056                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     1057                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s',
     1058                    $permalink,
     1059                    $url[1],
     1060                    $language[1],
     1061                    $script[1],
     1062                    $locale[1],
     1063                    $url[2],
     1064                    $language[2],
     1065                    $script[2],
     1066                    $locale[2],
     1067                    $url[3],
     1068                    $language[3],
     1069                    $script[3],
     1070                    $locale[3],
     1071                    $url[4],
     1072                    $language[4],
     1073                    $script[4],
     1074                    $locale[4],
     1075                    $url[5],
     1076                    $language[5],
     1077                    $script[5],
     1078                    $locale[5],
     1079                    $url[6],
     1080                    $language[6],
     1081                    $script[6],
     1082                    $locale[6],
     1083                    $url[7],
     1084                    $language[7],
     1085                    $script[7],
     1086                    $locale[7],
     1087                    $url[8],
     1088                    $language[8],
     1089                    $script[8],
     1090                    $locale[8],
     1091                    $url[9],
     1092                    $language[9],
     1093                    $script[9],
     1094                    $locale[9],
     1095                    $url[10],
     1096                    $language[10],
     1097                    $script[10],
     1098                    $locale[10]
     1099                )
     1100            );
     1101
     1102        }
     1103    }
     1104
    5741105    /**
    5751106     * Register the admin menu.
  • hreflang-manager-lite/trunk/admin/inc/class-daexthrmal-pagination.php

    r3379980 r3462372  
    184184                esc_html( $this->current_page ) .
    185185                '&nbsp' .
    186                 esc_html__( 'of' ) .
     186                esc_html__( 'of', 'hreflang-manager-lite' ) .
    187187                '&nbsp' .
    188188                esc_html( $last_page ) .
  • hreflang-manager-lite/trunk/admin/inc/menu/class-daexthrmal-menu-elements.php

    r3379980 r3462372  
    966966                            <?php
    967967                            esc_html_e(
    968                                 'Sync hreflang data across multiple websites, bulk import entries from a spreadsheet, unlock advanced tools like the Locale Selector and Hreflang Checker, add hreflang directly in the post editor, and more!',
     968                                'Sync hreflang data across multiple websites, bulk import entries from spreadsheets, unlock advanced tools like the Locale Selector and Hreflang Checker, implement hreflang in XML sitemaps, and more!',
    969969                                'hreflang-manager-lite'
    970970                            );
  • hreflang-manager-lite/trunk/inc/class-daexthrmal-rest.php

    r3379980 r3462372  
    5959     */
    6060    public function rest_api_register_route() {
     61
     62        // Add the GET 'hreflang-manager-lite/v1/post' endpoint to the Rest API.
     63        register_rest_route(
     64            'hreflang-manager-lite/v1',
     65            '/post/(?P<id>\d+)',
     66            array(
     67                'methods'             => 'GET',
     68                'callback'            => array( $this, 'rest_api_daext_hreflang_manager_read_connections_callback' ),
     69                'permission_callback' => array( $this, 'rest_api_daext_hreflang_manager_read_connections_callback_permission_check' ),
     70            )
     71        );
     72
     73        // Add the POST 'hreflang-manager-lite/v1/post' endpoint to the Rest API.
     74        register_rest_route(
     75            'hreflang-manager-lite/v1',
     76            '/post/',
     77            array(
     78                'methods'             => 'POST',
     79                'callback'            => array( $this, 'rest_api_daext_hreflang_manager_post_connection_callback' ),
     80                'permission_callback' => array( $this, 'rest_api_daext_hreflang_manager_post_connection_callback_permission_check' ),
     81            )
     82        );
    6183
    6284        // Add the GET 'hreflang-manager-lite/v1/options' endpoint to the Rest API.
     
    87109     * Callback for the GET 'hreflang-manager-lite/v1/options' endpoint of the Rest API.
    88110     *
     111     * @param array $data Data received from the request.
     112     *
     113     * @return false|WP_REST_Response
     114     */
     115    public function rest_api_daext_hreflang_manager_read_connections_callback( $data ) {
     116
     117        // Generate the response.
     118
     119        $url_to_connect = $this->shared->get_permalink( $data['id'], true );
     120
     121        global $wpdb;
     122        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     123        $row = $wpdb->get_row(
     124            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $url_to_connect ),
     125            ARRAY_A
     126        );
     127
     128        if ( $wpdb->num_rows > 0 ) {
     129
     130            // Prepare the response.
     131            $response = new WP_REST_Response( $row );
     132
     133        } else {
     134
     135            return false;
     136        }
     137
     138        return $response;
     139    }
     140
     141    /**
     142     * Check the user capability.
     143     *
     144     * @return true|WP_Error
     145     */
     146    public function rest_api_daext_hreflang_manager_read_connections_callback_permission_check() {
     147
     148        // Check the capability.
     149        if ( ! current_user_can( 'edit_others_posts' ) ) {
     150            return new WP_Error(
     151                'rest_read_error',
     152                'Sorry, you are not allowed to view the Hreflang Manager connections.',
     153                array( 'status' => 403 )
     154            );
     155        }
     156
     157        return true;
     158    }
     159
     160    /**
     161     * Callback for the POST 'hreflang-manager-lite/v1/post/' endpoint of the Rest API.
     162     *
     163     *  This method is in the following contexts:
     164     *  - To save the connection when the "Update" button of the Gutenberg editor is clicked.
     165     *
     166     * @param array $data Data received from the request.
     167     *
     168     * @return void|WP_REST_Response
     169     */
     170    public function rest_api_daext_hreflang_manager_post_connection_callback( $data ) {
     171
     172        $data    = json_decode( $data->get_body() );
     173        $post_id = $data->post_id;
     174        $old_permalink = isset( $data->old_permalink ) ? esc_url_raw( $data->old_permalink ) : '';
     175        $new_permalink = isset( $data->new_permalink ) ? esc_url_raw( $data->new_permalink ) : '';
     176        $data    = $data->connection_data;
     177
     178        // Init vars.
     179        $url      = array();
     180        $language = array();
     181        $script   = array();
     182        $locale   = array();
     183
     184        // Initialize the variables that include the URLs, the languages, the script and the locale.
     185        for ( $i = 1;$i <= 10;$i++ ) {
     186
     187            if ( isset( $data->{'url' . $i} ) && strlen( trim( $data->{'url' . $i} ) ) > 0 ) {
     188                $url[ $i ]        = esc_url_raw( $data->{'url' . $i} );
     189                $at_least_one_url = true;
     190            } else {
     191                $url[ $i ] = '';
     192            }
     193
     194            if ( isset( $data->{'language' . $i} ) && strlen( trim( $data->{'language' . $i} ) ) > 0 ) {
     195                $language[ $i ] = sanitize_text_field( $data->{'language' . $i} );
     196            } else {
     197                $language[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_language_' . $i );
     198            }
     199
     200            if ( isset( $data->{'script' . $i} ) ) {
     201                $script[ $i ] = sanitize_text_field( $data->{'script' . $i} );
     202            } else {
     203                $script[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_script_' . $i );
     204            }
     205
     206            if ( isset( $data->{'locale' . $i} ) ) {
     207                $locale[ $i ] = sanitize_text_field( $data->{'locale' . $i} );
     208            } else {
     209                $locale[ $i ] = get_option( $this->shared->get( 'slug' ) . '_default_locale_' . $i );
     210            }
     211        }
     212
     213        /*
     214         * Save the fields in the daexthrmal_connection database table:
     215         *
     216         * - if a row with the url_to_connect equal to the current permalink already exists update the row
     217         * - if a row with the url_to_connect equal to the current permalink doesn't exist create a new row
     218         */
     219        $permalink = $this->shared->get_permalink( $post_id, true );
     220
     221        if ( ! empty( $new_permalink ) ) {
     222            $permalink = $new_permalink;
     223        }
     224
     225        // Update url_to_connect when a permalink change is detected.
     226        global $wpdb;
     227        if ( ! empty( $old_permalink ) && ! empty( $new_permalink ) && $old_permalink !== $new_permalink ) {
     228            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     229            $query_result = $wpdb->query(
     230                $wpdb->prepare(
     231                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     232                    . 'url_to_connect = %s WHERE url_to_connect = %s ',
     233                    $new_permalink,
     234                    $old_permalink
     235                )
     236            );
     237        }
     238
     239        // Look for $permalink in the url_to_connect field of the daexthrmal_connection database table.
     240        global $wpdb;
     241        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     242        $permalink_connections = $wpdb->get_row(
     243            $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}daexthrmal_connection WHERE url_to_connect = %s", $permalink )
     244        );
     245
     246        if ( null !== $permalink_connections ) {
     247
     248            // Update an existing connection.
     249
     250            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     251            $query_result = $wpdb->query(
     252                $wpdb->prepare(
     253                    "UPDATE {$wpdb->prefix}daexthrmal_connection SET "
     254                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     255                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     256                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     257                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     258                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     259                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     260                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     261                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     262                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     263                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s WHERE url_to_connect = %s ',
     264                    $url[1],
     265                    $language[1],
     266                    $script[1],
     267                    $locale[1],
     268                    $url[2],
     269                    $language[2],
     270                    $script[2],
     271                    $locale[2],
     272                    $url[3],
     273                    $language[3],
     274                    $script[3],
     275                    $locale[3],
     276                    $url[4],
     277                    $language[4],
     278                    $script[4],
     279                    $locale[4],
     280                    $url[5],
     281                    $language[5],
     282                    $script[5],
     283                    $locale[5],
     284                    $url[6],
     285                    $language[6],
     286                    $script[6],
     287                    $locale[6],
     288                    $url[7],
     289                    $language[7],
     290                    $script[7],
     291                    $locale[7],
     292                    $url[8],
     293                    $language[8],
     294                    $script[8],
     295                    $locale[8],
     296                    $url[9],
     297                    $language[9],
     298                    $script[9],
     299                    $locale[9],
     300                    $url[10],
     301                    $language[10],
     302                    $script[10],
     303                    $locale[10],
     304                    $permalink
     305                )
     306            );
     307
     308        } else {
     309
     310            // Return ( do not create a new connection ) if there are not a single url defined.
     311            if ( ! isset( $at_least_one_url ) ) {
     312                return new WP_REST_Response( array( 'message' => 'No URLs provided' ), 200 );
     313            }
     314
     315            // Add a new connection into the database.
     316
     317            // phpcs:ignore WordPress.DB.DirectDatabaseQuery
     318            $query_result = $wpdb->query(
     319                $wpdb->prepare(
     320                    "INSERT INTO {$wpdb->prefix}daexthrmal_connection SET url_to_connect = %s ,"
     321                    . 'url1 = %s, language1 = %s, script1 = %s, locale1 = %s,'
     322                    . 'url2 = %s, language2 = %s, script2 = %s, locale2 = %s ,'
     323                    . 'url3 = %s, language3 = %s, script3 = %s, locale3 = %s ,'
     324                    . 'url4 = %s, language4 = %s, script4 = %s, locale4 = %s ,'
     325                    . 'url5 = %s, language5 = %s, script5 = %s, locale5 = %s ,'
     326                    . 'url6 = %s, language6 = %s, script6 = %s, locale6 = %s ,'
     327                    . 'url7 = %s, language7 = %s, script7 = %s, locale7 = %s ,'
     328                    . 'url8 = %s, language8 = %s, script8 = %s, locale8 = %s ,'
     329                    . 'url9 = %s, language9 = %s, script9 = %s, locale9 = %s ,'
     330                    . 'url10 = %s, language10 = %s, script10 = %s, locale10 = %s',
     331                    $permalink,
     332                    $url[1],
     333                    $language[1],
     334                    $script[1],
     335                    $locale[1],
     336                    $url[2],
     337                    $language[2],
     338                    $script[2],
     339                    $locale[2],
     340                    $url[3],
     341                    $language[3],
     342                    $script[3],
     343                    $locale[3],
     344                    $url[4],
     345                    $language[4],
     346                    $script[4],
     347                    $locale[4],
     348                    $url[5],
     349                    $language[5],
     350                    $script[5],
     351                    $locale[5],
     352                    $url[6],
     353                    $language[6],
     354                    $script[6],
     355                    $locale[6],
     356                    $url[7],
     357                    $language[7],
     358                    $script[7],
     359                    $locale[7],
     360                    $url[8],
     361                    $language[8],
     362                    $script[8],
     363                    $locale[8],
     364                    $url[9],
     365                    $language[9],
     366                    $script[9],
     367                    $locale[9],
     368                    $url[10],
     369                    $language[10],
     370                    $script[10],
     371                    $locale[10]
     372                )
     373            );
     374
     375        }
     376
     377        // Generate the response.
     378        $response = new WP_REST_Response( $data );
     379
     380        return $response;
     381    }
     382
     383    /**
     384     * Check the user capability.
     385     *
     386     * @return true|WP_Error
     387     */
     388    public function rest_api_daext_hreflang_manager_post_connection_callback_permission_check() {
     389
     390        // Check the capability.
     391        if ( ! current_user_can( 'edit_others_posts' ) ) {
     392            return new WP_Error(
     393                'rest_read_error',
     394                'Sorry, you are not allowed to add a connection.',
     395                array( 'status' => 403 )
     396            );
     397        }
     398
     399        return true;
     400    }
     401
     402
     403    /**
     404     * Callback for the GET 'hreflang-manager-lite/v1/options' endpoint of the Rest API.
     405     *
    89406     * @return WP_REST_Response
    90407     */
     
    110427    public function rest_api_daext_hreflang_manager_read_options_callback_permission_check() {
    111428
    112         if ( ! current_user_can( 'manage_options' ) ) {
     429        if ( ! current_user_can( 'edit_others_posts' ) ) {
    113430            return new WP_Error(
    114431                'rest_read_error',
  • hreflang-manager-lite/trunk/init.php

    r3379980 r3462372  
    33 * Plugin Name: Hreflang Manager
    44 * Description: Set language and regional URL for better SEO performance. (Lite Version)
    5  * Version: 1.13
     5 * Version: 1.14
    66 * Author: DAEXT
    77 * Author URI: https://daext.com
     
    3030require_once plugin_dir_path( __FILE__ ) . 'public/class-daexthrmal-public.php';
    3131add_action( 'plugins_loaded', array( 'Daexthrmal_Public', 'get_instance' ) );
     32
     33// Perform the Gutenberg related activities only if Gutenberg is present.
     34if ( function_exists( 'register_block_type' ) ) {
     35    require_once plugin_dir_path( __FILE__ ) . 'blocks/src/init.php';
     36}
    3237
    3338// Admin.
  • hreflang-manager-lite/trunk/public/class-daexthrmal-public.php

    r3379980 r3462372  
    8282         * Don't show the tag inspector if:
    8383         *
    84          * - The current user has no edit_posts capabilities
     84         * - The current user has no edit_others_posts capabilities
    8585         * - The Tag Inspector is not enabled.
    8686         */
    87         if ( ! current_user_can( 'manage_options' ) ||
     87        if ( ! current_user_can( 'edit_others_posts' ) ||
    8888             ( 1 !== intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ||
    8989             ! $this->shared->has_valid_hreflang_tags()
     
    101101                    <div class="daexthrmal-tag-inspector__header-wrapper-left">
    102102                        <?php $this->shared->echo_icon_svg( 'drag-handle' ); ?>
    103                         <div class="daexthrmal-tag-inspector__title"><?php esc_html_e('Tag Inspector', 'hreflang-manager'); ?></div>
     103                        <div class="daexthrmal-tag-inspector__title"><?php esc_html_e('Tag Inspector', 'hreflang-manager-lite'); ?></div>
    104104                    </div>
    105105                    <div class="daexthrmal-tag-inspector__header-wrapper-right">
     
    118118                        <thead>
    119119                        <tr>
    120                             <th><?php esc_html_e( 'Language/Locale', 'hreflang-manager' ); ?></th>
    121                             <th><?php esc_html_e( 'URL', 'hreflang-manager' ); ?></th>
     120                            <th><?php esc_html_e( 'Language/Locale', 'hreflang-manager-lite' ); ?></th>
     121                            <th><?php esc_html_e( 'URL', 'hreflang-manager-lite' ); ?></th>
    122122                        </tr>
    123123                        </thead>
     
    135135            <div id="daexthrmal-tag-inspector__footer" class="daexthrmal-tag-inspector__footer">
    136136                <div class="daexthrmal-tag-inspector__controls">
    137                     <button id="daexthrmal-tag-inspector__table-view-btn" class="daexthrmal-tag-inspector__table-view-btn daexthrmal-tag-inspector__table-view-btn-active"><?php esc_html_e('Table View', 'hreflang-manager'); ?></button>
    138                     <button id="daexthrmal-tag-inspector__tag-view-btn" class="daexthrmal-tag-inspector__tag-view-btn"><?php esc_html_e('Tag View', 'hreflang-manager'); ?></button>
     137                    <button id="daexthrmal-tag-inspector__table-view-btn" class="daexthrmal-tag-inspector__table-view-btn daexthrmal-tag-inspector__table-view-btn-active"><?php esc_html_e('Table View', 'hreflang-manager-lite'); ?></button>
     138                    <button id="daexthrmal-tag-inspector__tag-view-btn" class="daexthrmal-tag-inspector__tag-view-btn"><?php esc_html_e('Tag View', 'hreflang-manager-lite'); ?></button>
    139139                </div>
    140140            </div>
     
    151151    public function enqueue_styles() {
    152152
    153         // Enqueue the style used to show the log if the current user has the edit_posts capability and if the log is enabled.
    154         if ( current_user_can( 'manage_options' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
     153        // Enqueue the style used to show the log if the current user has the edit_others_posts capability and if the log is enabled.
     154        if ( current_user_can( 'edit_others_posts' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
    155155
    156156            wp_enqueue_style(
     
    169169    public function enqueue_scripts() {
    170170
    171         // Enqueue the script used to handle the tag inspector if the current user has the edit_posts capability and if the tag inspector is enabled.
    172         if ( current_user_can( 'manage_options' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
     171        // Enqueue the script used to handle the tag inspector if the current user has the edit_others_posts capability and if the tag inspector is enabled.
     172        if ( current_user_can( 'edit_others_posts' ) && 1 === ( intval( get_option( 'daexthrmal_show_log' ), 10 ) ) ) {
    173173            wp_enqueue_script(
    174174                $this->shared->get( 'slug' ) . '-tag-inspector',
  • hreflang-manager-lite/trunk/readme.txt

    r3379980 r3462372  
    44Donate link: https://daext.com
    55Requires at least: 4.0
    6 Tested up to: 6.8.3
     6Tested up to: 6.9.1
    77Requires PHP: 5.2
    8 Stable tag: 1.13
     8Stable tag: 1.14
    99License: GPLv3
    1010
     
    6464
    6565== Changelog ==
     66
     67= 1.14 =
     68
     69*February 16, 2026*
     70
     71* Added new interfaces for adding and managing Hreflang data in both the Block Editor (via a dedicated sidebar) and the Classic or non-standard editors (via a dedicated meta box).
    6672
    6773= 1.13 =
  • hreflang-manager-lite/trunk/shared/class-daexthrmal-shared.php

    r3379980 r3462372  
    4141
    4242        $this->data['slug'] = 'daexthrmal';
    43         $this->data['ver']  = '1.13';
     43        $this->data['ver']  = '1.14';
    4444        $this->data['dir']  = substr( plugin_dir_path( __FILE__ ), 0, -7 );
    4545        $this->data['url']  = substr( plugin_dir_url( __FILE__ ), 0, -7 );
     
    21512151    }
    21522152
     2153    /**
     2154     * Get the post types with UI.
     2155     *
     2156     * @return array|string[]|WP_Post_Type[]
     2157     */
     2158    public function get_post_types_with_ui() {
     2159
     2160        // Load the assets for the post editor.
     2161        $available_post_types_a = get_post_types(
     2162                array(
     2163                        'public'  => true,
     2164                        'show_ui' => true,
     2165                )
     2166        );
     2167
     2168        // Remove the "attachment" post type.
     2169        $available_post_types_a = array_diff( $available_post_types_a, array( 'attachment' ) );
     2170
     2171        return $available_post_types_a;
     2172    }
     2173
    21532174}
Note: See TracChangeset for help on using the changeset viewer.