|
7 | 7 |
|
8 | 8 | namespace Cloudinary; |
9 | 9 |
|
10 | | -use Cloudinary\Plugin; |
| 10 | +use Cloudinary\Traits\CLI_Trait; |
11 | 11 |
|
12 | 12 | /** |
13 | 13 | * CLI class. |
14 | 14 | * |
15 | 15 | * @since 2.5.1 |
16 | 16 | */ |
17 | | -class CLI { |
| 17 | +class CLI extends \WP_CLI_Command { // phpcs:ignore WordPressVIPMinimum.Classes.RestrictedExtendClasses.wp_cli |
18 | 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 | | - $this->plugin = $plugin; |
54 | | - } |
55 | | - |
56 | | - /** |
57 | | - * Output the Intro. |
58 | | - * |
59 | | - * @since 2.5.1 |
60 | | - */ |
61 | | - public function do_intro() { |
62 | | - static $intro; |
63 | | - if ( ! $intro ) { |
64 | | - \WP_CLI::log( '' ); |
65 | | - \WP_CLI::log( '╔═╗┬ ┌─┐┬ ┬┌┬┐┬┌┐┌┌─┐┬─┐┬ ┬ ╔═╗╦ ╦' ); |
66 | | - \WP_CLI::log( '║ │ │ ││ │ ││││││├─┤├┬┘└┬┘ ║ ║ ║' ); |
67 | | - \WP_CLI::log( '╚═╝┴─┘└─┘└─┘─┴┘┴┘└┘┴ ┴┴└─ ┴ ╚═╝╩═╝╩' ); |
68 | | - $intro = true; |
69 | | - } |
70 | | - } |
71 | | - |
72 | | - /** |
73 | | - * Syncs assets with Cloudinary. |
74 | | - * ## EXAMPLES |
75 | | - * |
76 | | - * wp cloudinary sync |
77 | | - * |
78 | | - * @when after_wp_load |
79 | | - * @since 2.5.1 |
80 | | - * |
81 | | - * @param array $args Ignored. |
82 | | - * @param array $assoc_args Ignored. |
83 | | - * |
84 | | - * @return void |
85 | | - */ |
86 | | - public function sync( $args, $assoc_args ) { |
87 | | - |
88 | | - // Check if analyzed first. |
89 | | - if ( empty( get_option( '_cld_cli_analyzed' ) ) ) { |
90 | | - $this->analyze(); |
91 | | - } |
92 | | - |
93 | | - // Initial Query. |
94 | | - $query_args = $this->base_query_args; |
95 | | - // phpcs:ignore WordPress.DB.SlowDBQuery |
96 | | - $query_args['meta_query'] = array( |
97 | | - 'AND', |
98 | | - array( |
99 | | - 'key' => '_cld_unsynced', |
100 | | - 'compare' => 'EXISTS', |
101 | | - ), |
102 | | - ); |
103 | | - |
104 | | - // Get assets that need to be synced. |
105 | | - $query = new \WP_Query( $query_args ); |
106 | | - $this->do_process( $query, 'sync' ); |
107 | | - if ( ! $query->have_posts() ) { |
108 | | - \WP_CLI::log( \WP_CLI::colorize( '%gAll assets synced.%n' ) ); |
109 | | - } |
110 | | - |
111 | | - } |
| 19 | + use CLI_Trait; |
112 | 20 |
|
113 | 21 | /** |
114 | | - * Analyze assets with Cloudinary. |
115 | | - * ## EXAMPLES |
116 | | - * |
117 | | - * wp cloudinary analyze |
118 | | - * |
119 | | - * @when after_wp_load |
120 | | - * @since 2.5.1 |
121 | | - * |
122 | | - * @return void |
| 22 | + * Workaround to prevent memory leaks from growing variables |
123 | 23 | */ |
124 | | - public function analyze() { |
125 | | - |
126 | | - // Initial query. |
127 | | - $query_args = $this->base_query_args; |
128 | | - $query = new \WP_Query( $query_args ); |
129 | | - |
130 | | - // Kill all _cld_ related meta. |
131 | | - delete_post_meta_by_key( '_cld_unsynced' ); |
132 | | - delete_option( '_cld_cli_analyzed' ); |
133 | | - |
134 | | - // Do process. |
135 | | - $this->do_process( $query, 'analyze' ); |
136 | | - } |
137 | | - |
138 | | - /** |
139 | | - * Do a process on the query. |
140 | | - * |
141 | | - * @since 2.5.1 |
142 | | - * |
143 | | - * @param \WP_Query $query The initial query object. |
144 | | - * @param string $process The process to do. |
145 | | - */ |
146 | | - protected function do_process( &$query, $process ) { |
147 | | - $this->do_intro(); |
148 | | - |
149 | | - // Bail early. |
150 | | - if ( ! method_exists( $this, "process_{$process}" ) ) { |
151 | | - \WP_CLI::log( \WP_CLI::colorize( "%Invalid Process: {$process}.%n" ) ); |
152 | | - |
153 | | - return; |
154 | | - } |
155 | | - if ( method_exists( $this, $process ) ) { |
156 | | - // Setup process. |
157 | | - $total = $query->found_posts; |
158 | | - $process = "process_{$process}"; |
159 | | - do { |
160 | | - $posts = $query->get_posts(); |
161 | | - $this->{$process}( $posts, $total ); |
162 | | - |
163 | | - // Free up memory. |
164 | | - if ( method_exists( $this, 'stop_the_insanity' ) ) { |
165 | | - $this->stop_the_insanity(); |
166 | | - } |
167 | | - |
168 | | - // Paginate. |
169 | | - $query_args = $query->query_vars; |
170 | | - $query_args['paged'] ++; |
171 | | - $query = new \WP_Query( $query_args ); |
172 | | - } while ( $query->have_posts() ); |
173 | | - } |
174 | | - \WP_CLI::line( '' ); |
175 | | - } |
176 | | - |
177 | | - /** |
178 | | - * Sync Assets. |
179 | | - * |
180 | | - * @param array $posts Array of Post IDs to process. |
181 | | - * @param int $total Count of total posts to process. |
182 | | - */ |
183 | | - protected function process_sync( $posts, $total ) { |
184 | | - static $bar, $done; |
185 | | - if ( ! $bar && ! empty( $posts ) ) { |
186 | | - \WP_CLI::log( \WP_CLI::colorize( '%gSyncing assets%n' ) ); |
187 | | - $bar = \WP_CLI\Utils\make_progress_bar( 'Syncing ' . $total . ' assets', $total, 10 ); |
188 | | - $done = 0; |
189 | | - } |
190 | | - foreach ( $posts as $index => $asset ) { |
191 | | - $done ++; // Set $done early to not show 0 of x. |
192 | | - $file = get_attached_file( $asset ); |
193 | | - $filename = self::pad_name( basename( $file ), 20, ' ', '*' ); |
194 | | - $bar->tick( 0, 'Syncing (' . ( $done ) . ' of ' . $total . ') : ' . $filename ); |
195 | | - if ( ! $this->plugin->get_component( 'sync' )->is_synced( $asset ) ) { |
196 | | - $this->plugin->get_component( 'sync' )->managers['push']->process_assets( $asset, $bar ); |
| 24 | + protected function stop_the_insanity() { |
| 25 | + global $wpdb, $wp_object_cache; |
| 26 | + $wpdb->queries = array(); |
| 27 | + if ( is_object( $wp_object_cache ) ) { |
| 28 | + $wp_object_cache->group_ops = array(); |
| 29 | + $wp_object_cache->stats = array(); |
| 30 | + $wp_object_cache->memcache_debug = array(); |
| 31 | + $wp_object_cache->cache = array(); |
| 32 | + if ( method_exists( $wp_object_cache, '__remoteset' ) ) { |
| 33 | + $wp_object_cache->__remoteset(); |
197 | 34 | } |
198 | | - delete_post_meta( $asset, '_cld_unsynced', true ); |
199 | | - $bar->tick(); |
200 | 35 | } |
201 | | - // Done message - reanalyze. |
202 | | - if ( $done === $total ) { |
203 | | - $bar->tick( 0, 'Sync Completed.' ); |
204 | | - $bar->finish(); |
205 | | - $bar = null; |
206 | | - \WP_CLI::line( '' ); |
207 | | - $this->analyze(); |
208 | | - delete_option( '_cld_cli_analyzed' ); |
209 | | - } |
210 | | - } |
211 | | - |
212 | | - /** |
213 | | - * Analyze and mark assets that need to be synced. |
214 | | - * |
215 | | - * @since 2.5.1 |
216 | | - * |
217 | | - * @param array $posts Array of Post IDs to process. |
218 | | - * @param int $total Count of total posts to process. |
219 | | - */ |
220 | | - protected function process_analyze( $posts, $total ) { |
221 | | - static $bar, $done, $info; |
222 | | - |
223 | | - if ( ! $bar ) { |
224 | | - \WP_CLI::log( \WP_CLI::colorize( '%gAnalyzing ' . $total . ' assets:%n' ) ); |
225 | | - $bar = \WP_CLI\Utils\make_progress_bar( '', $total, 10 ); |
226 | | - $done = 0; |
227 | | - $info = array( |
228 | | - '_cld_unsupported' => 0, |
229 | | - '_cld_synced' => 0, |
230 | | - '_cld_unsynced' => 0, |
231 | | - ); |
232 | | - } |
233 | | - foreach ( $posts as $index => $asset ) { |
234 | | - $done ++; |
235 | | - $key = '_cld_unsupported'; |
236 | | - if ( $this->plugin->get_component( 'media' )->is_media( $asset ) ) { |
237 | | - // Add a key. |
238 | | - $key = '_cld_synced'; |
239 | | - if ( ! $this->plugin->get_component( 'sync' )->is_synced( $asset ) ) { |
240 | | - $key = '_cld_unsynced'; |
241 | | - add_post_meta( $asset, $key, true, true ); |
242 | | - } |
243 | | - } |
244 | | - $info[ $key ] ++; |
245 | | - $bar->tick( 1, $done . ' of ' . $total . ' |' ); |
246 | | - } |
247 | | - // Done message. |
248 | | - if ( $done === $total ) { |
249 | | - $bar->tick( 0, $total . ' Analyzed |' ); |
250 | | - $bar->finish(); |
251 | | - $bar = null; |
252 | | - \WP_CLI::log( '' ); |
253 | | - \WP_CLI::log( \WP_CLI::colorize( '%gSynced%n :' ) . ' ' . $info['_cld_synced'] ); |
254 | | - \WP_CLI::log( \WP_CLI::colorize( '%yUn-synced%n :' ) . ' ' . $info['_cld_unsynced'] ); |
255 | | - \WP_CLI::log( \WP_CLI::colorize( '%rUnsupported%n :' ) . ' ' . $info['_cld_unsupported'] ); |
256 | | - update_option( '_cld_cli_analyzed', true, false ); |
257 | | - } |
258 | | - } |
259 | | - |
260 | | - /** |
261 | | - * Pad a file name to fit within max chars. |
262 | | - * |
263 | | - * @param string $name The name to pad. |
264 | | - * @param int $max_length The max length of the filename. |
265 | | - * @param string $pad_char The pad char to use when name is less of the max. |
266 | | - * @param string $concat_char The char to use when shortening names to fit. |
267 | | - * |
268 | | - * @return string |
269 | | - */ |
270 | | - protected static function pad_name( $name, $max_length, $pad_char = '.', $concat_char = '*' ) { |
271 | | - $name_length = strlen( $name ); |
272 | | - $prefix = null; |
273 | | - if ( $name_length > $max_length ) { |
274 | | - $diff = $name_length - $max_length; |
275 | | - $concat_length = $diff > 3 ? 3 : $diff; |
276 | | - $usable_length = $max_length - $concat_length; |
277 | | - $front = substr( $name, 0, floor( $usable_length / 2 ) ); |
278 | | - $back = substr( $name, strlen( $name ) - ceil( $usable_length / 2 ) ); |
279 | | - $name = $front . implode( array_fill( 0, $concat_length, $concat_char ) ) . $back; |
280 | | - } |
281 | | - $used_length = $max_length - strlen( $name ); |
282 | | - if ( 0 < $used_length ) { |
283 | | - $prefix = implode( array_fill( 0, $used_length, $pad_char ) ); |
284 | | - } |
285 | | - $out = $prefix . $name; |
286 | | - |
287 | | - return $out; |
288 | 36 | } |
289 | 37 | } |
0 commit comments