db_table = $wpdb->prefix . 'advaipbl_cache'; } /** * Retrieves a value from the custom cache table. * * @param string $key The cache key. * @param bool $get_full_object Whether to return the full row object (including expiry). * @return mixed The cached value, or false if not found/expired. */ public function get($key, $get_full_object = false) { global $wpdb; if (! $this->db_table) { return false; } // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter $query = $wpdb->prepare( "SELECT cache_value, expires_at FROM {$this->db_table} WHERE cache_key = %s", $key ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter $row = $wpdb->get_row($query, ARRAY_A); if (! $row) { return false; } if (time() > $row['expires_at']) { $this->delete($key); return false; } $value = maybe_unserialize($row['cache_value']); if ($get_full_object) { return [ 'value' => $value, 'expires_at' => $row['expires_at'] ]; } return $value; } /** * Saves a value to the custom cache table. * * @param string $key The cache key. * @param mixed $value The value to store (will be serialized). * @param int $expiration TTL in seconds. * @return int|false Number of rows affected or false on error. */ public function set($key, $value, $expiration) { global $wpdb; $serialized_value = maybe_serialize($value); $expires_at = time() + $expiration; // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->suppress_errors(); $result = $wpdb->query($wpdb->prepare( "REPLACE INTO {$this->db_table} (cache_key, cache_value, expires_at) VALUES (%s, %s, %d)", $key, $serialized_value, $expires_at )); $wpdb->show_errors(); return $result; // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching } /** * Deletes a specific cache key. * * @param string $key The cache key. * @return int|false Number of rows affected. */ public function delete($key) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->delete($this->db_table, ['cache_key' => $key]); } /** * Cleans up all expired entries. * Should be called via Cron. * * @return int|false Number of rows deleted. */ public function cleanup_expired() { global $wpdb; // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->suppress_errors(); $result = $wpdb->query($wpdb->prepare( "DELETE FROM {$this->db_table} WHERE expires_at < %d", time() )); $wpdb->show_errors(); return $result; // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching } }