diff --git a/includes/api/products.php b/includes/api/products.php new file mode 100644 index 00000000..d7111af1 --- /dev/null +++ b/includes/api/products.php @@ -0,0 +1,47 @@ + + */ + +use wishthis\User; + +$api = true; +$response = array( + 'success' => false, +); + +require '../../index.php'; + +switch ($_SERVER['REQUEST_METHOD']) { + case 'PUT': + parse_str(file_get_contents("php://input"), $_PUT); + + if (isset($_PUT['productID'], $_PUT['productStatus'])) { + $database->query('UPDATE `products` + SET `status` = "' . $_PUT['productStatus'] . '" + WHERE `id` = ' . $_PUT['productID'] . ' + ;'); + + $response['success'] = true; + } + break; + + case 'DELETE': + parse_str(file_get_contents("php://input"), $_DELETE); + + if (isset($_DELETE['productID'])) { + $database->query('DELETE FROM `products` + WHERE `id` = ' . $_DELETE['productID'] . ' + ;'); + + $response['success'] = true; + } + break; +} + +echo json_encode($response); +header('Content-type: application/json; charset=utf-8'); +die(); diff --git a/includes/api/wishlists.php b/includes/api/wishlists.php index 0bf4be8a..d174b9f9 100644 --- a/includes/api/wishlists.php +++ b/includes/api/wishlists.php @@ -8,7 +8,7 @@ use wishthis\User; -$api = true; +$api = true; $response = array( 'success' => false, ); diff --git a/includes/assets/css/default.css b/includes/assets/css/default.css index 7234d370..095ab884 100644 --- a/includes/assets/css/default.css +++ b/includes/assets/css/default.css @@ -19,3 +19,19 @@ .ui.progress.nolabel:last-child { margin: 0; } + +/** + * Card + */ +.ui.card .header > img { + height: 1.25em; +} + +/** + * Label + */ +p .ui.horizontal.label { + margin: 0; + cursor: default; + user-select: none; +} diff --git a/includes/assets/js/default.js b/includes/assets/js/default.js index ec00a022..7ab59f3e 100644 --- a/includes/assets/js/default.js +++ b/includes/assets/js/default.js @@ -3,15 +3,143 @@ $(function() { * Fomantic UI */ $.fn.api.settings.api = { - 'get wishlists' : '/includes/api/wishlists.php', - 'delete wishlist' : '/includes/api/wishlists.php' + 'get wishlists' : '/includes/api/wishlists.php', + 'delete wishlist' : '/includes/api/wishlists.php', + 'update product status': '/includes/api/products.php', + 'delete product' : '/includes/api/products.php', }; $('.ui.dropdown.wishlists').dropdown({ filterRemoteData: true }); + /** + * Refresh Wishlist + */ wishlistRefresh(); + + /** + * Commit to Product + */ + $('.ui.button.commit').on('click', function() { + var button = $(this); + var card = button.closest('.ui.card'); + var column = card.closest('.column'); + + $('body') + .modal({ + title: 'Really commit?', + content: 'Would you really like to commit to this purchase? It will no longer appear in the wishlist anymore.', + class: 'tiny', + actions: [ + { + text: 'Yes, commit', + class: 'approve primary' + }, + { + text: 'Cancel', + class: '' + } + ], + onApprove: function() { + /** + * Update product status + */ + button.api({ + action: 'update product status', + method: 'PUT', + data: { + productID: card.data('id'), + productStatus: 'unavailable' + }, + on: 'now', + onResponse: function(response) { + return response; + }, + successTest: function(response) { + return response.success || false; + }, + onComplete: function(response, element, xhr) { + + }, + onSuccess: function(response, element, xhr) { + column.fadeOut(); + }, + onFailure: function(response, element, xhr) { + + }, + onError: function(errorMessage, element, xhr) { + + }, + onAbort: function(errorMessage, element, xhr) { + + } + }); + } + }) + .modal('show'); + }); + + /** + * Delete Product + */ + $('.ui.button.delete').on('click', function() { + var button = $(this); + var card = button.closest('.ui.card'); + var column = card.closest('.column'); + + $('body') + .modal({ + title: 'Really delete?', + content: 'Would you really like to delete to this product? It will be gone forever.', + class: 'tiny', + actions: [ + { + text: 'Yes, delete', + class: 'approve primary' + }, + { + text: 'Cancel', + class: '' + } + ], + onApprove: function() { + /** + * Delete product + */ + button.api({ + action: 'delete product', + method: 'DELETE', + data: { + productID: card.data('id'), + }, + on: 'now', + onResponse: function(response) { + return response; + }, + successTest: function(response) { + return response.success || false; + }, + onComplete: function(response, element, xhr) { + + }, + onSuccess: function(response, element, xhr) { + column.fadeOut(); + }, + onFailure: function(response, element, xhr) { + + }, + onError: function(errorMessage, element, xhr) { + + }, + onAbort: function(errorMessage, element, xhr) { + + } + }); + } + }) + .modal('show'); + }); }); function wishlistRefresh() { diff --git a/includes/assets/js/wishlist-view.js b/includes/assets/js/wishlist-view.js index 10dee88d..cd7b040e 100644 --- a/includes/assets/js/wishlist-view.js +++ b/includes/assets/js/wishlist-view.js @@ -9,10 +9,16 @@ $(function() { if (wishlistValue) { $('.wishlist-view').removeClass('disabled'); + } else { + $('.wishlist-view').addClass('disabled'); + } + + const urlParams = new URLSearchParams(window.location.search); + + if (wishlistValue === urlParams.get('wishlist')) { $('.wishlist-share').removeClass('disabled'); $('.wishlist-delete button').removeClass('disabled'); } else { - $('.wishlist-view').addClass('disabled'); $('.wishlist-share').addClass('disabled'); $('.wishlist-delete button').addClass('disabled'); } diff --git a/includes/assets/js/wishlist.js b/includes/assets/js/wishlist.js new file mode 100644 index 00000000..c0d70cd7 --- /dev/null +++ b/includes/assets/js/wishlist.js @@ -0,0 +1,25 @@ +$(function() { + /** + * User Warning + */ + if ($('.wishlist-own').length) { + $('body') + .modal({ + title: $('.wishlist-own .header').text(), + content: $('.wishlist-own .text').html(), + class: '', + blurring: true, + closable: false, + actions: [ + { + text: 'Show wishlist anyway', + class: 'approve primary' + } + ], + onApprove: function() { + $('.wishlist-own').slideUp(); + } + }) + .modal('show'); + } +}); diff --git a/includes/classes/options.php b/includes/classes/options.php index e1130aa4..a20761f6 100644 --- a/includes/classes/options.php +++ b/includes/classes/options.php @@ -43,15 +43,9 @@ class Options public function setOption(string $key, string $value): void { - try { - $option = $this->database->query('UPDATE `options` - SET `value` - WHERE `key` = ' . $key . ' - ;'); - - $value = $option['value'] ?? ''; - } catch (\Throwable $th) { - //throw $th; - } + $this->database->query('UPDATE `options` + SET `value` = "' . $value . '" + WHERE `key` = "' . $key . '" + ;'); } } diff --git a/includes/classes/page.php b/includes/classes/page.php index 47d7b6fe..502c4b84 100644 --- a/includes/classes/page.php +++ b/includes/classes/page.php @@ -177,9 +177,6 @@ class Page Update -
-
-
diff --git a/includes/classes/wishlist.php b/includes/classes/wishlist.php new file mode 100644 index 00000000..95cc14b1 --- /dev/null +++ b/includes/classes/wishlist.php @@ -0,0 +1,161 @@ + + */ + +namespace wishthis; + +class Wishlist +{ + private int $id; + private string $hash; + + public array $data; + public array $products = array(); + + public bool $exists = false; + + public function __construct(int|string $id_or_hash) + { + global $database; + + $column; + + if (is_int($id_or_hash)) { + $column = 'id'; + } + if (is_string($id_or_hash)) { + $column = 'hash'; + $id_or_hash = '"' . $id_or_hash . '"'; + } + + /** + * Get Wishlist + */ + $this->data = $database->query('SELECT * + FROM `wishlists` + WHERE `' . $column . '` = ' . $id_or_hash . ';') + ->fetch(); + + /** Exists */ + if (isset($this->data['id'])) { + $this->id = $this->data['id']; + $this->exists = true; + } else { + return; + } + + /** + * Get Products + */ + $this->products = $database->query('SELECT * + FROM `products` + WHERE `wishlist` = ' . $this->id . ';') + ->fetchAll(); + } + + public function getCards($options = array()): void + { + /** + * Exclude + */ + $exclude = isset($options['exclude']) ? $options['exclude'] : array(); + + if ($exclude) { + $products = array_filter($this->products, function ($product) use ($exclude) { + return !in_array($product['status'], $exclude); + }); + } else { + $products = $this->products; + } + + /** + * Cards + */ + if (!empty($products)) { ?> +
+ + get($product['url']); + ?> +
+
+ + image) { ?> +
+ +
+ + +
+ title) { ?> +
+ favicon) { ?> + + + + url) { ?> + title ?> + + title ?> + +
+ + + keywords) { ?> +
+ keywords ?> +
+ + + description) { ?> +
+ description ?> +
+ +
+
+ publishedTime) { ?> + + publishedTime ?> + + + providerName) { ?> + providerName ?> + +
+
+ data['user'] === $_SESSION['user']['id']) { ?> + Delete + + Commit + +
+ +
+
+ + +
+ + +
+ +
+
+ Empty +
+

This wishlist seems to be empty.

+
+
query('ALTER TABLE `users` ADD INDEX(`password`);'); $database->query('ALTER TABLE `wishlists` - ADD `hash` VARCHAR(128) NOT NULL AFTER `name` + ADD `hash` VARCHAR(128) NOT NULL AFTER `name` ;'); $database->query('ALTER TABLE `wishlists` ADD INDEX(`hash`);'); $database->query('INSERT INTO `options` (`key`, `value`) VALUES ("version", "' . VERSION . '");'); - - // Use this for future versions since it didn't existsin 0.1.0 - // $options->setOption('version', VERSION); } + /** Current version is below 0.3.0 */ + if (-1 === version_compare($options->version, '0.3.0')) { + $database->query('ALTER TABLE `products` + ADD `status` VARCHAR(32) NOT NULL AFTER `url` + ;'); + } + + /** Update version */ + $options->setOption('version', VERSION); + header('Location: /?page=home'); die(); } diff --git a/includes/pages/wishlist-create.php b/includes/pages/wishlist-create.php index ee163869..3e666a87 100644 --- a/includes/pages/wishlist-create.php +++ b/includes/pages/wishlist-create.php @@ -19,7 +19,7 @@ if (isset($_POST['name'])) { ) VALUES ( ' . $_SESSION['user']['id'] . ', "' . $_POST['name'] . '", - "' . time() . $_SESSION['user']['id'] . $_POST['name'] . '" + "' . sha1(time() . $_SESSION['user']['id'] . $_POST['name']) . '" ) ;'); diff --git a/includes/pages/wishlist-product-add.php b/includes/pages/wishlist-product-add.php index ffb626b4..1437e237 100644 --- a/includes/pages/wishlist-product-add.php +++ b/includes/pages/wishlist-product-add.php @@ -31,6 +31,7 @@ $page->navigation();
+ diff --git a/includes/pages/wishlist-view.php b/includes/pages/wishlist-view.php index e1f83269..aaca52a9 100644 --- a/includes/pages/wishlist-view.php +++ b/includes/pages/wishlist-view.php @@ -6,23 +6,17 @@ * @author Jay Trees */ -use wishthis\{Page, User}; -use Embed\Embed; +use wishthis\{Page, User, Wishlist}; $page = new page(__FILE__, 'View wishlist'); $page->header(); $page->navigation(); -$products = array(); - /** * Get wishlist products */ if (isset($_GET['wishlist'])) { - $wishlist = $database->query('SELECT * FROM `wishlists` - WHERE `id` = "' . $_GET['wishlist'] . '"') - ->fetch(); - $products = $user->getProducts($_GET['wishlist']); + $wishlist = new Wishlist(intval($_GET['wishlist'])); } /** @@ -38,7 +32,7 @@ if (isset($_POST['wishlist_delete_id'])) {

title ?>

-
+

Wishlists

Please select a wishlist to view.

@@ -60,7 +54,7 @@ if (isset($_POST['wishlist_delete_id'])) {

Options

Wishlist related options.

- + Share @@ -68,7 +62,7 @@ if (isset($_POST['wishlist_delete_id'])) {
- @@ -76,96 +70,11 @@ if (isset($_POST['wishlist_delete_id'])) {
- -
- - - get($product['url']); - ?> -
-
- - image) { ?> -
- -
- - -
- title) { ?> -
- url) { ?> - title ?> - - title ?> - -
- - - keywords) { ?> -
- keywords ?> -
- - - description) { ?> -
- description ?> -
- -
-
- publishedTime) { ?> - - publishedTime ?> - - - favicon) { ?> - providerName) { ?> - <?= $info->providerName ?> - - - - -
- -
-
- - -
- - -
- -
-
- Empty -
-

The selected wishlist seems to be empty.

- Add a product -
-
- -
- -
-
- No wishlist selected -
-

Select a wishlist to see it's products.

-
-
- - + getCards(); + } + ?>
diff --git a/includes/pages/wishlist.php b/includes/pages/wishlist.php index 7fe9f525..a5a1f736 100644 --- a/includes/pages/wishlist.php +++ b/includes/pages/wishlist.php @@ -1,123 +1,74 @@ */ -use wishthis\{Page, User}; -use Embed\Embed; +use wishthis\{Page, User, Wishlist}; -$page = new page(__FILE__, 'Wishlist'); +$wishlist = new Wishlist($_GET['wishlist']); + +if (!$wishlist->exists) { + http_response_code(404); + ?> +

Not found

+

The requested Wishlist was not found and likely deleted by its creator.

+ data['name']); $page->header(); $page->navigation(); - -$wishlist = $database->query('SELECT * FROM `wishlists` - WHERE `hash` = "' . $_GET['wishlist'] . '"') - ->fetch(); - -$products = $user->getProducts($wishlist['id']); ?>

title ?>

+ id) && $user->id === intval($wishlist->data['user'])) { ?> +
+ +
+
+ Careful +
+
+

+ You are viewing your own wishlist! + You will be able to see which products have already been bought for you. + Don't you want to be surprised? +

+

+ It's probably best to just close this tab. +

+
+
+
+ +
-

+

What to do?

+

+ If you found something you would like to buy, + click the Commit button + and it will become unavailable for others. +

- -
- - - get($product['url']); - ?> -
-
- - image) { ?> -
- -
- - -
- title) { ?> -
- url) { ?> - title ?> - - title ?> - -
- - - keywords) { ?> -
- keywords ?> -
- - - description) { ?> -
- description ?> -
- -
-
- publishedTime) { ?> - - publishedTime ?> - - - favicon) { ?> - providerName) { ?> - <?= $info->providerName ?> - - - - -
- -
-
- - -
- - -
- -
-
- Empty -
-

The selected wishlist seems to be empty.

- Add a product -
-
- -
- -
-
- No wishlist selected -
-

Select a wishlist to see it's products.

-
-
- - + getCards( + array( + 'exclude' => array('unavailable'), + ) + ); + ?>
diff --git a/index.php b/index.php index 59431e29..4fdcf6e5 100644 --- a/index.php +++ b/index.php @@ -77,7 +77,7 @@ if ($options) { /** * Update */ -define('VERSION', '0.2.0'); +define('VERSION', '0.3.0'); if ($options) { if (-1 === version_compare($options->version, VERSION)) {