|
7 | 7 |
|
8 | 8 | namespace Cloudinary; |
9 | 9 |
|
| 10 | +use Cloudinary\Plugin; |
| 11 | + |
10 | 12 | /** |
11 | 13 | * CLI class. |
| 14 | + * |
| 15 | + * @since 2.5.1 |
12 | 16 | */ |
13 | 17 | class CLI { |
14 | 18 |
|
15 | 19 | /** |
16 | 20 | * Holds the plugin instance. |
17 | 21 | * |
18 | | - * @since 0.1 |
| 22 | + * @since 2.5.1 |
19 | 23 | * |
20 | 24 | * @var Plugin Instance of the global plugin. |
21 | 25 | */ |
22 | 26 | public $plugin; |
23 | 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 | + |
24 | 45 | /** |
25 | 46 | * CLI constructor. |
26 | 47 | * |
27 | | - * @param \Cloudinary\Plugin $plugin The plugin instance. |
| 48 | + * @since 2.5.1 |
| 49 | + * |
| 50 | + * @param Plugin $plugin The plugin instance. |
28 | 51 | */ |
29 | 52 | public function __construct( $plugin ) { |
| 53 | + \WP_CLI::log( '' ); |
| 54 | + \WP_CLI::log( '╔═╗┬ ┌─┐┬ ┬┌┬┐┬┌┐┌┌─┐┬─┐┬ ┬ ╔═╗╦ ╦' ); |
| 55 | + \WP_CLI::log( '║ │ │ ││ │ ││││││├─┤├┬┘└┬┘ ║ ║ ║' ); |
| 56 | + \WP_CLI::log( '╚═╝┴─┘└─┘└─┘─┴┘┴┘└┘┴ ┴┴└─ ┴ ╚═╝╩═╝╩' ); |
30 | 57 | $this->plugin = $plugin; |
31 | | - |
32 | 58 | } |
33 | 59 |
|
34 | 60 | /** |
35 | 61 | * Syncs assets with Cloudinary. |
36 | | - * |
37 | | - * ## OPTIONS |
38 | | - * [--assets=<assets>] |
39 | | - * : Optional list of assets, comma separated. |
40 | | - * |
41 | 62 | * ## EXAMPLES |
42 | 63 | * |
43 | 64 | * wp cloudinary sync |
44 | 65 | * |
45 | | - * @when after_wp_load |
| 66 | + * @when after_wp_load |
| 67 | + * @since 2.5.1 |
46 | 68 | * |
47 | 69 | * @param array $args Ignored. |
48 | | - * @param array $assoc_args Passed parameters. |
| 70 | + * @param array $assoc_args Ignored. |
| 71 | + * |
| 72 | + * @return void |
49 | 73 | */ |
50 | 74 | public function sync( $args, $assoc_args ) { |
51 | 75 |
|
52 | | - \WP_CLI::log( '' ); |
53 | | - \WP_CLI::log( '╔═╗┬ ┌─┐┬ ┬┌┬┐┬┌┐┌┌─┐┬─┐┬ ┬ ╔═╗╦ ╦' ); |
54 | | - \WP_CLI::log( '║ │ │ ││ │ ││││││├─┤├┬┘└┬┘ ║ ║ ║' ); |
55 | | - \WP_CLI::log( '╚═╝┴─┘└─┘└─┘─┴┘┴┘└┘┴ ┴┴└─ ┴ ╚═╝╩═╝╩' ); |
| 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 | + ); |
56 | 91 |
|
57 | | - $assets = null; |
58 | | - if ( ! empty( $assoc_args['assets'] ) ) { |
59 | | - $assets = explode( ',', $assoc_args['assets'] ); |
60 | | - $assets = array_map( 'trim', $assets ); |
| 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' ) ); |
61 | 97 | } |
62 | | - $assets = $this->get_all_unsynced( $assets ); |
63 | 98 |
|
64 | | - if ( empty( $assets ) ) { |
| 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 | + |
65 | 139 | return; |
66 | 140 | } |
67 | | - $total = count( $assets ); |
68 | | - \WP_CLI::log( '' ); |
69 | | - \WP_CLI::log( \WP_CLI::colorize( '%gStarting Sync:%n' ) ); |
70 | | - $bar = \WP_CLI\Utils\make_progress_bar( 'Syncing ' . $total . ' assets', $total, 10 ); |
71 | | - foreach ( $assets as $index => $asset ) { |
| 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. |
72 | 178 | $file = get_attached_file( $asset ); |
73 | | - $bar->tick( 0, 'Syncing: ' . basename( $file ) . ' (' . ( $index + 1 ) . ' of ' . $total . ')' ); |
74 | | - $this->plugin->get_component( 'sync' )->managers['push']->process_assets( $asset, $bar ); |
| 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 ); |
75 | 184 | $bar->tick(); |
76 | 185 | } |
77 | | - $bar->tick( 0, 'Sync Completed.' ); |
78 | | - $bar->finish(); |
79 | | - $this->get_all_unsynced(); |
80 | | - \WP_CLI::success( 'Assets all synced' ); |
| 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 | + } |
81 | 195 | } |
82 | 196 |
|
83 | 197 | /** |
84 | | - * Allocate unsynced items to the queue threads. |
| 198 | + * Analyze and mark assets that need to be synced. |
85 | 199 | * |
86 | | - * @param array|bool $include Include already found items. |
| 200 | + * @since 2.5.1 |
87 | 201 | * |
88 | | - * @return array |
| 202 | + * @param array $posts Array of Post IDs to process. |
| 203 | + * @param int $total Count of total posts to process. |
89 | 204 | */ |
90 | | - private function get_all_unsynced( $include = false ) { |
91 | | - |
92 | | - $params = array( |
93 | | - 'post_type' => 'attachment', |
94 | | - 'post_status' => 'inherit', |
95 | | - 'fields' => 'ids', |
96 | | - 'posts_per_page' => - 1, |
97 | | - ); |
| 205 | + protected function process_analyze( $posts, $total ) { |
| 206 | + static $bar, $done, $info; |
98 | 207 |
|
99 | | - if ( ! empty( $include ) ) { |
100 | | - $params['post__in'] = $include; |
| 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 | + ); |
101 | 217 | } |
102 | | - $ids = array(); |
103 | | - |
104 | | - $query = new \WP_Query( $params ); |
105 | | - $posts = $query->get_posts(); |
106 | | - \WP_CLI::log( '' ); |
107 | | - \WP_CLI::log( \WP_CLI::colorize( '%yAnalysing assets:%n' ) ); |
108 | | - $bar = \WP_CLI\Utils\make_progress_bar( '', $query->found_posts, 10 ); |
109 | | - $info = array( |
110 | | - '_cld_unsupported' => 0, |
111 | | - '_cld_synced' => 0, |
112 | | - '_cld_unsynced' => 0, |
113 | | - ); |
114 | | - foreach ( $posts as $index => $post ) { |
115 | | - delete_post_meta( $post, '_cld_unsupported', true ); |
116 | | - delete_post_meta( $post, '_cld_synced', true ); |
117 | | - delete_post_meta( $post, '_cld_unsynced', true ); |
| 218 | + foreach ( $posts as $index => $asset ) { |
| 219 | + $done ++; |
118 | 220 | $key = '_cld_unsupported'; |
119 | | - if ( $this->plugin->get_component( 'media' )->is_media( $post ) ) { |
| 221 | + if ( $this->plugin->get_component( 'media' )->is_media( $asset ) ) { |
120 | 222 | // Add a key. |
121 | 223 | $key = '_cld_synced'; |
122 | | - if ( ! $this->plugin->get_component( 'sync' )->is_synced( $post ) ) { |
123 | | - $key = '_cld_unsynced'; |
124 | | - $ids[] = $post; |
| 224 | + if ( ! $this->plugin->get_component( 'sync' )->is_synced( $asset ) ) { |
| 225 | + $key = '_cld_unsynced'; |
| 226 | + add_post_meta( $asset, $key, true, true ); |
125 | 227 | } |
126 | 228 | } |
127 | 229 | $info[ $key ] ++; |
128 | | - add_post_meta( $post, $key, true, true ); |
129 | | - $bar->tick( 1, $index . ' of ' . $query->found_posts . ' |' ); |
| 230 | + $bar->tick( 1, $done . ' of ' . $total . ' |' ); |
130 | 231 | } |
131 | | - $bar->tick( 0, ' ' ); |
132 | | - $bar->finish(); |
133 | | - |
134 | | - \WP_CLI::success( $query->found_posts . ' analysed.' ); |
135 | | - \WP_CLI::log( '' ); |
136 | | - \WP_CLI::log( \WP_CLI::colorize( '%gSynced%n :' ) . ' ' . $info['_cld_synced'] ); |
137 | | - \WP_CLI::log( \WP_CLI::colorize( '%yUn-synced%n :' ) . ' ' . $info['_cld_unsynced'] ); |
138 | | - \WP_CLI::log( \WP_CLI::colorize( '%rUnsupported%n :' ) . ' ' . $info['_cld_unsupported'] ); |
139 | | - \WP_CLI::log( '' ); |
140 | | - if ( ! empty( $info['_cld_unsynced'] ) ) { |
141 | | - \WP_CLI::confirm( 'Sync ' . count( $ids ) . ' assets?' ); |
142 | | - } else { |
143 | | - return; |
| 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 ); |
144 | 242 | } |
145 | | - |
146 | | - return $ids; |
147 | 243 | } |
148 | 244 | } |
0 commit comments