Skip to content

Commit ca6fa54

Browse files
authored
Merge pull request #297 from cloudinary/sync-component-revision
Sync system revision
2 parents 0fc67c3 + 45c049d commit ca6fa54

File tree

5 files changed

+753
-301
lines changed

5 files changed

+753
-301
lines changed

instance.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ function get_plugin_instance() {
2525

2626
return $cloudinary_plugin;
2727
}
28+
29+
if ( defined( 'WP_CLI' ) && WP_CLI ) {
30+
$instance = new CLI( get_plugin_instance() );
31+
\WP_CLI::add_command( 'cloudinary', $instance );
32+
}

php/class-cli.php

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
<?php
2+
/**
3+
* Cloudinary CLI.
4+
*
5+
* @package Cloudinary
6+
*/
7+
8+
namespace Cloudinary;
9+
10+
use Cloudinary\Plugin;
11+
12+
/**
13+
* CLI class.
14+
*
15+
* @since 2.5.1
16+
*/
17+
class CLI {
18+
19+
/**
20+
* Holds the plugin instance.
21+
*
22+
* @since 2.5.1
23+
*
24+
* @var Plugin Instance of the global plugin.
25+
*/
26+
public $plugin;
27+
28+
/**
29+
* Holds the base query args.
30+
*
31+
* @since 2.5.1
32+
*
33+
* @var array
34+
*/
35+
protected $base_query_args = array(
36+
'post_type' => 'attachment',
37+
'post_status' => 'inherit',
38+
'fields' => 'ids',
39+
'posts_per_page' => 100,
40+
'update_post_term_cache' => false,
41+
'update_post_meta_cache' => false,
42+
'paged' => 1,
43+
);
44+
45+
/**
46+
* CLI constructor.
47+
*
48+
* @since 2.5.1
49+
*
50+
* @param Plugin $plugin The plugin instance.
51+
*/
52+
public function __construct( $plugin ) {
53+
\WP_CLI::log( '' );
54+
\WP_CLI::log( '╔═╗┬ ┌─┐┬ ┬┌┬┐┬┌┐┌┌─┐┬─┐┬ ┬ ╔═╗╦ ╦' );
55+
\WP_CLI::log( '║ │ │ ││ │ ││││││├─┤├┬┘└┬┘ ║ ║ ║' );
56+
\WP_CLI::log( '╚═╝┴─┘└─┘└─┘─┴┘┴┘└┘┴ ┴┴└─ ┴ ╚═╝╩═╝╩' );
57+
$this->plugin = $plugin;
58+
}
59+
60+
/**
61+
* Syncs assets with Cloudinary.
62+
* ## EXAMPLES
63+
*
64+
* wp cloudinary sync
65+
*
66+
* @when after_wp_load
67+
* @since 2.5.1
68+
*
69+
* @param array $args Ignored.
70+
* @param array $assoc_args Ignored.
71+
*
72+
* @return void
73+
*/
74+
public function sync( $args, $assoc_args ) {
75+
76+
// Check if analyzed first.
77+
if ( empty( get_option( '_cld_cli_analyzed' ) ) ) {
78+
$this->analyze();
79+
}
80+
81+
// Initial Query.
82+
$query_args = $this->base_query_args;
83+
// phpcs:ignore WordPress.DB.SlowDBQuery
84+
$query_args['meta_query'] = array(
85+
'AND',
86+
array(
87+
'key' => '_cld_unsynced',
88+
'compare' => 'EXISTS',
89+
),
90+
);
91+
92+
// Get assets that need to be synced.
93+
$query = new \WP_Query( $query_args );
94+
$this->do_process( $query, 'sync' );
95+
if ( ! $query->have_posts() ) {
96+
\WP_CLI::log( \WP_CLI::colorize( '%gAll assets synced.%n' ) );
97+
}
98+
99+
}
100+
101+
/**
102+
* Analyze assets with Cloudinary.
103+
* ## EXAMPLES
104+
*
105+
* wp cloudinary analyze
106+
*
107+
* @when after_wp_load
108+
* @since 2.5.1
109+
*
110+
* @return void
111+
*/
112+
public function analyze() {
113+
114+
// Initial query.
115+
$query_args = $this->base_query_args;
116+
$query = new \WP_Query( $query_args );
117+
118+
// Kill all _cld_ related meta.
119+
delete_post_meta_by_key( '_cld_unsynced' );
120+
delete_option( '_cld_cli_analyzed' );
121+
122+
// Do process.
123+
$this->do_process( $query, 'analyze' );
124+
}
125+
126+
/**
127+
* Do a process on the query.
128+
*
129+
* @since 2.5.1
130+
*
131+
* @param \WP_Query $query The initial query object.
132+
* @param string $process The process to do.
133+
*/
134+
protected function do_process( &$query, $process ) {
135+
// Bail early.
136+
if ( ! method_exists( $this, "process_{$process}" ) ) {
137+
\WP_CLI::log( \WP_CLI::colorize( "%Invalid Process: {$process}.%n" ) );
138+
139+
return;
140+
}
141+
if ( method_exists( $this, $process ) ) {
142+
// Setup process.
143+
$total = $query->found_posts;
144+
$process = "process_{$process}";
145+
do {
146+
$posts = $query->get_posts();
147+
$this->{$process}( $posts, $total );
148+
149+
// Free up memory.
150+
if ( method_exists( $this, 'stop_the_insanity' ) ) {
151+
$this->stop_the_insanity();
152+
}
153+
154+
// Paginate.
155+
$query_args = $query->query_vars;
156+
$query_args['paged'] ++;
157+
$query = new \WP_Query( $query_args );
158+
} while ( $query->have_posts() );
159+
}
160+
\WP_CLI::line( '' );
161+
}
162+
163+
/**
164+
* Sync Assets.
165+
*
166+
* @param array $posts Array of Post IDs to process.
167+
* @param int $total Count of total posts to process.
168+
*/
169+
protected function process_sync( $posts, $total ) {
170+
static $bar, $done;
171+
if ( ! $bar && ! empty( $posts ) ) {
172+
\WP_CLI::log( \WP_CLI::colorize( '%gSyncing assets%n' ) );
173+
$bar = \WP_CLI\Utils\make_progress_bar( 'Syncing ' . $total . ' assets', $total, 10 );
174+
$done = 0;
175+
}
176+
foreach ( $posts as $index => $asset ) {
177+
$done ++; // Set $done early to not show 0 of x.
178+
$file = get_attached_file( $asset );
179+
$bar->tick( 0, 'Syncing: ' . basename( $file ) . ' (' . ( $done ) . ' of ' . $total . ')' );
180+
if ( ! $this->plugin->get_component( 'sync' )->is_synced( $asset ) ) {
181+
$this->plugin->get_component( 'sync' )->managers['push']->process_assets( $asset, $bar );
182+
}
183+
delete_post_meta( $asset, '_cld_unsynced', true );
184+
$bar->tick();
185+
}
186+
// Done message - reanalyze.
187+
if ( $done === $total ) {
188+
$bar->tick( 0, 'Sync Completed.' );
189+
$bar->finish();
190+
$bar = null;
191+
\WP_CLI::line( '' );
192+
$this->analyze();
193+
delete_option( '_cld_cli_analyzed' );
194+
}
195+
}
196+
197+
/**
198+
* Analyze and mark assets that need to be synced.
199+
*
200+
* @since 2.5.1
201+
*
202+
* @param array $posts Array of Post IDs to process.
203+
* @param int $total Count of total posts to process.
204+
*/
205+
protected function process_analyze( $posts, $total ) {
206+
static $bar, $done, $info;
207+
208+
if ( ! $bar ) {
209+
\WP_CLI::log( \WP_CLI::colorize( '%gAnalyzing ' . $total . ' assets:%n' ) );
210+
$bar = \WP_CLI\Utils\make_progress_bar( '', $total, 10 );
211+
$done = 0;
212+
$info = array(
213+
'_cld_unsupported' => 0,
214+
'_cld_synced' => 0,
215+
'_cld_unsynced' => 0,
216+
);
217+
}
218+
foreach ( $posts as $index => $asset ) {
219+
$done ++;
220+
$key = '_cld_unsupported';
221+
if ( $this->plugin->get_component( 'media' )->is_media( $asset ) ) {
222+
// Add a key.
223+
$key = '_cld_synced';
224+
if ( ! $this->plugin->get_component( 'sync' )->is_synced( $asset ) ) {
225+
$key = '_cld_unsynced';
226+
add_post_meta( $asset, $key, true, true );
227+
}
228+
}
229+
$info[ $key ] ++;
230+
$bar->tick( 1, $done . ' of ' . $total . ' |' );
231+
}
232+
// Done message.
233+
if ( $done === $total ) {
234+
$bar->tick( 0, $total . ' Analyzed |' );
235+
$bar->finish();
236+
$bar = null;
237+
\WP_CLI::log( '' );
238+
\WP_CLI::log( \WP_CLI::colorize( '%gSynced%n :' ) . ' ' . $info['_cld_synced'] );
239+
\WP_CLI::log( \WP_CLI::colorize( '%yUn-synced%n :' ) . ' ' . $info['_cld_unsynced'] );
240+
\WP_CLI::log( \WP_CLI::colorize( '%rUnsupported%n :' ) . ' ' . $info['_cld_unsupported'] );
241+
update_option( '_cld_cli_analyzed', true, false );
242+
}
243+
}
244+
}

php/class-sync.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Cloudinary\Component\Assets;
1111
use Cloudinary\Component\Setup;
12+
use Cloudinary\Settings\Setting;
1213
use Cloudinary\Sync\Delete_Sync;
1314
use Cloudinary\Sync\Download_Sync;
1415
use Cloudinary\Sync\Push_Sync;
@@ -67,9 +68,9 @@ class Sync implements Setup, Assets {
6768
/**
6869
* Holds the sync settings object.
6970
*
70-
* @var Settings
71+
* @var Setting
7172
*/
72-
protected $settings;
73+
public $settings;
7374

7475
/**
7576
* Holds the meta keys for sync meta to maintain consistency.
@@ -90,6 +91,7 @@ class Sync implements Setup, Assets {
9091
'downloading' => '_cloudinary_downloading',
9192
'process_log' => '_process_log',
9293
'storage' => '_cloudinary_storage',
94+
'queued' => '_cloudinary_sync_queued',
9395
);
9496

9597
/**
@@ -791,18 +793,8 @@ public function set_signature_item( $attachment_id, $type, $value = null ) {
791793
*/
792794
public function init_background_upload() {
793795
if ( ! empty( $this->to_sync ) ) {
794-
795-
$threads = $this->managers['push']->queue->threads;
796-
$chunk_size = ceil( count( $this->to_sync ) / count( $threads ) ); // Max of 3 threads to prevent server overload.
797-
$chunks = array_chunk( $this->to_sync, $chunk_size );
798-
$token = uniqid();
799-
foreach ( $chunks as $key => $ids ) {
800-
$params = array(
801-
'process_key' => $token . '-' . $threads[ $key ],
802-
);
803-
set_transient( $params['process_key'], $ids, 120 );
804-
$this->plugin->components['api']->background_request( 'process', $params );
805-
}
796+
$this->managers['queue']->add_to_queue( $this->to_sync, 'autosync' );
797+
$this->managers['queue']->start_threads( 'autosync' );
806798
}
807799
}
808800

0 commit comments

Comments
 (0)