| @@ -14,8 +14,9 @@ | ||
| 14 | 14 | */ |
| 15 | 15 | private $block_attributes = [ |
| 16 | 16 | 'url' => [ |
| 17 | 17 | 'type' => 'string', |
| 18 | + 'default' => '', | |
| 18 | 19 | ], |
| 19 | 20 | 'primaryColor' => [ |
| 20 | 21 | 'type' => 'string', |
| 21 | 22 | 'default' => '#577BF9', |
| @@ -196,13 +197,13 @@ | ||
| 196 | 197 | * |
| 197 | 198 | * @since 4.0.0 |
| 198 | 199 | */ |
| 199 | 200 | public function render_video_player_block( $attributes, $content, $block ) { |
| 200 | - $attributes = wp_parse_args( $attributes, $this->block_attributes ); | |
| 201 | + $attributes = wp_parse_args( $attributes, $this->get_default_attributes() ); | |
| 201 | 202 | |
| 202 | 203 | $style = [ |
| 203 | 204 | '--om-primary-color' => $attributes['primaryColor'], |
| 204 | - '--om-aspect-ratio' => $attributes['aspectRatio'], | |
| 205 | + '--om-aspect-ratio' => $this->sanitize_aspect_ratio( $attributes['aspectRatio'] ), | |
| 205 | 206 | ]; |
| 206 | 207 | |
| 207 | 208 | if ( isset( $attributes['style'] ) ) { |
| 208 | 209 | $style = array_merge( $style, $this->block_style_attributes_to_css_array( $attributes['style'] ) ); |
| @@ -230,19 +231,12 @@ | ||
| 230 | 231 | array_keys( $tag_attributes ), |
| 231 | 232 | $tag_attributes |
| 232 | 233 | ); |
| 233 | 234 | |
| 234 | - $wrapper_attributes = array_filter( | |
| 235 | - $attributes, | |
| 236 | - function ( $key ) { | |
| 237 | - return ! in_array( $key, array_keys( $this->block_attributes ), true ) && $key !== 'style'; | |
| 238 | - }, | |
| 239 | - ARRAY_FILTER_USE_KEY | |
| 240 | - ); | |
| 241 | - | |
| 235 | + // Alignment and custom classes already come from block supports, so no attribute is forwarded here. | |
| 242 | 236 | return sprintf( |
| 243 | 237 | '<div %s><optimole-video-player %s></optimole-video-player></div>', |
| 244 | - get_block_wrapper_attributes( $wrapper_attributes ), | |
| 238 | + get_block_wrapper_attributes(), | |
| 245 | 239 | implode( ' ', $tag_attributes ), |
| 246 | 240 | ); |
| 247 | 241 | } |
| 248 | 242 | |
| @@ -302,19 +296,86 @@ | ||
| 302 | 296 | */ |
| 303 | 297 | private function block_style_attributes_to_css_array( $attributes ) { |
| 304 | 298 | $css = []; |
| 305 | 299 | |
| 306 | - if ( isset( $attributes['spacing'] ) ) { | |
| 307 | - $spacing = $attributes['spacing']; | |
| 300 | + if ( ! isset( $attributes['spacing'] ) || ! is_array( $attributes['spacing'] ) ) { | |
| 301 | + return $css; | |
| 302 | + } | |
| 308 | 303 | |
| 309 | - foreach ( $spacing as $css_prop_prefix => $values ) { | |
| 310 | - foreach ( $values as $direction => $value ) { | |
| 311 | - $css[ $css_prop_prefix . '-' . $direction ] = $this->core_var_to_css_var( $value ); | |
| 304 | + $allowed_props = [ 'margin', 'padding' ]; | |
| 305 | + $allowed_directions = [ 'top', 'right', 'bottom', 'left' ]; | |
| 306 | + | |
| 307 | + foreach ( $attributes['spacing'] as $css_prop_prefix => $values ) { | |
| 308 | + if ( ! in_array( $css_prop_prefix, $allowed_props, true ) || ! is_array( $values ) ) { | |
| 309 | + continue; | |
| 310 | + } | |
| 311 | + | |
| 312 | + foreach ( $values as $direction => $value ) { | |
| 313 | + if ( ! in_array( $direction, $allowed_directions, true ) || ! is_string( $value ) ) { | |
| 314 | + continue; | |
| 312 | 315 | } |
| 316 | + | |
| 317 | + $value = $this->core_var_to_css_var( $value ); | |
| 318 | + | |
| 319 | + if ( ! $this->is_safe_css_length( $value ) ) { | |
| 320 | + continue; | |
| 321 | + } | |
| 322 | + | |
| 323 | + $css[ $css_prop_prefix . '-' . $direction ] = $value; | |
| 313 | 324 | } |
| 314 | 325 | } |
| 315 | 326 | |
| 316 | 327 | return $css; |
| 328 | + } | |
| 329 | + | |
| 330 | + /** | |
| 331 | + * Get the default value of every declared block attribute. | |
| 332 | + * | |
| 333 | + * @return array<string, mixed> The default attributes. | |
| 334 | + */ | |
| 335 | + private function get_default_attributes() { | |
| 336 | + $defaults = []; | |
| 337 | + | |
| 338 | + foreach ( $this->block_attributes as $name => $schema ) { | |
| 339 | + if ( ! isset( $schema['default'] ) ) { | |
| 340 | + continue; | |
| 341 | + } | |
| 342 | + | |
| 343 | + $defaults[ $name ] = $schema['default']; | |
| 344 | + } | |
| 345 | + | |
| 346 | + return $defaults; | |
| 347 | + } | |
| 348 | + | |
| 349 | + /** | |
| 350 | + * Sanitize the player aspect ratio, falling back to the default when it is not a known one. | |
| 351 | + * | |
| 352 | + * @param mixed $aspect_ratio The aspect ratio to sanitize. | |
| 353 | + * @return string The sanitized aspect ratio. | |
| 354 | + */ | |
| 355 | + private function sanitize_aspect_ratio( $aspect_ratio ) { | |
| 356 | + $allowed = [ 'auto', '16/9', '4/3', '1/1', '9/16', '1/2', '2/1' ]; | |
| 357 | + | |
| 358 | + if ( is_string( $aspect_ratio ) && in_array( $aspect_ratio, $allowed, true ) ) { | |
| 359 | + return $aspect_ratio; | |
| 360 | + } | |
| 361 | + | |
| 362 | + return $this->block_attributes['aspectRatio']['default']; | |
| 363 | + } | |
| 364 | + | |
| 365 | + /** | |
| 366 | + * Whether a value is a css length or a core preset variable. | |
| 367 | + * | |
| 368 | + * @param string $value The value to check. | |
| 369 | + * @return bool Whether the value is safe to use as a css length. | |
| 370 | + */ | |
| 371 | + private function is_safe_css_length( $value ) { | |
| 372 | + if ( preg_match( '/^var\(--wp--[a-z0-9-]+\)$/i', $value ) ) { | |
| 373 | + return true; | |
| 374 | + } | |
| 375 | + | |
| 376 | + // Number plus an optional unit; no css separator can pass this shape. | |
| 377 | + return (bool) preg_match( '/^-?(?:\d+|\d*\.\d+)(?:%|[a-z]{1,6})?$/i', $value ); | |
| 317 | 378 | } |
| 318 | 379 | |
| 319 | 380 | /** |
| 320 | 381 | * Convert a core var to a css var. |