PluginProbe
ActivityPub / 9.2.1
ActivityPub v9.2.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / cli / class-cache-command.php

class-cache-command.php in ActivityPub 9.2.1, at includes/cli/class-cache-command.php

276 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cache CLI Command.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Cli;
9
10 use Activitypub\Cache;
11 use Activitypub\Cache\Avatar;
12 use Activitypub\Cache\Emoji;
13 use Activitypub\Cache\File;
14 use Activitypub\Cache\Media;
15
16 /**
17 * Manage ActivityPub remote media cache.
18 *
19 * @package Activitypub
20 */
21 class Cache_Command extends \WP_CLI_Command {
22
23 /**
24 * Clear the remote media cache.
25 *
26 * Removes cached files from the uploads directory. By default clears all
27 * cache types, or specify --type to clear only a specific cache.
28 *
29 * ## OPTIONS
30 *
31 * [--type=<type>]
32 * : The cache type to clear. If omitted, clears all caches.
33 * ---
34 * options:
35 * - avatar
36 * - media
37 * - emoji
38 * - all
39 * default: all
40 * ---
41 *
42 * [--yes]
43 * : Skip confirmation prompt.
44 *
45 * ## EXAMPLES
46 *
47 * # Clear all caches
48 * $ wp activitypub cache clear
49 *
50 * # Clear only avatar cache
51 * $ wp activitypub cache clear --type=avatar
52 *
53 * # Clear emoji cache without confirmation
54 * $ wp activitypub cache clear --type=emoji --yes
55 *
56 * @subcommand clear
57 *
58 * @param array $args The positional arguments.
59 * @param array $assoc_args The associative arguments.
60 */
61 public function clear( $args, $assoc_args ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
62 $type = $assoc_args['type'] ?? 'all';
63
64 $types_to_clear = array();
65 if ( 'all' === $type ) {
66 $types_to_clear = array( 'avatar', 'media', 'emoji' );
67 } else {
68 $types_to_clear = array( $type );
69 }
70
71 $type_label = 'all' === $type ? 'all cache types' : "{$type} cache";
72 \WP_CLI::confirm( "Are you sure you want to clear {$type_label}?", $assoc_args );
73
74 $total_cleared = 0;
75
76 foreach ( $types_to_clear as $cache_type ) {
77 $cleared = $this->clear_cache_type( $cache_type );
78 $total_cleared += $cleared;
79 \WP_CLI::log( \sprintf( 'Cleared %d %s cache directories.', $cleared, $cache_type ) );
80 }
81
82 \WP_CLI::success( \sprintf( 'Cache cleared. Total directories removed: %d', $total_cleared ) );
83 }
84
85 /**
86 * Show cache status and statistics.
87 *
88 * Displays information about cached files including count and total size
89 * for each cache type.
90 *
91 * ## OPTIONS
92 *
93 * [--format=<format>]
94 * : Output format.
95 * ---
96 * default: table
97 * options:
98 * - table
99 * - json
100 * - csv
101 * - yaml
102 * ---
103 *
104 * ## EXAMPLES
105 *
106 * # Show cache status
107 * $ wp activitypub cache status
108 *
109 * # Show status as JSON
110 * $ wp activitypub cache status --format=json
111 *
112 * @subcommand status
113 *
114 * @param array $args The positional arguments.
115 * @param array $assoc_args The associative arguments.
116 */
117 public function status( $args, $assoc_args ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
118 $upload_dir = \wp_upload_dir();
119
120 $cache_types = array(
121 'avatar' => array(
122 'label' => 'Avatars',
123 'path' => Avatar::get_base_dir(),
124 ),
125 'media' => array(
126 'label' => 'Post Media',
127 'path' => Media::get_base_dir(),
128 ),
129 'emoji' => array(
130 'label' => 'Emoji',
131 'path' => Emoji::get_base_dir(),
132 ),
133 );
134
135 $data = array();
136 $total_files = 0;
137 $total_size = 0;
138
139 foreach ( $cache_types as $type => $info ) {
140 $dir = $upload_dir['basedir'] . $info['path'];
141 $stats = $this->get_directory_stats( $dir );
142
143 $data[] = array(
144 'type' => $info['label'],
145 'enabled' => $this->is_cache_enabled( $type ) ? 'Yes' : 'No',
146 'files' => $stats['files'],
147 'size' => \size_format( $stats['size'] ),
148 'path' => $info['path'],
149 );
150
151 $total_files += $stats['files'];
152 $total_size += $stats['size'];
153 }
154
155 // Add totals row for table format.
156 if ( 'table' === ( $assoc_args['format'] ?? 'table' ) ) {
157 $data[] = array(
158 'type' => '---',
159 'enabled' => '---',
160 'files' => '---',
161 'size' => '---',
162 'path' => '---',
163 );
164 $data[] = array(
165 'type' => 'TOTAL',
166 'enabled' => '',
167 'files' => $total_files,
168 'size' => \size_format( $total_size ),
169 'path' => '/activitypub/',
170 );
171 }
172
173 $format = $assoc_args['format'] ?? 'table';
174 \WP_CLI\Utils\format_items( $format, $data, array( 'type', 'enabled', 'files', 'size', 'path' ) );
175 }
176
177 /**
178 * Clear a specific cache type.
179 *
180 * @param string $type The cache type (avatar, media, emoji).
181 *
182 * @return int Number of directories cleared.
183 */
184 private function clear_cache_type( $type ) {
185 $upload_dir = \wp_upload_dir();
186
187 switch ( $type ) {
188 case 'avatar':
189 $base_dir = $upload_dir['basedir'] . Avatar::get_base_dir();
190 break;
191 case 'media':
192 $base_dir = $upload_dir['basedir'] . Media::get_base_dir();
193 break;
194 case 'emoji':
195 $base_dir = $upload_dir['basedir'] . Emoji::get_base_dir();
196 break;
197 default:
198 return 0;
199 }
200
201 if ( ! \is_dir( $base_dir ) ) {
202 return 0;
203 }
204
205 // Count subdirectories before clearing.
206 $subdirs = \glob( $base_dir . '/*', GLOB_ONLYDIR );
207 $count = $subdirs ? \count( $subdirs ) : 0;
208
209 // Remove all subdirectories using the cache's native delete_directory helper.
210 foreach ( $subdirs as $subdir ) {
211 File::delete_directory( $subdir );
212 }
213
214 // Clean up legacy avatar URL meta from previous versions.
215 if ( 'avatar' === $type ) {
216 \delete_metadata( 'post', 0, '_activitypub_avatar_url', '', true );
217 }
218
219 return $count;
220 }
221
222 /**
223 * Get statistics for a cache directory.
224 *
225 * @param string $dir The directory path.
226 *
227 * @return array {
228 * Directory statistics.
229 *
230 * @type int $files Total number of files.
231 * @type int $size Total size in bytes.
232 * }
233 */
234 private function get_directory_stats( $dir ) {
235 $stats = array(
236 'files' => 0,
237 'size' => 0,
238 );
239
240 if ( ! \is_dir( $dir ) ) {
241 return $stats;
242 }
243
244 $iterator = new \RecursiveIteratorIterator(
245 new \RecursiveDirectoryIterator( $dir, \RecursiveDirectoryIterator::SKIP_DOTS ),
246 \RecursiveIteratorIterator::LEAVES_ONLY
247 );
248
249 foreach ( $iterator as $file ) {
250 if ( $file->isFile() ) {
251 ++$stats['files'];
252 $stats['size'] += $file->getSize();
253 }
254 }
255
256 return $stats;
257 }
258
259 /**
260 * Check if a cache type is enabled.
261 *
262 * @param string $type The cache type.
263 *
264 * @return bool True if enabled.
265 */
266 private function is_cache_enabled( $type ) {
267 // Check global cache enablement (includes constant and activitypub_remote_cache_enabled filter).
268 if ( ! Cache::is_enabled() ) {
269 return false;
270 }
271
272 // Check type-specific filter.
273 return (bool) \apply_filters( "activitypub_cache_{$type}_enabled", true );
274 }
275 }
276