Plugin Directory

Changeset 3259677


Ignore:
Timestamp:
03/21/2025 11:44:11 AM (12 months ago)
Author:
daext
Message:

Committing and tagging 1.15

Location:
daext-interlinks-manager
Files:
6 edited
1 copied

Legend:

Unmodified
Added
Removed
  • daext-interlinks-manager/tags/1.15/init.php

    r3197491 r3259677  
    33 * Plugin Name: Interlinks Manager
    44 * Description: Manages the internal links of your WordPress website. (Lite Version)
    5  * Version: 1.14
     5 * Version: 1.15
    66 * Author: DAEXT
    77 * Author URI: https://daext.com
  • daext-interlinks-manager/tags/1.15/readme.txt

    r3197491 r3259677  
    44Donate link: https://daext.com
    55Requires at least: 4.6
    6 Tested up to: 6.7.1
     6Tested up to: 6.7.2
    77Requires PHP: 5.3
    8 Stable tag: 1.14
     8Stable tag: 1.15
    99License: GPLv3
    1010
     
    119119
    120120== Changelog ==
     121
     122= 1.15 =
     123
     124*Mar 21, 2025*
     125
     126* The internal link analysis now detects relative URLs.
    121127
    122128= 1.14 =
  • daext-interlinks-manager/tags/1.15/shared/class-daextinma-shared.php

    r3197491 r3259677  
    3333
    3434        $this->data['slug'] = 'daextinma';
    35         $this->data['ver']  = '1.14';
     35        $this->data['ver']  = '1.15';
    3636        $this->data['dir']  = substr( plugin_dir_path( __FILE__ ), 0, -7 );
    3737        $this->data['url']  = substr( plugin_dir_url( __FILE__ ), 0, -7 );
     
    122122        $text = $this->remove_script_tags( $text );
    123123
    124         /*
    125          * Get the website url and escape the regex character. # and
    126          * whitespace ( used with the 'x' modifier ) are not escaped, thus
    127          * should not be included in the $site_url string
    128          */
    129         $site_url = preg_quote( get_home_url() );
    130 
    131124        // Working regex.
    132125        $num_matches = preg_match_all(
    133             '{
    134             <a                      #1 Match the element a start-tag
    135             [^>]+                   #2 Match everything except > for at least one time
    136             href\s*=\s*             #3 Equal may have whitespaces on both sides
    137             ([\'"]?)                #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    138             ' . $site_url . '       #5 The site URL ( Scheme and Domain )
    139             [^\'">\s]+              #6 The rest of the URL ( Path and/or File )
    140             (\1)                    #7 Backreference that matches the href value delimiter matched at line 4
    141             [^>]*                   #8 Any character except > zero or more times
    142             >                       #9 End of the start-tag
    143             .*?                     #10 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    144             <\/a\s*>                #11 Element a end-tag with optional white-spaces characters before the >
    145             }ix',
     126            $this->internal_links_regex(),
    146127            $text,
    147128            $matches
     
    331312
    332313        $num_matches = preg_match_all(
    333             '{<a                                #1 Begin the element a start-tag
    334             [^>]+                               #2 Any character except > at least one time
    335             href\s*=\s*                         #3 Equal may have whitespaces on both sides
    336             ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    337             [^\'">\s]+                          #5 The site URL
    338             \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
    339             [^>]*                               #7 Any character except > zero or more times
    340             >                                   #8 End of the start-tag
    341             .*?                                 #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    342             <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
    343             }ix',
     314            $this->links_regex(),
    344315            $s,
    345316            $matches
     
    15851556
    15861557            /**
    1587              * Get the website url and quote and escape the regex character. # and
    1588              * whitespace ( used with the 'x' modifier ) are not escaped, thus
    1589              * should not be included in the $site_url string.
    1590              */
    1591             $site_url = preg_quote( get_home_url(), '/' );
    1592 
    1593             /**
    15941558             * Find all the manual and auto interlinks matches with a regular
    15951559             * expression and add them in the $juice_a array.
    15961560             */
    15971561            preg_match_all(
    1598                 '{<a                                #1 Begin the element a start-tag
    1599                 [^>]+                               #2 Any character except > at least one time
    1600                 href\s*=\s*                         #3 Equal may have whitespaces on both sides
    1601                 ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    1602                 (' . $site_url . '[^\'">\s]* )      #5 The site URL ( Scheme and Domain ) and the rest of the URL ( Path and/or File ) ( captured )
    1603                 \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
    1604                 [^>]*                               #7 Any character except > zero or more times
    1605                 >                                   #8 End of the start-tag
    1606                 (.*?)                               #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    1607                 <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
    1608                 }ix',
     1562                $this->internal_links_regex(),
    16091563                $post_content,
    16101564                $matches,
     
    16201574
    16211575                // save the captured URL.
    1622                 $url = $single_capture[0];
     1576                $url = $this->relative_to_absolute_url( $single_capture[0], $single_post['ID'] );
    16231577
    16241578                /**
     
    19111865    }
    19121866
     1867    /**
     1868     * Converts relative URLs to absolute URLs.
     1869     *
     1870     * The following type of URLs are supported:
     1871     *
     1872     * - Absolute URLs | E.g., "https://example.com/post/"
     1873     * - Protocol-relative URLs | E.g., "//localhost/image.jpg".
     1874     * - Root-relative URLs | E.g., "/post/".
     1875     * - Fragment-only URLs | E.g., "#section1".
     1876     * - Relative URLs with relative paths. | E.g., "./post/", "../post", "../../post".
     1877     * - Page-relative URLs | E.g., "post/".
     1878     *
     1879     * @param String $relative_url The relative URL that should be converted.
     1880     * @param Int $post_id The ID of the post.
     1881     *
     1882     * @return mixed|string
     1883     */
     1884    public function relative_to_absolute_url( $relative_url, $post_id ) {
     1885
     1886        $post_permalink = get_permalink( $post_id );
     1887
     1888        /**
     1889         * If already an absolute URL, return as is.
     1890         *
     1891         * -------------------------------------------------------------------------------------------------------------
     1892         */
     1893        if ( empty( $relative_url ) || wp_parse_url( $relative_url, PHP_URL_SCHEME ) ) {
     1894            return $relative_url;
     1895        }
     1896
     1897        // Get the site URL. Ensure trailing slash for proper resolution.
     1898        $base_url = home_url( '/' );
     1899
     1900        // Parse base URL.
     1901        $base_parts = wp_parse_url( $base_url );
     1902
     1903        /**
     1904         * Protocol-relative URL | If it's a protocol-relative URL (e.g., //example.com/image.jpg), add "https:" as
     1905         * default.
     1906         *
     1907         * -------------------------------------------------------------------------------------------------------------
     1908         */
     1909        if ( str_starts_with( $relative_url, '//' ) ) {
     1910            if ( $this->is_site_using_https() ) {
     1911                return 'https:' . $relative_url;
     1912            } else {
     1913                return 'http:' . $relative_url;
     1914            }
     1915        }
     1916
     1917        /**
     1918         * Root-relative URLs | Handle root-relative URLs (e.g., "/some-page/").
     1919         *
     1920         * -------------------------------------------------------------------------------------------------------------
     1921         */
     1922        if ( str_starts_with( $relative_url, '/' ) ) {
     1923            return $base_parts['scheme'] . '://' . $base_parts['host'] . $relative_url;
     1924        }
     1925
     1926        /**
     1927         * Fragment identifier | Handle fragment-only URLs (e.g., "#section").
     1928         *
     1929         * -------------------------------------------------------------------------------------------------------------
     1930         */
     1931        if ( str_starts_with( $relative_url, '#' ) ) {
     1932            return $post_permalink . $relative_url;
     1933        }
     1934
     1935        /**
     1936         * Relative URLs with relative paths.
     1937         *
     1938         * Handles the relative URLs with relative paths like "./page", "../page", and "../../page'.
     1939         *
     1940         * Check if the relative URLs starts with "./", or "../", or subsequent levels like "../../".
     1941         * If it does, use the exact relative URL to retrieve and return the absolute URL.
     1942         *
     1943         * -------------------------------------------------------------------------------------------------------------
     1944         */
     1945
     1946        // This conditional supports all the levels like '../../', etc.
     1947        if ( str_starts_with( $relative_url, './' ) || str_starts_with( $relative_url, '../' ) ) {
     1948
     1949            /**
     1950             * Here, based on the type of relative URL, we move up one or more levels in the directory tree
     1951             * to create the correct absolute URL.
     1952             *
     1953             * Note that the URL on which we should move levels is stored in the $current_url variable.
     1954             */
     1955            $post_permalink_parts = wp_parse_url( $post_permalink );
     1956
     1957            // Ensure we have a valid base URL.
     1958            if ( ! isset( $post_permalink_parts['scheme'], $post_permalink_parts['host'], $post_permalink_parts['path'] ) ) {
     1959                return $relative_url; // Return as-is if current URL is invalid.
     1960            }
     1961
     1962            // Get the directory of the current URL.
     1963            $base_path = rtrim( $post_permalink_parts['path'], '/' );
     1964
     1965            // Split the base path into segments.
     1966            $base_parts = explode( '/', $base_path );
     1967
     1968            // Split the relative URL into segments.
     1969            $relative_parts = explode( '/', $relative_url );
     1970
     1971            // Process the relative path.
     1972            foreach ( $relative_parts as $part ) {
     1973                if ( '..' === $part ) {
     1974                    // Move up one directory level.
     1975                    if ( count( $base_parts ) > 1 ) {
     1976                        array_pop( $base_parts );
     1977                    }
     1978                } elseif ( '.' !== $part && '' !== $part ) {
     1979                    // Append valid segments.
     1980                    $base_parts[] = $part;
     1981                }
     1982            }
     1983
     1984            // If there is a trailing slash in the permalink add it to the $trailing_slash string.
     1985            $trailing_slash = str_ends_with( $relative_url, '/' ) ? '/' : '';
     1986
     1987            // Construct the final absolute URL and return it.
     1988            return $post_permalink_parts['scheme'] . '://' . $post_permalink_parts['host'] . implode( '/', $base_parts ) . $trailing_slash;
     1989
     1990        }
     1991
     1992        /**
     1993         * Page-relative URLs.
     1994         *
     1995         * Handle relative URLs without a leading slash (page-relative URLs like "example-post/").
     1996         */
     1997        $base_parts = wp_parse_url( $post_permalink );
     1998        return $base_parts['scheme'] . '://' . $base_parts['host'] . $base_parts['path'] . $relative_url;
     1999
     2000    }
     2001
     2002    /**
     2003     * A regex to match internal links. Specifically absolute internal links and relative internal links.
     2004     *
     2005     * @return string The regex to match manual and auto internal links.
     2006     */
     2007    public function internal_links_regex() {
     2008
     2009        /**
     2010         * Get the website URL and escape the regex character. # and
     2011         * whitespace ( used with the 'x' modifier ) are not escaped, thus
     2012         * should not be included in the $site_url string
     2013         */
     2014        $site_url = preg_quote( get_home_url(), '{' );
     2015
     2016        // Get the website URL without the protocol part.
     2017        $site_url_without_protocol_part = preg_quote( wp_parse_url( get_home_url(), PHP_URL_HOST ), '{' );
     2018
     2019        return '{<a                                                     #1 Begin the element a start-tag
     2020            [^>]+                                                       #2 Any character except > at least one time
     2021            href\s*=\s*                                                 #3 Equal may have whitespaces on both sides
     2022            ([\'"]?)                                                    #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
     2023            (                                                           #5 Capture group for both full and relative URLs
     2024                (?:' . $site_url . '[^\'">\s]*)                         #5a Match full URL starting with $site_url ( captured )
     2025                |                                                       # OR
     2026                (?!//)(?:\/|\.{1,2}\/)[^\'">\s]*                        #5b Match relative URLs (must start with /, ./, or ../) ( captured )
     2027                            |                                           # OR
     2028                \#[^\'">\s]*                                            #5c Match fragment-only URLs (e.g., #section2) ( captured )
     2029                            |                                           # OR
     2030                (?!//)[^\'"\s<>:]+                                      #5d Match page-relative URLs (must not contain "://") (captured)
     2031                |                                                       # OR
     2032                (?://' . $site_url_without_protocol_part . '[^\'">\s]*) #5e Match protocol-relative URLs with $site_url_without_protocol_part (captured)
     2033            )   
     2034            \1                                                          #6 Backreference that matches the href value delimiter matched at line 4
     2035            [^>]*                                                       #7 Any character except > zero or more times
     2036            >                                                           #8 End of the start-tag
     2037            (.*?)                                                       #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
     2038            <\/a\s*>                                                    #10 Element a end-tag with optional white-spaces characters before the >
     2039            }ix';
     2040    }
     2041
     2042    /**
     2043     * A regex to match any link (internal links, external links, and relative links).
     2044     *
     2045     * @return string The regex to match manual and auto internal links.
     2046     */
     2047    public function links_regex() {
     2048
     2049        return '{<a                             #1 Begin the element a start-tag
     2050            [^>]+                               #2 Any character except > at least one time
     2051            href\s*=\s*                         #3 Equal may have whitespaces on both sides
     2052            ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
     2053            [^\'">\s]+                          #5 The site URL
     2054            \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
     2055            [^>]*                               #7 Any character except > zero or more times
     2056            >                                   #8 End of the start-tag
     2057            .*?                                 #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
     2058            <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
     2059            }ix';
     2060
     2061    }
     2062
     2063    /**
     2064     * Checks if the WordPress site URL is using the HTTPS protocol.
     2065     *
     2066     * @return bool Returns true if the site URL starts with https:// (i.e., the site is using HTTPS). false if the site
     2067     * URL does not start with https:// (i.e., the site is using HTTP).
     2068     */
     2069    public function is_site_using_https() {
     2070
     2071        $site_url = get_option( 'siteurl' );
     2072
     2073        return ( str_starts_with( $site_url, 'https://' ) );
     2074    }
     2075
    19132076}
  • daext-interlinks-manager/trunk/init.php

    r3197491 r3259677  
    33 * Plugin Name: Interlinks Manager
    44 * Description: Manages the internal links of your WordPress website. (Lite Version)
    5  * Version: 1.14
     5 * Version: 1.15
    66 * Author: DAEXT
    77 * Author URI: https://daext.com
  • daext-interlinks-manager/trunk/readme.txt

    r3197491 r3259677  
    44Donate link: https://daext.com
    55Requires at least: 4.6
    6 Tested up to: 6.7.1
     6Tested up to: 6.7.2
    77Requires PHP: 5.3
    8 Stable tag: 1.14
     8Stable tag: 1.15
    99License: GPLv3
    1010
     
    119119
    120120== Changelog ==
     121
     122= 1.15 =
     123
     124*Mar 21, 2025*
     125
     126* The internal link analysis now detects relative URLs.
    121127
    122128= 1.14 =
  • daext-interlinks-manager/trunk/shared/class-daextinma-shared.php

    r3197491 r3259677  
    3333
    3434        $this->data['slug'] = 'daextinma';
    35         $this->data['ver']  = '1.14';
     35        $this->data['ver']  = '1.15';
    3636        $this->data['dir']  = substr( plugin_dir_path( __FILE__ ), 0, -7 );
    3737        $this->data['url']  = substr( plugin_dir_url( __FILE__ ), 0, -7 );
     
    122122        $text = $this->remove_script_tags( $text );
    123123
    124         /*
    125          * Get the website url and escape the regex character. # and
    126          * whitespace ( used with the 'x' modifier ) are not escaped, thus
    127          * should not be included in the $site_url string
    128          */
    129         $site_url = preg_quote( get_home_url() );
    130 
    131124        // Working regex.
    132125        $num_matches = preg_match_all(
    133             '{
    134             <a                      #1 Match the element a start-tag
    135             [^>]+                   #2 Match everything except > for at least one time
    136             href\s*=\s*             #3 Equal may have whitespaces on both sides
    137             ([\'"]?)                #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    138             ' . $site_url . '       #5 The site URL ( Scheme and Domain )
    139             [^\'">\s]+              #6 The rest of the URL ( Path and/or File )
    140             (\1)                    #7 Backreference that matches the href value delimiter matched at line 4
    141             [^>]*                   #8 Any character except > zero or more times
    142             >                       #9 End of the start-tag
    143             .*?                     #10 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    144             <\/a\s*>                #11 Element a end-tag with optional white-spaces characters before the >
    145             }ix',
     126            $this->internal_links_regex(),
    146127            $text,
    147128            $matches
     
    331312
    332313        $num_matches = preg_match_all(
    333             '{<a                                #1 Begin the element a start-tag
    334             [^>]+                               #2 Any character except > at least one time
    335             href\s*=\s*                         #3 Equal may have whitespaces on both sides
    336             ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    337             [^\'">\s]+                          #5 The site URL
    338             \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
    339             [^>]*                               #7 Any character except > zero or more times
    340             >                                   #8 End of the start-tag
    341             .*?                                 #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    342             <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
    343             }ix',
     314            $this->links_regex(),
    344315            $s,
    345316            $matches
     
    15851556
    15861557            /**
    1587              * Get the website url and quote and escape the regex character. # and
    1588              * whitespace ( used with the 'x' modifier ) are not escaped, thus
    1589              * should not be included in the $site_url string.
    1590              */
    1591             $site_url = preg_quote( get_home_url(), '/' );
    1592 
    1593             /**
    15941558             * Find all the manual and auto interlinks matches with a regular
    15951559             * expression and add them in the $juice_a array.
    15961560             */
    15971561            preg_match_all(
    1598                 '{<a                                #1 Begin the element a start-tag
    1599                 [^>]+                               #2 Any character except > at least one time
    1600                 href\s*=\s*                         #3 Equal may have whitespaces on both sides
    1601                 ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
    1602                 (' . $site_url . '[^\'">\s]* )      #5 The site URL ( Scheme and Domain ) and the rest of the URL ( Path and/or File ) ( captured )
    1603                 \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
    1604                 [^>]*                               #7 Any character except > zero or more times
    1605                 >                                   #8 End of the start-tag
    1606                 (.*?)                               #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
    1607                 <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
    1608                 }ix',
     1562                $this->internal_links_regex(),
    16091563                $post_content,
    16101564                $matches,
     
    16201574
    16211575                // save the captured URL.
    1622                 $url = $single_capture[0];
     1576                $url = $this->relative_to_absolute_url( $single_capture[0], $single_post['ID'] );
    16231577
    16241578                /**
     
    19111865    }
    19121866
     1867    /**
     1868     * Converts relative URLs to absolute URLs.
     1869     *
     1870     * The following type of URLs are supported:
     1871     *
     1872     * - Absolute URLs | E.g., "https://example.com/post/"
     1873     * - Protocol-relative URLs | E.g., "//localhost/image.jpg".
     1874     * - Root-relative URLs | E.g., "/post/".
     1875     * - Fragment-only URLs | E.g., "#section1".
     1876     * - Relative URLs with relative paths. | E.g., "./post/", "../post", "../../post".
     1877     * - Page-relative URLs | E.g., "post/".
     1878     *
     1879     * @param String $relative_url The relative URL that should be converted.
     1880     * @param Int $post_id The ID of the post.
     1881     *
     1882     * @return mixed|string
     1883     */
     1884    public function relative_to_absolute_url( $relative_url, $post_id ) {
     1885
     1886        $post_permalink = get_permalink( $post_id );
     1887
     1888        /**
     1889         * If already an absolute URL, return as is.
     1890         *
     1891         * -------------------------------------------------------------------------------------------------------------
     1892         */
     1893        if ( empty( $relative_url ) || wp_parse_url( $relative_url, PHP_URL_SCHEME ) ) {
     1894            return $relative_url;
     1895        }
     1896
     1897        // Get the site URL. Ensure trailing slash for proper resolution.
     1898        $base_url = home_url( '/' );
     1899
     1900        // Parse base URL.
     1901        $base_parts = wp_parse_url( $base_url );
     1902
     1903        /**
     1904         * Protocol-relative URL | If it's a protocol-relative URL (e.g., //example.com/image.jpg), add "https:" as
     1905         * default.
     1906         *
     1907         * -------------------------------------------------------------------------------------------------------------
     1908         */
     1909        if ( str_starts_with( $relative_url, '//' ) ) {
     1910            if ( $this->is_site_using_https() ) {
     1911                return 'https:' . $relative_url;
     1912            } else {
     1913                return 'http:' . $relative_url;
     1914            }
     1915        }
     1916
     1917        /**
     1918         * Root-relative URLs | Handle root-relative URLs (e.g., "/some-page/").
     1919         *
     1920         * -------------------------------------------------------------------------------------------------------------
     1921         */
     1922        if ( str_starts_with( $relative_url, '/' ) ) {
     1923            return $base_parts['scheme'] . '://' . $base_parts['host'] . $relative_url;
     1924        }
     1925
     1926        /**
     1927         * Fragment identifier | Handle fragment-only URLs (e.g., "#section").
     1928         *
     1929         * -------------------------------------------------------------------------------------------------------------
     1930         */
     1931        if ( str_starts_with( $relative_url, '#' ) ) {
     1932            return $post_permalink . $relative_url;
     1933        }
     1934
     1935        /**
     1936         * Relative URLs with relative paths.
     1937         *
     1938         * Handles the relative URLs with relative paths like "./page", "../page", and "../../page'.
     1939         *
     1940         * Check if the relative URLs starts with "./", or "../", or subsequent levels like "../../".
     1941         * If it does, use the exact relative URL to retrieve and return the absolute URL.
     1942         *
     1943         * -------------------------------------------------------------------------------------------------------------
     1944         */
     1945
     1946        // This conditional supports all the levels like '../../', etc.
     1947        if ( str_starts_with( $relative_url, './' ) || str_starts_with( $relative_url, '../' ) ) {
     1948
     1949            /**
     1950             * Here, based on the type of relative URL, we move up one or more levels in the directory tree
     1951             * to create the correct absolute URL.
     1952             *
     1953             * Note that the URL on which we should move levels is stored in the $current_url variable.
     1954             */
     1955            $post_permalink_parts = wp_parse_url( $post_permalink );
     1956
     1957            // Ensure we have a valid base URL.
     1958            if ( ! isset( $post_permalink_parts['scheme'], $post_permalink_parts['host'], $post_permalink_parts['path'] ) ) {
     1959                return $relative_url; // Return as-is if current URL is invalid.
     1960            }
     1961
     1962            // Get the directory of the current URL.
     1963            $base_path = rtrim( $post_permalink_parts['path'], '/' );
     1964
     1965            // Split the base path into segments.
     1966            $base_parts = explode( '/', $base_path );
     1967
     1968            // Split the relative URL into segments.
     1969            $relative_parts = explode( '/', $relative_url );
     1970
     1971            // Process the relative path.
     1972            foreach ( $relative_parts as $part ) {
     1973                if ( '..' === $part ) {
     1974                    // Move up one directory level.
     1975                    if ( count( $base_parts ) > 1 ) {
     1976                        array_pop( $base_parts );
     1977                    }
     1978                } elseif ( '.' !== $part && '' !== $part ) {
     1979                    // Append valid segments.
     1980                    $base_parts[] = $part;
     1981                }
     1982            }
     1983
     1984            // If there is a trailing slash in the permalink add it to the $trailing_slash string.
     1985            $trailing_slash = str_ends_with( $relative_url, '/' ) ? '/' : '';
     1986
     1987            // Construct the final absolute URL and return it.
     1988            return $post_permalink_parts['scheme'] . '://' . $post_permalink_parts['host'] . implode( '/', $base_parts ) . $trailing_slash;
     1989
     1990        }
     1991
     1992        /**
     1993         * Page-relative URLs.
     1994         *
     1995         * Handle relative URLs without a leading slash (page-relative URLs like "example-post/").
     1996         */
     1997        $base_parts = wp_parse_url( $post_permalink );
     1998        return $base_parts['scheme'] . '://' . $base_parts['host'] . $base_parts['path'] . $relative_url;
     1999
     2000    }
     2001
     2002    /**
     2003     * A regex to match internal links. Specifically absolute internal links and relative internal links.
     2004     *
     2005     * @return string The regex to match manual and auto internal links.
     2006     */
     2007    public function internal_links_regex() {
     2008
     2009        /**
     2010         * Get the website URL and escape the regex character. # and
     2011         * whitespace ( used with the 'x' modifier ) are not escaped, thus
     2012         * should not be included in the $site_url string
     2013         */
     2014        $site_url = preg_quote( get_home_url(), '{' );
     2015
     2016        // Get the website URL without the protocol part.
     2017        $site_url_without_protocol_part = preg_quote( wp_parse_url( get_home_url(), PHP_URL_HOST ), '{' );
     2018
     2019        return '{<a                                                     #1 Begin the element a start-tag
     2020            [^>]+                                                       #2 Any character except > at least one time
     2021            href\s*=\s*                                                 #3 Equal may have whitespaces on both sides
     2022            ([\'"]?)                                                    #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
     2023            (                                                           #5 Capture group for both full and relative URLs
     2024                (?:' . $site_url . '[^\'">\s]*)                         #5a Match full URL starting with $site_url ( captured )
     2025                |                                                       # OR
     2026                (?!//)(?:\/|\.{1,2}\/)[^\'">\s]*                        #5b Match relative URLs (must start with /, ./, or ../) ( captured )
     2027                            |                                           # OR
     2028                \#[^\'">\s]*                                            #5c Match fragment-only URLs (e.g., #section2) ( captured )
     2029                            |                                           # OR
     2030                (?!//)[^\'"\s<>:]+                                      #5d Match page-relative URLs (must not contain "://") (captured)
     2031                |                                                       # OR
     2032                (?://' . $site_url_without_protocol_part . '[^\'">\s]*) #5e Match protocol-relative URLs with $site_url_without_protocol_part (captured)
     2033            )   
     2034            \1                                                          #6 Backreference that matches the href value delimiter matched at line 4
     2035            [^>]*                                                       #7 Any character except > zero or more times
     2036            >                                                           #8 End of the start-tag
     2037            (.*?)                                                       #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
     2038            <\/a\s*>                                                    #10 Element a end-tag with optional white-spaces characters before the >
     2039            }ix';
     2040    }
     2041
     2042    /**
     2043     * A regex to match any link (internal links, external links, and relative links).
     2044     *
     2045     * @return string The regex to match manual and auto internal links.
     2046     */
     2047    public function links_regex() {
     2048
     2049        return '{<a                             #1 Begin the element a start-tag
     2050            [^>]+                               #2 Any character except > at least one time
     2051            href\s*=\s*                         #3 Equal may have whitespaces on both sides
     2052            ([\'"]?)                            #4 Match double quotes, single quote or no quote ( captured for the backreference \1 )
     2053            [^\'">\s]+                          #5 The site URL
     2054            \1                                  #6 Backreference that matches the href value delimiter matched at line 4     
     2055            [^>]*                               #7 Any character except > zero or more times
     2056            >                                   #8 End of the start-tag
     2057            .*?                                 #9 Link text or nested tags. After the dot ( enclose in parenthesis ) negative lookbehinds can be applied to avoid specific stuff inside the link text or nested tags. Example with single negative lookbehind (.(?<!word1))*? Example with multiple negative lookbehind (.(?<!word1)(?<!word2)(?<!word3))*?
     2058            <\/a\s*>                            #10 Element a end-tag with optional white-spaces characters before the >
     2059            }ix';
     2060
     2061    }
     2062
     2063    /**
     2064     * Checks if the WordPress site URL is using the HTTPS protocol.
     2065     *
     2066     * @return bool Returns true if the site URL starts with https:// (i.e., the site is using HTTPS). false if the site
     2067     * URL does not start with https:// (i.e., the site is using HTTP).
     2068     */
     2069    public function is_site_using_https() {
     2070
     2071        $site_url = get_option( 'siteurl' );
     2072
     2073        return ( str_starts_with( $site_url, 'https://' ) );
     2074    }
     2075
    19132076}
Note: See TracChangeset for help on using the changeset viewer.