@@ -220,6 +220,139 @@ public function type() {
220220 WP_CLI ::line ( $ message );
221221 }
222222
223+ /**
224+ * Lists transients and their values.
225+ *
226+ * ## OPTIONS
227+ *
228+ * [--network]
229+ * : Get the values of network|site transients. On single site, this is
230+ * is a specially-named cache key. On multisite, this is a global cache
231+ * (instead of local to the site).
232+ *
233+ * [--unserialize]
234+ * : Unserialize transient values in output.
235+ *
236+ * [--fields=<fields>]
237+ * : Limit the output to specific object fields.
238+ *
239+ * [--format=<format>]
240+ * : The serialization format for the value.
241+ * ---
242+ * default: table
243+ * options:
244+ * - table
245+ * - json
246+ * - csv
247+ * - count
248+ * - yaml
249+ * ---
250+ *
251+ * ## AVAILABLE FIELDS
252+ *
253+ * This field will be displayed by default for each matching option:
254+ *
255+ * * name
256+ * * value
257+ * * expiration
258+ *
259+ * ## EXAMPLES
260+ *
261+ * # List all transients
262+ * $ wp transient list
263+ * +------+-------+---------------+
264+ * | name | value | expiration |
265+ * +------+-------+---------------+
266+ * | foo | bar | 39 mins |
267+ * | foo2 | bar2 | no expiration |
268+ * | foo3 | bar2 | expired |
269+ * | foo4 | bar4 | 4 hours |
270+ * +------+-------+---------------+
271+ *
272+ * @subcommand list
273+ */
274+ public function _list ( $ args , $ assoc_args ) {
275+ global $ wpdb ;
276+
277+ $ fields = array ( 'name ' , 'value ' , 'expiration ' );
278+ $ network = \WP_CLI \Utils \get_flag_value ( $ assoc_args , 'network ' , false );
279+ $ unserialize = \WP_CLI \Utils \get_flag_value ( $ assoc_args , 'unserialize ' , false );
280+
281+ if ( isset ( $ assoc_args ['fields ' ] ) ) {
282+ $ fields = explode ( ', ' , $ assoc_args ['fields ' ] );
283+ }
284+
285+ if ( $ network ) {
286+ if ( is_multisite () ) {
287+ $ query = $ wpdb ->prepare (
288+ "SELECT `meta_key` as `name`, `meta_value` as `value` FROM {$ wpdb ->sitemeta } WHERE meta_key LIKE %s AND meta_key NOT LIKE %s " ,
289+ \WP_CLI \Utils \esc_like ( '_site_transient_ ' ) . '% ' ,
290+ \WP_CLI \Utils \esc_like ( '_site_transient_timeout_ ' ) . '% '
291+ );
292+ } else {
293+ $ query = $ wpdb ->prepare (
294+ "SELECT `option_name` as `name`, `option_value` as `value` FROM {$ wpdb ->options } WHERE option_name LIKE %s AND option_name NOT LIKE %s " ,
295+ \WP_CLI \Utils \esc_like ( '_site_transient_ ' ) . '% ' ,
296+ \WP_CLI \Utils \esc_like ( '_site_transient_timeout_ ' ) . '% '
297+ );
298+ }
299+ } else {
300+ $ query = $ wpdb ->prepare (
301+ "SELECT `option_name` as `name`, `option_value` as `value` FROM {$ wpdb ->options } WHERE option_name LIKE %s AND option_name NOT LIKE %s " ,
302+ \WP_CLI \Utils \esc_like ( '_transient_ ' ) . '% ' ,
303+ \WP_CLI \Utils \esc_like ( '_transient_timeout_ ' ) . '% '
304+ );
305+ }
306+
307+ $ results = $ wpdb ->get_results ( $ query );
308+
309+ foreach ( $ results as $ result ) {
310+ $ result ->name = str_replace ( array ( '_site_transient_ ' , '_transient_ ' ), '' , $ result ->name );
311+ $ result ->expiration = $ this ->get_transient_expiration ( $ result ->name , $ network );
312+
313+ if ( $ unserialize ) {
314+ $ result ->value = maybe_unserialize ( $ result ->value );
315+ }
316+ }
317+
318+ $ formatter = new \WP_CLI \Formatter (
319+ $ assoc_args ,
320+ $ fields
321+ );
322+ $ formatter ->display_items ( $ results );
323+ }
324+
325+ /**
326+ * Retrieves the human-friendly expiration time.
327+ *
328+ * @param string $name Transient name.
329+ * @param bool $is_site_transient Optional. Whether this is a site transient. Default false.
330+ * @return string Expiration time string.
331+ */
332+ private function get_transient_expiration ( $ name , $ is_site_transient = false ) {
333+ if ( $ is_site_transient ) {
334+ if ( is_multisite () ) {
335+ $ expiration = (int ) get_site_option ( '_site_transient_timeout_ ' . $ name );
336+ } else {
337+ $ expiration = (int ) get_option ( '_site_transient_timeout_ ' . $ name );
338+ }
339+ } else {
340+ $ expiration = (int ) get_option ( '_transient_timeout_ ' . $ name );
341+ }
342+
343+ if ( 0 === $ expiration ) {
344+ return 'no expiration ' ;
345+ }
346+
347+ $ now = time ();
348+
349+ if ( $ now > $ expiration ) {
350+ return 'expired ' ;
351+ }
352+
353+ return human_time_diff ( $ now , $ expiration );
354+ }
355+
223356 /**
224357 * Deletes all expired transients.
225358 */
0 commit comments