prefix . 'wc_download_log'; } /** * Cutoff as a MySQL date (UTC). * * @param array $state State with a fixed `cutoff`, if any. * @return string */ private function cutoff( array $state = array() ): string { if ( isset( $state['cutoff'] ) && is_string( $state['cutoff'] ) ) { return $state['cutoff']; } return gmdate( 'Y-m-d H:i:s', time() - (int) $this->threshold() * DAY_IN_SECONDS ); } /** * {@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 { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- live count on the timestamp index. $count = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE timestamp < %s', self::table(), $this->cutoff() ) ); return array( 'count' => $count, '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 { global $wpdb; $state = array( 'cutoff' => $this->cutoff( $state ) ); $out = self::cleaned( $state, false ); $start = microtime( true ); do { // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- bounded delete in index order; the age condition is part of the DELETE. $gone = (int) $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE timestamp < %s ORDER BY timestamp LIMIT %d', self::table(), $state['cutoff'], $batch ) ); $out['deleted'] += max( 0, $gone ); if ( $gone < $batch || '' !== $wpdb->last_error ) { $out['done'] = '' === $wpdb->last_error; break; } } while ( self::time_left( $start, $budget ) ); return $out; } /** * {@inheritDoc} * * @param int $limit Rows (at most 10). * @return array{columns: array, rows: array>} */ public function sample( int $limit = 10 ): array { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a few rows for the sample. $rows = (array) $wpdb->get_results( $wpdb->prepare( 'SELECT download_log_id, timestamp, permission_id, user_id, user_ip_address FROM %i WHERE timestamp < %s ORDER BY timestamp LIMIT %d', self::table(), $this->cutoff(), max( 1, min( 10, $limit ) ) ) ); $out = array(); foreach ( $rows as $row ) { $out[] = array( 'id' => self::cell( $row->download_log_id ), 'date' => self::date_cell( (int) strtotime( $row->timestamp . ' UTC' ) ), 'permission' => self::cell( $row->permission_id ), 'user' => self::cell( $row->user_id ), 'ip' => self::mask_ip( (string) $row->user_ip_address ), ); } return array( 'columns' => array( 'id' => __( 'Log ID', 'admin-powerups-for-woocommerce' ), 'date' => __( 'Downloaded', 'admin-powerups-for-woocommerce' ), 'permission' => __( 'Permission ID', 'admin-powerups-for-woocommerce' ), 'user' => __( 'User ID', 'admin-powerups-for-woocommerce' ), 'ip' => __( 'IP address', 'admin-powerups-for-woocommerce' ), ), 'rows' => $out, ); } }