*/ public static function get() { $cached = get_transient( self::cache_key() ); if ( is_array( $cached ) && isset( $cached['total'], $cached['pending'], $cached['converted'], $cached['saved_bytes'] ) ) { return self::present( $cached ); } $counts = self::query(); set_transient( self::cache_key(), $counts, 30 ); return self::present( $counts ); } /** * Cache key scoped to the user when they cannot see the whole library. * * @return string */ private static function cache_key() { if ( Capabilities::can_see_all() ) { return self::CACHE_KEY; } return self::CACHE_KEY . '_' . get_current_user_id(); } /** * Run the count queries. * * @return array */ private static function query() { global $wpdb; // Zero means every author. The comparison stays inside prepare() so no SQL fragment is concatenated. $author_id = Capabilities::can_see_all() ? 0 : get_current_user_id(); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregate counts have no API. Results are cached by this class. $total = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->posts} p WHERE p.post_type = 'attachment' AND p.post_status != 'trash' AND p.post_mime_type IN ( %s, %s, %s, %s ) AND ( %d = 0 OR p.post_author = %d )", 'image/jpeg', 'image/png', 'image/gif', 'image/webp', $author_id, $author_id ) ); $pending = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( DISTINCT p.ID ) FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} m ON m.post_id = p.ID AND m.meta_key = %s WHERE p.post_type = 'attachment' AND p.post_status != 'trash' AND p.post_mime_type IN ( %s, %s, %s ) AND ( m.meta_id IS NULL OR m.meta_value NOT IN ( %s, %s ) ) AND ( %d = 0 OR p.post_author = %d )", '_flipwebp_status', 'image/jpeg', 'image/png', 'image/gif', 'converted', 'skipped', $author_id, $author_id ) ); $converted = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( DISTINCT p.ID ) FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} m ON m.post_id = p.ID AND m.meta_key = %s AND m.meta_value = %s WHERE p.post_type = 'attachment' AND p.post_status != 'trash' AND ( %d = 0 OR p.post_author = %d )", '_flipwebp_status', 'converted', $author_id, $author_id ) ); $saved = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE( SUM( CAST( m.meta_value AS UNSIGNED ) ), 0 ) FROM {$wpdb->postmeta} m INNER JOIN {$wpdb->posts} p ON p.ID = m.post_id WHERE m.meta_key = %s AND p.post_type = 'attachment' AND p.post_status != 'trash' AND ( %d = 0 OR p.post_author = %d )", '_flipwebp_saved_bytes', $author_id, $author_id ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return array( 'total' => max( 0, $total ), 'pending' => max( 0, $pending ), 'converted' => max( 0, $converted ), 'saved_bytes' => max( 0, $saved ), ); } /** * Add translated labels to raw counts. * * @param array $counts Raw counts. * @return array */ private static function present( $counts ) { $saved = (int) $counts['saved_bytes']; return array( 'total' => (int) $counts['total'], 'pending' => (int) $counts['pending'], 'converted' => (int) $counts['converted'], 'saved_bytes' => $saved, 'total_label' => number_format_i18n( (int) $counts['total'] ), 'pending_label' => number_format_i18n( (int) $counts['pending'] ), 'converted_label' => number_format_i18n( (int) $counts['converted'] ), 'saved_label' => size_format( $saved, 1 ), ); } }