From 411491f7f5ea1291e69de1bfb656998af0eadc85 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sat, 2 Dec 2023 21:20:19 +0100 Subject: [PATCH] feat: Add endpoint for adding new URLs --- controllers/manage/POST.php | 53 +++++++++++++++++++++++++++++++ controllers/routes.php | 1 + persistence/repositories/URLs.php | 43 ++++++++++++++++++++----- templates/pages/homepage.php | 2 +- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 controllers/manage/POST.php diff --git a/controllers/manage/POST.php b/controllers/manage/POST.php new file mode 100644 index 0000000..9508241 --- /dev/null +++ b/controllers/manage/POST.php @@ -0,0 +1,53 @@ + $charset[rand(0, strlen($charset) - 1)], + range(1, $length) + ) + ); +} + +return function (array &$context) { + $url = $_POST["url"] ?? ""; + + if (!$url) { + setStatusCode(400); + echo json_encode( + errorResponse("URL missing", "Please provide a URL.") + ); + return; + } + + $repository = $context[REPOSITORIES]->urls; + + $candidates = []; + for ($length = MIN_LENGTH; count($candidates) == 0 || $length > MAX_LENGTH; $length++) { + $candidates = $repository->getUnusedSlugs( + array_map( + fn($_) => generate_candidate($length), + range(1, CANDIDATES_PER_ITERATION) + ) + ); + } + + $slug = $candidates[0]; + $accessKey = sha1($url . "-" . $url . "-" . microtime() . "-" . rand()); + + $result = $context[REPOSITORIES]->urls->add(new URL( + $slug, + $url, + $accessKey + )); + + echo json_encode($result); +}; diff --git a/controllers/routes.php b/controllers/routes.php index 7bb9ef0..6ac50e7 100644 --- a/controllers/routes.php +++ b/controllers/routes.php @@ -13,6 +13,7 @@ function fromController(string $path, string $endpoint = null) { return function(Router $router) { $router->addRoute(GET, "/", fromController("/GET")); + $router->addRoute(POST, "/manage", fromController("/manage/POST")); $router->addRoute(GET, "/.*", fromController("/slug/GET")); }; diff --git a/persistence/repositories/URLs.php b/persistence/repositories/URLs.php index 233b9df..a9ec1ed 100644 --- a/persistence/repositories/URLs.php +++ b/persistence/repositories/URLs.php @@ -22,6 +22,40 @@ class URLs { $entry->url, $entry->accessKey, ]); + + return $this->getById($this->connection->lastInsertId()); + } + + public function getUnusedSlugs(array $slugs) { + $placeholderList = join(",", array_map(fn($_) => "?", $slugs)); + + $statement = $this->connection->prepare(<<table` + WHERE `slug` IN ($placeholderList) + EOF); + $statement->execute($slugs); + + $existing = $statement->fetchAll(PDO::FETCH_COLUMN, 0); + + return array_values(array_diff($slugs, $existing)); + } + + private function entityFromRow($row) { + $url = new URL($row["slug"], $row["url"], $row["access_key"]); + $url->id = $row["id"]; + $url->created = new DateTime($row["created"]); + $url->updated = new DateTime($row["updated"]); + $url->deleted = ($row["deleted"]) ? new DateTime($row["deleted"]) : null; + + return $url; + } + + public function getById(int $id) { + $statement = $this->connection->prepare(<<table` WHERE `id` = ? + EOF); + $statement->execute([$id]); + return $this->entityFromRow($statement->fetch()); } public function getBySlug(string $slug) { @@ -34,14 +68,7 @@ class URLs { if ($statement->rowCount() == 0) { return null; } else { - $row = $statement->fetch(); - $url = new URL($row["slug"], $row["url"], $row["access_key"]); - $url->id = $row["id"]; - $url->created = new DateTime($row["created"]); - $url->updated = new DateTime($row["updated"]); - $url->deleted = ($row["deleted"]) ? new DateTime($row["deleted"]) : null; - - return $url; + return $this->entityFromRow($statement->fetch()); } } } diff --git a/templates/pages/homepage.php b/templates/pages/homepage.php index 167cbad..05cb432 100644 --- a/templates/pages/homepage.php +++ b/templates/pages/homepage.php @@ -10,7 +10,7 @@ require(__DIR__ . "/../layout/top.php"); picture of a vile with a tag 'Drnk Me'
-
+ ">