Merge branch 'develop' into add-statistics
This commit is contained in:
commit
ca6b01f447
9 changed files with 302 additions and 48 deletions
10
.htaccess
Normal file
10
.htaccess
Normal 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
33
src/api/url.php
Normal 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();
|
|
@ -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);
|
||||||
|
|
|
@ -4,6 +4,7 @@ $(function() {
|
||||||
fields: {
|
fields: {
|
||||||
email: 'email',
|
email: 'email',
|
||||||
password: ['minLength[6]', 'empty'],
|
password: ['minLength[6]', 'empty'],
|
||||||
|
planet: ['minLength[3]', 'empty'],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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
85
src/classes/url.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'])) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue