Skip to content

Commit e4798d3

Browse files
author
Felix Arntz
committed
Implement classes for view transition animations and allow registering additional animations.
1 parent eb89cfc commit e4798d3

4 files changed

Lines changed: 483 additions & 25 deletions

File tree

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
/**
3+
* Class 'WP_View_Transition_Animation_Registry'.
4+
*
5+
* @package WordPress
6+
* @subpackage View Transitions
7+
* @since 6.9.0
8+
*/
9+
10+
/**
11+
* Class representing a view transition animation registry.
12+
*
13+
* @since 6.9.0
14+
*/
15+
final class WP_View_Transition_Animation_Registry {
16+
17+
/**
18+
* Registered animation class instances, keyed by slug.
19+
*
20+
* @since 6.9.0
21+
* @var array<string, WP_View_Transition_Animation>
22+
*/
23+
private $registered_animations = array();
24+
25+
/**
26+
* Map of aliases to their animation slugs.
27+
*
28+
* Includes the animation slug itself to avoid unnecessary conditionals.
29+
*
30+
* @since 6.9.0
31+
* @var array<string, string>
32+
*/
33+
private $alias_map = array();
34+
35+
/**
36+
* Registers a view transition animation.
37+
*
38+
* @since 6.9.0
39+
*
40+
* @param string $slug Unique animation slug.
41+
* @param array<string, mixed> $config Animation configuration. See
42+
* {@see WP_View_Transition_Animation::__construct()} for possible
43+
* values.
44+
* @param array<string, mixed> $default_args Optional. Default animation arguments. Default empty array.
45+
* @return bool True on success, false on failure.
46+
*/
47+
public function register_animation( string $slug, array $config, array $default_args = array() ): bool {
48+
// Check slug conflict.
49+
if ( isset( $this->alias_map[ $slug ] ) ) {
50+
_doing_it_wrong(
51+
__METHOD__,
52+
sprintf(
53+
/* translators: %s: duplicate slug */
54+
__( 'The animation slug "%s" conflicts with an existing slug or alias.' ),
55+
esc_html( $slug )
56+
),
57+
'6.9.0'
58+
);
59+
return false;
60+
}
61+
62+
try {
63+
$animation = new WP_View_Transition_Animation( $slug, $config, $default_args );
64+
} catch ( InvalidArgumentException $e ) {
65+
_doing_it_wrong(
66+
__METHOD__,
67+
$e->getMessage(),
68+
'6.9.0'
69+
);
70+
return false;
71+
}
72+
73+
// Check alias conflicts.
74+
$aliases = $animation->get_aliases();
75+
foreach ( $aliases as $alias ) {
76+
if ( isset( $this->alias_map[ $alias ] ) ) {
77+
_doing_it_wrong(
78+
__METHOD__,
79+
sprintf(
80+
/* translators: %s: duplicate alias */
81+
__( 'The animation alias "%s" conflicts with an existing slug or alias.' ),
82+
esc_html( $alias )
83+
),
84+
'6.9.0'
85+
);
86+
return false;
87+
}
88+
}
89+
90+
$this->registered_animations[ $slug ] = $animation;
91+
$this->alias_map[ $slug ] = $slug;
92+
foreach ( $aliases as $alias ) {
93+
$this->alias_map[ $alias ] = $slug;
94+
}
95+
96+
return true;
97+
}
98+
99+
/**
100+
* Gets the animation stylesheet for the given alias, as inline CSS.
101+
*
102+
* @since 6.9.0
103+
*
104+
* @param string $alias Slug or alias to reference the animation with. May be used to alter the
105+
* animation's behavior.
106+
* @param array<string, mixed> $args Optional. Animation arguments. Default is the animation's default arguments.
107+
* @return string Animation stylesheet, as inline CSS, or empty string if none.
108+
*/
109+
public function get_animation_stylesheet( string $alias, array $args = array() ): string {
110+
if ( ! isset( $this->alias_map[ $alias ] ) ) {
111+
return '';
112+
}
113+
114+
return $this->registered_animations[ $this->alias_map[ $alias ] ]->get_stylesheet( $alias, $args );
115+
}
116+
117+
/**
118+
* Returns whether to apply the global view transition names for the given animation alias.
119+
*
120+
* @since 6.9.0
121+
*
122+
* @param string $alias Slug or alias for the animation.
123+
* @return bool True if the global view transition names should be applied, false otherwise.
124+
*/
125+
public function use_animation_global_transition_names( string $alias ): bool {
126+
if ( ! isset( $this->alias_map[ $alias ] ) ) {
127+
return true;
128+
}
129+
130+
return $this->registered_animations[ $this->alias_map[ $alias ] ]->use_global_transition_names();
131+
}
132+
133+
/**
134+
* Returns whether to apply the post specific view transition names for the given animation alias.
135+
*
136+
* @since 6.9.0
137+
*
138+
* @param string $alias Slug or alias for the animation.
139+
* @return bool True if the post specific view transition names should be applied, false otherwise.
140+
*/
141+
public function use_animation_post_transition_names( string $alias ): bool {
142+
if ( ! isset( $this->alias_map[ $alias ] ) ) {
143+
return true;
144+
}
145+
146+
return $this->registered_animations[ $this->alias_map[ $alias ] ]->use_post_transition_names();
147+
}
148+
}
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
<?php
2+
/**
3+
* Class 'WP_View_Transition_Animation'.
4+
*
5+
* @package WordPress
6+
* @subpackage View Transitions
7+
* @since 6.9.0
8+
*/
9+
10+
/**
11+
* Class representing a view transition animation.
12+
*
13+
* @since 6.9.0
14+
* @access private
15+
*/
16+
final class WP_View_Transition_Animation {
17+
18+
/**
19+
* The unique animation slug.
20+
*
21+
* @since 6.9.0
22+
* @var string
23+
*/
24+
private $slug;
25+
26+
/**
27+
* Unique aliases for the animation, if any.
28+
*
29+
* @since 6.9.0
30+
* @var string[]
31+
*/
32+
private $aliases = array();
33+
34+
/**
35+
* Whether the animation uses a stylesheet.
36+
*
37+
* If so, the stylesheet will be `/wp-includes/css/view-transitions-animation-{$slug}.css`.
38+
*
39+
* @since 6.9.0
40+
* @var bool
41+
*/
42+
private $use_stylesheet = false;
43+
44+
/**
45+
* Whether to apply the global view transition names while using this animation.
46+
*
47+
* @since 6.9.0
48+
* @var bool
49+
*/
50+
private $use_global_transition_names = true;
51+
52+
/**
53+
* Whether to apply the post specific view transition names while using this animation.
54+
*
55+
* @since 6.9.0
56+
* @var bool
57+
*/
58+
private $use_post_transition_names = true;
59+
60+
/**
61+
* Callback to get the stylesheet for the animation, as inline CSS.
62+
*
63+
* This can be used if the animation CSS requires further preparation other than simply loading its stylesheet from
64+
* the animation's corresponding CSS file.
65+
*
66+
* If the animation is configured with `$use_stylesheet = true`, the callback will receive the CSS from that file,
67+
* and the `$alias` and `$args` used as parameters. Otherwise, the callback will receive the `$alias` and `$args`
68+
* used as parameters.
69+
*
70+
* @since 6.9.0
71+
* @var callable|null
72+
*/
73+
private $get_stylesheet_callback = null;
74+
75+
/**
76+
* Default animation arguments.
77+
*
78+
* These are provided during registration, and they are used if no specific arguments are provided when using the
79+
* animation.
80+
*
81+
* @since 6.9.0
82+
* @var array<string, mixed>
83+
*/
84+
private $default_args = array();
85+
86+
/**
87+
* Constructor.
88+
*
89+
* @since 6.9.0
90+
*
91+
* @param string $slug Unique animation slug.
92+
* @param array<string, mixed> $config {
93+
* Animation configuration.
94+
*
95+
* @type string[] $aliases Unique aliases for the animation, if any. Default empty
96+
* array.
97+
* @type bool $use_stylesheet Whether the animation uses a stylesheet. Default false.
98+
* @type bool $use_global_transition_names Whether to apply the global view transition names while
99+
* using this animation. Default true.
100+
* @type bool $use_post_transition_names Whether to apply the post specific view transition names
101+
* while using this animation. Default true.
102+
* @type callable|null $get_stylesheet_callback Callback to get the stylesheet for the animation, as
103+
* inline CSS. This can be used if the animation CSS requires
104+
* further preparation other than simply loading its
105+
* stylesheet from the animation's corresponding CSS file.
106+
* Default null.
107+
* }
108+
* @param array<string, mixed> $default_args Optional. Default animation arguments. Default empty array.
109+
*
110+
* @throws InvalidArgumentException Thrown if the slug or an alias is invalid.
111+
*/
112+
public function __construct( string $slug, array $config, array $default_args = array() ) {
113+
if ( ! $this->is_valid_slug( $slug ) ) {
114+
throw new InvalidArgumentException(
115+
sprintf(
116+
/* translators: %s: invalid slug */
117+
__( 'The animation slug "%s" is invalid.' ),
118+
esc_html( $slug )
119+
)
120+
);
121+
}
122+
123+
$this->slug = $slug;
124+
125+
$this->apply_config( $config );
126+
127+
$this->default_args = $default_args;
128+
}
129+
130+
/**
131+
* Gets the unique animation slug.
132+
*
133+
* @since 6.9.0
134+
*
135+
* @return string Unique animation slug.
136+
*/
137+
public function get_slug(): string {
138+
return $this->slug;
139+
}
140+
141+
/**
142+
* Gets the unique aliases for the animation, if any.
143+
*
144+
* @since 6.9.0
145+
*
146+
* @return string[] Unique aliases for the animation, or empty array if none.
147+
*/
148+
public function get_aliases(): array {
149+
return $this->aliases;
150+
}
151+
152+
/**
153+
* Gets the animation stylesheet, as inline CSS.
154+
*
155+
* @since 6.9.0
156+
*
157+
* @param string $alias Optional. Slug or alias to reference the animation with. May be used to alter
158+
* the animation's behavior. Default is the animation's slug.
159+
* @param array<string, mixed> $args Optional. Animation arguments. Default is the animation's default arguments.
160+
* @return string Animation stylesheet, as inline CSS, or empty string if none.
161+
*/
162+
public function get_stylesheet( string $alias = '', array $args = array() ): string {
163+
if ( $this->use_stylesheet ) {
164+
$suffix = wp_scripts_get_suffix();
165+
$css = file_get_contents( ABSPATH . WPINC . "/css/view-transitions-animation-{$this->slug}{$suffix}.css" );
166+
}
167+
if ( is_callable( $this->get_stylesheet_callback ) ) {
168+
if ( ! $alias ) {
169+
$alias = $this->slug;
170+
}
171+
$args = wp_parse_args( $args, $this->default_args );
172+
return (string) call_user_func_array(
173+
$this->get_stylesheet_callback,
174+
isset( $css ) ? array( $css, $alias, $args ) : array( $alias, $args )
175+
);
176+
}
177+
return '';
178+
}
179+
180+
/**
181+
* Returns whether to apply the global view transition names while using this animation.
182+
*
183+
* @since 6.9.0
184+
*
185+
* @return bool True if the global view transition names should be applied, false otherwise.
186+
*/
187+
public function use_global_transition_names(): bool {
188+
return $this->use_global_transition_names;
189+
}
190+
191+
/**
192+
* Returns whether to apply the post specific view transition names while using this animation.
193+
*
194+
* @since 6.9.0
195+
*
196+
* @return bool True if the post specific view transition names should be applied, false otherwise.
197+
*/
198+
public function use_post_transition_names(): bool {
199+
return $this->use_post_transition_names;
200+
}
201+
202+
/**
203+
* Applies the given configuration to the class properties.
204+
*
205+
* @since 6.9.0
206+
*
207+
* @param array<string, mixed> $config Animation configuration. See
208+
* {@see WP_View_Transition_Animation::__construct()} for possible values.
209+
*/
210+
private function apply_config( array $config ): void {
211+
if ( isset( $config['aliases'] ) ) {
212+
$this->aliases = (array) $config['aliases'];
213+
foreach ( $this->aliases as $alias ) {
214+
if ( ! $this->is_valid_slug( $alias ) ) {
215+
throw new InvalidArgumentException(
216+
sprintf(
217+
/* translators: %s: invalid alias */
218+
__( 'The animation alias "%s" is invalid.' ),
219+
esc_html( $alias )
220+
)
221+
);
222+
}
223+
}
224+
}
225+
if ( isset( $config['use_stylesheet'] ) ) {
226+
$this->use_stylesheet = (bool) $config['use_stylesheet'];
227+
}
228+
if ( isset( $config['use_global_transition_names'] ) ) {
229+
$this->use_global_transition_names = (bool) $config['use_global_transition_names'];
230+
}
231+
if ( isset( $config['use_post_transition_names'] ) ) {
232+
$this->use_post_transition_names = (bool) $config['use_post_transition_names'];
233+
}
234+
if ( isset( $config['get_stylesheet_callback'] ) && is_callable( $config['get_stylesheet_callback'] ) ) {
235+
$this->get_stylesheet_callback = $config['get_stylesheet_callback'];
236+
}
237+
}
238+
239+
/**
240+
* Checks whether the given slug (or alias) is valid.
241+
*
242+
* @since 6.9.0
243+
*
244+
* @param string $slug Animation slug or alias.
245+
* @return bool True if the ID is valid, false otherwise.
246+
*/
247+
private function is_valid_slug( string $slug ): bool {
248+
return (bool) preg_match( '/^[a-z][a-z0-9_-]+$/', $slug );
249+
}
250+
}

0 commit comments

Comments
 (0)