From 3fe5e2d59844b7e9b87f7b6c3d27af3ed9684558 Mon Sep 17 00:00:00 2001 From: David Cramer Date: Wed, 29 Jun 2022 07:28:16 +0200 Subject: [PATCH 001/131] cron --- php/class-cron.php | 225 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 php/class-cron.php diff --git a/php/class-cron.php b/php/class-cron.php new file mode 100644 index 000000000..bd765be6a --- /dev/null +++ b/php/class-cron.php @@ -0,0 +1,225 @@ +init_time = time(); + $this->init(); + } + + /** + * Initialize the cron. + */ + public function init() { + $this->load_schedule(); + add_action( 'cloudinary_cron_job', array( $this, 'run_queue' ) ); + add_action( 'shutdown', array( $this, 'process_schedule' ) ); + } + + /** + * Load the saved schedule. + */ + protected function load_schedule() { + $this->schedule = get_option( self::CRON_META_KEY, array() ); + foreach ( $this->schedule as &$item ) { + $item['active'] = false; + } + } + + /** + * Register a new cron process. + * + * @param string $name Name of the process. + * @param callable $callback Callback to run. + * @param int $interval Interval in seconds. + * @param int $offset First call offset in seconds, or 0 for now. + */ + public static function register_process( $name, $callback, $interval = 60, $offset = 0 ) { + $cron = self::get_instance(); + $cron->processes[ $name ] = array( + 'callback' => $callback, + 'interval' => $interval, + 'offset' => $offset, + ); + $cron->register_schedule( $name ); + } + + /** + * Registered cron process's schedule and set it as active. + * + * @param string $name Name of the process. + */ + public function register_schedule( $name ) { + if ( ! isset( $this->schedule[ $name ] ) ) { + $process = $this->processes[ $name ]; + $runtime = $this->init_time + $process['offset']; + $this->schedule[ $name ] = array( + 'last_run' => $runtime, + 'next_run' => $runtime, + 'timeout' => 0, + ); + } + $this->schedule[ $name ]['active'] = true; + } + + /** + * Unregister a cron process from the schedule. + * + * @param string $name Name of the process. + */ + public function unregister_schedule( $name ) { + if ( isset( $this->schedule[ $name ] ) ) { + unset( $this->schedule[ $name ] ); + } + } + + /** + * Update the cron schedule with the last run time and the next run time. + * + * @param string $name Name of the process to update. + */ + public function update_schedule( $name ) { + $this->schedule[ $name ]['last_run'] = $this->init_time; + $this->schedule[ $name ]['next_run'] = $this->init_time + $this->processes[ $name ]['interval']; + } + + /** + * Save the cron schedule. + */ + public function save_schedule() { + update_option( self::CRON_META_KEY, $this->schedule ); + } + + /** + * Process the cron schedule. + */ + public function process_schedule() { + $queue = array(); + foreach ( $this->schedule as $name => $schedule ) { + // Remove schedules that are not active. + if ( ! $schedule['active'] ) { + $this->unregister_schedule( $name ); + continue; + } + // Queue the process if it's time to run. + if ( empty( $schedule['timeout'] ) && $this->init_time >= $schedule['next_run'] ) { + $queue[] = $name; + $this->update_schedule( $name ); + $this->lock_schedule_process( $name ); + } + } + // Run the queued processes. + if ( ! empty( $queue ) ) { + $this->push_queue( $queue ); + } + } + + /** + * Push the queue to the cron. + * + * @param array $queue Queue to push. + */ + protected function push_queue( $queue ) { + $this->save_schedule(); + wp_schedule_single_event( $this->init_time, 'cloudinary_cron_job', array( $queue ) ); + spawn_cron(); // This is a failsafe to trigger the cron on this run, rather than waiting for the next page load. + } + + /** + * Lock a cron schedule process. + * + * @param string $name Name of the process to lock. + */ + protected function lock_schedule_process( $name ) { + $this->schedule[ $name ]['timeout'] = $this->init_time + 60; // 60 seconds. + } + + /** + * Unlock the cron schedule process. + * + * @param string $name Name of the process to unlock. + */ + protected function unlock_schedule_process( $name ) { + $this->schedule[ $name ]['timeout'] = 0; + } + + /** + * Run the queue. + * + * @param array $queue Queue to run. + */ + public function run_queue( $queue ) { + foreach ( $queue as $name ) { + $process = $this->processes[ $name ]; + // translators: variable is process name. + $action_message = sprintf( __( 'Cloudinary Cron Process Start: %s', 'cloudinary' ), $name ); + do_action( '_cloudinary_cron_action', $action_message ); + $data = $process['callback']( $name ); + if ( ! empty( $data ) ) { + // translators: variable is process result. + $result = sprintf( __( 'Result: %s', 'cloudinary' ), $data ); + do_action( '_cloudinary_cron_action', $result ); + } + // translators: variable is process name. + $result = sprintf( __( 'Cloudinary Cron Process End: %s', 'cloudinary' ), $name ); + do_action( '_cloudinary_cron_action', $result ); + $this->unlock_schedule_process( $name ); + } + $this->save_schedule(); + } + + /** + * Get the instance of the class. + * + * @return Cron + */ + public static function get_instance() { + static $instance; + + if ( null === $instance ) { + $instance = new self(); + } + + return $instance; + } + +} From 1a301ce0f339601496a7586c30a3e01141cb22c4 Mon Sep 17 00:00:00 2001 From: David Cramer Date: Tue, 5 Jul 2022 08:25:47 +0200 Subject: [PATCH 002/131] WIP cron system --- php/class-cron.php | 90 +++++++++++++++++++++++++++++++++++++------- php/class-plugin.php | 1 + 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/php/class-cron.php b/php/class-cron.php index bd765be6a..ff9f99359 100644 --- a/php/class-cron.php +++ b/php/class-cron.php @@ -38,6 +38,13 @@ class Cron { */ const CRON_META_KEY = 'cloudinary_cron_schedule'; + /** + * Holds the cron watcher interval. + * + * @var int + */ + const DAEMON_WATCHER_INTERVAL = 20; + /** * Cron constructor. */ @@ -51,8 +58,29 @@ public function __construct() { */ public function init() { $this->load_schedule(); - add_action( 'cloudinary_cron_job', array( $this, 'run_queue' ) ); - add_action( 'shutdown', array( $this, 'process_schedule' ) ); + //add_action( 'cloudinary_cron_job', array( $this, 'run_queue' ) ); + //add_action( 'cloudinary_cron_daemon', array( $this, 'daemon_watcher' ) ); + // add_action( 'shutdown', array( $this, 'process_schedule' ) ); + add_action( 'shutdown', array( $this, 'start_daemon' ) ); + add_filter( 'cloudinary_api_rest_endpoints', array( $this, 'rest_endpoints' ) ); + } + + /** + * Register REST endpoints. + */ + public function rest_endpoints( $endpoints ) { + $endpoints['cron_watch'] = array( + 'method' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'daemon_watcher' ), + 'permission_callback' => '__return_true', + ); + $endpoints['cron_process'] = array( + 'method' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'run_queue' ), + 'permission_callback' => '__return_true', + ); + + return $endpoints; } /** @@ -141,7 +169,7 @@ public function process_schedule() { continue; } // Queue the process if it's time to run. - if ( empty( $schedule['timeout'] ) && $this->init_time >= $schedule['next_run'] ) { + if ( $this->init_time >= $schedule['next_run'] ) { $queue[] = $name; $this->update_schedule( $name ); $this->lock_schedule_process( $name ); @@ -155,13 +183,30 @@ public function process_schedule() { /** * Push the queue to the cron. - * - * @param array $queue Queue to push. */ protected function push_queue( $queue ) { + $this->save_schedule(); - wp_schedule_single_event( $this->init_time, 'cloudinary_cron_job', array( $queue ) ); - spawn_cron(); // This is a failsafe to trigger the cron on this run, rather than waiting for the next page load. + $instance = get_plugin_instance(); + $rest = $instance->get_component( 'api' ); + $rest->background_request( 'cron_process', array( 'queue' => $queue ), 'POST' ); + //wp_schedule_single_event( $this->init_time, 'cloudinary_cron_job', array( $queue ) ); + //spawn_cron(); // This is a failsafe to trigger the cron on this run, rather than waiting for the next page load. + } + + /** + * Start cron daemon. + */ + public function start_daemon() { + $check = get_transient( 'cloudinary_cron_daemon' ); + if ( ! empty ( $check ) ) { + return; + } + + set_transient( 'cloudinary_cron_daemon', '1', self::DAEMON_WATCHER_INTERVAL ); + $instance = get_plugin_instance(); + $rest = $instance->get_component( 'api' ); + $rest->background_request( 'cron_watch', array(), 'GET' ); } /** @@ -185,28 +230,47 @@ protected function unlock_schedule_process( $name ) { /** * Run the queue. * - * @param array $queue Queue to run. + * @param WP_REST_Request $request Queue to run. */ - public function run_queue( $queue ) { + public function run_queue( \WP_REST_Request $request ) { + $queue = $request->get_param( 'queue' ); + //error_log( 'Running queue ' . print_r( $queue, true ) ); foreach ( $queue as $name ) { $process = $this->processes[ $name ]; // translators: variable is process name. $action_message = sprintf( __( 'Cloudinary Cron Process Start: %s', 'cloudinary' ), $name ); - do_action( '_cloudinary_cron_action', $action_message ); - $data = $process['callback']( $name ); + //do_action( '_cloudinary_cron_action', $action_message ); + $data = $process['callback']( $name ); if ( ! empty( $data ) ) { // translators: variable is process result. $result = sprintf( __( 'Result: %s', 'cloudinary' ), $data ); - do_action( '_cloudinary_cron_action', $result ); + //do_action( '_cloudinary_cron_action', $result ); } // translators: variable is process name. $result = sprintf( __( 'Cloudinary Cron Process End: %s', 'cloudinary' ), $name ); - do_action( '_cloudinary_cron_action', $result ); + //do_action( '_cloudinary_cron_action', $result ); $this->unlock_schedule_process( $name ); } $this->save_schedule(); } + /** + * Cron daemon watcher. + */ + public function daemon_watcher() { + $tag = uniqid(); + //error_log( 'Cloudinary Cron Daemon Watcher start' ); + $start_time = $this->init_time; + while ( $this->init_time < $start_time + self::DAEMON_WATCHER_INTERVAL ) { + $this->init_time = time(); + $this->process_schedule(); + // error_log( $tag ); + sleep( 1 ); + } + //error_log( 'Cloudinary Cron Daemon Watcher end' ); + + } + /** * Get the instance of the class. * diff --git a/php/class-plugin.php b/php/class-plugin.php index f9fed7d48..a634770f2 100644 --- a/php/class-plugin.php +++ b/php/class-plugin.php @@ -133,6 +133,7 @@ public function __construct() { * that extend the Customizer to ensure resources are available in time. */ public function init() { + Cron::get_instance(); $this->components['admin'] = new Admin( $this ); $this->components['state'] = new State( $this ); $this->components['connect'] = new Connect( $this ); From c68faf3f29a2a33b00ae5f6bfe88b38c64fce109 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:24:10 +0100 Subject: [PATCH 003/131] Add option to disable the delivery per type --- ui-definitions/settings-image.php | 227 +++++++++++++---------- ui-definitions/settings-video.php | 293 +++++++++++++++++------------- 2 files changed, 291 insertions(+), 229 deletions(-) diff --git a/ui-definitions/settings-image.php b/ui-definitions/settings-image.php index ea2fd126e..86a5bc26e 100644 --- a/ui-definitions/settings-image.php +++ b/ui-definitions/settings-image.php @@ -32,14 +32,14 @@ 'tab_id' => 'settings', array( 'type' => 'on_off', - 'slug' => 'image_optimization', - 'title' => __( 'Image optimization', 'cloudinary' ), - 'optimisation_title' => __( 'Image optimization', 'cloudinary' ), + 'slug' => 'image_delivery', + 'title' => __( 'Image delivery', 'cloudinary' ), + 'optimisation_title' => __( 'Image delivery', 'cloudinary' ), 'tooltip_text' => __( - 'Images will be delivered using Cloudinary’s automatic format and quality algorithms for the best tradeoff between visual quality and file size. Use Advanced Optimization options to manually tune format and quality.', + 'Images will be uploaded and delivered from Cloudinary.', 'cloudinary' ), - 'description' => __( 'Optimize images on my site.', 'cloudinary' ), + 'description' => __( 'Optimize and deliver images on my site.', 'cloudinary' ), 'default' => 'on', 'attributes' => array( 'data-context' => 'image', @@ -48,122 +48,153 @@ array( 'type' => 'group', 'condition' => array( - 'image_optimization' => true, + 'image_delivery' => true, ), array( - 'type' => 'select', - 'slug' => 'image_format', - 'title' => __( 'Image format', 'cloudinary' ), - 'tooltip_text' => __( - "The image format to use for delivery. Leave as Auto to automatically deliver the most optimal format based on the user's browser and device.", + 'type' => 'tag', + 'element' => 'hr', + ), + array( + 'type' => 'on_off', + 'slug' => 'image_optimization', + 'title' => __( 'Image optimization', 'cloudinary' ), + 'optimisation_title' => __( 'Image optimization', 'cloudinary' ), + 'tooltip_text' => __( + 'Images will be delivered using Cloudinary’s automatic format and quality algorithms for the best tradeoff between visual quality and file size. Use Advanced Optimization options to manually tune format and quality.', 'cloudinary' ), - 'default' => 'auto', - 'options' => array( - 'none' => __( 'Not set', 'cloudinary' ), - 'auto' => __( 'Auto', 'cloudinary' ), - 'png' => __( 'PNG', 'cloudinary' ), - 'jpg' => __( 'JPG', 'cloudinary' ), - 'gif' => __( 'GIF', 'cloudinary' ), - 'webp' => __( 'WebP', 'cloudinary' ), - ), - 'suffix' => 'f_@value', - 'attributes' => array( + 'description' => __( 'Optimize images on my site.', 'cloudinary' ), + 'default' => 'on', + 'attributes' => array( 'data-context' => 'image', - 'data-meta' => 'f', + ), + 'depends' => array( + 'image_delivery', ), ), array( - 'type' => 'select', - 'slug' => 'image_quality', - 'title' => __( 'Image quality', 'cloudinary' ), - 'tooltip_text' => __( - 'The compression quality to apply when delivering images. Leave as Auto to apply an algorithm that finds the best tradeoff between visual quality and file size.', - 'cloudinary' + 'type' => 'group', + 'condition' => array( + 'image_optimization' => true, ), - 'default' => 'auto', - 'suffix' => 'q_@value', - 'options' => array( - 'none' => __( 'Not set', 'cloudinary' ), - 'auto' => __( 'Auto', 'cloudinary' ), - 'auto:best' => __( 'Auto best', 'cloudinary' ), - 'auto:good' => __( 'Auto good', 'cloudinary' ), - 'auto:eco' => __( 'Auto eco', 'cloudinary' ), - 'auto:low' => __( 'Auto low', 'cloudinary' ), - '100' => '100', - '80' => '80', - '60' => '60', - '40' => '40', - '20' => '20', + array( + 'type' => 'select', + 'slug' => 'image_format', + 'title' => __( 'Image format', 'cloudinary' ), + 'tooltip_text' => __( + "The image format to use for delivery. Leave as Auto to automatically deliver the most optimal format based on the user's browser and device.", + 'cloudinary' + ), + 'default' => 'auto', + 'options' => array( + 'none' => __( 'Not set', 'cloudinary' ), + 'auto' => __( 'Auto', 'cloudinary' ), + 'png' => __( 'PNG', 'cloudinary' ), + 'jpg' => __( 'JPG', 'cloudinary' ), + 'gif' => __( 'GIF', 'cloudinary' ), + 'webp' => __( 'WebP', 'cloudinary' ), + ), + 'suffix' => 'f_@value', + 'attributes' => array( + 'data-context' => 'image', + 'data-meta' => 'f', + ), ), - 'attributes' => array( - 'data-context' => 'image', - 'data-meta' => 'q', + array( + 'type' => 'select', + 'slug' => 'image_quality', + 'title' => __( 'Image quality', 'cloudinary' ), + 'tooltip_text' => __( + 'The compression quality to apply when delivering images. Leave as Auto to apply an algorithm that finds the best tradeoff between visual quality and file size.', + 'cloudinary' + ), + 'default' => 'auto', + 'suffix' => 'q_@value', + 'options' => array( + 'none' => __( 'Not set', 'cloudinary' ), + 'auto' => __( 'Auto', 'cloudinary' ), + 'auto:best' => __( 'Auto best', 'cloudinary' ), + 'auto:good' => __( 'Auto good', 'cloudinary' ), + 'auto:eco' => __( 'Auto eco', 'cloudinary' ), + 'auto:low' => __( 'Auto low', 'cloudinary' ), + '100' => '100', + '80' => '80', + '60' => '60', + '40' => '40', + '20' => '20', + ), + 'attributes' => array( + 'data-context' => 'image', + 'data-meta' => 'q', + ), ), ), - ), - array( - 'type' => 'tag', - 'element' => 'hr', - ), - array( - 'type' => 'text', - 'slug' => 'image_freeform', - 'title' => __( 'Additional image transformations', 'cloudinary' ), - 'tooltip_text' => sprintf( + array( + 'type' => 'tag', + 'element' => 'hr', + ), + array( + 'type' => 'text', + 'slug' => 'image_freeform', + 'title' => __( 'Additional image transformations', 'cloudinary' ), + 'tooltip_text' => sprintf( // translators: The link to transformation reference. - __( - 'A set of additional transformations to apply to all images. Specify your transformations using Cloudinary URL transformation syntax. See %1$sreference%2$s for all available transformations and syntax.', - 'cloudinary' + __( + 'A set of additional transformations to apply to all images. Specify your transformations using Cloudinary URL transformation syntax. See %1$sreference%2$s for all available transformations and syntax.', + 'cloudinary' + ), + '', + '' + ), + 'link' => array( + 'text' => __( 'See examples', 'cloudinary' ), + 'href' => 'https://cloudinary.com/documentation/image_transformations', + ), + 'attributes' => array( + 'data-context' => 'image', + 'placeholder' => 'w_90,r_max', + ), + 'taxonomy_field' => array( + 'context' => 'image', + 'priority' => 10, ), - '', - '' - ), - 'link' => array( - 'text' => __( 'See examples', 'cloudinary' ), - 'href' => 'https://cloudinary.com/documentation/image_transformations', - ), - 'attributes' => array( - 'data-context' => 'image', - 'placeholder' => 'w_90,r_max', ), - 'taxonomy_field' => array( - 'context' => 'image', - 'priority' => 10, + array( + 'type' => 'info_box', + 'icon' => $this->dir_url . 'css/images/crop.svg', + 'title' => __( 'What are transformations?', 'cloudinary' ), + 'text' => __( + 'A set of parameters included in a Cloudinary URL to programmatically transform the visual appearance of the assets on your website.', + 'cloudinary' + ), ), - ), - array( - 'type' => 'info_box', - 'icon' => $this->dir_url . 'css/images/crop.svg', - 'title' => __( 'What are transformations?', 'cloudinary' ), - 'text' => __( - 'A set of parameters included in a Cloudinary URL to programmatically transform the visual appearance of the assets on your website.', - 'cloudinary' + array( + 'type' => 'tag', + 'element' => 'hr', ), - ), - array( - 'type' => 'tag', - 'element' => 'hr', - ), - array( - 'type' => 'on_off', - 'slug' => 'svg_support', - 'title' => __( 'SVG Support (beta)', 'cloudinary' ), - 'optimisation_title' => __( 'SVG Support (beta)', 'cloudinary' ), - 'tooltip_text' => __( - 'Enable Cloudinary\'s beta SVG Support.', - 'cloudinary' + array( + 'type' => 'on_off', + 'slug' => 'svg_support', + 'title' => __( 'SVG Support (beta)', 'cloudinary' ), + 'optimisation_title' => __( 'SVG Support (beta)', 'cloudinary' ), + 'tooltip_text' => __( + 'Enable Cloudinary\'s beta SVG Support.', + 'cloudinary' + ), + 'description' => __( 'Enable SVG support.', 'cloudinary' ), + 'default' => 'off', ), - 'description' => __( 'Enable SVG support.', 'cloudinary' ), - 'default' => 'off', ), ), array( - 'type' => 'column', - 'tab_id' => 'preview', - 'class' => array( + 'type' => 'column', + 'tab_id' => 'preview', + 'class' => array( 'cld-ui-preview', ), + 'condition' => array( + 'image_delivery' => true, + ), array( 'type' => 'image_preview', 'title' => __( 'Preview', 'cloudinary' ), diff --git a/ui-definitions/settings-video.php b/ui-definitions/settings-video.php index 9c780d7ff..a526ce6d0 100644 --- a/ui-definitions/settings-video.php +++ b/ui-definitions/settings-video.php @@ -30,172 +30,203 @@ 'type' => 'column', 'tab_id' => 'settings', array( - 'type' => 'select', - 'slug' => 'video_player', - 'title' => __( 'Video player', 'cloudinary' ), - 'tooltip_text' => __( 'Which video player to use on all videos.', 'cloudinary' ), - 'default' => 'wp', - 'options' => array( - 'wp' => __( 'WordPress player', 'cloudinary' ), - 'cld' => __( 'Cloudinary player', 'cloudinary' ), + 'type' => 'on_off', + 'slug' => 'video_delivery', + 'title' => __( 'Video delivery', 'cloudinary' ), + 'optimisation_title' => __( 'Video delivery', 'cloudinary' ), + 'tooltip_text' => __( + 'Videos will be uploaded and delivered from Cloudinary.', + 'cloudinary' + ), + 'description' => __( 'Optimize and deliver videos on my site.', 'cloudinary' ), + 'default' => 'on', + 'attributes' => array( + 'data-context' => 'image', ), ), array( 'type' => 'group', 'condition' => array( - 'video_player' => 'cld', + 'video_delivery' => true, ), array( - 'slug' => 'video_controls', - 'description' => __( 'Show controls', 'cloudinary' ), - 'type' => 'on_off', - 'default' => 'on', + 'type' => 'tag', + 'element' => 'hr', ), array( - 'slug' => 'video_loop', - 'description' => __( 'Repeat video', 'cloudinary' ), - 'type' => 'on_off', - 'default' => 'off', + 'type' => 'select', + 'slug' => 'video_player', + 'title' => __( 'Video player', 'cloudinary' ), + 'tooltip_text' => __( 'Which video player to use on all videos.', 'cloudinary' ), + 'default' => 'wp', + 'options' => array( + 'wp' => __( 'WordPress player', 'cloudinary' ), + 'cld' => __( 'Cloudinary player', 'cloudinary' ), + ), ), array( - 'slug' => 'video_autoplay_mode', - 'title' => __( 'Autoplay', 'cloudinary' ), - 'type' => 'radio', - 'default' => 'off', - 'options' => array( - 'off' => __( 'Off', 'cloudinary' ), - 'always' => __( 'Always', 'cloudinary' ), - 'on-scroll' => __( 'On-scroll (autoplay when in view)', 'cloudinary' ), + 'type' => 'group', + 'condition' => array( + 'video_player' => 'cld', ), - 'tooltip_text' => sprintf( - // translators: Placeholders are tags. - __( - 'Please note that when choosing "always", the video will autoplay without sound (muted). This is a built-in browser feature and applies to all major browsers.%1$sRead more about muted autoplay%2$s', - 'cloudinary' + array( + 'slug' => 'video_controls', + 'description' => __( 'Show controls', 'cloudinary' ), + 'type' => 'on_off', + 'default' => 'on', + ), + array( + 'slug' => 'video_loop', + 'description' => __( 'Repeat video', 'cloudinary' ), + 'type' => 'on_off', + 'default' => 'off', + ), + array( + 'slug' => 'video_autoplay_mode', + 'title' => __( 'Autoplay', 'cloudinary' ), + 'type' => 'radio', + 'default' => 'off', + 'options' => array( + 'off' => __( 'Off', 'cloudinary' ), + 'always' => __( 'Always', 'cloudinary' ), + 'on-scroll' => __( 'On-scroll (autoplay when in view)', 'cloudinary' ), + ), + 'tooltip_text' => sprintf( + // translators: Placeholders are tags. + __( + 'Please note that when choosing "always", the video will autoplay without sound (muted). This is a built-in browser feature and applies to all major browsers.%1$sRead more about muted autoplay%2$s', + 'cloudinary' + ), + '
', + '' ), - '
', - '' ), ), - ), - array( - 'type' => 'tag', - 'element' => 'hr', - ), - array( - 'type' => 'group', array( - 'type' => 'on_off', - 'slug' => 'video_optimization', - 'title' => __( 'Video optimization', 'cloudinary' ), - 'tooltip_text' => __( - 'Videos will be delivered using Cloudinary’s automatic format and quality algorithms for the best tradeoff between visual quality and file size. Use Advanced Optimization options to manually tune format and quality.', - 'cloudinary' - ), - 'description' => __( 'Optimize videos on my site.', 'cloudinary' ), - 'default' => 'on', - 'attributes' => array( - 'data-context' => 'video', - ), + 'type' => 'tag', + 'element' => 'hr', ), - ), - array( - 'type' => 'group', - 'condition' => array( - 'video_optimization' => true, + array( + 'type' => 'group', + array( + 'type' => 'on_off', + 'slug' => 'video_optimization', + 'title' => __( 'Video optimization', 'cloudinary' ), + 'tooltip_text' => __( + 'Videos will be delivered using Cloudinary’s automatic format and quality algorithms for the best tradeoff between visual quality and file size. Use Advanced Optimization options to manually tune format and quality.', + 'cloudinary' + ), + 'description' => __( 'Optimize videos on my site.', 'cloudinary' ), + 'default' => 'on', + 'attributes' => array( + 'data-context' => 'video', + ), + 'depends' => array( + 'video_delivery', + ), + ), ), array( - 'type' => 'select', - 'slug' => 'video_format', - 'title' => __( 'Video format', 'cloudinary' ), - 'tooltip_text' => __( - "The video format to use for delivery. Leave as Auto to automatically deliver the most optimal format based on the user's browser and device.", - 'cloudinary' + 'type' => 'group', + 'condition' => array( + 'video_optimization' => true, ), - 'default' => 'auto', - 'options' => array( - 'none' => __( 'Not set', 'cloudinary' ), - 'auto' => __( 'Auto', 'cloudinary' ), + array( + 'type' => 'select', + 'slug' => 'video_format', + 'title' => __( 'Video format', 'cloudinary' ), + 'tooltip_text' => __( + "The video format to use for delivery. Leave as Auto to automatically deliver the most optimal format based on the user's browser and device.", + 'cloudinary' + ), + 'default' => 'auto', + 'options' => array( + 'none' => __( 'Not set', 'cloudinary' ), + 'auto' => __( 'Auto', 'cloudinary' ), + ), + 'suffix' => 'f_@value', + 'attributes' => array( + 'data-context' => 'video', + 'data-meta' => 'f', + ), ), - 'suffix' => 'f_@value', - 'attributes' => array( - 'data-context' => 'video', - 'data-meta' => 'f', + array( + 'type' => 'select', + 'slug' => 'video_quality', + 'title' => __( 'Video quality', 'cloudinary' ), + 'tooltip_text' => __( + 'The compression quality to apply when delivering videos. Leave as Auto to apply an algorithm that finds the best tradeoff between visual quality and file size.', + 'cloudinary' + ), + 'default' => 'auto', + 'options' => array( + 'none' => __( 'Not set', 'cloudinary' ), + 'auto' => __( 'Auto', 'cloudinary' ), + 'auto:best' => __( 'Auto best', 'cloudinary' ), + 'auto:good' => __( 'Auto good', 'cloudinary' ), + 'auto:eco' => __( 'Auto eco', 'cloudinary' ), + 'auto:low' => __( 'Auto low', 'cloudinary' ), + '100' => '100', + '80' => '80', + '60' => '60', + '40' => '40', + '20' => '20', + ), + 'suffix' => 'q_@value', + 'attributes' => array( + 'data-context' => 'video', + 'data-meta' => 'q', + ), ), + ), array( - 'type' => 'select', - 'slug' => 'video_quality', - 'title' => __( 'Video quality', 'cloudinary' ), - 'tooltip_text' => __( - 'The compression quality to apply when delivering videos. Leave as Auto to apply an algorithm that finds the best tradeoff between visual quality and file size.', - 'cloudinary' + 'type' => 'tag', + 'element' => 'hr', + ), + array( + 'type' => 'text', + 'slug' => 'video_freeform', + 'title' => __( 'Additional video transformations', 'cloudinary' ), + 'tooltip_text' => sprintf( + // translators: The link to transformation reference. + __( + 'A set of additional transformations to apply to all videos. Specify your transformations using Cloudinary URL transformation syntax. See %1$sreference%2$s for all available transformations and syntax.', + 'cloudinary' + ), + '', + '' ), - 'default' => 'auto', - 'options' => array( - 'none' => __( 'Not set', 'cloudinary' ), - 'auto' => __( 'Auto', 'cloudinary' ), - 'auto:best' => __( 'Auto best', 'cloudinary' ), - 'auto:good' => __( 'Auto good', 'cloudinary' ), - 'auto:eco' => __( 'Auto eco', 'cloudinary' ), - 'auto:low' => __( 'Auto low', 'cloudinary' ), - '100' => '100', - '80' => '80', - '60' => '60', - '40' => '40', - '20' => '20', + 'link' => array( + 'text' => __( 'See examples', 'cloudinary' ), + 'href' => 'https://cloudinary.com/documentation/transformation_reference', ), - 'suffix' => 'q_@value', - 'attributes' => array( + 'attributes' => array( 'data-context' => 'video', - 'data-meta' => 'q', + 'placeholder' => 'fps_15-25,ac_none', + ), + 'taxonomy_field' => array( + 'context' => 'video', + 'priority' => 10, ), ), - - ), - array( - 'type' => 'tag', - 'element' => 'hr', - ), - array( - 'type' => 'text', - 'slug' => 'video_freeform', - 'title' => __( 'Additional video transformations', 'cloudinary' ), - 'tooltip_text' => sprintf( - // translators: The link to transformation reference. - __( - 'A set of additional transformations to apply to all videos. Specify your transformations using Cloudinary URL transformation syntax. See %1$sreference%2$s for all available transformations and syntax.', + array( + 'type' => 'info_box', + 'icon' => $this->dir_url . 'css/images/video.svg', + 'title' => __( 'What are transformations?', 'cloudinary' ), + 'text' => __( + 'A set of parameters included in a Cloudinary URL to programmatically transform the visual appearance of the assets on your website.', 'cloudinary' ), - '', - '' - ), - 'link' => array( - 'text' => __( 'See examples', 'cloudinary' ), - 'href' => 'https://cloudinary.com/documentation/transformation_reference', - ), - 'attributes' => array( - 'data-context' => 'video', - 'placeholder' => 'fps_15-25,ac_none', - ), - 'taxonomy_field' => array( - 'context' => 'video', - 'priority' => 10, - ), - ), - array( - 'type' => 'info_box', - 'icon' => $this->dir_url . 'css/images/video.svg', - 'title' => __( 'What are transformations?', 'cloudinary' ), - 'text' => __( - 'A set of parameters included in a Cloudinary URL to programmatically transform the visual appearance of the assets on your website.', - 'cloudinary' ), ), ), array( - 'type' => 'column', - 'tab_id' => 'preview', + 'type' => 'column', + 'tab_id' => 'preview', + 'condition' => array( + 'video_delivery' => true, + ), array( 'type' => 'video_preview', 'title' => __( 'Video preview', 'cloudinary' ), From eb5aeafcca8ea8102f7efa025e0b01ac76cebc93 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:26:41 +0100 Subject: [PATCH 004/131] Add delivery as optimization level --- php/ui/component/class-opt-level.php | 30 +++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/php/ui/component/class-opt-level.php b/php/ui/component/class-opt-level.php index 792bb0222..f99d834ea 100644 --- a/php/ui/component/class-opt-level.php +++ b/php/ui/component/class-opt-level.php @@ -36,7 +36,9 @@ class Opt_Level extends Line_Stat { * @var string[] */ protected $settings_slugs = array( + 'image_settings.image_delivery', 'image_settings.image_optimization', + 'video_settings.video_delivery', 'video_settings.video_optimization', 'connect.cache.enable', 'lazy_loading.use_lazy_load', @@ -87,8 +89,18 @@ protected function get_setting_line( $slug ) { $link['content'] = $setting->get_param( 'optimisation_title', $setting->get_param( 'title' ) ); $row['children']['link'] = $link; + $params = $setting->get_params(); + $meet_depends = true; + if ( ! empty( $params['depends'] ) ) { + foreach ( $params['depends'] as $depend ) { + if ( 'off' === $setting->get_value( $depend ) ) { + $meet_depends = false; + } + } + } + // Get the status. - if ( 'on' === $setting->get_value() ) { + if ( $meet_depends && 'on' === $setting->get_value() ) { $row['children']['active'] = $this->get_badge(); } else { $row['children']['not-active'] = $this->get_badge( 'not-active' ); @@ -185,11 +197,23 @@ public function calculate_percentage() { $this->limit = count( $this->settings_slugs ); $enabled = 0; foreach ( $this->settings_slugs as $slug ) { - if ( 'on' === $this->plugin_settings->get_value( $slug ) ) { + $setting = $this->plugin_settings->get_setting( $slug ); + $meet_depends = true; + if ( null !== $setting && ! is_wp_error( $setting ) ) { + $params = $setting->get_params(); + if ( ! empty( $params['depends'] ) ) { + foreach ( $params['depends'] as $depend ) { + if ( 'off' === $setting->get_value( $depend ) ) { + $meet_depends = false; + } + } + } + } + if ( $meet_depends && 'on' === $this->plugin_settings->get_value( $slug ) ) { $enabled ++; } } - return $enabled / $this->limit * 100; + return round( $enabled / $this->limit * 100 ); } } From 907ed6201bf4b3497f2b39856b8fcf79e77d838c Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:27:58 +0100 Subject: [PATCH 005/131] Fix warnings on missing dimension assets as PDF --- php/class-media.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/class-media.php b/php/class-media.php index 94a8e1fca..8fe8045ee 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -1742,7 +1742,7 @@ public function image_srcset( $sources, $size_array, $image_src, $image_meta, $a // Use Cloudinary breakpoints for same ratio. $image_meta['overwrite_transformations'] = ! empty( $image_meta['overwrite_transformations'] ) ? $image_meta['overwrite_transformations'] : false; - if ( 'on' === $this->settings->get_setting( 'enable_breakpoints' )->get_value() && wp_image_matches_ratio( $image_meta['width'], $image_meta['height'], $size_array[0], $size_array[1] ) ) { + if ( ! empty( $image_meta['width'] ) && ! empty( $image_meta['height'] ) && 'on' === $this->settings->get_setting( 'enable_breakpoints' )->get_value() && wp_image_matches_ratio( $image_meta['width'], $image_meta['height'], $size_array[0], $size_array[1] ) ) { $meta = $this->get_post_meta( $attachment_id, Sync::META_KEYS['breakpoints'], true ); if ( ! empty( $meta ) ) { // Since srcset is primary and src is a fallback, we need to set the first srcset with the main image. From 199591173d6ad38e5dd6c81c5006599aafb0bde7 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:30:16 +0100 Subject: [PATCH 006/131] Use deliverable option to control sync --- php/class-assets.php | 28 ++++++++++++++++++++-------- php/class-delivery.php | 21 +++++++++++++++++++-- php/class-media.php | 16 ++++++++++++++++ php/class-sync.php | 17 ++++++++++++++++- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/php/class-assets.php b/php/class-assets.php index d530b23eb..f91306f50 100644 --- a/php/class-assets.php +++ b/php/class-assets.php @@ -268,6 +268,10 @@ public function can_sync( $can, $asset_id ) { $can = true; } + if ( $can && ! $this->plugin->get_component( 'delivery' )->is_deliverable( $asset_id ) ) { + $can = false; + } + return $can; } @@ -319,18 +323,23 @@ public function meta_updates() { foreach ( $this->delivery->unusable as $unusable ) { if ( 'asset' === $unusable['sync_type'] && isset( $this->active_parents[ $unusable['parent_path'] ] ) && ! in_array( $unusable['post_id'], $assets, true ) ) { $asset_id = (int) $unusable['post_id']; - $this->media->sync->set_signature_item( $asset_id, 'cld_asset', 'reset' ); - $this->media->sync->add_to_sync( $asset_id ); - $assets[] = $unusable['post_id']; + if ( $this->media->sync->can_sync( $asset_id ) ) { + $this->media->sync->set_signature_item( $asset_id, 'cld_asset', 'reset' ); + $this->media->sync->add_to_sync( $asset_id ); + $assets[] = $unusable['post_id']; + } } } } // Create found asset that's not media library. if ( ! empty( $this->to_create ) && ! empty( $this->delivery->unknown ) ) { - foreach ( $this->delivery->unknown as $url ) { - if ( isset( $this->to_create[ $url ] ) ) { - $this->create_asset( $url, $this->to_create[ $url ] ); + // Do not create assets if the image delivery is disabled. + if ( 'on' === $this->plugin->settings->get_value( 'image_delivery' ) ) { + foreach ( $this->delivery->unknown as $url ) { + if ( isset( $this->to_create[ $url ] ) ) { + $this->create_asset( $url, $this->to_create[ $url ] ); + } } } } @@ -845,8 +854,11 @@ public function check_asset( $is_local, $url ) { } } if ( $found instanceof \WP_Post ) { - $is_local = true; - $this->to_create[ $url ] = $found->ID; + $is_local = true; + + if ( $this->delivery->is_deliverable( $found->ID ) ) { + $this->to_create[ $url ] = $found->ID; + } } return $is_local; diff --git a/php/class-delivery.php b/php/class-delivery.php index f2a4825fc..fc991444c 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -343,7 +343,15 @@ public function generate_signature( $attachment_id ) { * @return bool */ public function is_deliverable( $attachment_id ) { - $is = wp_attachment_is_image( $attachment_id ) || wp_attachment_is( 'video', $attachment_id ); + $is = false; + + if ( wp_attachment_is_image( $attachment_id ) && 'on' === $this->plugin->settings->get_value( 'image_delivery' ) ) { + $is = true; + } + + if ( ! $is && wp_attachment_is( 'video', $attachment_id ) && 'on' === $this->plugin->settings->get_value( 'video_delivery' ) ) { + $is = true; + } // Ensure that the attachment has dimensions to be delivered. if ( $is ) { @@ -351,6 +359,10 @@ public function is_deliverable( $attachment_id ) { $is = ! empty( $meta['width'] ) && ! empty( $meta['height'] ); } + if ( ! $is ) { + $is = ! wp_attachment_is_image( $attachment_id ) && ! wp_attachment_is( 'video', $attachment_id ); + } + /** * Filter deliverable attachments. * @@ -834,6 +846,9 @@ public function find_attachment_size_urls() { if ( $results ) { foreach ( $results as $result ) { + if ( ! $this->is_deliverable( $result->post_id ) ) { + continue; + } // If we are here, it means that an attachment in the media library doesn't have a delivery for the url. // Reset the signature for delivery and add to sync, to update it. $this->create_delivery( $result->post_id ); @@ -1664,7 +1679,9 @@ public function prepare_delivery( $content ) { $auto_sync = $this->sync->is_auto_sync_enabled(); foreach ( $results as $result ) { - $this->set_usability( $result, $auto_sync ); + if ( $this->is_deliverable( $result['post_id'] ) ) { + $this->set_usability( $result, $auto_sync ); + } } // Set unknowns. $this->unknown = array_diff( $urls, array_keys( $this->known ) ); diff --git a/php/class-media.php b/php/class-media.php index 8fe8045ee..288fb8634 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -1044,6 +1044,10 @@ public function get_transformations_from_string( $str, $type = 'image' ) { */ public function attachment_url( $url, $attachment_id ) { + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + return $url; + } + // Previous v1 and Cloudinary only storage. if ( false !== strpos( $url, 'https://', 5 ) ) { $dirs = wp_get_upload_dir(); @@ -1635,6 +1639,10 @@ public function cloudinary_id( $attachment_id ) { * @uses filter:image_downsize */ public function filter_downsize( $image, $attachment_id, $size ) { + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + return $image; + } + // Don't do this while saving. if ( true === $this->in_downsize || doing_filter( 'content_save_pre' ) || wp_attachment_is( 'video', $attachment_id ) || Utils::is_saving_metadata() ) { return $image; @@ -1727,6 +1735,10 @@ public function convert_url( $url, $attachment_id, $transformations = array(), $ */ public function image_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id ) { + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + return $sources; + } + $cloudinary_id = isset( $image_meta['cloudinary_id'] ) ? $image_meta['cloudinary_id'] : $this->cloudinary_id( $attachment_id ); if ( ! $cloudinary_id ) { return $sources; // Return WordPress default sources. @@ -2644,6 +2656,10 @@ public function set_doing_featured( $post_id, $attachment_id ) { * @return string */ public function maybe_srcset_post_thumbnail( $content, $post_id, $attachment_id ) { + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + return $content; + } + // Check the attachment is synced and does not already have a srcset (some themes do this already). if ( $this->doing_featured_image === $attachment_id ) { $overwrite_transformations = $this->maybe_overwrite_featured_image( $attachment_id ); diff --git a/php/class-sync.php b/php/class-sync.php index 617bf79d8..7a4fb0936 100644 --- a/php/class-sync.php +++ b/php/class-sync.php @@ -319,6 +319,11 @@ public function can_sync( $attachment_id, $type = 'file' ) { $can = false; } + // Only sync deliverable attachments. + if ( $can && ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + $can = false; + } + /** * Filter to allow changing if an asset is allowed to be synced. * Return a WP Error with reason why it can't be synced. @@ -507,7 +512,11 @@ public function setup_sync_base_struct() { 'priority' => 5.1, 'sync' => array( $this->managers['upload'], 'upload_asset' ), 'validate' => function ( $attachment_id ) { - return ! $this->managers['media']->has_public_id( $attachment_id ) && ! $this->managers['media']->is_oversize_media( $attachment_id ); + $valid = ! $this->managers['media']->has_public_id( $attachment_id ) && ! $this->managers['media']->is_oversize_media( $attachment_id ); + if ( $valid ) { + $valid = $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ); + } + return $valid; }, 'state' => 'uploading', 'note' => __( 'Uploading to Cloudinary', 'cloudinary' ), @@ -972,6 +981,12 @@ public function set_pending( $attachment_id ) { */ public function add_to_sync( $attachment_id ) { if ( ! in_array( $attachment_id, $this->to_sync, true ) ) { + + // There are cases where we do not check can_sync. This is to make sure we don't add to the to_sync array if we can't sync. + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) { + return; + } + // Flag image as pending to prevent duplicate upload. $this->set_pending( $attachment_id ); $this->to_sync[] = $attachment_id; From 5579de0598c250e49a42c88fb87a19b820c112b0 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:30:52 +0100 Subject: [PATCH 007/131] Clean up metadata on running queues --- php/class-assets.php | 10 ++++++++++ php/class-utils.php | 21 +++++++++++++++++++++ php/sync/class-push-sync.php | 12 +----------- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/php/class-assets.php b/php/class-assets.php index f91306f50..b023ed104 100644 --- a/php/class-assets.php +++ b/php/class-assets.php @@ -640,6 +640,16 @@ public function validate_asset_sync( $attachment_id ) { } } + if ( $valid && $this->delivery->is_deliverable( $attachment_id ) ) { + $valid = false; + + // translators: The attachment ID. + $action_message = sprintf( __( 'Clean up sync metadata for %d', 'cloudinary' ), $attachment_id ); + do_action( '_cloudinary_queue_action', $action_message ); + + Utils::clean_up_sync_meta( $attachment_id ); + } + return $valid; } diff --git a/php/class-utils.php b/php/class-utils.php index 0702a29eb..6eed55c1a 100644 --- a/php/class-utils.php +++ b/php/class-utils.php @@ -799,4 +799,25 @@ public static function maybe_get_third_party_changes( $attributes ) { return $is; } + + /** + * Clean up meta after sync. + * + * @param int $attachment_id The attachment ID. + * + * @return void + */ + public static function clean_up_sync_meta( $attachment_id ) { + // remove pending. + delete_post_meta( $attachment_id, Sync::META_KEYS['pending'] ); + + // Remove processing flag. + delete_post_meta( $attachment_id, Sync::META_KEYS['syncing'] ); + + $sync_thread = get_post_meta( $attachment_id, Sync::META_KEYS['queued'], true ); + if ( ! empty( $sync_thread ) ) { + delete_post_meta( $attachment_id, Sync::META_KEYS['queued'] ); + delete_post_meta( $attachment_id, $sync_thread ); + } + } } diff --git a/php/sync/class-push-sync.php b/php/sync/class-push-sync.php index e224fccca..4d0d085f3 100644 --- a/php/sync/class-push-sync.php +++ b/php/sync/class-push-sync.php @@ -228,17 +228,7 @@ public function process_assets( $attachments = array() ) { } } - // remove pending. - delete_post_meta( $attachment_id, Sync::META_KEYS['pending'] ); - - // Remove processing flag. - delete_post_meta( $attachment_id, Sync::META_KEYS['syncing'] ); - - $sync_thread = get_post_meta( $attachment_id, Sync::META_KEYS['queued'], true ); - if ( ! empty( $sync_thread ) ) { - delete_post_meta( $attachment_id, Sync::META_KEYS['queued'] ); - delete_post_meta( $attachment_id, $sync_thread ); - } + Utils::clean_up_sync_meta( $attachment_id ); } return $stat; From 9b53eb48cf9549413447e396307b9063e2a4a881 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Fri, 7 Oct 2022 18:31:22 +0100 Subject: [PATCH 008/131] Add support for asset state for disabled delivery --- php/class-media.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/php/class-media.php b/php/class-media.php index 288fb8634..b4c972733 100644 --- a/php/class-media.php +++ b/php/class-media.php @@ -2164,7 +2164,11 @@ public function media_column( $cols ) { */ public function media_column_value( $column_name, $attachment_id ) { if ( 'cld_status' === $column_name ) { - if ( ! $this->is_uploadable_media( $attachment_id ) ) : + if ( ! $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) ) : + ?> + + is_uploadable_media( $attachment_id ) ) : ?> Date: Fri, 7 Oct 2022 18:32:00 +0100 Subject: [PATCH 009/131] Respect the disabled mime types when finding assets to sync --- php/sync/class-sync-queue.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/php/sync/class-sync-queue.php b/php/sync/class-sync-queue.php index 3ba013d53..4c23a5d90 100644 --- a/php/sync/class-sync-queue.php +++ b/php/sync/class-sync-queue.php @@ -434,7 +434,7 @@ public function build_queue() { $args = array( 'post_type' => 'attachment', - 'post_mime_type' => array( 'image', 'video' ), + 'post_mime_type' => array(), 'post_status' => 'inherit', 'paged' => 1, 'posts_per_page' => 100, @@ -459,6 +459,14 @@ public function build_queue() { 'no_found_rows' => true, ); + if ( 'on' === $this->plugin->settings->get_value( 'image_delivery' ) ) { + $args['post_mime_type'][] = 'image'; + } + + if ( 'on' === $this->plugin->settings->get_value( 'video_delivery' ) ) { + $args['post_mime_type'][] = 'video'; + } + /** * Filter the params for the query used to build a queue. * @@ -471,6 +479,13 @@ public function build_queue() { */ $args = apply_filters( 'cloudinary_build_queue_query', $args ); + if ( empty( $args['post_mime_type'] ) ) { + $action_message = __( 'No mime types to query.', 'cloudinary' ); + do_action( '_cloudinary_queue_action', $action_message ); + + return; + } + // translators: variable is page number. $action_message = __( 'Building Queue.', 'cloudinary' ); do_action( '_cloudinary_queue_action', $action_message ); From a8de086ff46aa32adbd67b0cb649cade7f10433c Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 11 Oct 2022 00:09:43 +0100 Subject: [PATCH 010/131] Let the `set_usablity` to decide whether the asset is `known` or `unusable` --- php/class-delivery.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/php/class-delivery.php b/php/class-delivery.php index fc991444c..16381f353 100644 --- a/php/class-delivery.php +++ b/php/class-delivery.php @@ -1518,15 +1518,22 @@ protected function set_usability( $item, $auto_sync = null ) { */ $item = apply_filters( 'cloudinary_set_usable_asset', $item ); - $this->known[ $item['public_id'] ] = $item; + $found[ $item['public_id'] ] = $item; $scaled = self::make_scaled_url( $item['sized_url'] ); $descaled = self::descaled_url( $item['sized_url'] ); $scaled_slashed = addcslashes( $scaled, '/' ); $descaled_slashed = addcslashes( $descaled, '/' ); - $this->known[ $scaled ] = $item; - $this->known[ $descaled ] = $item; - $this->known[ $scaled_slashed ] = array_merge( $item, array( 'slashed' => true ) ); - $this->known[ $descaled_slashed ] = array_merge( $item, array( 'slashed' => true ) ); + $found[ $scaled ] = $item; + $found[ $descaled ] = $item; + $found[ $scaled_slashed ] = array_merge( $item, array( 'slashed' => true ) ); + $found[ $descaled_slashed ] = array_merge( $item, array( 'slashed' => true ) ); + + if ( ! $this->is_deliverable( $item['post_id'] ) ) { + $this->unusable = array_merge( $this->unusable, $found ); + return; + } + + $this->known = array_merge( $this->known, $found ); if ( 'disable' === $item['post_state'] ) { return; @@ -1679,9 +1686,7 @@ public function prepare_delivery( $content ) { $auto_sync = $this->sync->is_auto_sync_enabled(); foreach ( $results as $result ) { - if ( $this->is_deliverable( $result['post_id'] ) ) { - $this->set_usability( $result, $auto_sync ); - } + $this->set_usability( $result, $auto_sync ); } // Set unknowns. $this->unknown = array_diff( $urls, array_keys( $this->known ) ); From 59ab14f2f38d4fb92a4af5d6b4f93e516168b254 Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 11 Oct 2022 00:09:59 +0100 Subject: [PATCH 011/131] Fix typo --- php/class-string-replace.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/class-string-replace.php b/php/class-string-replace.php index a4f663a89..d275c7960 100644 --- a/php/class-string-replace.php +++ b/php/class-string-replace.php @@ -120,7 +120,7 @@ public function pre_filter_rest_echo( $result, $server, $request ) { } /** - * Filter out local urls in an 'edit' context rest request ( i.e for Gutenburg ). + * Filter out local urls in an 'edit' context rest request ( i.e for Gutenberg ). * * @param \WP_REST_Response $response The post data array to save. * @param \WP_Post $post The current post. From 3aab3f6c6207c4939dad13a5c572033f38bd359a Mon Sep 17 00:00:00 2001 From: Marco Pereirinha Date: Tue, 11 Oct 2022 10:20:51 +0100 Subject: [PATCH 012/131] Media Library actions should reflect the deliverability of the asset --- php/delivery/class-bypass.php | 25 ++++++++++++++++------ php/media/class-global-transformations.php | 5 +++++ php/sync/class-upload-sync.php | 8 ++++++- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/php/delivery/class-bypass.php b/php/delivery/class-bypass.php index 2a7646852..0e8350b9f 100644 --- a/php/delivery/class-bypass.php +++ b/php/delivery/class-bypass.php @@ -132,12 +132,23 @@ public function handle_bulk_actions( $location, $action, $post_ids ) { /** * Get the actions for delivery types. * + * @param int|null $attachment_id The attachment ID to get action or generic action. + * * @return array */ - protected function get_actions() { - return array( - self::BYPASS_KEYS['wp'] => __( 'Deliver from WordPress', 'cloudinary' ), - ); + protected function get_actions( $attachment_id = null ) { + $actions = array(); + + if ( + null === $attachment_id + || $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id ) + ) { + $actions = array( + self::BYPASS_KEYS['wp'] => __( 'Deliver from WordPress', 'cloudinary' ), + ); + } + + return $actions; } /** @@ -152,7 +163,7 @@ public function add_inline_action( $actions, $post ) { $bypassed = $this->is_bypassed( $post->ID ); $action = $bypassed ? self::BYPASS_KEYS['cld'] : self::BYPASS_KEYS['wp']; - $messages = $this->get_actions(); + $messages = $this->get_actions( $post->ID ); if ( ! empty( $messages[ $action ] ) ) { // Set url for action handling. @@ -224,7 +235,7 @@ public function add_bulk_actions( $actions ) { */ public function filter_status( $status, $attachment_id ) { if ( ! empty( $status ) && $this->is_bypassed( $attachment_id ) ) { - $actions = $this->get_actions(); + $actions = $this->get_actions( $attachment_id ); $status = array( 'state' => 'info', 'note' => $actions[ self::BYPASS_KEYS['wp'] ], @@ -240,7 +251,7 @@ public function filter_status( $status, $attachment_id ) { * @param WP_Post $attachment The attachment post object. */ public function delivery_actions( $attachment ) { - $actions = $this->get_actions(); + $actions = $this->get_actions( $attachment->ID ); ?>