Edit File by line

Deprecated: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in /home/sportsfever/public_html/filemanger/function.php on line 93
/home/sportsfe.../public_h.../wp-inclu.../interact...
File: class-wp-interactivity-api.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* Interactivity API: WP_Interactivity_API class.
[2] Fix | Delete
*
[3] Fix | Delete
* @package WordPress
[4] Fix | Delete
* @subpackage Interactivity API
[5] Fix | Delete
* @since 6.5.0
[6] Fix | Delete
*/
[7] Fix | Delete
[8] Fix | Delete
/**
[9] Fix | Delete
* Class used to process the Interactivity API on the server.
[10] Fix | Delete
*
[11] Fix | Delete
* @since 6.5.0
[12] Fix | Delete
*/
[13] Fix | Delete
final class WP_Interactivity_API {
[14] Fix | Delete
/**
[15] Fix | Delete
* Holds the mapping of directive attribute names to their processor methods.
[16] Fix | Delete
*
[17] Fix | Delete
* @since 6.5.0
[18] Fix | Delete
* @var array
[19] Fix | Delete
*/
[20] Fix | Delete
private static $directive_processors = array(
[21] Fix | Delete
'data-wp-interactive' => 'data_wp_interactive_processor',
[22] Fix | Delete
'data-wp-router-region' => 'data_wp_router_region_processor',
[23] Fix | Delete
'data-wp-context' => 'data_wp_context_processor',
[24] Fix | Delete
'data-wp-bind' => 'data_wp_bind_processor',
[25] Fix | Delete
'data-wp-class' => 'data_wp_class_processor',
[26] Fix | Delete
'data-wp-style' => 'data_wp_style_processor',
[27] Fix | Delete
'data-wp-text' => 'data_wp_text_processor',
[28] Fix | Delete
/*
[29] Fix | Delete
* `data-wp-each` needs to be processed in the last place because it moves
[30] Fix | Delete
* the cursor to the end of the processed items to prevent them to be
[31] Fix | Delete
* processed twice.
[32] Fix | Delete
*/
[33] Fix | Delete
'data-wp-each' => 'data_wp_each_processor',
[34] Fix | Delete
);
[35] Fix | Delete
[36] Fix | Delete
/**
[37] Fix | Delete
* Holds the initial state of the different Interactivity API stores.
[38] Fix | Delete
*
[39] Fix | Delete
* This state is used during the server directive processing. Then, it is
[40] Fix | Delete
* serialized and sent to the client as part of the interactivity data to be
[41] Fix | Delete
* recovered during the hydration of the client interactivity stores.
[42] Fix | Delete
*
[43] Fix | Delete
* @since 6.5.0
[44] Fix | Delete
* @var array
[45] Fix | Delete
*/
[46] Fix | Delete
private $state_data = array();
[47] Fix | Delete
[48] Fix | Delete
/**
[49] Fix | Delete
* Holds the configuration required by the different Interactivity API stores.
[50] Fix | Delete
*
[51] Fix | Delete
* This configuration is serialized and sent to the client as part of the
[52] Fix | Delete
* interactivity data and can be accessed by the client interactivity stores.
[53] Fix | Delete
*
[54] Fix | Delete
* @since 6.5.0
[55] Fix | Delete
* @var array
[56] Fix | Delete
*/
[57] Fix | Delete
private $config_data = array();
[58] Fix | Delete
[59] Fix | Delete
/**
[60] Fix | Delete
* Flag that indicates whether the `data-wp-router-region` directive has
[61] Fix | Delete
* been found in the HTML and processed.
[62] Fix | Delete
*
[63] Fix | Delete
* The value is saved in a private property of the WP_Interactivity_API
[64] Fix | Delete
* instance instead of using a static variable inside the processor
[65] Fix | Delete
* function, which would hold the same value for all instances
[66] Fix | Delete
* independently of whether they have processed any
[67] Fix | Delete
* `data-wp-router-region` directive or not.
[68] Fix | Delete
*
[69] Fix | Delete
* @since 6.5.0
[70] Fix | Delete
* @var bool
[71] Fix | Delete
*/
[72] Fix | Delete
private $has_processed_router_region = false;
[73] Fix | Delete
[74] Fix | Delete
/**
[75] Fix | Delete
* Stack of namespaces defined by `data-wp-interactive` directives, in
[76] Fix | Delete
* the order they are processed.
[77] Fix | Delete
*
[78] Fix | Delete
* This is only available during directive processing, otherwise it is `null`.
[79] Fix | Delete
*
[80] Fix | Delete
* @since 6.6.0
[81] Fix | Delete
* @var array<string>|null
[82] Fix | Delete
*/
[83] Fix | Delete
private $namespace_stack = null;
[84] Fix | Delete
[85] Fix | Delete
/**
[86] Fix | Delete
* Stack of contexts defined by `data-wp-context` directives, in
[87] Fix | Delete
* the order they are processed.
[88] Fix | Delete
*
[89] Fix | Delete
* This is only available during directive processing, otherwise it is `null`.
[90] Fix | Delete
*
[91] Fix | Delete
* @since 6.6.0
[92] Fix | Delete
* @var array<array<mixed>>|null
[93] Fix | Delete
*/
[94] Fix | Delete
private $context_stack = null;
[95] Fix | Delete
[96] Fix | Delete
/**
[97] Fix | Delete
* Gets and/or sets the initial state of an Interactivity API store for a
[98] Fix | Delete
* given namespace.
[99] Fix | Delete
*
[100] Fix | Delete
* If state for that store namespace already exists, it merges the new
[101] Fix | Delete
* provided state with the existing one.
[102] Fix | Delete
*
[103] Fix | Delete
* When no namespace is specified, it returns the state defined for the
[104] Fix | Delete
* current value in the internal namespace stack during a `process_directives` call.
[105] Fix | Delete
*
[106] Fix | Delete
* @since 6.5.0
[107] Fix | Delete
* @since 6.6.0 The `$store_namespace` param is optional.
[108] Fix | Delete
*
[109] Fix | Delete
* @param string $store_namespace Optional. The unique store namespace identifier.
[110] Fix | Delete
* @param array $state Optional. The array that will be merged with the existing state for the specified
[111] Fix | Delete
* store namespace.
[112] Fix | Delete
* @return array The current state for the specified store namespace. This will be the updated state if a $state
[113] Fix | Delete
* argument was provided.
[114] Fix | Delete
*/
[115] Fix | Delete
public function state( ?string $store_namespace = null, ?array $state = null ): array {
[116] Fix | Delete
if ( ! $store_namespace ) {
[117] Fix | Delete
if ( $state ) {
[118] Fix | Delete
_doing_it_wrong(
[119] Fix | Delete
__METHOD__,
[120] Fix | Delete
__( 'The namespace is required when state data is passed.' ),
[121] Fix | Delete
'6.6.0'
[122] Fix | Delete
);
[123] Fix | Delete
return array();
[124] Fix | Delete
}
[125] Fix | Delete
if ( null !== $store_namespace ) {
[126] Fix | Delete
_doing_it_wrong(
[127] Fix | Delete
__METHOD__,
[128] Fix | Delete
__( 'The namespace should be a non-empty string.' ),
[129] Fix | Delete
'6.6.0'
[130] Fix | Delete
);
[131] Fix | Delete
return array();
[132] Fix | Delete
}
[133] Fix | Delete
if ( null === $this->namespace_stack ) {
[134] Fix | Delete
_doing_it_wrong(
[135] Fix | Delete
__METHOD__,
[136] Fix | Delete
__( 'The namespace can only be omitted during directive processing.' ),
[137] Fix | Delete
'6.6.0'
[138] Fix | Delete
);
[139] Fix | Delete
return array();
[140] Fix | Delete
}
[141] Fix | Delete
[142] Fix | Delete
$store_namespace = end( $this->namespace_stack );
[143] Fix | Delete
}
[144] Fix | Delete
if ( ! isset( $this->state_data[ $store_namespace ] ) ) {
[145] Fix | Delete
$this->state_data[ $store_namespace ] = array();
[146] Fix | Delete
}
[147] Fix | Delete
if ( is_array( $state ) ) {
[148] Fix | Delete
$this->state_data[ $store_namespace ] = array_replace_recursive(
[149] Fix | Delete
$this->state_data[ $store_namespace ],
[150] Fix | Delete
$state
[151] Fix | Delete
);
[152] Fix | Delete
}
[153] Fix | Delete
return $this->state_data[ $store_namespace ];
[154] Fix | Delete
}
[155] Fix | Delete
[156] Fix | Delete
/**
[157] Fix | Delete
* Gets and/or sets the configuration of the Interactivity API for a given
[158] Fix | Delete
* store namespace.
[159] Fix | Delete
*
[160] Fix | Delete
* If configuration for that store namespace exists, it merges the new
[161] Fix | Delete
* provided configuration with the existing one.
[162] Fix | Delete
*
[163] Fix | Delete
* @since 6.5.0
[164] Fix | Delete
*
[165] Fix | Delete
* @param string $store_namespace The unique store namespace identifier.
[166] Fix | Delete
* @param array $config Optional. The array that will be merged with the existing configuration for the
[167] Fix | Delete
* specified store namespace.
[168] Fix | Delete
* @return array The configuration for the specified store namespace. This will be the updated configuration if a
[169] Fix | Delete
* $config argument was provided.
[170] Fix | Delete
*/
[171] Fix | Delete
public function config( string $store_namespace, array $config = array() ): array {
[172] Fix | Delete
if ( ! isset( $this->config_data[ $store_namespace ] ) ) {
[173] Fix | Delete
$this->config_data[ $store_namespace ] = array();
[174] Fix | Delete
}
[175] Fix | Delete
if ( is_array( $config ) ) {
[176] Fix | Delete
$this->config_data[ $store_namespace ] = array_replace_recursive(
[177] Fix | Delete
$this->config_data[ $store_namespace ],
[178] Fix | Delete
$config
[179] Fix | Delete
);
[180] Fix | Delete
}
[181] Fix | Delete
return $this->config_data[ $store_namespace ];
[182] Fix | Delete
}
[183] Fix | Delete
[184] Fix | Delete
/**
[185] Fix | Delete
* Prints the serialized client-side interactivity data.
[186] Fix | Delete
*
[187] Fix | Delete
* Encodes the config and initial state into JSON and prints them inside a
[188] Fix | Delete
* script tag of type "application/json". Once in the browser, the state will
[189] Fix | Delete
* be parsed and used to hydrate the client-side interactivity stores and the
[190] Fix | Delete
* configuration will be available using a `getConfig` utility.
[191] Fix | Delete
*
[192] Fix | Delete
* @since 6.5.0
[193] Fix | Delete
*/
[194] Fix | Delete
public function print_client_interactivity_data() {
[195] Fix | Delete
if ( empty( $this->state_data ) && empty( $this->config_data ) ) {
[196] Fix | Delete
return;
[197] Fix | Delete
}
[198] Fix | Delete
[199] Fix | Delete
$interactivity_data = array();
[200] Fix | Delete
[201] Fix | Delete
$config = array();
[202] Fix | Delete
foreach ( $this->config_data as $key => $value ) {
[203] Fix | Delete
if ( ! empty( $value ) ) {
[204] Fix | Delete
$config[ $key ] = $value;
[205] Fix | Delete
}
[206] Fix | Delete
}
[207] Fix | Delete
if ( ! empty( $config ) ) {
[208] Fix | Delete
$interactivity_data['config'] = $config;
[209] Fix | Delete
}
[210] Fix | Delete
[211] Fix | Delete
$state = array();
[212] Fix | Delete
foreach ( $this->state_data as $key => $value ) {
[213] Fix | Delete
if ( ! empty( $value ) ) {
[214] Fix | Delete
$state[ $key ] = $value;
[215] Fix | Delete
}
[216] Fix | Delete
}
[217] Fix | Delete
if ( ! empty( $state ) ) {
[218] Fix | Delete
$interactivity_data['state'] = $state;
[219] Fix | Delete
}
[220] Fix | Delete
[221] Fix | Delete
if ( ! empty( $interactivity_data ) ) {
[222] Fix | Delete
/*
[223] Fix | Delete
* This data will be printed as JSON inside a script tag like this:
[224] Fix | Delete
* <script type="application/json"></script>
[225] Fix | Delete
*
[226] Fix | Delete
* A script tag must be closed by a sequence beginning with `</`. It's impossible to
[227] Fix | Delete
* close a script tag without using `<`. We ensure that `<` is escaped and `/` can
[228] Fix | Delete
* remain unescaped, so `</script>` will be printed as `\u003C/script\u00E3`.
[229] Fix | Delete
*
[230] Fix | Delete
* - JSON_HEX_TAG: All < and > are converted to \u003C and \u003E.
[231] Fix | Delete
* - JSON_UNESCAPED_SLASHES: Don't escape /.
[232] Fix | Delete
*
[233] Fix | Delete
* If the page will use UTF-8 encoding, it's safe to print unescaped unicode:
[234] Fix | Delete
*
[235] Fix | Delete
* - JSON_UNESCAPED_UNICODE: Encode multibyte Unicode characters literally (instead of as `\uXXXX`).
[236] Fix | Delete
* - JSON_UNESCAPED_LINE_TERMINATORS: The line terminators are kept unescaped when
[237] Fix | Delete
* JSON_UNESCAPED_UNICODE is supplied. It uses the same behaviour as it was
[238] Fix | Delete
* before PHP 7.1 without this constant. Available as of PHP 7.1.0.
[239] Fix | Delete
*
[240] Fix | Delete
* The JSON specification requires encoding in UTF-8, so if the generated HTML page
[241] Fix | Delete
* is not encoded in UTF-8 then it's not safe to include those literals. They must
[242] Fix | Delete
* be escaped to avoid encoding issues.
[243] Fix | Delete
*
[244] Fix | Delete
* @see https://www.rfc-editor.org/rfc/rfc8259.html for details on encoding requirements.
[245] Fix | Delete
* @see https://www.php.net/manual/en/json.constants.php for details on these constants.
[246] Fix | Delete
* @see https://html.spec.whatwg.org/#script-data-state for details on script tag parsing.
[247] Fix | Delete
*/
[248] Fix | Delete
$json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS;
[249] Fix | Delete
if ( ! is_utf8_charset() ) {
[250] Fix | Delete
$json_encode_flags = JSON_HEX_TAG | JSON_UNESCAPED_SLASHES;
[251] Fix | Delete
}
[252] Fix | Delete
[253] Fix | Delete
wp_print_inline_script_tag(
[254] Fix | Delete
wp_json_encode(
[255] Fix | Delete
$interactivity_data,
[256] Fix | Delete
$json_encode_flags
[257] Fix | Delete
),
[258] Fix | Delete
array(
[259] Fix | Delete
'type' => 'application/json',
[260] Fix | Delete
'id' => 'wp-interactivity-data',
[261] Fix | Delete
)
[262] Fix | Delete
);
[263] Fix | Delete
}
[264] Fix | Delete
}
[265] Fix | Delete
[266] Fix | Delete
/**
[267] Fix | Delete
* Returns the latest value on the context stack with the passed namespace.
[268] Fix | Delete
*
[269] Fix | Delete
* When the namespace is omitted, it uses the current namespace on the
[270] Fix | Delete
* namespace stack during a `process_directives` call.
[271] Fix | Delete
*
[272] Fix | Delete
* @since 6.6.0
[273] Fix | Delete
*
[274] Fix | Delete
* @param string $store_namespace Optional. The unique store namespace identifier.
[275] Fix | Delete
*/
[276] Fix | Delete
public function get_context( ?string $store_namespace = null ): array {
[277] Fix | Delete
if ( null === $this->context_stack ) {
[278] Fix | Delete
_doing_it_wrong(
[279] Fix | Delete
__METHOD__,
[280] Fix | Delete
__( 'The context can only be read during directive processing.' ),
[281] Fix | Delete
'6.6.0'
[282] Fix | Delete
);
[283] Fix | Delete
return array();
[284] Fix | Delete
}
[285] Fix | Delete
[286] Fix | Delete
if ( ! $store_namespace ) {
[287] Fix | Delete
if ( null !== $store_namespace ) {
[288] Fix | Delete
_doing_it_wrong(
[289] Fix | Delete
__METHOD__,
[290] Fix | Delete
__( 'The namespace should be a non-empty string.' ),
[291] Fix | Delete
'6.6.0'
[292] Fix | Delete
);
[293] Fix | Delete
return array();
[294] Fix | Delete
}
[295] Fix | Delete
[296] Fix | Delete
$store_namespace = end( $this->namespace_stack );
[297] Fix | Delete
}
[298] Fix | Delete
[299] Fix | Delete
$context = end( $this->context_stack );
[300] Fix | Delete
[301] Fix | Delete
return ( $store_namespace && $context && isset( $context[ $store_namespace ] ) )
[302] Fix | Delete
? $context[ $store_namespace ]
[303] Fix | Delete
: array();
[304] Fix | Delete
}
[305] Fix | Delete
[306] Fix | Delete
/**
[307] Fix | Delete
* Registers the `@wordpress/interactivity` script modules.
[308] Fix | Delete
*
[309] Fix | Delete
* @since 6.5.0
[310] Fix | Delete
*/
[311] Fix | Delete
public function register_script_modules() {
[312] Fix | Delete
$suffix = wp_scripts_get_suffix();
[313] Fix | Delete
[314] Fix | Delete
wp_register_script_module(
[315] Fix | Delete
'@wordpress/interactivity',
[316] Fix | Delete
includes_url( "js/dist/interactivity$suffix.js" )
[317] Fix | Delete
);
[318] Fix | Delete
[319] Fix | Delete
wp_register_script_module(
[320] Fix | Delete
'@wordpress/interactivity-router',
[321] Fix | Delete
includes_url( "js/dist/interactivity-router$suffix.js" ),
[322] Fix | Delete
array( '@wordpress/interactivity' )
[323] Fix | Delete
);
[324] Fix | Delete
}
[325] Fix | Delete
[326] Fix | Delete
/**
[327] Fix | Delete
* Adds the necessary hooks for the Interactivity API.
[328] Fix | Delete
*
[329] Fix | Delete
* @since 6.5.0
[330] Fix | Delete
*/
[331] Fix | Delete
public function add_hooks() {
[332] Fix | Delete
add_action( 'wp_enqueue_scripts', array( $this, 'register_script_modules' ) );
[333] Fix | Delete
add_action( 'wp_footer', array( $this, 'print_client_interactivity_data' ) );
[334] Fix | Delete
[335] Fix | Delete
add_action( 'admin_enqueue_scripts', array( $this, 'register_script_modules' ) );
[336] Fix | Delete
add_action( 'admin_print_footer_scripts', array( $this, 'print_client_interactivity_data' ) );
[337] Fix | Delete
}
[338] Fix | Delete
[339] Fix | Delete
/**
[340] Fix | Delete
* Processes the interactivity directives contained within the HTML content
[341] Fix | Delete
* and updates the markup accordingly.
[342] Fix | Delete
*
[343] Fix | Delete
* @since 6.5.0
[344] Fix | Delete
*
[345] Fix | Delete
* @param string $html The HTML content to process.
[346] Fix | Delete
* @return string The processed HTML content. It returns the original content when the HTML contains unbalanced tags.
[347] Fix | Delete
*/
[348] Fix | Delete
public function process_directives( string $html ): string {
[349] Fix | Delete
if ( ! str_contains( $html, 'data-wp-' ) ) {
[350] Fix | Delete
return $html;
[351] Fix | Delete
}
[352] Fix | Delete
[353] Fix | Delete
$this->namespace_stack = array();
[354] Fix | Delete
$this->context_stack = array();
[355] Fix | Delete
[356] Fix | Delete
$result = $this->_process_directives( $html );
[357] Fix | Delete
[358] Fix | Delete
$this->namespace_stack = null;
[359] Fix | Delete
$this->context_stack = null;
[360] Fix | Delete
[361] Fix | Delete
return null === $result ? $html : $result;
[362] Fix | Delete
}
[363] Fix | Delete
[364] Fix | Delete
/**
[365] Fix | Delete
* Processes the interactivity directives contained within the HTML content
[366] Fix | Delete
* and updates the markup accordingly.
[367] Fix | Delete
*
[368] Fix | Delete
* It uses the WP_Interactivity_API instance's context and namespace stacks,
[369] Fix | Delete
* which are shared between all calls.
[370] Fix | Delete
*
[371] Fix | Delete
* This method returns null if the HTML contains unbalanced tags.
[372] Fix | Delete
*
[373] Fix | Delete
* @since 6.6.0
[374] Fix | Delete
*
[375] Fix | Delete
* @param string $html The HTML content to process.
[376] Fix | Delete
* @return string|null The processed HTML content. It returns null when the HTML contains unbalanced tags.
[377] Fix | Delete
*/
[378] Fix | Delete
private function _process_directives( string $html ) {
[379] Fix | Delete
$p = new WP_Interactivity_API_Directives_Processor( $html );
[380] Fix | Delete
$tag_stack = array();
[381] Fix | Delete
$unbalanced = false;
[382] Fix | Delete
[383] Fix | Delete
$directive_processor_prefixes = array_keys( self::$directive_processors );
[384] Fix | Delete
$directive_processor_prefixes_reversed = array_reverse( $directive_processor_prefixes );
[385] Fix | Delete
[386] Fix | Delete
/*
[387] Fix | Delete
* Save the current size for each stack to restore them in case
[388] Fix | Delete
* the processing finds unbalanced tags.
[389] Fix | Delete
*/
[390] Fix | Delete
$namespace_stack_size = count( $this->namespace_stack );
[391] Fix | Delete
$context_stack_size = count( $this->context_stack );
[392] Fix | Delete
[393] Fix | Delete
while ( $p->next_tag( array( 'tag_closers' => 'visit' ) ) ) {
[394] Fix | Delete
$tag_name = $p->get_tag();
[395] Fix | Delete
[396] Fix | Delete
/*
[397] Fix | Delete
* Directives inside SVG and MATH tags are not processed,
[398] Fix | Delete
* as they are not compatible with the Tag Processor yet.
[399] Fix | Delete
* We still process the rest of the HTML.
[400] Fix | Delete
*/
[401] Fix | Delete
if ( 'SVG' === $tag_name || 'MATH' === $tag_name ) {
[402] Fix | Delete
if ( $p->get_attribute_names_with_prefix( 'data-wp-' ) ) {
[403] Fix | Delete
/* translators: 1: SVG or MATH HTML tag, 2: Namespace of the interactive block. */
[404] Fix | Delete
$message = sprintf( __( 'Interactivity directives were detected on an incompatible %1$s tag when processing "%2$s". These directives will be ignored in the server side render.' ), $tag_name, end( $this->namespace_stack ) );
[405] Fix | Delete
_doing_it_wrong( __METHOD__, $message, '6.6.0' );
[406] Fix | Delete
}
[407] Fix | Delete
$p->skip_to_tag_closer();
[408] Fix | Delete
continue;
[409] Fix | Delete
}
[410] Fix | Delete
[411] Fix | Delete
if ( $p->is_tag_closer() ) {
[412] Fix | Delete
list( $opening_tag_name, $directives_prefixes ) = end( $tag_stack );
[413] Fix | Delete
[414] Fix | Delete
if ( 0 === count( $tag_stack ) || $opening_tag_name !== $tag_name ) {
[415] Fix | Delete
[416] Fix | Delete
/*
[417] Fix | Delete
* If the tag stack is empty or the matching opening tag is not the
[418] Fix | Delete
* same than the closing tag, it means the HTML is unbalanced and it
[419] Fix | Delete
* stops processing it.
[420] Fix | Delete
*/
[421] Fix | Delete
$unbalanced = true;
[422] Fix | Delete
break;
[423] Fix | Delete
} else {
[424] Fix | Delete
// Remove the last tag from the stack.
[425] Fix | Delete
array_pop( $tag_stack );
[426] Fix | Delete
}
[427] Fix | Delete
} else {
[428] Fix | Delete
if ( 0 !== count( $p->get_attribute_names_with_prefix( 'data-wp-each-child' ) ) ) {
[429] Fix | Delete
/*
[430] Fix | Delete
* If the tag has a `data-wp-each-child` directive, jump to its closer
[431] Fix | Delete
* tag because those tags have already been processed.
[432] Fix | Delete
*/
[433] Fix | Delete
$p->next_balanced_tag_closer_tag();
[434] Fix | Delete
continue;
[435] Fix | Delete
} else {
[436] Fix | Delete
$directives_prefixes = array();
[437] Fix | Delete
[438] Fix | Delete
// Checks if there is a server directive processor registered for each directive.
[439] Fix | Delete
foreach ( $p->get_attribute_names_with_prefix( 'data-wp-' ) as $attribute_name ) {
[440] Fix | Delete
list( $directive_prefix ) = $this->extract_prefix_and_suffix( $attribute_name );
[441] Fix | Delete
if ( array_key_exists( $directive_prefix, self::$directive_processors ) ) {
[442] Fix | Delete
$directives_prefixes[] = $directive_prefix;
[443] Fix | Delete
}
[444] Fix | Delete
}
[445] Fix | Delete
[446] Fix | Delete
/*
[447] Fix | Delete
* If this tag will visit its closer tag, it adds it to the tag stack
[448] Fix | Delete
* so it can process its closing tag and check for unbalanced tags.
[449] Fix | Delete
*/
[450] Fix | Delete
if ( $p->has_and_visits_its_closer_tag() ) {
[451] Fix | Delete
$tag_stack[] = array( $tag_name, $directives_prefixes );
[452] Fix | Delete
}
[453] Fix | Delete
}
[454] Fix | Delete
}
[455] Fix | Delete
/*
[456] Fix | Delete
* If the matching opener tag didn't have any directives, it can skip the
[457] Fix | Delete
* processing.
[458] Fix | Delete
*/
[459] Fix | Delete
if ( 0 === count( $directives_prefixes ) ) {
[460] Fix | Delete
continue;
[461] Fix | Delete
}
[462] Fix | Delete
[463] Fix | Delete
// Directive processing might be different depending on if it is entering the tag or exiting it.
[464] Fix | Delete
$modes = array(
[465] Fix | Delete
'enter' => ! $p->is_tag_closer(),
[466] Fix | Delete
'exit' => $p->is_tag_closer() || ! $p->has_and_visits_its_closer_tag(),
[467] Fix | Delete
);
[468] Fix | Delete
[469] Fix | Delete
foreach ( $modes as $mode => $should_run ) {
[470] Fix | Delete
if ( ! $should_run ) {
[471] Fix | Delete
continue;
[472] Fix | Delete
}
[473] Fix | Delete
[474] Fix | Delete
/*
[475] Fix | Delete
* Sorts the attributes by the order of the `directives_processor` array
[476] Fix | Delete
* and checks what directives are present in this element.
[477] Fix | Delete
*/
[478] Fix | Delete
$existing_directives_prefixes = array_intersect(
[479] Fix | Delete
'enter' === $mode ? $directive_processor_prefixes : $directive_processor_prefixes_reversed,
[480] Fix | Delete
$directives_prefixes
[481] Fix | Delete
);
[482] Fix | Delete
foreach ( $existing_directives_prefixes as $directive_prefix ) {
[483] Fix | Delete
$func = is_array( self::$directive_processors[ $directive_prefix ] )
[484] Fix | Delete
? self::$directive_processors[ $directive_prefix ]
[485] Fix | Delete
: array( $this, self::$directive_processors[ $directive_prefix ] );
[486] Fix | Delete
[487] Fix | Delete
call_user_func_array( $func, array( $p, $mode, &$tag_stack ) );
[488] Fix | Delete
}
[489] Fix | Delete
}
[490] Fix | Delete
}
[491] Fix | Delete
[492] Fix | Delete
if ( $unbalanced ) {
[493] Fix | Delete
// Reset the namespace and context stacks to their previous values.
[494] Fix | Delete
array_splice( $this->namespace_stack, $namespace_stack_size );
[495] Fix | Delete
array_splice( $this->context_stack, $context_stack_size );
[496] Fix | Delete
}
[497] Fix | Delete
[498] Fix | Delete
/*
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function