[
'type' => 'string',
'default' => '',
],
'primaryColor' => [
'type' => 'string',
'default' => '#577BF9',
],
'aspectRatio' => [
'type' => 'string',
'default' => 'auto',
],
'loop' => [
'type' => 'boolean',
'default' => false,
],
'hideControls' => [
'type' => 'boolean',
'default' => false,
],
];
const LOCALIZATION_VAR = 'OMVideoPlayerBlock';
/**
* Icons
*
* @var array
*/
private $icons = [
'play' => '',
'volume-mute' => '',
'volume-high' => '',
'volume-low' => '',
'spinner' => '',
'maximize' => '',
'minimize' => '',
'pause' => '',
];
/**
* Constructor.
*
* @since 4.0.0
*/
public function __construct() {
$settings = new Optml_Settings();
if ( ! $settings->is_connected() ) {
return;
}
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_admin_video_player_assets' ] );
add_action( 'admin_head', [ $this, 'add_editor_player_icons' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'maybe_enqueue_video_player_script' ] );
add_action( 'init', [ $this, 'register_video_player_block' ] );
}
/**
* Enqueue the admin video player assets.
*
* @since 4.0.0
*/
public function enqueue_admin_video_player_assets() {
$asset_file = include OPTML_PATH . 'assets/build/video-player/editor/editor.asset.php';
if ( empty( $asset_file ) ) {
return;
}
$handle = 'optimole-video-player-editor';
wp_register_script(
$handle,
OPTML_URL . 'assets/build/video-player/editor/editor.js',
array_merge( $asset_file['dependencies'] ),
$asset_file['version'],
true
);
wp_localize_script( $handle, 'OMVideoPlayerBlock', $this->get_localization( true ) );
wp_enqueue_script( $handle );
wp_enqueue_style( $handle, OPTML_URL . 'assets/build/video-player/frontend/style-frontend.css', [], $asset_file['version'] );
}
/**
* Add the video player icons to the editor.
*
* @since 4.0.0
*/
public function add_editor_player_icons() {
$screen = get_current_screen();
if ( ! $screen || ! $screen->is_block_editor() ) {
return;
}
$this->render_player_icons();
}
/**
* Maybe enqueue the video player component script.
*
* @since 4.0.0
*/
public function maybe_enqueue_video_player_script() {
if ( ! has_block( 'optimole/video-player' ) ) {
return;
}
$this->enqueue_video_player_component_script();
$this->render_player_icons();
}
/**
* Enqueue the video player component script.
*
* @since 4.0.0
*/
private function enqueue_video_player_component_script() {
$asset_file = include OPTML_PATH . 'assets/build/video-player/frontend/frontend.asset.php';
if ( empty( $asset_file ) ) {
return;
}
wp_register_script(
'optimole-video-player-component',
OPTML_URL . 'assets/build/video-player/frontend/frontend.js',
$asset_file['dependencies'],
);
wp_localize_script( 'optimole-video-player-component', self::LOCALIZATION_VAR, $this->get_localization() );
wp_enqueue_script( 'optimole-video-player-component' );
wp_enqueue_style(
'optimole-video-player-component',
OPTML_URL . 'assets/build/video-player/frontend/style-frontend.css',
[],
$asset_file['version']
);
}
/**
* Render the video player icons
*
* @since 4.0.0
*/
private function render_player_icons() {
?>
[ $this, 'render_video_player_block' ],
'attributes' => $this->block_attributes,
'supports' => [
'align' => true,
],
]
);
}
/**
* Render the video player block.
*
* @param array $attributes The block attributes.
* @return string The video player block markup.
*
* @since 4.0.0
*/
public function render_video_player_block( $attributes, $content, $block ) {
$attributes = wp_parse_args( $attributes, $this->get_default_attributes() );
$style = [
'--om-primary-color' => $attributes['primaryColor'],
'--om-aspect-ratio' => $this->sanitize_aspect_ratio( $attributes['aspectRatio'] ),
];
if ( isset( $attributes['style'] ) ) {
$style = array_merge( $style, $this->block_style_attributes_to_css_array( $attributes['style'] ) );
}
$css = array_map(
function ( $key, $value ) {
return $key . ': ' . $value;
},
array_keys( $style ),
$style
);
$tag_attributes = [
'video-src' => esc_url( $attributes['url'] ),
'loop' => $attributes['loop'] ? 'true' : 'false',
'hide-controls' => $attributes['hideControls'] ? 'true' : 'false',
'style' => esc_attr( implode( ';', $css ) ),
];
$tag_attributes = array_map(
function ( $key, $value ) {
return $key . '="' . $value . '"';
},
array_keys( $tag_attributes ),
$tag_attributes
);
// Alignment and custom classes already come from block supports, so no attribute is forwarded here.
return sprintf(
'
',
get_block_wrapper_attributes(),
implode( ' ', $tag_attributes ),
);
}
/**
* Get the localization strings.
*
* @param boolean $editor Whether to get the localization for the editor.
* @return array The localization strings.
*
* @since 4.0.0
*/
private function get_localization( $editor = false ) {
$strings = [
'play' => __( 'Play', 'optimole-wp' ),
'pause' => __( 'Pause', 'optimole-wp' ),
'mute' => __( 'Mute', 'optimole-wp' ),
'unmute' => __( 'Unmute', 'optimole-wp' ),
'fullscreen' => __( 'Fullscreen', 'optimole-wp' ),
'exitFullscreen' => __( 'Exit Fullscreen', 'optimole-wp' ),
];
if ( ! $editor ) {
return $strings;
}
$options = new Optml_Settings();
$cdn_url = $options->get_cdn_url();
return array_merge(
$strings,
[
'domain' => $cdn_url,
'blockTitle' => __( 'Optimole Video', 'optimole-wp' ),
'blockDescription' => __( 'Optimole Video', 'optimole-wp' ),
'aspectRatioLabel' => __( 'Aspect Ratio', 'optimole-wp' ),
'urlLabel' => __( 'Video URL', 'optimole-wp' ),
'urlHelp' => __( 'Enter the URL of the video you want to display.', 'optimole-wp' ),
'editLabel' => __( 'Change URL', 'optimole-wp' ),
'loopLabel' => __( 'Loop Video', 'optimole-wp' ),
'hideControlsLabel' => __( 'Hide Video Controls Bar', 'optimole-wp' ),
// translators: %s is 'Optimole Dashboard'.
'invalidUrlError' => sprintf( __( 'Invalid URL. Please enter a valid video URL from %s', 'optimole-wp' ), '' . __( 'Optimole Dashboard', 'optimole-wp' ) . '' ),
'auto' => __( 'Auto', 'optimole-wp' ),
'save' => __( 'Save', 'optimole-wp' ),
'primaryColorLabel' => __( 'Controls color', 'optimole-wp' ),
]
);
}
/**
* Convert the block style attributes to a css array.
*
* @param array $attributes The block attributes.
* @return array The css array.
*
* @since 4.0.0
*/
private function block_style_attributes_to_css_array( $attributes ) {
$css = [];
if ( ! isset( $attributes['spacing'] ) || ! is_array( $attributes['spacing'] ) ) {
return $css;
}
$allowed_props = [ 'margin', 'padding' ];
$allowed_directions = [ 'top', 'right', 'bottom', 'left' ];
foreach ( $attributes['spacing'] as $css_prop_prefix => $values ) {
if ( ! in_array( $css_prop_prefix, $allowed_props, true ) || ! is_array( $values ) ) {
continue;
}
foreach ( $values as $direction => $value ) {
if ( ! in_array( $direction, $allowed_directions, true ) || ! is_string( $value ) ) {
continue;
}
$value = $this->core_var_to_css_var( $value );
if ( ! $this->is_safe_css_length( $value ) ) {
continue;
}
$css[ $css_prop_prefix . '-' . $direction ] = $value;
}
}
return $css;
}
/**
* Get the default value of every declared block attribute.
*
* @return array The default attributes.
*/
private function get_default_attributes() {
$defaults = [];
foreach ( $this->block_attributes as $name => $schema ) {
if ( ! isset( $schema['default'] ) ) {
continue;
}
$defaults[ $name ] = $schema['default'];
}
return $defaults;
}
/**
* Sanitize the player aspect ratio, falling back to the default when it is not a known one.
*
* @param mixed $aspect_ratio The aspect ratio to sanitize.
* @return string The sanitized aspect ratio.
*/
private function sanitize_aspect_ratio( $aspect_ratio ) {
$allowed = [ 'auto', '16/9', '4/3', '1/1', '9/16', '1/2', '2/1' ];
if ( is_string( $aspect_ratio ) && in_array( $aspect_ratio, $allowed, true ) ) {
return $aspect_ratio;
}
return $this->block_attributes['aspectRatio']['default'];
}
/**
* Whether a value is a css length or a core preset variable.
*
* @param string $value The value to check.
* @return bool Whether the value is safe to use as a css length.
*/
private function is_safe_css_length( $value ) {
if ( preg_match( '/^var\(--wp--[a-z0-9-]+\)$/i', $value ) ) {
return true;
}
// Number plus an optional unit; no css separator can pass this shape.
return (bool) preg_match( '/^-?(?:\d+|\d*\.\d+)(?:%|[a-z]{1,6})?$/i', $value );
}
/**
* Convert a core var to a css var.
* e.g.: var:preset|spacing|50 -> var(--wp--preset--spacing--50)
*
* @param string $css_value The css value.
* @return string The css var.
*
* @since 4.0.0
*/
private function core_var_to_css_var( $css_value ) {
if ( strpos( $css_value, 'var:' ) !== 0 ) {
return $css_value;
}
$css_value = str_replace( 'var:', '', $css_value );
$css_value = str_replace( '|', '--', $css_value );
return 'var(--wp--' . $css_value . ')';
}
}