From 8588874c21c08313a5b4f1768c86bad4367fb8cf Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Chenneth@users.noreply.github.com> Date: Sat, 22 Jun 2024 15:38:37 -0500 Subject: [PATCH 01/18] Create basic logic and table structure --- api/api-cache.php | 50 ++++++++++++++++++++++++++++++++++ sql/outgoing_request_cache.sql | 20 ++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 api/api-cache.php create mode 100644 sql/outgoing_request_cache.sql diff --git a/api/api-cache.php b/api/api-cache.php new file mode 100644 index 00000000..154cc336 --- /dev/null +++ b/api/api-cache.php @@ -0,0 +1,50 @@ +query('SELECT * FROM api_cache WHERE endpoint = "' . $db->real_escape_string($endpoint) . '"'); + if ($q) { + $r = $q->fetch_array(MYSQLI_ASSOC); + return $r; + } + return null; + } + + public static function getCached(string $endpoint){ + $r = self::get($endpoint); + if ($r) { + $config = $db->query('SELECT * FROM outgoing_request_cache_config WHERE id = '. $r['config_id']); + $ttl = $config['ttl']; + $now = time(); + if($now - $r['last_successfully_retrieved'] <= $ttl){ + return $r; + } + } + return null; + } + + public static function put(string $endpoint, string $content, $config){ + $r = self::get($endpoint); + $queryString = ""; + if($r) { + $id = $r['id']; + $queryString = 'UPDATE api_cache SET last_successfully_retrieved = UTC_TIMESTAMP, last_attempted_retrieval = UTC_TIMESTAMP, retry_count = 0, content =' . $db->real_escape_string($content) . 'WHERE id = . $id)'; + + } else{ + $configId = 1; + if(gettype($config) == 'integer'){ + $configId = $config; + } else if (gettype($config) == 'string'){ + $configId = $db->query('SELECT * FROM outgoing_request_cache_config WHERE config_name = "' . $db->real_escape_string($config) . '"')->fetch_array(MYSQLI_ASSOC)['id']; + } + $queryString = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_atetempted_retrieval, config_id, content) + values (" . $db->real_escape_string($endpoint) . ", UTC_TIMESTAMP, + UTC_TIMESTAMP," . $configId . ", '" . $db->real_escape_string($content) . "',)"; + } + $q = $db->query($queryString); + if($q === false){ + error_log('Failed to update API cache: ' . $db->error); + } + } +} \ No newline at end of file diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql new file mode 100644 index 00000000..1fe3ceda --- /dev/null +++ b/sql/outgoing_request_cache.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `outgoing_request_cache_config`; +CREATE TABLE `outgoing_request_cache_config`( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ttl` int(6) NOT NULL DEFAULT 86400, -- ttl measured in seconds + `config_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (id) +)ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; + +DROP TABLE IF EXISTS `api_cache`; +CREATE TABLE `api_cache`( + `id` int(11) NOT NULL AUTO_INCREMENT, + `endpoint` varchar(255) DEFAULT NULL, + `last_successfully_retrieved` datetime, + `last_attempted_retrieval` datetime DEFAULT UTC_TIMESTAMP(), + `retry_count` int DEFAULT 0, + `config_id` int(11) NOT NULL, + `content` text NOT NULL, + PRIMARY KEY (id), + FOREIGN KEY (config_id) REFERENCES outgoing_request_cache_config(id) +)ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; From caa767f0fe9e254036f4d3bd2bd5548ba087e2ca Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Chenneth@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:54:25 -0500 Subject: [PATCH 02/18] Cleanup table config --- sql/outgoing_request_cache.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index 1fe3ceda..6715a2b5 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -1,20 +1,20 @@ DROP TABLE IF EXISTS `outgoing_request_cache_config`; CREATE TABLE `outgoing_request_cache_config`( `id` int(11) NOT NULL AUTO_INCREMENT, - `ttl` int(6) NOT NULL DEFAULT 86400, -- ttl measured in seconds + `ttl` int(6) NOT NULL, -- ttl measured in seconds `config_name` varchar(255) DEFAULT NULL, PRIMARY KEY (id) -)ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; +)AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `api_cache`; CREATE TABLE `api_cache`( `id` int(11) NOT NULL AUTO_INCREMENT, - `endpoint` varchar(255) DEFAULT NULL, - `last_successfully_retrieved` datetime, - `last_attempted_retrieval` datetime DEFAULT UTC_TIMESTAMP(), + `endpoint` varchar(4000) DEFAULT NULL, + `last_successfully_retrieved` timestamp, + `last_attempted_retrieval` timestamp DEFAULT NULL, `retry_count` int DEFAULT 0, `config_id` int(11) NOT NULL, `content` text NOT NULL, PRIMARY KEY (id), FOREIGN KEY (config_id) REFERENCES outgoing_request_cache_config(id) -)ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; +)AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; From 9837f63cb49d02b58f46524f87e549de72a557b3 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Chenneth@users.noreply.github.com> Date: Fri, 28 Jun 2024 10:49:45 -0500 Subject: [PATCH 03/18] Update Printful API to use cache --- api/api-cache.php | 124 +++++++++++++++++++++++---------- api/printful/printful.php | 21 +++++- sql/outgoing_request_cache.sql | 2 + 3 files changed, 106 insertions(+), 41 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 154cc336..6638425d 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -1,50 +1,98 @@ query('SELECT * FROM api_cache WHERE endpoint = "' . $db->real_escape_string($endpoint) . '"'); - if ($q) { - $r = $q->fetch_array(MYSQLI_ASSOC); + global $db; + $q = $db->query('SELECT * FROM api_cache WHERE endpoint = "' . $db->real_escape_string($endpoint) . '"'); + if ($q) { + $r = $q->fetch_array(MYSQLI_ASSOC); + return $r; + } + return null; +} + +function getCached(string $endpoint) +{ + global $db; + $r = getFromApiCacheTable($endpoint); + if ($r) { + $config = $db->query('SELECT * FROM outgoing_request_cache_config WHERE id = ' . $r['config_id'])->fetch_array(MYSQLI_ASSOC); + $ttl = $config['ttl']; + $now = time(); + $retrievalTime = strtotime($r['last_successfully_retrieved'] . 'UTC'); + if ($now - $retrievalTime <= $ttl) { return $r; } - return null; + return false; } + return null; +} - public static function getCached(string $endpoint){ - $r = self::get($endpoint); - if ($r) { - $config = $db->query('SELECT * FROM outgoing_request_cache_config WHERE id = '. $r['config_id']); - $ttl = $config['ttl']; - $now = time(); - if($now - $r['last_successfully_retrieved'] <= $ttl){ - return $r; - } +function insertCached(string $endpoint, string $content, $config) +{ + global $db; + $r = getFromApiCacheTable($endpoint); + $queryString = ""; + if ($r) { + $id = $r['id']; + $queryString = 'UPDATE api_cache + SET last_successfully_retrieved = UTC_TIMESTAMP, + last_attempted_retrieval = UTC_TIMESTAMP, + retry_count = 0, + content =\'' . $db->real_escape_string($content) . '\' + WHERE id = ' . $id; + + } else { + $configId = 1; + if (gettype($config) == 'integer') { + $configId = $config; + } else if (gettype($config) == 'string') { + $configId = $db->query('SELECT * FROM outgoing_request_cache_config WHERE config_name = "' . $db->real_escape_string($config) . '"')->fetch_array(MYSQLI_ASSOC)['id']; } - return null; + $queryString = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) + values ('" . $db->real_escape_string($endpoint) . "', UTC_TIMESTAMP, + UTC_TIMESTAMP," . $configId . ", '" . $db->real_escape_string($content) . "')"; + } + $q = $db->query($queryString); + if ($q === false) { + error_log('Failed to update API cache: ' . $db->error); + } +} + +function clearCached(string $endpoint = null){ + global $db; + if ($endpoint) { + $queryString = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; + } else{ + $queryString = "DELETE FROM api_cache"; + } + $q = $db->query($queryString); + if ($q === false) { + error_log("Failed to clear API cache: " . $db->error); } +} - public static function put(string $endpoint, string $content, $config){ - $r = self::get($endpoint); - $queryString = ""; - if($r) { - $id = $r['id']; - $queryString = 'UPDATE api_cache SET last_successfully_retrieved = UTC_TIMESTAMP, last_attempted_retrieval = UTC_TIMESTAMP, retry_count = 0, content =' . $db->real_escape_string($content) . 'WHERE id = . $id)'; +function addNewCacheConfig(int $ttl, $config_name = null) +{ + global $db; + if ($config_name) { + return $db->query('INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (' . $ttl . ', "' . $db->real_escape_string($config_name) . '")'); + } + return $db->query('INSERT INTO outgoing_request_cache_config (ttl) VALUES (' . $ttl . ')'); +} - } else{ - $configId = 1; - if(gettype($config) == 'integer'){ - $configId = $config; - } else if (gettype($config) == 'string'){ - $configId = $db->query('SELECT * FROM outgoing_request_cache_config WHERE config_name = "' . $db->real_escape_string($config) . '"')->fetch_array(MYSQLI_ASSOC)['id']; - } - $queryString = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_atetempted_retrieval, config_id, content) - values (" . $db->real_escape_string($endpoint) . ", UTC_TIMESTAMP, - UTC_TIMESTAMP," . $configId . ", '" . $db->real_escape_string($content) . "',)"; - } - $q = $db->query($queryString); - if($q === false){ - error_log('Failed to update API cache: ' . $db->error); - } +function updateCacheConfig(int $id, $config_name = null, $ttl = null){ + global $db; + if($config_name === null){ + if($ttl === null) + return; + $queryString = 'UPDATE outgoing_request_cache_config SET ttl = ' . $ttl . ' WHERE id = ' . $id; + } else if($ttl === null){ + $queryString = "UPDATE outgoing_request_cache_config SET config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + } else{ + $queryString = "UPDATE outgoing_request_cache_config SET ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + } + $q = $db->query($queryString); + if(!$q){ + error_log('Failed to update API cache config: ' . $db->error); } } \ No newline at end of file diff --git a/api/printful/printful.php b/api/printful/printful.php index 8e63967f..9fb7ed50 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -1,5 +1,5 @@ api_key; - curl_setopt($ch, CURLOPT_URL, 'https://api.printful.com/' . $URI); + curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if ($data !== false) { @@ -41,7 +53,9 @@ protected function send_request($URI, $data = false) { } curl_close($ch); - + if(!$isOrder){ + insertCached($endpoint, $result, 1); + } return json_decode($result); } @@ -98,6 +112,7 @@ public function get_products($search_string = "") { if (!empty($search_string)) { $search_string = "&search=" . $search_string; } + echo 'test'; $products_results = $this->send_request("store/products?limit=5" . $search_string); $parsed_products_results = $this->parse_results($products_results); diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index 6715a2b5..c1b183e6 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -1,4 +1,6 @@ +SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS `outgoing_request_cache_config`; +SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE `outgoing_request_cache_config`( `id` int(11) NOT NULL AUTO_INCREMENT, `ttl` int(6) NOT NULL, -- ttl measured in seconds From fd89fc43d90924bd850de9d909c75750f9f32381 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Chenneth@users.noreply.github.com> Date: Fri, 28 Jun 2024 12:02:07 -0500 Subject: [PATCH 04/18] Add documentation --- api/api-cache.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/api/api-cache.php b/api/api-cache.php index 6638425d..8bbfdfcb 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -1,4 +1,11 @@ query('INSERT INTO outgoing_request_cache_config (ttl) VALUES (' . $ttl . ')'); } +/** + * Updates the information of one of the cache configs. Does nothing if both $config_name and $ttl are null + * @param int $id The ID of the config to be updated + * @param string|null $config_name (optional) The name of the config + * @param int|null $ttl (optional) The time to live for cached entries, measured in seconds + */ function updateCacheConfig(int $id, $config_name = null, $ttl = null){ global $db; if($config_name === null){ From 7cb4d48d92ed8b96f4b83fad0e49a547c37e9203 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:47:38 -0500 Subject: [PATCH 05/18] Refactor and make api-cache.php execute cURL instead --- api/api-cache.php | 165 +++++++++++++++++++++++++------------- api/printful/printful.php | 43 ++++------ 2 files changed, 123 insertions(+), 85 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 8bbfdfcb..60a56ceb 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -1,12 +1,14 @@ query('SELECT * FROM api_cache WHERE endpoint = "' . $db->real_escape_string($endpoint) . '"'); @@ -17,38 +19,86 @@ function getFromApiCacheTable(string $endpoint) return null; } +class CacheResult{ + /** + * @var string $content The response content + */ + public $content; + /** + * @var bool $curl_executed true if curl_exec was called, false otherwise + */ + public $curl_executed; + /** + * @var int|null $httpcode HTTP response code from cURL. Null if curl_exec wasn't called + * @var int|null $curl_errno cURL error number. Null if curl_exec wasn't called + */ + public $httpcode, $curl_errno; + + /** + * @param string $content + * @param bool $curl_executed Defaults to false + * @param int|null $httpcode (optional) + * @param int|null $curl_errno (optional) + */ + public function __construct(string $content, bool $curl_executed = false, $httpcode = null, $curl_errno = null) + { + $this->content = $content; + $this->curl_executed = $curl_executed; + $this->httpcode = $httpcode; + $this->curl_errno = $curl_errno; + } +} + /** * Gets the first entry from the API cache that has a matching endpoint. Will not return if the entry is expired. * @param string $endpoint The endpoint for the API request - * @return array|false|null The first entry that matches, false if the entry is expired, or null if no entry exists + * @param resource|CurlHandle $ch The Curl Handle to send the request + * @param int|null $configId (optional) The config ID for the cached response. Optional if result won't be cached + * @return CacheResult An object containing the response content, and some cURL info if curl_exec was called */ -function getCached(string $endpoint) +function get_valid_cache_entry(string $endpoint, $ch, $configId = null) { global $db; - $r = getFromApiCacheTable($endpoint); - if ($r) { - $config = $db->query('SELECT * FROM outgoing_request_cache_config WHERE id = ' . $r['config_id'])->fetch_array(MYSQLI_ASSOC); - $ttl = $config['ttl']; + if (preg_match(IGNORED_ENDPOINTS, $endpoint)) { + return new CacheResult(curl_exec($ch),true,curl_getinfo($ch,CURLINFO_HTTP_CODE),curl_errno($ch)); + } + $q = $db->query("SELECT + * + FROM + api_cache + JOIN + outgoing_request_cache_config + ON + api_cache.config_id = outgoing_request_cache_config.id + WHERE + endpoint = '{$db->real_escape_string($endpoint)}'"); + if ($q) { + $r = $q->fetch_array(MYSQLI_ASSOC); + $ttl = $r['ttl']; $now = time(); - $retrievalTime = strtotime($r['last_successfully_retrieved'] . 'UTC'); - if ($now - $retrievalTime <= $ttl) { - return $r; + $retrievalTime = $r['last_successfully_retrieved']; + if ($retrievalTime !== null && $now - strtotime($retrievalTime . 'UTC') < $ttl) { + return new CacheResult($r['content']); } - return false; } - return null; -} + $result = curl_exec($ch); + // add to cache if no errors and HTTP OK + if (!curl_errno($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) { + insertCached($endpoint, $result, $configId); + } + + return new CacheResult(curl_exec($ch),true,curl_getinfo($ch,CURLINFO_HTTP_CODE),curl_errno($ch));} /** * Adds or updates an entry into the cache table. * @param string $endpoint The endpoint for the API request * @param string $content The content of API request's response - * @param int|string $config The ID of the config or its name in the config table + * @param int $config_id The ID of the config or its name in the config table */ -function insertCached(string $endpoint, string $content, $config) +function insertCached(string $endpoint, string $content, int $config_id) { global $db; - $r = getFromApiCacheTable($endpoint); + $r = get_cached_api_response($endpoint); $queryString = ""; if ($r) { $id = $r['id']; @@ -60,52 +110,53 @@ function insertCached(string $endpoint, string $content, $config) WHERE id = ' . $id; } else { - $configId = 1; - if (gettype($config) == 'integer') { - $configId = $config; - } else if (gettype($config) == 'string') { - $configId = $db->query('SELECT * FROM outgoing_request_cache_config WHERE config_name = "' . $db->real_escape_string($config) . '"')->fetch_array(MYSQLI_ASSOC)['id']; - } - $queryString = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) - values ('" . $db->real_escape_string($endpoint) . "', UTC_TIMESTAMP, - UTC_TIMESTAMP," . $configId . ", '" . $db->real_escape_string($content) . "')"; + +// $queryString = "INSERT INTO +// api_cache +// (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) +// values +// ('" . $db->real_escape_string($endpoint) . "', UTC_TIMESTAMP, +// UTC_TIMESTAMP," . $config_id . ", '" . $db->real_escape_string($content) . "')"; + $queryString = "INSERT INTO + api_cache + (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) + VALUES + ('{$db->real_escape_string($endpoint)}', UTC_TIMESTAMP, UTC_TIMESTAMP, + {$config_id}, '{$db->real_escape_string($content)}')"; } $q = $db->query($queryString); - if ($q === false) { + if (!$q) { error_log('Failed to update API cache: ' . $db->error); } } -/** - * Deletes an entry from the cache or deletes all entries from the cache. - * @param string|null $endpoint The endpoint of the API request to be removed. If null, empties the cache - */ -function clearCached(string $endpoint = null){ - global $db; - if ($endpoint) { - $queryString = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; - } else{ - $queryString = "DELETE FROM api_cache"; - } - $q = $db->query($queryString); - if ($q === false) { - error_log("Failed to clear API cache: " . $db->error); - } -} +///** +// * Deletes an entry from the cache or deletes all entries from the cache. +// * @param string|null $endpoint The endpoint of the API request to be removed. If null, empties the cache +// */ +//function clearCached(string $endpoint = null){ +// global $db; +// if ($endpoint) { +// $queryString = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; +// } else{ +// $queryString = "DELETE FROM api_cache"; +// } +// $q = $db->query($queryString); +// if ($q === false) { +// error_log("Failed to clear API cache: " . $db->error); +// } +//} /** * Adds a new cache config to the config table. * @param int $ttl The time to live for cached entries, measured in seconds - * @param string|null $config_name (optional) The name of the config + * @param string $config_name The name of the config * @return bool|mysqli_result The results of the MySQLi query */ -function addNewCacheConfig(int $ttl, $config_name = null) +function addNewCacheConfig(int $ttl, string $config_name) { global $db; - if ($config_name) { - return $db->query('INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (' . $ttl . ', "' . $db->real_escape_string($config_name) . '")'); - } - return $db->query('INSERT INTO outgoing_request_cache_config (ttl) VALUES (' . $ttl . ')'); + return $db->query('INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (' . $ttl . ', "' . $db->real_escape_string($config_name) . '")'); } /** @@ -114,19 +165,21 @@ function addNewCacheConfig(int $ttl, $config_name = null) * @param string|null $config_name (optional) The name of the config * @param int|null $ttl (optional) The time to live for cached entries, measured in seconds */ -function updateCacheConfig(int $id, $config_name = null, $ttl = null){ +function updateCacheConfig(int $id, $config_name = null, $ttl = null) +{ global $db; - if($config_name === null){ - if($ttl === null) + if ($config_name === null) { + if ($ttl === null) return; $queryString = 'UPDATE outgoing_request_cache_config SET ttl = ' . $ttl . ' WHERE id = ' . $id; - } else if($ttl === null){ + } else if ($ttl === null) { $queryString = "UPDATE outgoing_request_cache_config SET config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; - } else{ + } else { $queryString = "UPDATE outgoing_request_cache_config SET ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; } $q = $db->query($queryString); - if(!$q){ + if (!$q) { error_log('Failed to update API cache config: ' . $db->error); } -} \ No newline at end of file +} + diff --git a/api/printful/printful.php b/api/printful/printful.php index 9fb7ed50..57c02fc1 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -2,29 +2,17 @@ require(BASE . '/api/api-cache.php'); class PrintfulCustomAPI { private $api_key; - + private const PRINTFUL_CACHE_CONFIG_ID = 1; public function __construct($printful_api_key = PRINTFUL_API_KEY) { $this->api_key = $printful_api_key; } protected function send_request($URI, $data = false) { - $endpoint = 'https://api.printful.com/' . $URI; - $isOrder =substr($URI, 0, 6) == 'orders'; - if(!$isOrder){ // check cache, ignore orders because they shouldn't be cached - $r = getCached($endpoint); - if($r!== null){ // endpoint is in cache - if($r !== false){ - return json_decode($r['content']); - } - } - - } $ch = curl_init(); - $headers = array(); $headers[] = 'Authorization: Bearer ' . $this->api_key; - + $endpoint = 'https://api.printful.com/' . $URI; curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @@ -38,25 +26,23 @@ protected function send_request($URI, $data = false) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $result = curl_exec($ch); - - $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $cache_result = get_valid_cache_entry($endpoint, $ch, $this::PRINTFUL_CACHE_CONFIG_ID); - if (curl_errno($ch)) { - //echo 'Error:' . curl_error($ch); - // TODO: handle errors - throw new PrintfulCustomAPIException("Encountered an error executing the API request at {$URI}: " . curl_error($ch), 1); - } + if($cache_result->curl_executed) { + if ($cache_result->curl_errno) { + //echo 'Error:' . curl_error($ch); + // TODO: handle errors + throw new PrintfulCustomAPIException("Encountered an error executing the API request at {$URI}: " . curl_error($ch), 1); + } - if ($httpcode != 200) { - throw new PrintfulCustomAPIException("Received non-success response from the API request at {$URI}: {$httpcode} --- RAW: {$result}", 2); + if ($cache_result->httpcode != 200) { + throw new PrintfulCustomAPIException("Received non-success response from the API request at {$URI}: {$cache_result->httpcode} --- RAW: {$cache_result->content}", 2); + } } curl_close($ch); - if(!$isOrder){ - insertCached($endpoint, $result, 1); - } - return json_decode($result); + + return json_decode($cache_result->content); } public function create_order_single($name, $shipping_address, $item_price, $quantity, $sync_variant_id, $options = null, $amount_paid = null) { @@ -112,7 +98,6 @@ public function get_products($search_string = "") { if (!empty($search_string)) { $search_string = "&search=" . $search_string; } - echo 'test'; $products_results = $this->send_request("store/products?limit=5" . $search_string); $parsed_products_results = $this->parse_results($products_results); From 15b78fa2ab2cc2f7448e6be1525dbfac7df5d90c Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:57:44 -0500 Subject: [PATCH 06/18] Refactor function names --- api/api-cache.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 60a56ceb..2d64dded 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -84,7 +84,7 @@ function get_valid_cache_entry(string $endpoint, $ch, $configId = null) $result = curl_exec($ch); // add to cache if no errors and HTTP OK if (!curl_errno($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) { - insertCached($endpoint, $result, $configId); + insert_cached($endpoint, $result, $configId); } return new CacheResult(curl_exec($ch),true,curl_getinfo($ch,CURLINFO_HTTP_CODE),curl_errno($ch));} @@ -95,7 +95,7 @@ function get_valid_cache_entry(string $endpoint, $ch, $configId = null) * @param string $content The content of API request's response * @param int $config_id The ID of the config or its name in the config table */ -function insertCached(string $endpoint, string $content, int $config_id) +function insert_cached(string $endpoint, string $content, int $config_id) { global $db; $r = get_cached_api_response($endpoint); @@ -153,7 +153,7 @@ function insertCached(string $endpoint, string $content, int $config_id) * @param string $config_name The name of the config * @return bool|mysqli_result The results of the MySQLi query */ -function addNewCacheConfig(int $ttl, string $config_name) +function add_new_cache_config(int $ttl, string $config_name) { global $db; return $db->query('INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (' . $ttl . ', "' . $db->real_escape_string($config_name) . '")'); @@ -165,7 +165,7 @@ function addNewCacheConfig(int $ttl, string $config_name) * @param string|null $config_name (optional) The name of the config * @param int|null $ttl (optional) The time to live for cached entries, measured in seconds */ -function updateCacheConfig(int $id, $config_name = null, $ttl = null) +function update_cache_config(int $id, $config_name = null, $ttl = null) { global $db; if ($config_name === null) { From 97fdc9479c679fb2f054d9960a942e2085b91c9f Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:57:39 -0500 Subject: [PATCH 07/18] Refactoring. Changed API table's charset --- api/api-cache.php | 8 -------- api/printful/printful.php | 2 +- sql/outgoing_request_cache.sql | 4 ++-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 2d64dded..e8792dde 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -108,15 +108,7 @@ function insert_cached(string $endpoint, string $content, int $config_id) retry_count = 0, content =\'' . $db->real_escape_string($content) . '\' WHERE id = ' . $id; - } else { - -// $queryString = "INSERT INTO -// api_cache -// (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) -// values -// ('" . $db->real_escape_string($endpoint) . "', UTC_TIMESTAMP, -// UTC_TIMESTAMP," . $config_id . ", '" . $db->real_escape_string($content) . "')"; $queryString = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) diff --git a/api/printful/printful.php b/api/printful/printful.php index 57c02fc1..f04ac512 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -1,5 +1,5 @@ Date: Sat, 10 Aug 2024 11:08:29 -0500 Subject: [PATCH 08/18] Fixed for review --- api/api-cache.php | 37 +++++++++++++++++++------------------ api/printful/printful.php | 10 ++++------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index e8792dde..bdcbbc96 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -1,8 +1,6 @@ content = $content; - $this->curl_executed = $curl_executed; + $this->fetched_new_content = $fetched_new_content; $this->httpcode = $httpcode; $this->curl_errno = $curl_errno; } } /** - * Gets the first entry from the API cache that has a matching endpoint. Will not return if the entry is expired. + * Gets the first entry from the API cache that has a matching endpoint. If the entry is expired or does not exist, returns the results from executing cURL * @param string $endpoint The endpoint for the API request * @param resource|CurlHandle $ch The Curl Handle to send the request - * @param int|null $configId (optional) The config ID for the cached response. Optional if result won't be cached * @return CacheResult An object containing the response content, and some cURL info if curl_exec was called */ -function get_valid_cache_entry(string $endpoint, $ch, $configId = null) +function get_valid_cache_entry(string $endpoint, $ch) { global $db; - if (preg_match(IGNORED_ENDPOINTS, $endpoint)) { - return new CacheResult(curl_exec($ch),true,curl_getinfo($ch,CURLINFO_HTTP_CODE),curl_errno($ch)); - } $q = $db->query("SELECT * FROM api_cache - JOIN + LEFT JOIN outgoing_request_cache_config ON api_cache.config_id = outgoing_request_cache_config.id WHERE endpoint = '{$db->real_escape_string($endpoint)}'"); - if ($q) { + if($q===false){ + error_log("Failed to retrieve endpoint \"{$endpoint}\" from cache table: {$db->error}"); + return null; + } + $isInCache = $q && $q->num_rows > 0; + if ($isInCache) { $r = $q->fetch_array(MYSQLI_ASSOC); $ttl = $r['ttl']; $now = time(); @@ -80,14 +79,16 @@ function get_valid_cache_entry(string $endpoint, $ch, $configId = null) if ($retrievalTime !== null && $now - strtotime($retrievalTime . 'UTC') < $ttl) { return new CacheResult($r['content']); } + $configId = $r['config_id']; } $result = curl_exec($ch); - // add to cache if no errors and HTTP OK - if (!curl_errno($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) { + // add to cache if old cache entry, no errors, and HTTP OK + $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($isInCache && !curl_errno($ch) && $responseCode >= 200 && $responseCode <=299) { insert_cached($endpoint, $result, $configId); } - return new CacheResult(curl_exec($ch),true,curl_getinfo($ch,CURLINFO_HTTP_CODE),curl_errno($ch));} + return new CacheResult(curl_exec($ch),true, $responseCode,curl_errno($ch));} /** * Adds or updates an entry into the cache table. diff --git a/api/printful/printful.php b/api/printful/printful.php index f04ac512..cc2fb9c8 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -1,14 +1,13 @@ api_key = $printful_api_key; } protected function send_request($URI, $data = false) { - $ch = curl_init(); $headers = array(); $headers[] = 'Authorization: Bearer ' . $this->api_key; @@ -26,11 +25,10 @@ protected function send_request($URI, $data = false) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $cache_result = get_valid_cache_entry($endpoint, $ch, $this::PRINTFUL_CACHE_CONFIG_ID); + $cache_result = get_valid_cache_entry($endpoint, $ch); - if($cache_result->curl_executed) { + if($cache_result->fetched_new_content) { if ($cache_result->curl_errno) { - //echo 'Error:' . curl_error($ch); // TODO: handle errors throw new PrintfulCustomAPIException("Encountered an error executing the API request at {$URI}: " . curl_error($ch), 1); } From ff7316652eb4db7f23e1780f5332995df27ab9f5 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Wed, 14 Aug 2024 19:29:31 -0500 Subject: [PATCH 09/18] Refactoring, add endpoint to error_log in insert_cached --- api/api-cache.php | 51 ++++++++++++++++++++------------------- api/printful/printful.php | 8 +++--- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index bdcbbc96..bb4edd3d 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -30,7 +30,7 @@ class CacheResult{ * @var int|null $httpcode HTTP response code from cURL. Null if curl_exec wasn't called * @var int|null $curl_errno cURL error number. Null if curl_exec wasn't called */ - public $httpcode, $curl_errno; + public $http_code, $curl_errno; /** * @param string $content @@ -42,13 +42,13 @@ public function __construct(string $content, bool $fetched_new_content = false, { $this->content = $content; $this->fetched_new_content = $fetched_new_content; - $this->httpcode = $httpcode; + $this->http_code = $httpcode; $this->curl_errno = $curl_errno; } } /** - * Gets the first entry from the API cache that has a matching endpoint. If the entry is expired or does not exist, returns the results from executing cURL + * Gets the first entry from the API cache that has a matching endpoint. If the entry is expired or does not exist, returns the results from executing cURL. Updates the cache with fetched results if the entry existed * @param string $endpoint The endpoint for the API request * @param resource|CurlHandle $ch The Curl Handle to send the request * @return CacheResult An object containing the response content, and some cURL info if curl_exec was called @@ -70,25 +70,26 @@ function get_valid_cache_entry(string $endpoint, $ch) error_log("Failed to retrieve endpoint \"{$endpoint}\" from cache table: {$db->error}"); return null; } - $isInCache = $q && $q->num_rows > 0; - if ($isInCache) { + $is_in_cache = $q && $q->num_rows > 0; + if ($is_in_cache) { $r = $q->fetch_array(MYSQLI_ASSOC); $ttl = $r['ttl']; $now = time(); - $retrievalTime = $r['last_successfully_retrieved']; - if ($retrievalTime !== null && $now - strtotime($retrievalTime . 'UTC') < $ttl) { + $retrieval_time = $r['last_successfully_retrieved']; + if ($retrieval_time !== null && $now - strtotime($retrieval_time . 'UTC') < $ttl) { return new CacheResult($r['content']); } - $configId = $r['config_id']; + $config_id = $r['config_id']; } + curl_setopt($ch, CURLOPT_URL, $endpoint); $result = curl_exec($ch); // add to cache if old cache entry, no errors, and HTTP OK - $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if ($isInCache && !curl_errno($ch) && $responseCode >= 200 && $responseCode <=299) { - insert_cached($endpoint, $result, $configId); + $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($is_in_cache && !curl_errno($ch) && $response_code >= 200 && $response_code <=299) { + insert_cached($endpoint, $result, $config_id); } - return new CacheResult(curl_exec($ch),true, $responseCode,curl_errno($ch));} + return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch));} /** * Adds or updates an entry into the cache table. @@ -100,26 +101,26 @@ function insert_cached(string $endpoint, string $content, int $config_id) { global $db; $r = get_cached_api_response($endpoint); - $queryString = ""; + $query_string = ""; if ($r) { $id = $r['id']; - $queryString = 'UPDATE api_cache + $query_string = 'UPDATE api_cache SET last_successfully_retrieved = UTC_TIMESTAMP, last_attempted_retrieval = UTC_TIMESTAMP, retry_count = 0, content =\'' . $db->real_escape_string($content) . '\' WHERE id = ' . $id; } else { - $queryString = "INSERT INTO + $query_string = "INSERT INTO api_cache (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) VALUES ('{$db->real_escape_string($endpoint)}', UTC_TIMESTAMP, UTC_TIMESTAMP, {$config_id}, '{$db->real_escape_string($content)}')"; } - $q = $db->query($queryString); + $q = $db->query($query_string); if (!$q) { - error_log('Failed to update API cache: ' . $db->error); + error_log("Failed to update API cache for endpoint \"{$endpoint}\": " . $db->error); } } @@ -127,14 +128,14 @@ function insert_cached(string $endpoint, string $content, int $config_id) // * Deletes an entry from the cache or deletes all entries from the cache. // * @param string|null $endpoint The endpoint of the API request to be removed. If null, empties the cache // */ -//function clearCached(string $endpoint = null){ +//function clear_cached(string $endpoint = null){ // global $db; // if ($endpoint) { -// $queryString = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; +// $query_string = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; // } else{ -// $queryString = "DELETE FROM api_cache"; +// $query_string = "DELETE FROM api_cache"; // } -// $q = $db->query($queryString); +// $q = $db->query($query_string); // if ($q === false) { // error_log("Failed to clear API cache: " . $db->error); // } @@ -164,13 +165,13 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) if ($config_name === null) { if ($ttl === null) return; - $queryString = 'UPDATE outgoing_request_cache_config SET ttl = ' . $ttl . ' WHERE id = ' . $id; + $query_string = 'UPDATE outgoing_request_cache_config SET ttl = ' . $ttl . ' WHERE id = ' . $id; } else if ($ttl === null) { - $queryString = "UPDATE outgoing_request_cache_config SET config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + $query_string = "UPDATE outgoing_request_cache_config SET config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; } else { - $queryString = "UPDATE outgoing_request_cache_config SET ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + $query_string = "UPDATE outgoing_request_cache_config SET ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; } - $q = $db->query($queryString); + $q = $db->query($query_string); if (!$q) { error_log('Failed to update API cache config: ' . $db->error); } diff --git a/api/printful/printful.php b/api/printful/printful.php index cc2fb9c8..8d28634b 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -11,8 +11,6 @@ protected function send_request($URI, $data = false) { $ch = curl_init(); $headers = array(); $headers[] = 'Authorization: Bearer ' . $this->api_key; - $endpoint = 'https://api.printful.com/' . $URI; - curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if ($data !== false) { @@ -25,7 +23,7 @@ protected function send_request($URI, $data = false) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $cache_result = get_valid_cache_entry($endpoint, $ch); + $cache_result = get_valid_cache_entry('https://api.printful.com/' . $URI, $ch); if($cache_result->fetched_new_content) { if ($cache_result->curl_errno) { @@ -33,8 +31,8 @@ protected function send_request($URI, $data = false) { throw new PrintfulCustomAPIException("Encountered an error executing the API request at {$URI}: " . curl_error($ch), 1); } - if ($cache_result->httpcode != 200) { - throw new PrintfulCustomAPIException("Received non-success response from the API request at {$URI}: {$cache_result->httpcode} --- RAW: {$cache_result->content}", 2); + if ($cache_result->http_code != 200) { + throw new PrintfulCustomAPIException("Received non-success response from the API request at {$URI}: {$cache_result->http_code} --- RAW: {$cache_result->content}", 2); } } From 2dd0d3f8cd5e8861849ccc60857f630a329046a3 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:07:53 -0500 Subject: [PATCH 10/18] Add Printful cache config --- sql/migrations/URW-178-cache-configs.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 sql/migrations/URW-178-cache-configs.sql diff --git a/sql/migrations/URW-178-cache-configs.sql b/sql/migrations/URW-178-cache-configs.sql new file mode 100644 index 00000000..49518a8a --- /dev/null +++ b/sql/migrations/URW-178-cache-configs.sql @@ -0,0 +1 @@ +INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (86400, 'Printful') \ No newline at end of file From 5d8e2047d11a7be679a755a8c0c4da81f2a8e75b Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Sat, 24 Aug 2024 12:49:06 -0500 Subject: [PATCH 11/18] Change table columns, add endpoints to config Changed some SELECTs to grab fewer columns. Added newlines and indents to queries in PHP file to improve readability --- api/api-cache.php | 129 +++++++++++++++++------ sql/migrations/URW-178-cache-configs.sql | 86 ++++++++++++++- sql/outgoing_request_cache.sql | 2 +- 3 files changed, 183 insertions(+), 34 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index bb4edd3d..31d5f01a 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -9,7 +9,18 @@ function get_cached_api_response(string $endpoint): ?array { global $db; - $q = $db->query('SELECT * FROM api_cache WHERE endpoint = "' . $db->real_escape_string($endpoint) . '"'); + $q = $db->query(' + SELECT + * + FROM + api_cache + LEFT JOIN + outgoing_request_cache_config + ON + api_cache.config_id = outgoing_request_cache_config.id + WHERE + endpoint = "' . $db->real_escape_string($endpoint) . '" + '); if ($q) { $r = $q->fetch_array(MYSQLI_ASSOC); return $r; @@ -56,43 +67,47 @@ public function __construct(string $content, bool $fetched_new_content = false, function get_valid_cache_entry(string $endpoint, $ch) { global $db; - $q = $db->query("SELECT - * - FROM - api_cache - LEFT JOIN - outgoing_request_cache_config - ON - api_cache.config_id = outgoing_request_cache_config.id - WHERE - endpoint = '{$db->real_escape_string($endpoint)}'"); + $q = $db->query(" + SELECT + outgoing_request_cache_config.id as conf_id, ttl, content, last_successfully_retrieved + FROM + outgoing_request_cache_config + LEFT JOIN + api_cache + ON + outgoing_request_cache_config.id = api_cache.config_id + WHERE + endpoint = '{$db->real_escape_string($endpoint)}' + "); if($q===false){ error_log("Failed to retrieve endpoint \"{$endpoint}\" from cache table: {$db->error}"); return null; } - $is_in_cache = $q && $q->num_rows > 0; - if ($is_in_cache) { + $can_be_cached = $q && $q->num_rows > 0; + if ($can_be_cached) { $r = $q->fetch_array(MYSQLI_ASSOC); - $ttl = $r['ttl']; - $now = time(); - $retrieval_time = $r['last_successfully_retrieved']; - if ($retrieval_time !== null && $now - strtotime($retrieval_time . 'UTC') < $ttl) { - return new CacheResult($r['content']); + if($r['content']!==null){ + $ttl = $r['ttl']; + $now = time(); + $retrieval_time = $r['last_successfully_retrieved']; + if ($retrieval_time !== null && $now - strtotime($retrieval_time . 'UTC') < $ttl) { + return new CacheResult($r['content']); + } } - $config_id = $r['config_id']; + $config_id = $r['conf_id']; } curl_setopt($ch, CURLOPT_URL, $endpoint); $result = curl_exec($ch); // add to cache if old cache entry, no errors, and HTTP OK $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if ($is_in_cache && !curl_errno($ch) && $response_code >= 200 && $response_code <=299) { + if ($can_be_cached && !curl_errno($ch) && $response_code >= 200 && $response_code <=299) { insert_cached($endpoint, $result, $config_id); } return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch));} /** - * Adds or updates an entry into the cache table. + * Adds or updates an entry into the cache table. Does not check if data should be cached * @param string $endpoint The endpoint for the API request * @param string $content The content of API request's response * @param int $config_id The ID of the config or its name in the config table @@ -104,18 +119,23 @@ function insert_cached(string $endpoint, string $content, int $config_id) $query_string = ""; if ($r) { $id = $r['id']; - $query_string = 'UPDATE api_cache - SET last_successfully_retrieved = UTC_TIMESTAMP, + $query_string = ' + UPDATE + api_cache + SET + last_successfully_retrieved = UTC_TIMESTAMP, last_attempted_retrieval = UTC_TIMESTAMP, retry_count = 0, content =\'' . $db->real_escape_string($content) . '\' - WHERE id = ' . $id; + WHERE + id = ' . $id; } else { - $query_string = "INSERT INTO + $query_string = " + INSERT INTO api_cache - (endpoint, last_successfully_retrieved, last_attempted_retrieval, config_id, content) + (last_successfully_retrieved, last_attempted_retrieval, config_id, content) VALUES - ('{$db->real_escape_string($endpoint)}', UTC_TIMESTAMP, UTC_TIMESTAMP, + (UTC_TIMESTAMP, UTC_TIMESTAMP, {$config_id}, '{$db->real_escape_string($content)}')"; } $q = $db->query($query_string); @@ -124,6 +144,28 @@ function insert_cached(string $endpoint, string $content, int $config_id) } } +/** + * Checks if an endpoint should be cached + * @param string $endpoint The endpoint to check + * @return bool|null Returns null on error. Returns true if the endpoint should be cached. Returns false if the endpoint should not be cached + */ +function is_cachable(string $endpoint): ?bool{ + global $db; + $q = $db->query(" + SELECT + id + FROM + outgoing_request_cache_config + WHERE + endpoint = '{$db->real_escape_string($endpoint)}' + "); + if($q===false){ + error_log("Failed to retrieve endpoint {$endpoint} from cache config table: {$db->error}"); + return null; + } + return $q->num_rows > 0; +} + ///** // * Deletes an entry from the cache or deletes all entries from the cache. // * @param string|null $endpoint The endpoint of the API request to be removed. If null, empties the cache @@ -145,12 +187,18 @@ function insert_cached(string $endpoint, string $content, int $config_id) * Adds a new cache config to the config table. * @param int $ttl The time to live for cached entries, measured in seconds * @param string $config_name The name of the config + * @param string $endpoint The endpoint for the config * @return bool|mysqli_result The results of the MySQLi query */ -function add_new_cache_config(int $ttl, string $config_name) +function add_new_cache_config(int $ttl, string $config_name, string $endpoint) { global $db; - return $db->query('INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (' . $ttl . ', "' . $db->real_escape_string($config_name) . '")'); + return $db->query(" + INSERT INTO + outgoing_request_cache_config (ttl, config_name, endpoint) + VALUES + ({$ttl}, '{$db->real_escape_string($config_name)}', '{$db->real_escape_string($endpoint)}') + "); } /** @@ -165,11 +213,28 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) if ($config_name === null) { if ($ttl === null) return; - $query_string = 'UPDATE outgoing_request_cache_config SET ttl = ' . $ttl . ' WHERE id = ' . $id; + $query_string = ' + UPDATE + outgoing_request_cache_config + SET + ttl = ' . $ttl . ' + WHERE + id = ' . $id; } else if ($ttl === null) { - $query_string = "UPDATE outgoing_request_cache_config SET config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + $query_string = " + UPDATE + outgoing_request_cache_config + SET + config_name = '{$db->real_escape_string($config_name)}' + WHERE + id = {$id}"; } else { - $query_string = "UPDATE outgoing_request_cache_config SET ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' WHERE id = {$id}"; + $query_string = "UPDATE + outgoing_request_cache_config + SET + ttl= {$ttl}, config_name = '{$db->real_escape_string($config_name)}' + WHERE + id = {$id}"; } $q = $db->query($query_string); if (!$q) { diff --git a/sql/migrations/URW-178-cache-configs.sql b/sql/migrations/URW-178-cache-configs.sql index 49518a8a..43ef8b59 100644 --- a/sql/migrations/URW-178-cache-configs.sql +++ b/sql/migrations/URW-178-cache-configs.sql @@ -1 +1,85 @@ -INSERT INTO outgoing_request_cache_config (ttl, config_name) VALUES (86400, 'Printful') \ No newline at end of file +# INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products'); +# INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/products/'); + +-- Individual product page endpoints + -- Hats + -- UNT Robotics Cuffed Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Cuffed Beanie','https://api.printful.com/store/products/@5f6ceb2cf3a5e5'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Cuffed Beanie (Catalog)','https://api.printful.com/products/266'); + -- UNT Robotics Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Beanie','https://api.printful.com/store/products/@5f6ce5cca7cd98'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Beanie (Catalog)','https://api.printful.com/products/81'); + -- UNT Robotics Pom Pom Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Pom Pom Beanie','https://api.printful.com/store/products/@5f6ce4b4acbe64'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Pom Pom Beanie (Catalog)','https://api.printful.com/products/93'); + -- UNT Robotics Snapback Front Logo Only + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front Logo Only','https://api.printful.com/store/products/@5f6ce6b2c96a55'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front Logo Only (Catalog)','https://api.printful.com/products/77'); + -- UNT Robotics Baseball Cap + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Baseball Cap','https://api.printful.com/store/products/@5f5a8f842802b1'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Baseball Cap (Catalog)','https://api.printful.com/products/206'); + -- UNT Robotics Snapback Front & Back Logo + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front & Back Logo','https://api.printful.com/store/products/@5f5a8f462d3964'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front & Back Logo (Catalog)','https://api.printful.com/products/77'); + -- Trousers + -- UNT Robotics Sweatpants + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Sweatpants','https://api.printful.com/store/products/@5f6d7466124ec4'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Sweatpants (Catalog)','https://api.printful.com/products/342'); + -- Gear + -- Aerospace Division T + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Aerospace Division T','https://api.printful.com/store/products/@636ea56986bad9'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Aerospace Division T (Catalog)','https://api.printful.com/products/71'); + -- UNT Robotics High Top Men's Canvas Shoes + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Men''s Canvas Shoes','https://api.printful.com/store/products/@61ef91b95fdf32'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Men''s Canvas Shoes (Catalog)','https://api.printful.com/products/513'); + -- UNT Robotics High Top Women's Canvas Shoes + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Women''s Canvas Shoes','https://api.printful.com/store/products/@61ef8ee3244566'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Women''s Canvas Shoes (Catalog)','https://api.printful.com/products/525'); + -- UNT Robotics Drawstring Bag + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Drawstring Bag','https://api.printful.com/store/products/@5f7666019c3354'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Drawstring Bag (Catalog)','https://api.printful.com/products/262'); + -- UNT Robotics Socks + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Socks','https://api.printful.com/store/products/@5f7664e32a1d17'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Socks (Catalog)','https://api.printful.com/products/186'); + -- UNT Robotics Flip-Flops + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Flip-Flops','https://api.printful.com/store/products/@5f766443335fa6'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Flip-Flops (Catalog)','https://api.printful.com/products/359'); + +-- Catalog search endpoints + # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Trousers)'); + # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Hat)'); + # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Gear)'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Trousers)'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Hat)'); + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Gear)'); + +-- Catalog product endpoints + -- Hats + -- UNT Robotics Cuffed Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194962427'); + -- UNT Robotics Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194960016'); + -- UNT Robotics Pom Pom Beanie + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194959831'); + -- UNT Robotics Snapback Front Logo Only + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194854253'); + -- UNT Robotics Baseball Cap + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/192857853'); + -- UNT Robotics Snapback Front & Back Logo + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/192857643'); + -- Trousers + -- UNT Robotics Sweatpants + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195023481'); + -- Gear + -- Aerospace Division T + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/291159152'); + -- UNT Robotics High Top Men's Canvas Shoes + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/264529951'); + -- UNT Robotics High Top Women's Canvas Shoes + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/264529433'); + -- UNT Robotics Drawstring Bag + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195968026'); + -- UNT Robotics Socks + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195967752'); + -- UNT Robotics Flip-Flops + INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195967367'); \ No newline at end of file diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index 9114cf7a..2785f074 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -5,13 +5,13 @@ CREATE TABLE `outgoing_request_cache_config`( `id` int(11) NOT NULL AUTO_INCREMENT, `ttl` int(6) NOT NULL, -- ttl measured in seconds `config_name` varchar(255) NOT NULL, + `endpoint` varchar(4000) NOT NULL, PRIMARY KEY (id) )AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `api_cache`; CREATE TABLE `api_cache`( `id` int(11) NOT NULL AUTO_INCREMENT, - `endpoint` varchar(4000) DEFAULT NULL, `last_successfully_retrieved` timestamp, `last_attempted_retrieval` timestamp DEFAULT NULL, `retry_count` int DEFAULT 0, From 23883c37f8143410a2c9f5323409b8a5571a8fea Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:15:36 -0500 Subject: [PATCH 12/18] Changed tables to separate specific endpoint info from generic info Rearranged some columns, specified default for columns of type timestamp because of MySQL server settings Parameterized endpoint strings and added helper function to convert parameterized endpoint strings to the full version Add varargs for send_request and api-cache functions Reformatted code --- api/api-cache.php | 134 +++++++++++++++-------- api/printful/printful.php | 16 +-- sql/migrations/URW-178-cache-configs.sql | 90 +-------------- sql/outgoing_request_cache.sql | 9 +- 4 files changed, 106 insertions(+), 143 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 31d5f01a..13a70f5e 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -4,23 +4,25 @@ /** * Gets the first entry from the API cache that has a matching endpoint. * @param string $endpoint The endpoint for the API request + * @param mixed ...$args The endpoint arguments for the API request * @return array|null The first entry that matches or null if no entry exists */ -function get_cached_api_response(string $endpoint): ?array -{ +function get_cached_api_response(string $endpoint, ...$args): ?array { global $db; - $q = $db->query(' - SELECT - * - FROM - api_cache - LEFT JOIN - outgoing_request_cache_config - ON - api_cache.config_id = outgoing_request_cache_config.id - WHERE - endpoint = "' . $db->real_escape_string($endpoint) . '" - '); + $q = $db->query(" + SELECT + * + FROM + api_cache + INNER JOIN + outgoing_request_cache_config + ON + api_cache.config_id = outgoing_request_cache_config.id + WHERE + endpoint = '{$db->real_escape_string($endpoint)}' + AND + endpoint_args = '{$db->real_escape_string(implode('|',$args))}' + "); if ($q) { $r = $q->fetch_array(MYSQLI_ASSOC); return $r; @@ -28,7 +30,7 @@ function get_cached_api_response(string $endpoint): ?array return null; } -class CacheResult{ +class CacheResult { /** * @var string $content The response content */ @@ -49,8 +51,7 @@ class CacheResult{ * @param int|null $httpcode (optional) * @param int|null $curl_errno (optional) */ - public function __construct(string $content, bool $fetched_new_content = false, $httpcode = null, $curl_errno = null) - { + public function __construct(string $content, bool $fetched_new_content = false, $httpcode = null, $curl_errno = null) { $this->content = $content; $this->fetched_new_content = $fetched_new_content; $this->http_code = $httpcode; @@ -62,10 +63,10 @@ public function __construct(string $content, bool $fetched_new_content = false, * Gets the first entry from the API cache that has a matching endpoint. If the entry is expired or does not exist, returns the results from executing cURL. Updates the cache with fetched results if the entry existed * @param string $endpoint The endpoint for the API request * @param resource|CurlHandle $ch The Curl Handle to send the request + * @param mixed ...$args Endpoint args * @return CacheResult An object containing the response content, and some cURL info if curl_exec was called */ -function get_valid_cache_entry(string $endpoint, $ch) -{ +function get_valid_cache_entry(string $endpoint, $ch, ...$args) { global $db; $q = $db->query(" SELECT @@ -78,15 +79,16 @@ function get_valid_cache_entry(string $endpoint, $ch) outgoing_request_cache_config.id = api_cache.config_id WHERE endpoint = '{$db->real_escape_string($endpoint)}' + AND + endpoint_args = '{$db->real_escape_string(implode('|',$args))}' "); - if($q===false){ - error_log("Failed to retrieve endpoint \"{$endpoint}\" from cache table: {$db->error}"); + if($q === false) { + error_log("Failed to retrieve endpoint \"". insert_args($endpoint, ...$args) ."\" from cache table: {$db->error}"); return null; } - $can_be_cached = $q && $q->num_rows > 0; - if ($can_be_cached) { + if ($q && $q->num_rows > 0) { $r = $q->fetch_array(MYSQLI_ASSOC); - if($r['content']!==null){ + if($r['content'] !== null) { $ttl = $r['ttl']; $now = time(); $retrieval_time = $r['last_successfully_retrieved']; @@ -95,30 +97,44 @@ function get_valid_cache_entry(string $endpoint, $ch) } } $config_id = $r['conf_id']; + $can_be_cached = true; } - curl_setopt($ch, CURLOPT_URL, $endpoint); + //inserts args into the endpoint at '$#' (e.g., $1, $2, $3, will be replaced by arg 1, arg 2, arg 3, respectively) + + $endpoint_full = insert_args($endpoint, ...$args); + curl_setopt($ch, CURLOPT_URL, $endpoint_full); $result = curl_exec($ch); // add to cache if old cache entry, no errors, and HTTP OK $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if(!isset($can_be_cached)) { // if set, specific endpoint is already in db, so we can try to cache + $config_id = get_config_id($endpoint); + if($config_id === null) { + error_log("Failed to check cachability of endpoint \"{$endpoint_full}\". Result not cached."); + return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch)); + } + // $config_id should be false if the endpoint can't be cached, otherwise it should be an int + $can_be_cached = $config_id !== false; + } if ($can_be_cached && !curl_errno($ch) && $response_code >= 200 && $response_code <=299) { - insert_cached($endpoint, $result, $config_id); + insert_cached($endpoint, $result, $config_id, ...$args); } - return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch));} + return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch)); +} /** * Adds or updates an entry into the cache table. Does not check if data should be cached * @param string $endpoint The endpoint for the API request * @param string $content The content of API request's response * @param int $config_id The ID of the config or its name in the config table + * @param mixed ...$args The endpoint args for the API request */ -function insert_cached(string $endpoint, string $content, int $config_id) -{ +function insert_cached(string $endpoint, string $content, int $config_id, ...$args) { global $db; - $r = get_cached_api_response($endpoint); - $query_string = ""; + $r = get_cached_api_response($endpoint, ...$args); if ($r) { $id = $r['id']; + $query_string = ' UPDATE api_cache @@ -130,26 +146,36 @@ function insert_cached(string $endpoint, string $content, int $config_id) WHERE id = ' . $id; } else { + $b = implode('|', $args); + $a = $db->real_escape_string($b); $query_string = " INSERT INTO api_cache - (last_successfully_retrieved, last_attempted_retrieval, config_id, content) + (config_id, + last_successfully_retrieved, + last_attempted_retrieval, + endpoint_args, + content) VALUES - (UTC_TIMESTAMP, UTC_TIMESTAMP, - {$config_id}, '{$db->real_escape_string($content)}')"; + ({$config_id}, + UTC_TIMESTAMP, + UTC_TIMESTAMP, + '{$a}', + '{$db->real_escape_string($content)}')"; } $q = $db->query($query_string); if (!$q) { - error_log("Failed to update API cache for endpoint \"{$endpoint}\": " . $db->error); + error_log("Failed to update API cache for endpoint \"" . insert_args($endpoint, ...$args) . "\": {$db->error}"); } } /** - * Checks if an endpoint should be cached + * Gives the id of an endpoint for the outgoing_request_cache_config table * @param string $endpoint The endpoint to check - * @return bool|null Returns null on error. Returns true if the endpoint should be cached. Returns false if the endpoint should not be cached + * @return mixed|null Returns null on MySQLi error. Returns false if no entry exists, or, if one exists, the config ID + * This is not good practice */ -function is_cachable(string $endpoint): ?bool{ +function get_config_id(string $endpoint) { global $db; $q = $db->query(" SELECT @@ -159,22 +185,25 @@ function is_cachable(string $endpoint): ?bool{ WHERE endpoint = '{$db->real_escape_string($endpoint)}' "); - if($q===false){ + if($q === false) { error_log("Failed to retrieve endpoint {$endpoint} from cache config table: {$db->error}"); return null; } - return $q->num_rows > 0; + // return $q->fetch_column(0); + if($q->num_rows < 1) + return false; + return $q->fetch_row()[0]; } ///** // * Deletes an entry from the cache or deletes all entries from the cache. // * @param string|null $endpoint The endpoint of the API request to be removed. If null, empties the cache // */ -//function clear_cached(string $endpoint = null){ +//function clear_cached(string $endpoint = null) { // global $db; // if ($endpoint) { // $query_string = "DELETE FROM api_cache WHERE endpoint = '" . $db->real_escape_string($endpoint) . "'"; -// } else{ +// } else { // $query_string = "DELETE FROM api_cache"; // } // $q = $db->query($query_string); @@ -190,8 +219,7 @@ function is_cachable(string $endpoint): ?bool{ * @param string $endpoint The endpoint for the config * @return bool|mysqli_result The results of the MySQLi query */ -function add_new_cache_config(int $ttl, string $config_name, string $endpoint) -{ +function add_new_cache_config(int $ttl, string $config_name, string $endpoint) { global $db; return $db->query(" INSERT INTO @@ -207,8 +235,7 @@ function add_new_cache_config(int $ttl, string $config_name, string $endpoint) * @param string|null $config_name (optional) The name of the config * @param int|null $ttl (optional) The time to live for cached entries, measured in seconds */ -function update_cache_config(int $id, $config_name = null, $ttl = null) -{ +function update_cache_config(int $id, $config_name = null, $ttl = null) { global $db; if ($config_name === null) { if ($ttl === null) @@ -242,3 +269,18 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) } } +/** + * Inserts arguments into an endpoint string. + * The expected format is "$1/$2/$3...$n" + * Forward slashes and other URL symbols will not be added automatically. Include those in the vararg + * @param string $endpoint The endpoint to insert args into + * @param mixed ...$args The arguments to insert into endpoint + * @return string The endpoint with each "$#" replaced with its corresponding vararg + */ +function insert_args(string $endpoint, ...$args): string { + $search = array(); + for($i = 1; $i <= count($args); $i++) { + $search[] = '$' . $i; + } + return str_replace($search, $args, $endpoint); +} \ No newline at end of file diff --git a/api/printful/printful.php b/api/printful/printful.php index 8d28634b..57292156 100644 --- a/api/printful/printful.php +++ b/api/printful/printful.php @@ -7,7 +7,7 @@ public function __construct($printful_api_key = PRINTFUL_API_KEY) { $this->api_key = $printful_api_key; } - protected function send_request($URI, $data = false) { + protected function send_request($URI, $data = false, ...$args) { $ch = curl_init(); $headers = array(); $headers[] = 'Authorization: Bearer ' . $this->api_key; @@ -23,7 +23,7 @@ protected function send_request($URI, $data = false) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $cache_result = get_valid_cache_entry('https://api.printful.com/' . $URI, $ch); + $cache_result = get_valid_cache_entry('https://api.printful.com/' . $URI, $ch, ...$args); if($cache_result->fetched_new_content) { if ($cache_result->curl_errno) { @@ -82,7 +82,7 @@ public function create_order_single($name, $shipping_address, $item_price, $quan } public function confirm_order($order_id) { - $create_order_results = $this->send_request("orders/{$order_id}/confirm", null); + $create_order_results = $this->send_request("orders/$1/confirm", null, $order_id); $parsed_created_order_results = $this->parse_results($create_order_results); $order = new PrintfulOrder($parsed_created_order_results->get_results()); @@ -94,7 +94,7 @@ public function get_products($search_string = "") { if (!empty($search_string)) { $search_string = "&search=" . $search_string; } - $products_results = $this->send_request("store/products?limit=5" . $search_string); + $products_results = $this->send_request("store/products$1", false, "?limit=10" . $search_string); $parsed_products_results = $this->parse_results($products_results); foreach ($parsed_products_results->get_results() as $product) { @@ -109,7 +109,7 @@ public function get_product($product_id) { throw new PrintfulCustomAPIException("Null or empty product id passed."); } - $product_results = $this->send_request("store/products/{$product_id}"); + $product_results = $this->send_request("store/products/$1", false, $product_id); $parsed_product_results = $this->parse_results($product_results); if ($parsed_product_results->get_results()) { @@ -124,7 +124,7 @@ public function get_variant($sync_variant_id) { throw new PrintfulCustomAPIException("Null or empty sync variant id passed."); } - $sync_variant_results = $this->send_request("store/variants/{$sync_variant_id}"); + $sync_variant_results = $this->send_request("store/variants/$1", false, $sync_variant_id); $parsed_sync_variant_results = $this->parse_results($sync_variant_results); if ($parsed_sync_variant_results->get_results()) { @@ -145,7 +145,7 @@ public function get_catalog_variant($variant_id) { throw new PrintfulCustomAPIException("Null or empty variant id passed."); } - $variant_results = $this->send_request("products/variant/{$variant_id}"); + $variant_results = $this->send_request("products/variant/$1", false, $variant_id); $parsed_variant_results = $this->parse_results($variant_results); if ($parsed_variant_results->get_results()) { @@ -160,7 +160,7 @@ public function get_catalog_product($product_id) { throw new PrintfulCustomAPIException("Null or empty product id passed."); } - $product_results = $this->send_request("products/{$product_id}"); + $product_results = $this->send_request("products/$1", false, $product_id); $parsed_product_results = $this->parse_results($product_results); if ($parsed_product_results->get_results()) { diff --git a/sql/migrations/URW-178-cache-configs.sql b/sql/migrations/URW-178-cache-configs.sql index 43ef8b59..520e9ce2 100644 --- a/sql/migrations/URW-178-cache-configs.sql +++ b/sql/migrations/URW-178-cache-configs.sql @@ -1,85 +1,5 @@ -# INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products'); -# INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/products/'); - --- Individual product page endpoints - -- Hats - -- UNT Robotics Cuffed Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Cuffed Beanie','https://api.printful.com/store/products/@5f6ceb2cf3a5e5'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Cuffed Beanie (Catalog)','https://api.printful.com/products/266'); - -- UNT Robotics Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Beanie','https://api.printful.com/store/products/@5f6ce5cca7cd98'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Beanie (Catalog)','https://api.printful.com/products/81'); - -- UNT Robotics Pom Pom Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Pom Pom Beanie','https://api.printful.com/store/products/@5f6ce4b4acbe64'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Pom Pom Beanie (Catalog)','https://api.printful.com/products/93'); - -- UNT Robotics Snapback Front Logo Only - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front Logo Only','https://api.printful.com/store/products/@5f6ce6b2c96a55'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front Logo Only (Catalog)','https://api.printful.com/products/77'); - -- UNT Robotics Baseball Cap - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Baseball Cap','https://api.printful.com/store/products/@5f5a8f842802b1'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Baseball Cap (Catalog)','https://api.printful.com/products/206'); - -- UNT Robotics Snapback Front & Back Logo - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front & Back Logo','https://api.printful.com/store/products/@5f5a8f462d3964'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Snapback Front & Back Logo (Catalog)','https://api.printful.com/products/77'); - -- Trousers - -- UNT Robotics Sweatpants - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Sweatpants','https://api.printful.com/store/products/@5f6d7466124ec4'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Sweatpants (Catalog)','https://api.printful.com/products/342'); - -- Gear - -- Aerospace Division T - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Aerospace Division T','https://api.printful.com/store/products/@636ea56986bad9'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Aerospace Division T (Catalog)','https://api.printful.com/products/71'); - -- UNT Robotics High Top Men's Canvas Shoes - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Men''s Canvas Shoes','https://api.printful.com/store/products/@61ef91b95fdf32'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Men''s Canvas Shoes (Catalog)','https://api.printful.com/products/513'); - -- UNT Robotics High Top Women's Canvas Shoes - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Women''s Canvas Shoes','https://api.printful.com/store/products/@61ef8ee3244566'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful High Top Women''s Canvas Shoes (Catalog)','https://api.printful.com/products/525'); - -- UNT Robotics Drawstring Bag - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Drawstring Bag','https://api.printful.com/store/products/@5f7666019c3354'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Drawstring Bag (Catalog)','https://api.printful.com/products/262'); - -- UNT Robotics Socks - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Socks','https://api.printful.com/store/products/@5f7664e32a1d17'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Socks (Catalog)','https://api.printful.com/products/186'); - -- UNT Robotics Flip-Flops - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Flip-Flops','https://api.printful.com/store/products/@5f766443335fa6'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful Flip-Flops (Catalog)','https://api.printful.com/products/359'); - --- Catalog search endpoints - # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Trousers)'); - # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Hat)'); - # INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?limit=5&search=(Gear)'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Trousers)'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Hat)'); - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products?search=(Gear)'); - --- Catalog product endpoints - -- Hats - -- UNT Robotics Cuffed Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194962427'); - -- UNT Robotics Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194960016'); - -- UNT Robotics Pom Pom Beanie - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194959831'); - -- UNT Robotics Snapback Front Logo Only - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/194854253'); - -- UNT Robotics Baseball Cap - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/192857853'); - -- UNT Robotics Snapback Front & Back Logo - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/192857643'); - -- Trousers - -- UNT Robotics Sweatpants - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195023481'); - -- Gear - -- Aerospace Division T - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/291159152'); - -- UNT Robotics High Top Men's Canvas Shoes - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/264529951'); - -- UNT Robotics High Top Women's Canvas Shoes - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/264529433'); - -- UNT Robotics Drawstring Bag - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195968026'); - -- UNT Robotics Socks - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195967752'); - -- UNT Robotics Flip-Flops - INSERT INTO outgoing_request_cache_config (ttl, config_name,endpoint) VALUES (86400, 'Printful','https://api.printful.com/store/products/195967367'); \ No newline at end of file +INSERT INTO outgoing_request_cache_config (ttl,config_name,endpoint) VALUES (86400, 'printful', 'https://api.printful.com/products/$1'); +INSERT INTO outgoing_request_cache_config (ttl,config_name,endpoint) VALUES (86400, 'printful', 'https://api.printful.com/products/variant/$1'); +INSERT INTO outgoing_request_cache_config (ttl,config_name,endpoint) VALUES (86400, 'printful', 'https://api.printful.com/store/products/$1'); +INSERT INTO outgoing_request_cache_config (ttl,config_name,endpoint) VALUES (86400, 'printful', 'https://api.printful.com/store/products$1'); +INSERT INTO outgoing_request_cache_config (ttl,config_name,endpoint) VALUES (86400, 'printful', 'https://api.printful.com/store/variants/$1'); \ No newline at end of file diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index 2785f074..096222ab 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -5,17 +5,18 @@ CREATE TABLE `outgoing_request_cache_config`( `id` int(11) NOT NULL AUTO_INCREMENT, `ttl` int(6) NOT NULL, -- ttl measured in seconds `config_name` varchar(255) NOT NULL, - `endpoint` varchar(4000) NOT NULL, + `endpoint` varchar(4000) NOT NULL, -- endpoint with '{}' replacing specific info, e.g., https://api.printful.com/store/products/{} instead of https://api.printful.com/store/products/@5f6ceb2cf3a5e5 PRIMARY KEY (id) )AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `api_cache`; CREATE TABLE `api_cache`( `id` int(11) NOT NULL AUTO_INCREMENT, - `last_successfully_retrieved` timestamp, - `last_attempted_retrieval` timestamp DEFAULT NULL, - `retry_count` int DEFAULT 0, `config_id` int(11) NOT NULL, + `last_successfully_retrieved` timestamp DEFAULT CURRENT_TIMESTAMP, + `last_attempted_retrieval` timestamp DEFAULT CURRENT_TIMESTAMP, + `retry_count` int DEFAULT 0, + `endpoint_args` varchar(4000) NOT NULL, -- args used to fill '{}'s in endpoint (e.g., https://api.printful.com/store/$1/$2/not-a-real-endpoint?$3) delimited with a '|' `content` text NOT NULL, PRIMARY KEY (id), FOREIGN KEY (config_id) REFERENCES outgoing_request_cache_config(id) From 60c91fe5855029eb51c8037a45d7f8a882c8d08b Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:55:36 -0500 Subject: [PATCH 13/18] Change content column type to mediumtext --- sql/outgoing_request_cache.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index 096222ab..cc8590ab 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -17,7 +17,7 @@ CREATE TABLE `api_cache`( `last_attempted_retrieval` timestamp DEFAULT CURRENT_TIMESTAMP, `retry_count` int DEFAULT 0, `endpoint_args` varchar(4000) NOT NULL, -- args used to fill '{}'s in endpoint (e.g., https://api.printful.com/store/$1/$2/not-a-real-endpoint?$3) delimited with a '|' - `content` text NOT NULL, + `content` mediumtext NOT NULL, PRIMARY KEY (id), FOREIGN KEY (config_id) REFERENCES outgoing_request_cache_config(id) )AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; From 8c9873937a339a8c34a8c8f0f5e9256c61b1d128 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Sun, 1 Sep 2024 14:24:59 -0500 Subject: [PATCH 14/18] Compress content column and change type to blob --- api/api-cache.php | 17 +++++++++++++---- sql/outgoing_request_cache.sql | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index 13a70f5e..ee1ed016 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -11,7 +11,13 @@ function get_cached_api_response(string $endpoint, ...$args): ?array { global $db; $q = $db->query(" SELECT - * + id, + config_id, + last_sucessfully_retrieved, + last_attempted_retrieval, + retry_count, + endpoint_args, + UNCOMPRESS(content) AS content FROM api_cache INNER JOIN @@ -70,7 +76,10 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { global $db; $q = $db->query(" SELECT - outgoing_request_cache_config.id as conf_id, ttl, content, last_successfully_retrieved + outgoing_request_cache_config.id AS conf_id, + ttl, + UNCOMPRESS(content) AS content, + last_successfully_retrieved FROM outgoing_request_cache_config LEFT JOIN @@ -142,7 +151,7 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar last_successfully_retrieved = UTC_TIMESTAMP, last_attempted_retrieval = UTC_TIMESTAMP, retry_count = 0, - content =\'' . $db->real_escape_string($content) . '\' + content = COMPRESS(\'' . $db->real_escape_string($content) . '\') WHERE id = ' . $id; } else { @@ -161,7 +170,7 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar UTC_TIMESTAMP, UTC_TIMESTAMP, '{$a}', - '{$db->real_escape_string($content)}')"; + COMPRESS('{$db->real_escape_string($content)}'))"; } $q = $db->query($query_string); if (!$q) { diff --git a/sql/outgoing_request_cache.sql b/sql/outgoing_request_cache.sql index cc8590ab..b6a35f8a 100644 --- a/sql/outgoing_request_cache.sql +++ b/sql/outgoing_request_cache.sql @@ -17,7 +17,7 @@ CREATE TABLE `api_cache`( `last_attempted_retrieval` timestamp DEFAULT CURRENT_TIMESTAMP, `retry_count` int DEFAULT 0, `endpoint_args` varchar(4000) NOT NULL, -- args used to fill '{}'s in endpoint (e.g., https://api.printful.com/store/$1/$2/not-a-real-endpoint?$3) delimited with a '|' - `content` mediumtext NOT NULL, + `content` blob NOT NULL, PRIMARY KEY (id), FOREIGN KEY (config_id) REFERENCES outgoing_request_cache_config(id) -)AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; +)AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; From ccabb762ae07abbdab3b664eec530b5ac4c04141 Mon Sep 17 00:00:00 2001 From: kenneth-w-chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Sat, 7 Sep 2024 14:14:48 -0500 Subject: [PATCH 15/18] refactor/reformating --- api/api-cache.php | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/api/api-cache.php b/api/api-cache.php index ee1ed016..689455c7 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -36,7 +36,8 @@ function get_cached_api_response(string $endpoint, ...$args): ?array { return null; } -class CacheResult { +class CacheResult +{ /** * @var string $content The response content */ @@ -69,7 +70,7 @@ public function __construct(string $content, bool $fetched_new_content = false, * Gets the first entry from the API cache that has a matching endpoint. If the entry is expired or does not exist, returns the results from executing cURL. Updates the cache with fetched results if the entry existed * @param string $endpoint The endpoint for the API request * @param resource|CurlHandle $ch The Curl Handle to send the request - * @param mixed ...$args Endpoint args + * @param mixed ...$args Endpoint args * @return CacheResult An object containing the response content, and some cURL info if curl_exec was called */ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { @@ -91,13 +92,13 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { AND endpoint_args = '{$db->real_escape_string(implode('|',$args))}' "); - if($q === false) { - error_log("Failed to retrieve endpoint \"". insert_args($endpoint, ...$args) ."\" from cache table: {$db->error}"); + if ($q === false) { + error_log("Failed to retrieve endpoint \"" . insert_args($endpoint, ...$args) . "\" from cache table: {$db->error}"); return null; } if ($q && $q->num_rows > 0) { $r = $q->fetch_array(MYSQLI_ASSOC); - if($r['content'] !== null) { + if ($r['content'] !== null) { $ttl = $r['ttl']; $now = time(); $retrieval_time = $r['last_successfully_retrieved']; @@ -115,20 +116,20 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { $result = curl_exec($ch); // add to cache if old cache entry, no errors, and HTTP OK $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if(!isset($can_be_cached)) { // if set, specific endpoint is already in db, so we can try to cache + if (!isset($can_be_cached)) { // if set, specific endpoint is already in db, so we can try to cache $config_id = get_config_id($endpoint); - if($config_id === null) { + if ($config_id === null) { error_log("Failed to check cachability of endpoint \"{$endpoint_full}\". Result not cached."); - return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch)); + return new CacheResult(curl_exec($ch), true, $response_code, curl_errno($ch)); } // $config_id should be false if the endpoint can't be cached, otherwise it should be an int $can_be_cached = $config_id !== false; } - if ($can_be_cached && !curl_errno($ch) && $response_code >= 200 && $response_code <=299) { + if ($can_be_cached && !curl_errno($ch) && $response_code >= 200 && $response_code <= 299) { insert_cached($endpoint, $result, $config_id, ...$args); } - return new CacheResult(curl_exec($ch),true, $response_code,curl_errno($ch)); + return new CacheResult(curl_exec($ch), true, $response_code, curl_errno($ch)); } /** @@ -143,7 +144,6 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar $r = get_cached_api_response($endpoint, ...$args); if ($r) { $id = $r['id']; - $query_string = ' UPDATE api_cache @@ -155,8 +155,6 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar WHERE id = ' . $id; } else { - $b = implode('|', $args); - $a = $db->real_escape_string($b); $query_string = " INSERT INTO api_cache @@ -169,7 +167,7 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar ({$config_id}, UTC_TIMESTAMP, UTC_TIMESTAMP, - '{$a}', + '{$db->real_escape_string(implode('|', $args))}', COMPRESS('{$db->real_escape_string($content)}'))"; } $q = $db->query($query_string); @@ -194,12 +192,12 @@ function get_config_id(string $endpoint) { WHERE endpoint = '{$db->real_escape_string($endpoint)}' "); - if($q === false) { + if ($q === false) { error_log("Failed to retrieve endpoint {$endpoint} from cache config table: {$db->error}"); return null; } // return $q->fetch_column(0); - if($q->num_rows < 1) + if ($q->num_rows < 1) return false; return $q->fetch_row()[0]; } @@ -274,7 +272,7 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) { } $q = $db->query($query_string); if (!$q) { - error_log('Failed to update API cache config: ' . $db->error); + error_log("Failed to update API cache config, ID {$id}: {$db->error}"); } } @@ -288,7 +286,7 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) { */ function insert_args(string $endpoint, ...$args): string { $search = array(); - for($i = 1; $i <= count($args); $i++) { + for ($i = 1; $i <= count($args); $i++) { $search[] = '$' . $i; } return str_replace($search, $args, $endpoint); From 42dd575f56a83e8773a2359f5336087bd23abee8 Mon Sep 17 00:00:00 2001 From: Kenneth-W-Chen <74205780+Kenneth-W-Chen@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:53:43 -0600 Subject: [PATCH 16/18] URW-207 Move old web devs to web team alumni page --- about/our-web-team-alumni.php | 108 ++++++++++++++++++++++++++++++++++ about/our-web-team.php | 93 +---------------------------- 2 files changed, 111 insertions(+), 90 deletions(-) create mode 100644 about/our-web-team-alumni.php diff --git a/about/our-web-team-alumni.php b/about/our-web-team-alumni.php new file mode 100644 index 00000000..6d5c117a --- /dev/null +++ b/about/our-web-team-alumni.php @@ -0,0 +1,108 @@ +'Peyton Thibodeaux', + 'title'=>'Webmaster', + 'description'=>"Peyton is a junior, studying computer science with a minor in mathematics. He's the webmaster for UNT Robotics and in charge of the website that you see in front of you. He enjoys learning and using new technologies and have a passion for creating things.", + 'picture_uri'=>'/images/web-team-pics/peyton-thibodeaux.jpg', + 'email'=>'webmaster@untrobotics.com', + 'linkedin_url'=>'https://www.linkedin.com/in/peyton-thibodeaux', + 'github_url'=>'https://www.github.com/peyton232', +// 'twitter_url'=>'' +]; +$members[] = [ + 'name'=>'Nicholas Tindle', + 'title'=>'Team Member', + 'description'=>"Nicholas Tindle is a Computer Engineering student at UNT. He works in software engineering and loves hackathons. You can generally find him wearing a hat and probably a sweatshirt. He has a long history of collaboration with UNT Robotics as the first president, a loyal advisor, and now Project Manager. He has also served as an advisor to the Dean and is currently an officer of Engineering United. Nick has helped host numerous events at the university over the years. In his professional life, he works in data analysis, web development, and python scripting.", + 'picture_uri'=>'/images/web-team-pics/nick-tindle.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/ntindle', + 'github_url'=>'https://www.github.com/ntindle', +]; +$members[] = [ + 'name'=>'Henry Legay', + 'title'=>'Team Member', + 'description'=>"Henry Legay is a Computer Science Student at UNT focused on web development. He is a web developer in Robotics with ready applicable experience and a willingness to learn.", + 'picture_uri'=>'/images/web-team-pics/henry-legay.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/henrylegay', + 'github_url'=>'https://www.github.com/henlegay', +]; + +$members[] = [ + 'name'=>'Mason Besmer', + 'title'=>'Team Member', + 'description'=>"Mason Besmer is a Computer Science student at UNT. He is a webmaster for UNT Robotics and participates in many student orgs. He creates many things and comes up with ideas for even more. In his free time, he likes to create environments for games and program the website in front of you. He likes organization and loves to tinker with things. Creator of his own magic mirror, Mason is a advocate for building his own electronics. Currently, he is working on a software solution for his Starcube. You can find out more about it on his LinkedIn.", + 'picture_uri'=>'/images/web-team-pics/mason-besmer.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/masonbesmer', + 'github_url'=>'https://www.github.com/shotbyapony', +]; +$members[] = [ + 'name'=>'Aryan Damle', + 'title'=>'Team Member', + 'description'=>"Aryan Damle is a Computer Science student at UNT. He is an aspiring full stack web developer and an avid Home Assistant enthusiast. He mentors a high school robotics team and loves to work on robots in his free time. You can find him at your local car meet on weekends if he isn't busy working on a robot or fixing something in his garage.", + 'picture_uri'=>'/images/web-team-pics/aryan-damle.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/aryan-damle-8691b11bb', + 'github_url'=>'https://www.github.com/aryan-damle', +]; +$members[] = [ + 'name'=>'Mary Plana', + 'title'=>'Team Member', + 'description'=>"Mary Plana is a Computer Science Student at UNT with studies focused on Front End Development. She loves designing and implementing the user interface of a project. She has a natural curiosity about the world and loves to learn and improve her skills. She is currently the president of Application Development Organization. She facilitates the meeting and leads student UI designers to design, implement, and improve the user interface of projects.", + 'picture_uri'=>'/images/web-team-pics/mary-plana.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/mary-plana', + 'github_url'=>'https://www.github.com/mcp31', +]; +$members[] = [ + 'name'=>'David Thompson', + 'title'=>'Team Member', + 'description'=>"David Thompson is a Computer Science Student at UNT with studies focused on Full Stack Development. He loves solving problems, learning new things, and is currently working with a start up on a social media application that is currently in Apple's TestFlight.", + 'picture_uri'=>'/images/web-team-pics/david-thompson.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/david-thompson-000', + 'github_url'=>'https://www.github.com/davidkt99', +]; +$members[] = [ + 'name'=>'Samin Yasar', + 'title'=>'Team Member', + 'description'=>"Samin Yasar is a senior Computer Science student at UNT. He is a team member of UNT Robotics webmaster helping maintain UNT Robotics website. He is also a part of the Application Development Organization as a team member. He likes to learn new things and solve complex problems.", + 'picture_uri'=>'/images/web-team-pics/samin-yasar.jpg', + 'linkedin_url'=>'https://www.linkedin.com/in/samin2668', + 'github_url'=>'https://www.github.com/samin2668', +]; +?> +
+ + +
+
+
+
+

Our Web Team Alumni

+
Meet the talented developers who helped shape our website into what it is today.
+
+
+ +
+
+
+ diff --git a/about/our-web-team.php b/about/our-web-team.php index 5191d5a7..ebd0a3f7 100644 --- a/about/our-web-team.php +++ b/about/our-web-team.php @@ -3,107 +3,22 @@ require('card.php'); head('Our Team', true); $members = array(); -$members[] = [ - 'name'=>'Peyton Thibodeaux', - 'title'=>'Webmaster | Team Member', - 'description'=>"Peyton is a junior, studying computer science with a minor in mathematics. He's the webmaster for UNT Robotics and in charge of the website that you see in front of you. He enjoys learning and using new technologies and have a passion for creating things.", - 'picture_uri'=>'/images/web-team-pics/peyton-thibodeaux.jpg', - 'email'=>'webmaster@untrobotics.com', - 'linkedin_url'=>'https://www.linkedin.com/in/peyton-thibodeaux', - 'github_url'=>'https://www.github.com/peyton232', -// 'twitter_url'=>'' -]; + $members[] = [ 'name'=>'Sebastian King', 'title'=>'Alumni | Team Member', 'description'=>"Sebastian is a post-baccalaureate world languages student, with a degree in Computer Science. His role is to oversee the day-to-day running of the organisation and help ensure the organisation best serves the students at UNT. His expertise are programming and electrical engineering and he specialises in networking and remote control systems. He is also responsible for a lot of the more ambitious projects around campus, including the famous Sofabot and our re-usable weather balloon project.", 'picture_uri'=>'/images/web-team-pics/sebastian-king.jpg', -// 'email'=>'', 'linkedin_url'=>'https://www.linkedin.com/in/sebastian-king', 'github_url'=>'https://www.github.com/sebastian-king', -// 'twitter_url'=>'' -]; -$members[] = [ - 'name'=>'Nicholas Tindle', - 'title'=>'President | Team Member', - 'description'=>"Nicholas Tindle is a Computer Engineering student at UNT. He works in software engineering and loves hackathons. You can generally find him wearing a hat and probably a sweatshirt. He has a long history of collaboration with UNT Robotics as the first president, a loyal advisor, and now Project Manager. He has also served as an advisor to the Dean and is currently an officer of Engineering United. Nick has helped host numerous events at the university over the years. In his professional life, he works in data analysis, web development, and python scripting.", - 'picture_uri'=>'/images/web-team-pics/nick-tindle.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/ntindle', - 'github_url'=>'https://www.github.com/ntindle', -// 'twitter_url'=>'' -]; -$members[] = [ - 'name'=>'Henry Legay', - 'title'=>'Team Member', - 'description'=>"Henry Legay is a Computer Science Student at UNT focused on web development. He is a web developer in Robotics with ready applicable experience and a willingness to learn.", - 'picture_uri'=>'/images/web-team-pics/henry-legay.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/henrylegay', - 'github_url'=>'https://www.github.com/henlegay', -// 'twitter_url'=>'' -]; -$members[] = [ - 'name'=>'Mason Besmer', - 'title'=>'Team Member', - 'description'=>"Mason Besmer is a Computer Science student at UNT. He is a webmaster for UNT Robotics and participates in many student orgs. He creates many things and comes up with ideas for even more. In his free time, he likes to create environments for games and program the website in front of you. He likes organization and loves to tinker with things. Creator of his own magic mirror, Mason is a advocate for building his own electronics. Currently, he is working on a software solution for his Starcube. You can find out more about it on his LinkedIn.", - 'picture_uri'=>'/images/web-team-pics/mason-besmer.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/masonbesmer', - 'github_url'=>'https://www.github.com/shotbyapony', -// 'twitter_url'=>'' -]; -$members[] = [ - 'name'=>'Aryan Damle', - 'title'=>'Team Member', - 'description'=>"Aryan Damle is a Computer Science student at UNT. He is an aspiring full stack web developer and an avid Home Assistant enthusiast. He mentors a high school robotics team and loves to work on robots in his free time. You can find him at your local car meet on weekends if he isn't busy working on a robot or fixing something in his garage.", - 'picture_uri'=>'/images/web-team-pics/aryan-damle.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/aryan-damle-8691b11bb', - 'github_url'=>'https://www.github.com/aryan-damle', -// 'twitter_url'=>'' ]; -$members[] = [ - 'name'=>'Mary Plana', - 'title'=>'Team Member', - 'description'=>"Mary Plana is a Computer Science Student at UNT with studies focused on Front End Development. She loves designing and implementing the user interface of a project. She has a natural curiosity about the world and loves to learn and improve her skills. She is currently the president of Application Development Organization. She facilitates the meeting and leads student UI designers to design, implement, and improve the user interface of projects.", - 'picture_uri'=>'/images/web-team-pics/mary-plana.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/mary-plana', - 'github_url'=>'https://www.github.com/mcp31', -// 'twitter_url'=>'' -]; -$members[] = [ - 'name'=>'David Thompson', - 'title'=>'Team Member', - 'description'=>"David Thompson is a Computer Science Student at UNT with studies focused on Full Stack Development. He loves solving problems, learning new things, and is currently working with a start up on a social media application that is currently in Apple's TestFlight.", - 'picture_uri'=>'/images/web-team-pics/david-thompson.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/david-thompson-000', - 'github_url'=>'https://www.github.com/davidkt99', -// 'twitter_url'=>'' -]; - -$members[] = [ - 'name'=>'Samin Yasar', - 'title'=>'Team Member', - 'description'=>"Samin Yasar is a senior Computer Science student at UNT. He is a team member of UNT Robotics webmaster helping maintain UNT Robotics website. He is also a part of the Application Development Organization as a team member. He likes to learn new things and solve complex problems.", - 'picture_uri'=>'/images/web-team-pics/samin-yasar.jpg', -// 'email'=>'', - 'linkedin_url'=>'https://www.linkedin.com/in/samin2668', - 'github_url'=>'https://www.github.com/samin2668', -// 'twitter_url'=>'' -]; - $members[] = [ 'name'=>'Kenneth Chen', 'title'=>'Team Member', 'description'=>"Kenneth Chen is a Computer Science and Accounting student at UNT. As part of UNT Robotics, he's programmed helpful things, such as the controller connections for Botathon Season 3. He is also the financial director of UNT Robotics. He enjoys learnings and helping others and hopes to make the website more accessible.", 'picture_uri'=>'/images/bio-pics/kenneth-chen.jpg', -// 'email'=>'', 'linkedin_url'=>'https://www.linkedin.com/in/kenneth-w-chen', 'github_url'=>'https://www.github.com/kenneth-w-chen', -// 'twitter_url'=>'' ]; $members[] = [ 'name'=>'Truitt Crozier', @@ -113,7 +28,6 @@ 'linkedin_url'=>'https://www.linkedin.com/in/truitt-crozier-719355293', 'github_url'=>'https://github.com/tjcrozier', ]; - $members[] = [ 'name'=>'Willow Houchin', 'title'=>'Team Member', @@ -122,7 +36,6 @@ 'linkedin_url'=>'https://www.linkedin.com/in/willow-houchin-127147252', 'github_url'=>'https://www.github.com/WillowHouchin', ]; - $members[] = [ 'name'=>'Logan Brewer', 'title'=>'Team Member', @@ -131,7 +44,6 @@ 'linkedin_url'=>'https://www.linkedin.com/in/logan-brewer-26a872256/', 'github_url'=>'https://github.com/loganthebrewer', ]; - ?>
@@ -154,7 +66,8 @@

Our Web Dev Team

-
These are the people who keep this site running.
+
These are the people who keep this site running. Meet our former web devs here. +
Date: Sat, 16 Nov 2024 18:13:17 -0600 Subject: [PATCH 17/18] URW-178: fix naming and serialisation --- api/api-cache.php | 16 ++++++++-------- sql/migrations/URW-64.sql | 1 - sql/migrations/urw-64.sql | 13 ------------- 3 files changed, 8 insertions(+), 22 deletions(-) delete mode 100644 sql/migrations/URW-64.sql delete mode 100644 sql/migrations/urw-64.sql diff --git a/api/api-cache.php b/api/api-cache.php index 689455c7..05dbea5b 100644 --- a/api/api-cache.php +++ b/api/api-cache.php @@ -27,7 +27,7 @@ function get_cached_api_response(string $endpoint, ...$args): ?array { WHERE endpoint = '{$db->real_escape_string($endpoint)}' AND - endpoint_args = '{$db->real_escape_string(implode('|',$args))}' + endpoint_args = '{$db->real_escape_string(serialize($args))}' "); if ($q) { $r = $q->fetch_array(MYSQLI_ASSOC); @@ -90,10 +90,10 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { WHERE endpoint = '{$db->real_escape_string($endpoint)}' AND - endpoint_args = '{$db->real_escape_string(implode('|',$args))}' + endpoint_args = '{$db->real_escape_string(serialize($args))}' "); if ($q === false) { - error_log("Failed to retrieve endpoint \"" . insert_args($endpoint, ...$args) . "\" from cache table: {$db->error}"); + error_log("Failed to retrieve endpoint \"" . qualify_endpoint($endpoint, ...$args) . "\" from cache table: {$db->error}"); return null; } if ($q && $q->num_rows > 0) { @@ -111,7 +111,7 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { } //inserts args into the endpoint at '$#' (e.g., $1, $2, $3, will be replaced by arg 1, arg 2, arg 3, respectively) - $endpoint_full = insert_args($endpoint, ...$args); + $endpoint_full = qualify_endpoint($endpoint, ...$args); curl_setopt($ch, CURLOPT_URL, $endpoint_full); $result = curl_exec($ch); // add to cache if old cache entry, no errors, and HTTP OK @@ -126,7 +126,7 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { $can_be_cached = $config_id !== false; } if ($can_be_cached && !curl_errno($ch) && $response_code >= 200 && $response_code <= 299) { - insert_cached($endpoint, $result, $config_id, ...$args); + cache($endpoint, $result, $config_id, ...$args); } return new CacheResult(curl_exec($ch), true, $response_code, curl_errno($ch)); @@ -139,7 +139,7 @@ function get_valid_cache_entry(string $endpoint, $ch, ...$args) { * @param int $config_id The ID of the config or its name in the config table * @param mixed ...$args The endpoint args for the API request */ -function insert_cached(string $endpoint, string $content, int $config_id, ...$args) { +function cache(string $endpoint, string $content, int $config_id, ...$args) { global $db; $r = get_cached_api_response($endpoint, ...$args); if ($r) { @@ -172,7 +172,7 @@ function insert_cached(string $endpoint, string $content, int $config_id, ...$ar } $q = $db->query($query_string); if (!$q) { - error_log("Failed to update API cache for endpoint \"" . insert_args($endpoint, ...$args) . "\": {$db->error}"); + error_log("Failed to update API cache for endpoint \"" . qualify_endpoint($endpoint, ...$args) . "\": {$db->error}"); } } @@ -284,7 +284,7 @@ function update_cache_config(int $id, $config_name = null, $ttl = null) { * @param mixed ...$args The arguments to insert into endpoint * @return string The endpoint with each "$#" replaced with its corresponding vararg */ -function insert_args(string $endpoint, ...$args): string { +function qualify_endpoint(string $endpoint, ...$args): string { $search = array(); for ($i = 1; $i <= count($args); $i++) { $search[] = '$' . $i; diff --git a/sql/migrations/URW-64.sql b/sql/migrations/URW-64.sql deleted file mode 100644 index 23d1a99b..00000000 --- a/sql/migrations/URW-64.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE TABLE ftpinvites (id int primary key auto_increment, email varchar(255), registration_token varchar(16)); diff --git a/sql/migrations/urw-64.sql b/sql/migrations/urw-64.sql deleted file mode 100644 index 30631c63..00000000 --- a/sql/migrations/urw-64.sql +++ /dev/null @@ -1,13 +0,0 @@ -ALTER TABLE ftpusers -ADD UNIQUE (name); - -ALTER TABLE ftpusers -MODIFY name char(128) NOT NULL; - -ALTER TABLE ftpusers -MODIFY passwd char(128) NOT NULL; - - - - - From 5cafc34d2b1b982b7658b4b589600580f77fb1ed Mon Sep 17 00:00:00 2001 From: Sebastian King Date: Sat, 16 Nov 2024 18:14:43 -0600 Subject: [PATCH 18/18] URW-64: fix naming conflicts in sql migration --- sql/migrations/URW-64-ftp-users.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 sql/migrations/URW-64-ftp-users.sql diff --git a/sql/migrations/URW-64-ftp-users.sql b/sql/migrations/URW-64-ftp-users.sql new file mode 100644 index 00000000..110d98a4 --- /dev/null +++ b/sql/migrations/URW-64-ftp-users.sql @@ -0,0 +1,10 @@ +ALTER TABLE ftpusers + ADD UNIQUE (name); + +ALTER TABLE ftpusers + MODIFY name char(128) NOT NULL; + +ALTER TABLE ftpusers + MODIFY passwd char(128) NOT NULL; + +CREATE TABLE ftpinvites (id int primary key auto_increment, email varchar(255), registration_token varchar(16)); \ No newline at end of file