Make WordPress Core

Changeset 58869


Ignore:
Timestamp:
08/08/2024 11:28:30 AM (4 months ago)
Author:
luisherranz
Message:

Interactivity API: Allow server derived state to appear in non-final position

In some cases, derived state returns an associative array. Directives may wish to continue to access properties of the associative array, when using the syntax state.arrayReturnedByClosure.property. This patch continues evaluating the path after the associative array has been returned by the Closure.

Reviewed by adamsilverstein and gziolo.
Merges [58825] to the 6.6 branch.

Props jonsurrell, luisherranz, adamsilverstein, gziolo.

Fixes #61741.

Location:
branches/6.6
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/6.6

  • branches/6.6/src/wp-includes/interactivity-api/class-wp-interactivity-api.php

    r58327 r58869  
    522522     * @since 6.6.0 The function now adds a warning when the namespace is null, falsy, or the directive value is empty.
    523523     * @since 6.6.0 Removed `default_namespace` and `context` arguments.
     524     * @since 6.6.0 Add support for derived state.
    524525     *
    525526     * @param string|true $directive_value The directive attribute value string or `true` when it's a boolean attribute.
     
    558559                return null;
    559560            }
    560         }
    561 
    562         if ( $current instanceof Closure ) {
    563             /*
    564              * This state getter's namespace is added to the stack so that
    565              * `state()` or `get_config()` read that namespace when called
    566              * without specifying one.
    567              */
    568             array_push( $this->namespace_stack, $ns );
    569             try {
    570                 $current = $current();
    571             } catch ( Throwable $e ) {
    572                 _doing_it_wrong(
    573                     __METHOD__,
    574                     sprintf(
    575                         /* translators: 1: Path pointing to an Interactivity API state property, 2: Namespace for an Interactivity API store. */
    576                         __( 'Uncaught error executing a derived state callback with path "%1$s" and namespace "%2$s".' ),
    577                         $path,
    578                         $ns
    579                     ),
    580                     '6.6.0'
    581                 );
    582                 return null;
    583             } finally {
    584                 // Remove the property's namespace from the stack.
    585                 array_pop( $this->namespace_stack );
     561
     562            if ( $current instanceof Closure ) {
     563                /*
     564                 * This state getter's namespace is added to the stack so that
     565                 * `state()` or `get_config()` read that namespace when called
     566                 * without specifying one.
     567                 */
     568                array_push( $this->namespace_stack, $ns );
     569                try {
     570                    $current = $current();
     571                } catch ( Throwable $e ) {
     572                    _doing_it_wrong(
     573                        __METHOD__,
     574                        sprintf(
     575                            /* translators: 1: Path pointing to an Interactivity API state property, 2: Namespace for an Interactivity API store. */
     576                            __( 'Uncaught error executing a derived state callback with path "%1$s" and namespace "%2$s".' ),
     577                            $path,
     578                            $ns
     579                        ),
     580                        '6.6.0'
     581                    );
     582                    return null;
     583                } finally {
     584                    // Remove the property's namespace from the stack.
     585                    array_pop( $this->namespace_stack );
     586                }
    586587            }
    587588        }
  • branches/6.6/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php

    r58327 r58869  
    14001400    }
    14011401
    1402 
    14031402    /**
    14041403     * Tests the `evaluate` method for derived state functions that throw.
     
    14231422        $result = $this->evaluate( 'state.derivedThatThrows' );
    14241423        $this->assertNull( $result );
     1424    }
     1425
     1426    /**
     1427     * Tests the `evaluate` method for derived state intermediate values.
     1428     *
     1429     * @ticket 61741
     1430     *
     1431     * @covers ::evaluate
     1432     */
     1433    public function test_evaluate_derived_state_intermediate() {
     1434        $this->interactivity->state(
     1435            'myPlugin',
     1436            array(
     1437                'derivedState' => function () {
     1438                    return array( 'property' => 'value' );
     1439                },
     1440            )
     1441        );
     1442        $this->set_internal_context_stack();
     1443        $this->set_internal_namespace_stack( 'myPlugin' );
     1444
     1445        $result = $this->evaluate( 'state.derivedState.property' );
     1446        $this->assertSame( 'value', $result );
    14251447    }
    14261448
Note: See TracChangeset for help on using the changeset viewer.