failed_last_week() ); } /** * Pure evaluation. * * @param int|null $failed Failed actions in the last 7 days, null if Action Scheduler tables are missing. * @return Result[] */ public static function evaluate( ?int $failed ): array { if ( null === $failed ) { return array(); } if ( 0 === $failed ) { return array( new Result( 'woocommerce.actions', Result::GOOD, __( 'No failed background jobs in the last 7 days', 'keepwatch' ) ) ); } return array( new Result( 'woocommerce.actions', $failed >= self::CRITICAL_COUNT ? Result::CRITICAL : Result::RECOMMENDED, /* translators: %d: number of failed jobs */ sprintf( _n( '%d background job failed in the last 7 days', '%d background jobs failed in the last 7 days', $failed, 'keepwatch' ), $failed ), __( 'WooCommerce uses Action Scheduler for e-mails, webhooks and renewals. Failed jobs can mean customers did not receive something.', 'keepwatch' ), admin_url( 'admin.php?page=wc-status&tab=action-scheduler&status=failed' ), __( 'View failed jobs', 'keepwatch' ) ), ); } /** * Count failed actions from the last 7 days. */ private function failed_last_week(): ?int { global $wpdb; $table = $wpdb->prefix . 'actionscheduler_actions'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- single read-only COUNT, shown on admin screens only. if ( $table !== $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ) ) ) { return null; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- see above. $count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE status = %s AND last_attempt_gmt >= %s', $table, 'failed', gmdate( 'Y-m-d H:i:s', time() - WEEK_IN_SECONDS ) ) ); return null === $count ? null : (int) $count; } }