Evaluates the reference path passed to a directive based on the current store namespace, state and context.
Parameters
$entryarrayrequired- An array containing a whole directive entry with its namespace, value, suffix, or unique ID.
Source
private function evaluate( $entry ) {
$context = end( $this->context_stack );
['namespace' => $ns, 'value' => $path] = $entry;
if ( ! $ns || ! $path ) {
/* translators: %s: The directive value referenced. */
$message = sprintf( __( 'Namespace or reference path cannot be empty. Directive value referenced: %s' ), json_encode( $entry ) );
_doing_it_wrong( __METHOD__, $message, '6.6.0' );
return null;
}
$store = array(
'state' => $this->state_data[ $ns ] ?? array(),
'context' => $context[ $ns ] ?? array(),
);
// Checks if the reference path is preceded by a negation operator (!).
$should_negate_value = '!' === $path[0];
$path = $should_negate_value ? substr( $path, 1 ) : $path;
// Extracts the value from the store using the reference path.
$path_segments = explode( '.', $path );
$current = $store;
foreach ( $path_segments as $index => $path_segment ) {
/*
* Special case for numeric arrays and strings. Add length
* property mimicking JavaScript behavior.
*
* @since 6.8.0
*/
if ( 'length' === $path_segment ) {
if ( is_array( $current ) && array_is_list( $current ) ) {
$current = count( $current );
break;
}
if ( is_string( $current ) ) {
/*
* Differences in encoding between PHP strings and
* JavaScript mean that it's complicated to calculate
* the string length JavaScript would see from PHP.
* `strlen` is a reasonable approximation.
*
* Users that desire a more precise length likely have
* more precise needs than "bytelength" and should
* implement their own length calculation in derived
* state taking into account encoding and their desired
* output (codepoints, graphemes, bytes, etc.).
*/
$current = strlen( $current );
break;
}
}
if ( ( is_array( $current ) || $current instanceof ArrayAccess ) && isset( $current[ $path_segment ] ) ) {
$current = $current[ $path_segment ];
} elseif ( is_object( $current ) && isset( $current->$path_segment ) ) {
$current = $current->$path_segment;
} else {
$current = null;
break;
}
if ( $current instanceof Closure ) {
/*
* This state getter's namespace is added to the stack so that
* `state()` or `get_config()` read that namespace when called
* without specifying one.
*/
array_push( $this->namespace_stack, $ns );
try {
$current = $current();
/*
* Tracks derived state properties that are accessed during
* rendering.
*
* @since 6.9.0
*/
$this->derived_state_closures[ $ns ] = $this->derived_state_closures[ $ns ] ?? array();
// Builds path for the current property and add it to tracking if not already present.
$current_path = implode( '.', array_slice( $path_segments, 0, $index + 1 ) );
if ( ! in_array( $current_path, $this->derived_state_closures[ $ns ], true ) ) {
$this->derived_state_closures[ $ns ][] = $current_path;
}
} catch ( Throwable $e ) {
_doing_it_wrong(
__METHOD__,
sprintf(
/* translators: 1: Path pointing to an Interactivity API state property, 2: Namespace for an Interactivity API store. */
__( 'Uncaught error executing a derived state callback with path "%1$s" and namespace "%2$s".' ),
$path,
$ns
),
'6.6.0'
);
return null;
} finally {
// Remove the property's namespace from the stack.
array_pop( $this->namespace_stack );
}
}
}
// Returns the opposite if it contains a negation operator (!).
return $should_negate_value ? ! $current : $current;
}
User Contributed Notes
You must log in before being able to contribute a note or feedback.