diff --git a/index.php b/index.php index 94c145f..1ae4ad6 100644 --- a/index.php +++ b/index.php @@ -9,7 +9,8 @@ $request = new Request($_SERVER); $handler = new RequestHandler($request); $handler->registerRoutes([ - new Route('GET', 'products', ['ProductList\View\Product', 'listAll']), + new Route('GET', 'products', ['ProductList\View\Product', 'list']), + new Route('DELETE', 'products', ['ProductList\View\Product', 'delete']), new Route('GET', 'add-product', function() { readfile('static/add-product.html'); }), new Route('GET', '', function() { readfile('static/index.html'); }), ]); diff --git a/src/Exception/NotFoundException.php b/src/Exception/NotFoundException.php new file mode 100644 index 0000000..a4a2584 --- /dev/null +++ b/src/Exception/NotFoundException.php @@ -0,0 +1,4 @@ +uri; } + public function getQueryString() + { + return $this->queryString; + } + public function __construct(array $params) { - $this->uri = basename($params['REQUEST_URI']); + $uri_base = trim($params['REQUEST_URI'], '?'.$params['QUERY_STRING']); + $uri_base = trim(urldecode($uri_base), '/'); + $this->uri = explode('/', $uri_base); + $this->method = $params['REQUEST_METHOD']; + + parse_str($params['QUERY_STRING'], $this->queryString); } } diff --git a/src/Http/Route.php b/src/Http/Route.php index 46fbf92..5726c5d 100644 --- a/src/Http/Route.php +++ b/src/Http/Route.php @@ -10,7 +10,7 @@ class Route public function __construct(string $method, string $uri, array|\Closure $view) { $this->method = $method; - $this->uri = $uri; + $this->uri = explode('/', $uri); $this->view = $view; } diff --git a/src/Model/Book.php b/src/Model/Book.php index 16ecef0..a62c8cf 100644 --- a/src/Model/Book.php +++ b/src/Model/Book.php @@ -66,7 +66,24 @@ class Book extends Product $this->setVariationId($conn->insert_id); return $conn->insert_id; } else { - throw new Exception("Unable to insert object"); + throw new \Exception("Unable to insert object"); } } + + public function delete($conn = null) + { + if ($conn === null) { + $conn = Database::connect(); + } + + $variationId = $this->getVariationId(); + $stmt = $conn->prepare('DELETE FROM '.BOOK.' WHERE id = ?'); + $stmt->bind_param('i', $variationId); + + if ($stmt->execute() === false) { + throw new \Exception("Unable to delete product with id '$id'"); + } + + parent::delete($conn); + } } diff --git a/src/Model/DVD.php b/src/Model/DVD.php index 5859c42..6e05e39 100644 --- a/src/Model/DVD.php +++ b/src/Model/DVD.php @@ -69,4 +69,21 @@ class DVD extends Product throw new Exception("Unable to insert object"); } } + + public function delete($conn = null) + { + if ($conn === null) { + $conn = Database::connect(); + } + + $variationId = $this->getVariationId(); + $stmt = $conn->prepare('DELETE FROM '.DVD.' WHERE id = ?'); + $stmt->bind_param('i', $variationId); + + if ($stmt->execute() === false) { + throw new \Exception("Unable to delete product with id '$id'"); + } + + parent::delete($conn); + } } diff --git a/src/Model/Furniture.php b/src/Model/Furniture.php index 10b73ba..91d558d 100644 --- a/src/Model/Furniture.php +++ b/src/Model/Furniture.php @@ -92,7 +92,24 @@ class Furniture extends Product $this->setVariationId($conn->insert_id); return $conn->insert_id; } else { - throw new Exception("Unable to insert object"); + throw new \Exception("Unable to insert object"); } } + + public function delete($conn = null) + { + if ($conn === null) { + $conn = Database::connect(); + } + + $variationId = $this->getVariationId(); + $stmt = $conn->prepare('DELETE FROM '.FURNITURE.' WHERE id = ?'); + $stmt->bind_param('i', $variationId); + + if ($stmt->execute() === false) { + throw new \Exception("Unable to delete product with id '$id'"); + } + + parent::delete($conn); + } } diff --git a/src/Model/Model.php b/src/Model/Model.php index 3002fce..d0ecda2 100644 --- a/src/Model/Model.php +++ b/src/Model/Model.php @@ -5,6 +5,7 @@ trait Model { abstract public static function fromRow($row) : self; abstract public function insert($conn = null) : int; // should return id + abstract public function delete($conn = null); abstract private static function getSelectAllQuery() : string; public static function selectAll($conn = null) : array diff --git a/src/Model/Product.php b/src/Model/Product.php index 22d4fa9..bf9f427 100644 --- a/src/Model/Product.php +++ b/src/Model/Product.php @@ -1,6 +1,8 @@ productId; } + public function getVariationId() + { + return $this->variationId; + } + public function setVariationId($id) { $this->variationId = $id; @@ -56,6 +63,43 @@ abstract class Product implements \JsonSerializable abstract public function getFormatedAttr(); + public function delete($conn = null) + { + if ($conn === null) { + $conn = Database::connect(); + } + + $productId = $this->getProductId(); + $stmt = $conn->prepare('DELETE FROM '.PRODUCT.' WHERE id = ?'); + $stmt->bind_param('i', $productId); + + if ($stmt->execute() === false) { + throw new \Exception("Unable to delete product with id '$id'"); + } + } + + public static function fromId($id, $conn = null) : self + { + if ($conn === null) { + $conn = Database::connect(); + } + + $stmt = $conn->prepare(self::getSelectAllQuery().' WHERE '.PRODUCT.'.id = ?'); + $stmt->bind_param('i', $id); + + if ($stmt->execute() === true) { + $row = $stmt->get_result()->fetch_assoc(); + + if($row === null) { + throw new NotFoundException("No product with id '$id'"); + } + + return self::fromRow($row); + } else { + throw new \Exception("Unable to select object"); + } + } + public static function fromRow($row) : self { if ($row['size'] !== null) { @@ -65,7 +109,7 @@ abstract class Product implements \JsonSerializable } elseif ($row['height'] !== null) { return Furniture::fromRow($row); } else { - throw new Exception("Product without a type"); + throw new \Exception("Product without a type"); } } @@ -77,7 +121,7 @@ abstract class Product implements \JsonSerializable FROM '.PRODUCT.' LEFT JOIN '.DVD.' ON '.PRODUCT.'.id = '.DVD.'.product_id LEFT JOIN '.BOOK.' ON '.PRODUCT.'.id = '.BOOK.'.product_id - LEFT JOIN '.FURNITURE.' ON '.PRODUCT.'.id = '.FURNITURE.'.product_id;'; + LEFT JOIN '.FURNITURE.' ON '.PRODUCT.'.id = '.FURNITURE.'.product_id'; } public function insert($conn = null) : int @@ -100,7 +144,7 @@ abstract class Product implements \JsonSerializable $this->setProductId($conn->insert_id); return $conn->insert_id; } else { - throw new Exception("Unable to insert object"); + throw new \Exception("Unable to insert object"); } } diff --git a/src/View/Product.php b/src/View/Product.php index 03867e0..a2124dd 100644 --- a/src/View/Product.php +++ b/src/View/Product.php @@ -3,11 +3,48 @@ namespace ProductList\View; use ProductList\Http\Request; use ProductList\Model\Product as ProductModel; +use ProductList\Exception\NotFoundException; class Product { - public static function listAll(Request $request) + public static function list(Request $request) { echo json_encode(ProductModel::selectAll()); } + + public static function delete(Request $request) + { + $queryString = $request->getQueryString(); + + if (array_key_exists('id', $queryString)) { + $ids = explode(',', $queryString['id']); + $ids = array_map('intval', $ids); + + foreach($ids as $id) { + try { + $product = ProductModel::fromId($id); + + try { + $product->delete(); + } catch (\Exception $e) { + http_response_code(500); + echo $e->getMessage(); + return; + } + + } catch (NotFoundException $e) { + http_response_code(404); + echo $e->getMessage(); + return; + } + } + } else { + http_response_code(400); + echo 'Missing parameter "id".'; + } + } + + public static function add(Request $request) + { + } } diff --git a/static/index.js b/static/index.js index 5c70a1e..420a03b 100644 --- a/static/index.js +++ b/static/index.js @@ -37,7 +37,7 @@ const deleteSelected = () => { loadItems(); } - xhttp.open('DELETE', 'products', true); + xhttp.open('DELETE', `products?id=${values.join(',')}`, true); xhttp.send(); }