*/ public static function shortcodes( string $content, string $base, string $source_key = '', bool $include_images = true ): array { if ( false === strpos( $content, '[' ) ) { return array(); } if ( ! preg_match_all( '/\[(?![\/\[])([a-zA-Z][a-zA-Z0-9_\-]*)(\s[^\]]*?)?\/?\]/', $content, $matches, PREG_SET_ORDER ) ) { return array(); } $found = array(); foreach ( $matches as $match ) { $tag = $match[1]; $atts_raw = isset( $match[2] ) ? trim( $match[2] ) : ''; if ( '' === $atts_raw ) { continue; } $atts = shortcode_parse_atts( $atts_raw ); if ( ! is_array( $atts ) ) { continue; } $anchor = ''; foreach ( self::TEXT_KEYS as $text_key ) { if ( isset( $atts[ $text_key ] ) && is_string( $atts[ $text_key ] ) && '' !== trim( $atts[ $text_key ] ) ) { $anchor = HtmlParser::squash( wp_strip_all_tags( $atts[ $text_key ] ) ); break; } } foreach ( $atts as $key => $value ) { if ( ! is_string( $key ) || ! is_string( $value ) || ! preg_match( self::SHORTCODE_KEY, $key ) || ! self::looks_like_url( $value ) ) { continue; } $element = self::is_image_key( $key ) ? 'img' : 'a'; if ( 'img' === $element && ! $include_images ) { continue; } $url = Url::normalize( $value, $base ); if ( null === $url ) { continue; } $found[] = array( 'url' => $url, 'element' => $element, 'anchor_text' => HtmlParser::truncate( $anchor, 255 ), 'context' => '[' . $tag . ' ' . $key . ']', 'source_key' => $source_key, ); } } return $found; } /** * Block attribute pass over serialized blocks. * * @param string $content Post content. * @param string $base Base URL. * @param string $source_key Source key. * @param bool $include_images Include image URLs. * @return array */ public static function blocks( string $content, string $base, string $source_key = '', bool $include_images = true ): array { if ( false === strpos( $content, '