Merge branch 'develop' into add-statistics

This commit is contained in:
grandeljay 2022-02-26 20:27:27 +01:00
commit ca6b01f447
9 changed files with 302 additions and 48 deletions

10
.htaccess Normal file
View file

@ -0,0 +1,10 @@
RewriteEngine On
# Wishlists
RewriteRule ^([a-z\-]+)/(\d+)$ /?page=$1&wishlist=$2 [QSA,L]
# Wishlist
RewriteRule ^wishlist/([a-z0-9]+)$ /?wishlist=$1 [QSA,L]
# Page
RewriteRule ^([a-z\-]+)$ /?page=$1 [QSA,L]

33
src/api/url.php Normal file
View file

@ -0,0 +1,33 @@
<?php
/**
* url.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\URL;
$api = true;
$response = array(
'success' => false,
);
require '../../index.php';
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
if (isset($_GET['url'])) {
$url = new URL(base64_decode($_GET['url']));
$response['data'] = array(
'url' => $url->getPretty()
);
$response['success'] = true;
}
break;
}
header('Content-type: application/json; charset=utf-8');
echo json_encode($response);
die();

View file

@ -10,7 +10,7 @@ if ('serviceWorker' in navigator) {
}) })
} }
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams($_GET);
$(function() { $(function() {
/** /**
@ -40,8 +40,8 @@ $(function() {
placeholder: 'No wishlist selected.' placeholder: 'No wishlist selected.'
}) })
if (urlParams.has('wishlist')) { if ($_GET.wishlist) {
element.dropdown('set selected', urlParams.get('wishlist')); element.dropdown('set selected', $_GET.wishlist);
} else { } else {
if (response.results[0]) { if (response.results[0]) {
element.dropdown('set selected', response.results[0].value); element.dropdown('set selected', response.results[0].value);

View file

@ -4,6 +4,7 @@ $(function() {
fields: { fields: {
email: 'email', email: 'email',
password: ['minLength[6]', 'empty'], password: ['minLength[6]', 'empty'],
planet: ['minLength[3]', 'empty'],
} }
}); });
}); });

View file

@ -17,8 +17,8 @@ $(function () {
placeholder: 'No wishlist selected.' placeholder: 'No wishlist selected.'
}) })
if (urlParams.has('wishlist')) { if ($_GET.wishlist) {
element.dropdown('set selected', urlParams.get('wishlist')); element.dropdown('set selected', $_GET.wishlist);
} else { } else {
if (wishlists[0]) { if (wishlists[0]) {
element.dropdown('set selected', wishlists[0].value); element.dropdown('set selected', wishlists[0].value);
@ -45,14 +45,26 @@ $(function () {
$('[name="wishlist_delete_id"]').val(wishlistValue); $('[name="wishlist_delete_id"]').val(wishlistValue);
if (wishlistValue) { if (wishlistValue) {
urlParams.set('wishlist', wishlistValue); $_GET.wishlist = wishlistValue;
window.history.pushState({}, '', '/?' + urlParams.toString());
$('.wishlist-share').attr('href', '/?wishlist=' + wishlists[wishlistIndex].hash); $('.wishlist-share').attr('href', '/?wishlist=' + wishlists[wishlistIndex].hash);
$('.button.wishlist-product-add').removeClass('disabled'); $('.button.wishlist-product-add').removeClass('disabled');
$('.button.wishlist-share').removeClass('disabled'); $('.button.wishlist-share').removeClass('disabled');
$('.wishlist-delete button').removeClass('disabled'); $('.wishlist-delete button').removeClass('disabled');
/** Update URL */
urlParams.set('wishlist', wishlistValue);
fetch('/src/api/url.php?url=' + btoa(urlParams.toString()), {
method: 'GET'
})
.then(response => response.json())
.then(response => {
if (response.success) {
window.history.pushState({}, '', response.data.url);
}
});
} else { } else {
$('.button.wishlist-product-add').addClass('disabled'); $('.button.wishlist-product-add').addClass('disabled');
$('.button.wishlist-share').addClass('disabled'); $('.button.wishlist-share').addClass('disabled');

View file

@ -6,7 +6,7 @@
namespace wishthis; namespace wishthis;
use wishthis\User; use wishthis\{User, URL};
class Page class Page
{ {
@ -125,6 +125,17 @@ class Page
header('Location: /?page=power&required=' . $this->power); header('Location: /?page=power&required=' . $this->power);
die(); die();
} }
/**
* Redirect
*/
$url = new URL($_SERVER['QUERY_STRING']);
$redirect_to = $url->getPretty();
if ($redirect_to && $redirect_to !== $_SERVER['REQUEST_URI']) {
header('Location: ' . $redirect_to);
die();
}
} }
public function header(): void public function header(): void
@ -157,12 +168,12 @@ class Page
/** Fomantic UI */ /** Fomantic UI */
$stylesheetFomantic = 'semantic/dist/semantic.min.css'; $stylesheetFomantic = 'semantic/dist/semantic.min.css';
$stylesheetFomanticModified = filemtime($stylesheetFomantic); $stylesheetFomanticModified = filemtime($stylesheetFomantic);
echo '<link rel="stylesheet" href="' . $stylesheetFomantic . '?m=' . $stylesheetFomanticModified . '" />'; echo '<link rel="stylesheet" type="text/css" href="/' . $stylesheetFomantic . '?m=' . $stylesheetFomanticModified . '" />';
/** Default */ /** Default */
$stylesheetDefault = 'src/assets/css/default.css'; $stylesheetDefault = 'src/assets/css/default.css';
$stylesheetDefaultModified = filemtime($stylesheetDefault); $stylesheetDefaultModified = filemtime($stylesheetDefault);
echo '<link rel="stylesheet" href="' . $stylesheetDefault . '?m=' . $stylesheetDefaultModified . '" />'; echo '<link rel="stylesheet" type="text/css" href="/' . $stylesheetDefault . '?m=' . $stylesheetDefaultModified . '" />';
/** Page */ /** Page */
$stylesheetPage = 'src/assets/css/' . $this->name . '.css'; $stylesheetPage = 'src/assets/css/' . $this->name . '.css';
@ -170,27 +181,32 @@ class Page
if (file_exists($stylesheetPage)) { if (file_exists($stylesheetPage)) {
$stylesheetPageModified = filemtime($stylesheetPage); $stylesheetPageModified = filemtime($stylesheetPage);
echo '<link rel="stylesheet" href="' . $stylesheetPage . '?m=' . $stylesheetPageModified . '" />'; echo '<link rel="stylesheet" type="text/css" href="/' . $stylesheetPage . '?m=' . $stylesheetPageModified . '" />';
} }
/** /**
* Scripts * Scripts
*/ */
?>
<script type="text/javascript">
var $_GET = JSON.parse('<?= isset($_GET) ? json_encode($_GET) : array() ?>');
</script>
<?php
/** jQuery */ /** jQuery */
$scriptjQuery = 'node_modules/jquery/dist/jquery.min.js'; $scriptjQuery = 'node_modules/jquery/dist/jquery.min.js';
$scriptjQueryModified = filemtime($scriptjQuery); $scriptjQueryModified = filemtime($scriptjQuery);
echo '<script defer src="' . $scriptjQuery . '?m=' . $scriptjQueryModified . '"></script>'; echo '<script defer src="/' . $scriptjQuery . '?m=' . $scriptjQueryModified . '"></script>';
/** Fomantic */ /** Fomantic */
$scriptFomantic = 'semantic/dist/semantic.min.js'; $scriptFomantic = 'semantic/dist/semantic.min.js';
$scriptFomanticModified = filemtime($scriptFomantic); $scriptFomanticModified = filemtime($scriptFomantic);
echo '<script defer src="' . $scriptFomantic . '?m=' . $scriptFomanticModified . '"></script>'; echo '<script defer src="/' . $scriptFomantic . '?m=' . $scriptFomanticModified . '"></script>';
/** Default */ /** Default */
$scriptDefault = 'src/assets/js/default.js'; $scriptDefault = 'src/assets/js/default.js';
$scriptDefaultModified = filemtime($scriptDefault); $scriptDefaultModified = filemtime($scriptDefault);
echo '<script defer src="' . $scriptDefault . '?m=' . $scriptDefaultModified . '"></script>'; echo '<script defer src="/' . $scriptDefault . '?m=' . $scriptDefaultModified . '"></script>';
/** Page */ /** Page */
$scriptPage = 'src/assets/js/' . $this->name . '.js'; $scriptPage = 'src/assets/js/' . $this->name . '.js';
@ -198,7 +214,7 @@ class Page
if (file_exists($scriptPage)) { if (file_exists($scriptPage)) {
$scriptPageModified = filemtime($scriptPage); $scriptPageModified = filemtime($scriptPage);
echo '<script defer src="' . $scriptPage . '?m=' . $scriptPageModified . '"></script>'; echo '<script defer src="/' . $scriptPage . '?m=' . $scriptPageModified . '"></script>';
} }
?> ?>
@ -321,4 +337,15 @@ class Page
</html> </html>
<?php <?php
} }
public function messages(array $messages): string
{
$html = '';
foreach ($messages as $message) {
$html .= $message;
}
return $html;
}
} }

