diff --git a/php/class-media.php b/php/class-media.php
index 0a3505aba..c79f2a2ad 100644
--- a/php/class-media.php
+++ b/php/class-media.php
@@ -589,6 +589,40 @@ public function get_transformation( $transformations, $type ) {
return false;
}
+ /**
+ * Get transformations for an attachment to use in a final URL.
+ *
+ * @param int $attachment_id The attachment ID.
+ * @param array $transformations Base/starter set of transformations.
+ * @param bool $overwrite_transformations Flag to indicate if default transformations should not be applied.
+ *
+ * @return array
+ */
+ public function get_transformations( $attachment_id, $transformations = array(), $overwrite_transformations = false ) {
+ // If not provided, get transformations from the attachment meta.
+ if ( empty( $transformations ) ) {
+ $transformations = $this->get_transformation_from_meta( $attachment_id );
+ }
+ if ( false === $overwrite_transformations ) {
+ $overwrite_transformations = $this->maybe_overwrite_featured_image( $attachment_id );
+ }
+
+ // Defaults are only to be added on front, main images ( not breakpoints, since these are adapted down), and videos.
+ if ( false === $overwrite_transformations && ! is_admin() ) {
+ $transformations = $this->apply_default_transformations( $transformations, $attachment_id );
+ }
+
+ /**
+ * Filter the Cloudinary transformations.
+ *
+ * @param array $transformations Array of transformation options.
+ * @param int $attachment_id The id of the asset.
+ *
+ * @return array
+ */
+ return apply_filters( 'cloudinary_transformations', $transformations, $attachment_id );
+ }
+
/**
* Extract the crop size part of a transformation that was done in the DAM widget.
*
@@ -698,13 +732,24 @@ public function attachment_url( $url, $attachment_id ) {
/**
* Apply default image transformations before building the URL.
*
- * @param array $transformations The set of transformations.
- * @param string $type Default transformations type.
+ * @param array $transformations The set of transformations.
+ * @param int $attachment_id The attachment ID.
*
* @return array
*/
- public function apply_default_transformations( array $transformations, $type = 'image' ) {
-
+ public function apply_default_transformations( array $transformations, $attachment_id ) {
+ /**
+ * Filter to allow bypassing defaults. Return false to not apply defaults.
+ *
+ * @param bool $true True to apply defaults.
+ * @param int $attachment_id The current attachment ID.
+ *
+ * @return bool
+ */
+ if ( false === apply_filters( 'cloudinary_apply_default_transformations', true, $attachment_id ) ) {
+ return $transformations;
+ }
+ $type = $this->get_media_type( $attachment_id );
// Base image level.
$new_transformations = array(
'image' => Api::generate_transformation_string( $transformations, $type ),
@@ -806,10 +851,10 @@ public function default_image_freeform_transformations( $default ) {
/**
* Generate a Cloudinary URL based on attachment ID and required size.
*
- * @param int $attachment_id The id of the attachment.
- * @param array|string $size The wp size to set for the URL.
- * @param array $transformations Set of transformations to apply to this url.
- * @param string $cloudinary_id Optional forced cloudinary ID.
+ * @param int $attachment_id The id of the attachment.
+ * @param array|string $size The wp size to set for the URL.
+ * @param array $transformations Set of transformations to apply to this url.
+ * @param string $cloudinary_id Optional forced cloudinary ID.
* @param bool $overwrite_transformations Flag url is a breakpoint URL to stop re-applying default transformations.
*
* @return string The converted URL.
@@ -821,9 +866,7 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation
return null;
}
}
- if ( empty( $transformations ) ) {
- $transformations = $this->get_transformation_from_meta( $attachment_id );
- }
+
// Get the attachment resource type.
$resource_type = $this->get_media_type( $attachment_id );
// Setup initial args for cloudinary_url.
@@ -834,24 +877,9 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation
);
$size = $this->prepare_size( $attachment_id, $size );
- if ( false === $overwrite_transformations ) {
- $overwrite_transformations = $this->maybe_overwrite_featured_image( $attachment_id );
- }
- /**
- * Filter the Cloudinary transformations.
- *
- * @param array $transformations Array of transformation options.
- * @param int $attachment_id The id of the asset.
- *
- * @return array
- */
- $pre_args['transformation'] = apply_filters( 'cloudinary_transformations', $transformations, $attachment_id );
- $apply_default_transformations = apply_filters( 'cloudinary_apply_default_transformations', true );
- // Defaults are only to be added on front, main images ( not breakpoints, since these are adapted down), and videos.
- if ( true === $apply_default_transformations && false === $overwrite_transformations && ! is_admin() ) {
- $pre_args['transformation'] = $this->apply_default_transformations( $pre_args['transformation'], $resource_type );
- }
+ // Prepare transformations.
+ $pre_args['transformation'] = $this->get_transformations( $attachment_id, $transformations, $overwrite_transformations );
// Make a copy as not to destroy the options in \Cloudinary::cloudinary_url().
$args = $pre_args;
diff --git a/php/class-utils.php b/php/class-utils.php
index 7522e1248..4be4688d9 100644
--- a/php/class-utils.php
+++ b/php/class-utils.php
@@ -62,6 +62,7 @@ public static function get_active_setting() {
*
* @param array $input The array that will be processed.
* @param string $separator Separator string.
+ *
* @return array
*/
public static function expand_dot_notation( array $input, $separator = '.' ) {
@@ -105,4 +106,27 @@ public static function is_amp( $html_string ) {
public static function is_webstory_post_type( $post_type ) {
return class_exists( Story_Post_Type::class ) && Story_Post_Type::POST_TYPE_SLUG === $post_type;
}
+
+ /**
+ * Get all the attributes from an HTML tag.
+ *
+ * @param string $tag HTML tag to get attributes from.
+ *
+ * @return array
+ */
+ public static function get_tag_attributes( $tag ) {
+ $tag = strstr( $tag, ' ', false );
+ $tag = trim( $tag, '> ' );
+ $args = shortcode_parse_atts( $tag );
+ $return = array();
+ foreach ( $args as $key => $value ) {
+ if ( is_int( $key ) ) {
+ $return[ $value ] = 'true';
+ continue;
+ }
+ $return[ $key ] = $value;
+ }
+
+ return $return;
+ }
}
diff --git a/php/media/class-video.php b/php/media/class-video.php
index ebb5a9e64..7c3225e1c 100644
--- a/php/media/class-video.php
+++ b/php/media/class-video.php
@@ -8,6 +8,7 @@
namespace Cloudinary\Media;
use Cloudinary\Media;
+use Cloudinary\Utils;
/**
* Class Video.
@@ -34,13 +35,6 @@ class Video {
*/
private $config;
- /**
- * Determines if the video player is active.
- *
- * @var bool
- */
- private $player_enabled = false;
-
/**
* List of attachment ID's to enable.
*
@@ -53,7 +47,7 @@ class Video {
*
* @var string
*/
- const PLAYER_VER = '1.4.0';
+ const PLAYER_VER = '1.5.1';
/**
* Cloudinary Core Version.
@@ -87,44 +81,7 @@ public function __construct( Media $media ) {
* @return bool
*/
public function player_enabled() {
- return $this->player_enabled;
- }
-
- /**
- * $this->>register_scripts();
- * Initialises the Cloudinary player if it's enabled and if video content is found.
- */
- public function init_player() {
- if ( isset( $this->config['video_player'] ) && 'cld' === $this->config['video_player'] && ! is_admin() ) {
- global $wp_query;
- $posts = $wp_query->get_posts();
- // Check content has a video to enqueue assets in correct location.
- foreach ( $posts as $post ) {
- $has_video = $this->media->filter->get_video_shortcodes( get_the_content() );
- $video_tags = $this->media->filter->get_media_tags( get_the_content(), 'video' );
- if ( ! empty( $has_video ) || ! empty( $video_tags ) ) {
- // Setup initial scripts.
- wp_enqueue_style( 'cld-player' );
- wp_enqueue_style( 'cld-player-local', $this->media->plugin->dir_url . 'css/video.css', null, self::PLAYER_VER );
- wp_enqueue_script( 'cld-player' );
-
- // Init cld script object.
- $cld = array(
- 'cloud_name' => $this->media->credentials['cloud_name'],
- );
- if ( ! empty( $this->media->credentials['cname'] ) ) {
- $cld['cname'] = $this->media->credentials['cname'];
- $cld['private_cdn'] = true;
- }
- $code = 'var cld = cloudinary.Cloudinary.new(' . wp_json_encode( $cld ) . ');';
- wp_add_inline_script( 'cld-player', $code );
-
- // Enable video for output.
- $this->player_enabled = true;
- break; // Exit since we determined that a video is present.
- }
- }
- }
+ return isset( $this->config['video_player'] ) && 'cld' === $this->config['video_player'] && ! is_admin();
}
/**
@@ -195,188 +152,31 @@ public function validate_usable_transformations( $attachment_id, $transformation
*/
public function filter_video_shortcode( $html, $attr ) {
- // If not CLD video init, return default.
- if ( false === $this->player_enabled ) {
- return $html;
- }
- // Check for override flag.
- $overwrite_transformations = false;
- if ( ! empty( $attr['cldoverwrite'] ) ) {
- $overwrite_transformations = true;
- }
- // Check for a cloudinary url, or prep sync if not found.
- $cloudinary_url = $this->media->cloudinary_url( $attr['id'], false, false, null, $overwrite_transformations );
- if ( ! $this->media->plugin->components['sync']->is_synced( $attr['id'] ) ) {
- // If the asset is not synced, then the metadata will not be complete since v1 didn't save any.
- // Return html for now since cloudinary_url will queue it up for syncing in the background.
+ // Confirm we have an ID and it's synced.
+ if ( empty( $attr['id'] ) || ! $this->media->has_public_id( $attr['id'] ) ) {
return $html;
}
- // Queue video.
- $video = wp_get_attachment_metadata( $attr['id'] );
- $transformations = $this->media->get_transformations_from_string( $cloudinary_url, 'video' );
- $args = array();
-
- if ( isset( $attr['autoplay'] ) ) {
- $args['autoplay'] = 'true' === $attr['autoplay'];
- $args['muted'] = 'true' === $attr['autoplay'];
- }
- if ( isset( $attr['loop'] ) ) {
- $args['loop'] = 'true' === $attr['loop'];
- }
- // Transformations.
- if ( ! empty( $transformations ) ) {
- $args['transformation'] = $transformations;
- }
- $args['overwrite_transformations'] = $overwrite_transformations;
- // Size settings.
- $size = '';
- if ( ! empty( $attr['width'] ) ) {
- $size .= ' width="' . esc_attr( $attr['width'] ) . '"';
- $args['size'] = true;
- }
- if ( ! empty( $attr['height'] ) ) {
- $size .= ' height="' . esc_attr( $attr['height'] ) . '"';
- $args['size'] = true;
- }
- $instance = $this->queue_video_config( $attr['id'], $attr[ $video['fileformat'] ], $video['fileformat'], $args );
-
- // Replace with video tag.
- return '';
- }
-
- /**
- * Filter video tags and queue them for the player.
- *
- * @param string $content HTML content of the post.
- *
- * @return mixed
- */
- public function filter_video_tags( $content ) {
-
- $video_tags = $this->media->filter->get_media_tags( $content, 'video' );
- foreach ( $video_tags as $tag ) {
- $args = array();
-
- // Catch poster.
- $poster_url = $this->media->filter->get_poster_from_tag( $tag );
- if ( false !== $poster_url ) {
-
- $poster_id = $this->media->get_id_from_url( $poster_url );
- $cloudinary_id = $this->media->cloudinary_id( $poster_id );
- $cloudinary_url = $this->media->cloudinary_url( $poster_id );
- $transformations = $this->media->get_transformations_from_string( $cloudinary_url );
- $args['posterOptions'] = array(
- 'publicId' => $cloudinary_id,
- );
- if ( ! empty( $transformations ) ) {
- $args['posterOptions']['transformation'] = $transformations;
- }
+ // If not CLD video init, return default.
+ if ( ! $this->player_enabled() ) {
+ if ( empty( $attr['cloudinary'] ) ) {
+ $video = wp_get_attachment_metadata( $attr['id'] );
+ $url = $this->media->cloudinary_url( $attr['id'] );
+ $attr[ $video['fileformat'] ] = $url;
+ $attr['cloudinary'] = true; // Flag Cloudinary to ensure we don't call it again.
+ $html = wp_video_shortcode( $attr, $html );
}
- $url = $this->media->filter->get_url_from_tag( $tag );
- if ( false === $url ) {
- continue;
- }
- $attachment_id = $this->media->filter->get_id_from_tag( $tag );
- if ( empty( $attachment_id ) ) {
- continue; // Missing or no attachment ID found.
- }
- // Enable Autoplay for this video.
- if ( false !== strpos( $tag, 'autoplay' ) ) {
- $args['autoplayMode'] = $this->config['video_autoplay_mode']; // if on, use defined mode.
- $args['muted'] = 'always' === $this->config['video_autoplay_mode'];
- }
- // Enable Loop.
- if ( false !== strpos( $tag, 'loop' ) ) {
- $args['loop'] = true;
- }
- // If there is no controls, it has been turned off.
- if ( false !== strpos( $tag, 'controls' ) ) {
- $args['controls'] = true;
- }
- // If there is a muted, it has been turned on.
- if ( false !== strpos( $tag, 'muted' ) ) {
- $args['muted'] = true;
- }
- // If preload.
- if ( preg_match( '/preload=\"([^\"]*)\"/i', $tag, $found ) ) {
- $args['preload'] = $found[1];
- }
- // Add transformations if found.
- $classes = $this->media->filter->get_classes( $tag ); // check if this is a transformation overwrite.
- $overwrite_transformations = false;
- if ( false !== strpos( $classes, 'cld-overwrite' ) ) {
- $overwrite_transformations = true;
- }
- $args['overwrite_transformations'] = $overwrite_transformations;
-
- $cloudinary_url = $this->media->cloudinary_url( $attachment_id, false, false, null, $overwrite_transformations );
- // Bail replacing the video URL for cases where it doesn't exist.
- // Cases are, for instance, when the file size is larger than the API limits — free accounts.
- if ( ! empty( $cloudinary_url ) ) {
- $transformations = $this->media->get_transformations_from_string( $cloudinary_url, 'video' );
- if ( ! empty( $transformations ) ) {
- $args['transformation'] = $transformations;
- }
- $video = wp_get_attachment_metadata( $attachment_id );
- if ( $this->player_enabled() ) {
- $instance = $this->queue_video_config( $attachment_id, $url, $video['fileformat'], $args );
- // Remove src and replace with an ID.
- $new_tag = str_replace( 'src="' . $url . '"', 'id="cloudinary-video-' . esc_attr( $instance ) . '"', $tag );
- $content = str_replace( $tag, $new_tag, $content );
- } else {
- // Just replace URL.
- $content = str_replace( $url, $cloudinary_url, $content );
- }
- }
+ return $html;
}
+ $attachment_id = $attr['id'];
+ unset( $attr['id'] );
+ unset( $attr['width'] );
+ unset( $attr['height'] );
- return $content;
- }
-
- /**
- * Output init scripts in footer for videos.
- */
- public function print_video_scripts() {
-
- if ( $this->player_enabled() && ! empty( $this->attachments ) ) {
-
- $cld_videos = array();
- foreach ( $this->attachments as $instance => $video ) {
- // @todo - ping the URL to ensure it has transformation available, else update an eager.
- $cloudinary_id = $this->media->get_public_id( $video['id'] );
- $default = array(
- 'publicId' => $cloudinary_id,
- 'sourceTypes' => array( $video['format'] ), // @todo Make this based on eager items as mentioned above.
- 'autoplay' => 'off' !== $this->config['video_autoplay_mode'],
- 'loop' => $this->config['video_loop'],
- );
-
- $valid_autoplay_modes = array( 'never', 'always', 'on-scroll' );
- if ( $default['autoplay'] && in_array( $this->config['video_autoplay_mode'], $valid_autoplay_modes, true ) ) {
- $default['autoplayMode'] = $this->config['video_autoplay_mode'];
- }
-
- $config = wp_parse_args( $video['args'], $default );
-
- if ( empty( $config['size'] ) && ! empty( $config['transformation'] ) && ! $this->media->get_crop_from_transformation( $config['transformation'] ) ) {
- $config['fluid'] = true;
- }
-
- $config['controls'] = $this->config['video_controls'];
- $cld_videos[ $instance ] = $config;
- }
-
- if ( empty( $cld_videos ) ) {
- return;
- }
-
- $json_cld_videos = wp_json_encode( $cld_videos );
- $video_freeform = esc_js( $this->config['video_freeform'] );
+ $overwrite_transformations = ! empty( $attr['cldoverwrite'] );
- wp_add_inline_script( 'cld-player', "var cldVideos = '{$json_cld_videos}'; var videoFreeForm = '{$video_freeform}';" );
- }
+ return $this->build_video_embed( $attachment_id, $attr, $overwrite_transformations );
}
/**
@@ -387,16 +187,6 @@ public function enqueue_block_assets() {
wp_add_inline_script( 'cloudinary-block', 'var CLD_VIDEO_PLAYER = ' . wp_json_encode( $this->config ), 'before' );
}
- /**
- * Register assets for the player.
- */
- public function register_scripts_styles() {
- wp_register_style( 'cld-player', 'https://unpkg.com/cloudinary-video-player@' . self::PLAYER_VER . '/dist/cld-video-player.min.css', null, self::PLAYER_VER );
- wp_register_script( 'cld-core', 'https://unpkg.com/cloudinary-core@' . self::CORE_VER . '/cloudinary-core-shrinkwrap.min.js', null, self::CORE_VER, true );
- wp_register_script( 'cld-player', 'https://unpkg.com/cloudinary-video-player@' . self::PLAYER_VER . '/dist/cld-video-player.min.js', array( 'cld-core' ), self::PLAYER_VER, true );
- wp_enqueue_script( 'cld-video-init', CLDN_URL . 'js/video-init.js', array( 'cld-player' ), self::CORE_VER, true );
- }
-
/**
* Filter a video block to add the class for cld-overriding.
*
@@ -407,23 +197,19 @@ public function register_scripts_styles() {
*/
public function filter_video_block_pre_render( $block, $source_block ) {
- if ( 'core/video' === $source_block['blockName'] ) {
- $classes = 'cld-fluid';
- if ( ! empty( $source_block['attrs']['overwrite_transformations'] ) ) {
- $classes .= ' cld-overwrite';
- }
- if ( ! empty( $source_block['attrs']['id'] ) ) {
- $classes .= ' wp-video-' . $source_block['attrs']['id'];
- }
+ if ( 'core/video' === $source_block['blockName'] && ! empty( $source_block['attrs']['id'] ) && $this->media->has_public_id( $source_block['attrs']['id'] ) ) {
+ $attachment_id = $source_block['attrs']['id'];
+ $overwrite_transformations = ! empty( $source_block['attrs']['overwrite_transformations'] );
foreach ( $block['innerContent'] as &$content ) {
-
$video_tags = $this->media->filter->get_media_tags( $content );
- foreach ( $video_tags as $tag ) {
- if ( false !== strpos( $tag, 'class="' ) ) {
- $content = str_replace( 'class="', 'class="' . $classes . ' ', $content );
- } else {
- $content = str_replace( '