args['status'] ?? '' ) ? 'canceled' : 'complete'; } /** * {@inheritDoc} Days of the effective retention (rounded down). */ public function threshold(): ?int { return intdiv( ActionHistory::retention_seconds(), DAY_IN_SECONDS ); } /** * The cutoff (UTC). * * @param array $state State with a fixed `cutoff` timestamp, if any. * @return \DateTime */ private static function cutoff( array $state = array() ): \DateTime { $time = isset( $state['cutoff'] ) ? (int) $state['cutoff'] : time() - ActionHistory::retention_seconds(); return new \DateTime( '@' . $time ); } /** * {@inheritDoc} * * @param array $state State from the last call. * @param float $budget Seconds to spend. * @return array{count: int, done: bool, state: array} */ public function count( array $state, float $budget ): array { return array( 'count' => ActionHistory::count_old( $this->status(), self::cutoff() ), 'done' => true, 'state' => array(), ); } /** * {@inheritDoc} * * @param array $state State from the last call. * @param int $batch Rows per statement. * @param float $budget Seconds to spend. * @return array{deleted: int, skipped: int, notes: array, done: bool, state: array} */ public function clean( array $state, int $batch, float $budget ): array { $cutoff = self::cutoff( $state ); $result = ActionHistory::purge_step( $this->status(), $cutoff, max( 20, min( 1000, $batch ) ), $budget, 'database-cleanup' ); $out = self::cleaned( array( 'cutoff' => $cutoff->getTimestamp() ), (bool) $result['done'] ); if ( ! $result['done'] && 0 === (int) $result['deleted'] ) { $out['done'] = true; // Nothing more can be deleted (another process holds them): stop, don't loop. } $out['deleted'] = (int) $result['deleted']; return $out; } /** * {@inheritDoc} ID, hook and date; never arguments. * * @param int $limit Rows (at most 10). * @return array{columns: array, rows: array>} */ public function sample( int $limit = 10 ): array { global $wpdb; $table = ActionHistory::tables()['actions']; $date = gmdate( 'Y-m-d H:i:s', self::cutoff()->getTimestamp() ); $column = ActionHistory::date_column( $this->status() ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a few rows for the sample. $rows = (array) $wpdb->get_results( $wpdb->prepare( 'SELECT action_id, hook, %i AS happened FROM %i WHERE status = %s AND %i <= %s LIMIT %d', $column, $table, $this->status(), $column, $date, max( 1, min( 10, $limit ) ) ) ); $out = array(); foreach ( $rows as $row ) { $out[] = array( 'id' => self::cell( $row->action_id ), 'hook' => self::cell( $row->hook ), 'date' => self::date_cell( (int) strtotime( $row->happened . ' UTC' ) ), ); } return array( 'columns' => array( 'id' => __( 'Action ID', 'admin-powerups-for-woocommerce' ), 'hook' => __( 'Hook', 'admin-powerups-for-woocommerce' ), 'date' => 'canceled' === $this->status() ? __( 'Scheduled for', 'admin-powerups-for-woocommerce' ) : __( 'Last run', 'admin-powerups-for-woocommerce' ), ), 'rows' => $out, ); } }