85
src/classes/url.php Normal file
View file

@ -0,0 +1,85 @@
<?php
/**
* Returns the pretty version of a URL.
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
namespace wishthis;
class URL
{
public function __construct(private string $url) {
}
public function getPretty(): string
{
$htaccess = explode(PHP_EOL, file_get_contents(ROOT . '/.htaccess'));
$pretty_url = '';
foreach ($htaccess as $index => $line) {
$parts = explode(chr(32), $line);
if (count($parts) >= 2) {
switch ($parts[0]) {
case 'RewriteRule':
$rewriteRule = $parts[1];
$rewriteRule = ltrim($rewriteRule, '^');
$rewriteRule = rtrim($rewriteRule, '$');
$target = $parts[2];
$keys = array_map(
function($item) {
return explode('=', $item)[0];
},
explode('&', parse_url($target, PHP_URL_QUERY))
);
$flags = explode(',', substr($parts[3], 1, -1)) ?? array();
$parameters_pairs = explode('&', parse_url($this->url, PHP_URL_PATH));
$parameters = array();
foreach ($parameters_pairs as $index => $pair) {
$parts = explode('=', $pair);
$key = $parts[0];
$value = $parts[1];
$parameters[$key] = $value;
}
preg_match_all('/\(.+?\)/', $rewriteRule, $regexes);
$countMatches = 0;
foreach ($regexes as $matches) {
foreach ($matches as $match) {
foreach ($parameters as $key => $value) {
if (
preg_match('/^' . $match . '$/', $value)
&& in_array($key, $keys)
&& count($parameters) === count($keys)
) {
$rewriteRule = str_replace($match, $value, $rewriteRule);
$countMatches++;
break;
}
}
}
if ($countMatches > 0 && $countMatches === count($matches)) {
$pretty_url = '/' . $rewriteRule;
if (in_array('L', $flags)) {
break 3;
}
}
}
break;
}
}
}
return $pretty_url;
}
}

View file

@ -35,10 +35,13 @@ class Wishlist
/** /**
* Get Wishlist * Get Wishlist
*/ */
$this->data = $database->query('SELECT * $result = $database
FROM `wishlists` ->query('SELECT *
WHERE `' . $column . '` = ' . $id_or_hash . ';') FROM `wishlists`
->fetch(); WHERE `' . $column . '` = ' . $id_or_hash . ';')
->fetch();
$this->data = $result ? $result : array();
/** Exists */ /** Exists */
if (isset($this->data['id'])) { if (isset($this->data['id'])) {

View file

@ -1,32 +1,84 @@
<?php <?php
/** /**
* register.php * Register a new user
* *
* @author Jay Trees <github.jay@grandel.anonaddy.me> * @author Jay Trees <github.jay@grandel.anonaddy.me>
*/ */
use wishthis\Page; use wishthis\Page;
$page = new page(__FILE__, 'Register'); $page = new page(__FILE__, 'Register');
$messages = array();
if (isset($_POST['email'], $_POST['password'])) { if (isset($_POST['email'], $_POST['password']) && !empty($_POST['planet'])) {
$users = $database->query('SELECT * FROM `users`;')->fetchAll(); $users = $database->query('SELECT * FROM `users`;')->fetchAll();
$emails = array_map(
function($user) {
return $user['email'];
},
$users
);
if (0 === count($users)) { $isHuman = false;
$database->query('INSERT INTO `users` $planet = strtolower($_POST['planet']);
(`email`, `password`, `power`) VALUES $planetName = strtoupper($planet[0]) . substr($planet, 1);
("' . $_POST['email'] . '", "' . sha1($_POST['password']) . '", 100) $planets = array(
;'); 'mercury',
} else { 'venus',
$database->query('INSERT INTO `users` 'earth',
(`email`, `password`) VALUES 'mars',
("' . $_POST['email'] . '", "' . sha1($_POST['password']) . '") 'jupiter',
;'); 'saturn',
'uranus',
'neptune',
);
$not_planets = array(
'pluto',
'sun'
);
if (in_array($planet, array_merge($planets, $not_planets))) {
$isHuman = true;
} }
header('Location: /?page=login'); if (in_array($planet, $not_planets)) {
die(); $messages[] = Page::warning('<strong>' . $planetName . '</strong> is not a planet but I\'ll let it slide, since only a human would make this kind of mistake.', 'Invalid planet');
}
if ($isHuman) {
if (0 === count($users)) {
$database->query('INSERT INTO `users`
(
`email`,
`password`,
`power`
) VALUES (
"' . $_POST['email'] . '",
"' . sha1($_POST['password']) . '",
100
)
;');
} else {
if (in_array($_POST['email'], $emails)) {
$messages[] = Page::error('An account with this email address already exists.', 'Invalid email address');
} else {
$database->query('INSERT INTO `users`
(
`email`,
`password`
) VALUES (
"' . $_POST['email'] . '",
"' . sha1($_POST['password']) . '"
)
;');
$messages[] = Page::success('Your account was successfully created.', 'Success');
}
}
} else {
$messages[] = Page::error('<strong>' . $planetName . '</strong> is not a planet in our solar system. Read this for more information: <a href="https://www.space.com/16080-solar-system-planets.html" target="_blank">Solar system planets: Order of the 8 (or 9) planets</a>', 'Invalid planet');
}
} }
$page->header(); $page->header();
@ -34,25 +86,56 @@ $page->navigation();
?> ?>
<main> <main>
<div class="ui container"> <div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<?= $page->messages($messages) ?>
<div class="ui segment"> <div class="ui segment">
<h1 class="ui header"><?= $page->title ?></h1>
<form class="ui form" method="post"> <form class="ui form" method="post">
<div class="field"> <div class="ui divided relaxed stackable two column grid">
<label>Email</label>
<input type="email" name="email" placeholder="john.doe@domain.tld" />
</div>
<div class="field">
<label>Password</label>
<input type="password" name="password" />
</div>
<div class="ui error message"></div> <div class=" row">
<div class="column">
<h2 class="ui header">Account details</h2>
<input class="ui primary button" type="submit" value="Register" /> <div class="field">
<a href="/?page=login">Login</a> <label>Email</label>
<input type="email" name="email" placeholder="john.doe@domain.tld" />
</div>
<div class="field">
<label>Password</label>
<input type="password" name="password" />
</div>
</div>
<div class="column">
<h2 class="ui header">Authentication</h2>
<p>
Prove you are a Human, Lizard-person or Zuck-Like creature.
Please name a planet from our solar system.
</p>
<div class="field">
<label>Planet</label>
<input type="text" name="planet" />
</div>
<p>Robots are obivously from another solar system so this will keep them at bay.</p>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui error message"></div>
<input class="ui primary button" type="submit" value="Register" />
<a class="ui tertiary button" href="/?page=login">Login</a>
</div>
</div>
</div>
</form> </form>
</div> </div>
</div> </div>
</main> </main>
<?php <?php