Make WordPress Core

Ticket #31093: 31093.4.diff

File 31093.4.diff, 7.0 KB (added by birgire, 7 years ago)
  • src/wp-includes/shortcodes.php

    diff --git src/wp-includes/shortcodes.php src/wp-includes/shortcodes.php
    index c6df28b..ffee3e3 100644
    function shortcode_exists( $tag ) { 
    127127}
    128128
    129129/**
    130  * Whether the passed content contains the specified shortcode
     130 * Whether the passed content contains any or specified shortcode.
     131 * Can accept an array of shortcode tags.
    131132 *
    132133 * @since 3.6.0
    133134 *
    134135 * @global array $shortcode_tags
    135136 *
    136  * @param string $content Content to search for shortcodes.
    137  * @param string $tag     Shortcode tag to check.
    138  * @return bool Whether the passed content contains the given shortcode.
     137 * @param string       $content      Content to search for shortcodes.
     138 * @param array|string $tag          Optional. Shortcode tag to check. Default empty string.
     139 * @param string       $tag_relation Optional. When multiple shortcode tags are passed,
     140 *                                   comparison operator for final result. Default 'OR'.
     141 * @return bool        $return       Whether the passed content contains the given shortcodes.
    139142 */
    140 function has_shortcode( $content, $tag ) {
     143function has_shortcode( $content, $tag = '', $tag_relation = 'OR' ) {
    141144        if ( false === strpos( $content, '[' ) ) {
    142145                return false;
    143146        }
    144147
    145         if ( shortcode_exists( $tag ) ) {
    146                 preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
    147                 if ( empty( $matches ) )
    148                         return false;
     148        if ( empty( $tag ) ) {
     149                return strip_shortcodes( $content ) !== $content;
     150        }
     151
     152        preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER );
    149153
     154        if ( empty( $matches ) ) {
     155                return false;
     156        }
     157
     158        if ( is_array( $tag ) ) {
     159                $tag_relation = strtoupper( $tag_relation );
     160                if ( 'OR' === $tag_relation ) {
     161                        // Return true as soon as the first shortcode tag is found.
     162                        foreach ( $tag as $stag ) {
     163                                foreach ( $matches as $shortcode ) {
     164                                        if ( $stag === $shortcode[2] ) {
     165                                                return true;
     166                                        } elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $stag ) ) {
     167                                                return true;
     168                                        }
     169                                }
     170                        }
     171                } elseif ( 'AND' === $tag_relation ) {
     172                        // Collect existence of all shortcode tags.
     173                        $found_shortcode = array();
     174                        foreach ( $tag as $stag ) {
     175                                $found_shortcode[ $stag ] = false;
     176                                foreach ( $matches as $shortcode ) {
     177                                        if ( $stag === $shortcode[2] ) {
     178                                                $found_shortcode[ $stag ] = true;
     179                                        } elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $stag ) ) {
     180                                                $found_shortcode[ $stag ] = true;
     181                                        }
     182                                }
     183                        }
     184                        // return true if all are true, else false.
     185                        return count( array_unique( $found_shortcode ) ) === 1 && current( $found_shortcode );
     186                }
     187        } else {
    150188                foreach ( $matches as $shortcode ) {
    151189                        if ( $tag === $shortcode[2] ) {
    152190                                return true;
  • tests/phpunit/tests/shortcode.php

    diff --git tests/phpunit/tests/shortcode.php tests/phpunit/tests/shortcode.php
    index 08ef1ac..0343f79 100644
    EOF; 
    580580                $this->assertTrue( has_shortcode( $content_nested, 'gallery' ) );
    581581                remove_shortcode( 'foo' );
    582582        }
     583       
     584        /**
     585         * Tests if has_shortcode() detects any shortcode without tag input argument.
     586         *
     587         * @ticket 31093
     588         */
     589        public function test_has_shortcode_should_detect_any_shortcode_without_tag_input_argument() {
     590                // Empty.
     591                $content = '';
     592                $this->assertFalse( has_shortcode( $content ) );
     593
     594                // Single shortcode.
     595                $content = 'This is a blob with [gallery] in it';
     596                $this->assertTrue( has_shortcode( $content ) );
     597
     598                // Two shortcodes.
     599                $content = 'This is a blob with [gallery] and [playlist] in it';
     600                $this->assertTrue( has_shortcode( $content ) );
     601
     602                // Un-registered [foo] shortcode.
     603                $content = 'This is a blob with [foo] in it';
     604                $this->assertFalse( has_shortcode( $content ) );
     605
     606                // Nested shortcode.
     607                $content = 'This is a blob with [foo][gallery][/foo] in it';
     608                $this->assertTrue( has_shortcode( $content ) );
     609
     610                // Register [foo] shortcode.
     611                add_shortcode( 'foo', '__return_empty_string' );
     612                $this->assertTrue( has_shortcode( $content ) );
     613                remove_shortcode( 'foo' );
     614        }
     615
     616        /**
     617         * Tests if has_shortcode() detects any shortcode from a list of shortcodes.
     618         *
     619         * @ticket 31093
     620         */
     621        public function test_has_shortcode_should_detect_any_listed_shortcodes() {
     622                // Empty.
     623                $content = '';
     624                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'playlist' ) ) );
     625
     626                // Single shortcode.
     627                $content = 'This is a blob with [gallery] in it';
     628                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'playlist' ), 'OR' ) );
     629                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'playlist' ) ) );
     630
     631                // Two shortcodes.
     632                $content = 'This is a blob with [foo], [gallery] and [playlist] in it';
     633                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'playlist' ), 'OR' ) );
     634                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'video' ), 'OR' ) );
     635                $this->assertFalse( has_shortcode( $content, array( 'foo' ), 'OR' ) );
     636                $this->assertFalse( has_shortcode( $content, array( 'foo' ) ) );
     637
     638                // Nested shortcode.
     639                $content = 'This is a blob with [foo][gallery][/foo] in it';
     640                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'foo' ), 'OR' ) );
     641                $this->assertFalse( has_shortcode( $content, array( 'video' ), 'OR' ) );
     642
     643                // Register [foo] shortcode.
     644                add_shortcode( 'foo', '__return_empty_string' );
     645                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'foo' ), 'OR' ) );
     646                $this->assertFalse( has_shortcode( $content, array( 'video' ), 'OR' ) );
     647                remove_shortcode( 'foo' );
     648        }
     649
     650        /**
     651         * Tests if has_shortcode() detects all shortcodes from a list.
     652         *
     653         * @ticket 31093
     654         */
     655        public function test_has_shortcode_should_detect_all_listed_shortcodes() {
     656                // Empty.
     657                $content = '';
     658                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'playlist' ), 'AND' ) );
     659
     660                // Single shortcode.
     661                $content = 'This is a blob with [gallery] in it';
     662                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'playlist' ), 'AND' ) );
     663
     664                // Two shortcodes.
     665                $content = 'This is a blob with [gallery] and [playlist] in it';
     666                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'playlist' ), 'AND' ) );
     667                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'video' ), 'AND' ) );
     668
     669                // Non-existing [foo] shortcode.
     670                $content = 'This is a blob with [foo] in it';
     671                $this->assertFalse( has_shortcode( $content, array( 'foo' ), 'AND' ) );
     672
     673                // Nested shortcode.
     674                $content = 'This is a blob with [foo][gallery][/foo] in it';
     675                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'foo' ), 'AND' ) );
     676                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'video' ), 'AND' ) );
     677
     678                // Register [foo] shortcode.
     679                add_shortcode( 'foo', '__return_empty_string' );
     680                $this->assertTrue( has_shortcode( $content, array( 'gallery', 'foo' ), 'AND' ) );
     681                $this->assertFalse( has_shortcode( $content, array( 'gallery', 'video' ), 'AND' ) );
     682                remove_shortcode( 'foo' );
     683        }
    583684
    584685        /**
    585686         * Make sure invalid shortcode names are not allowed.