Rework pretty URLs
This commit is contained in:
parent
29c9c3c472
commit
aa1c391166
6 changed files with 106 additions and 78 deletions
|
@ -10,11 +10,11 @@
|
||||||
RewriteRule ^([a-z\-]+)$ /?page=$1 [QSA,L]
|
RewriteRule ^([a-z\-]+)$ /?page=$1 [QSA,L]
|
||||||
|
|
||||||
# Wishlists (My lists)
|
# Wishlists (My lists)
|
||||||
RewriteRule ^(wishlists)/([0-9]+)$ /?page=$1&id=$2 [QSA,L]
|
RewriteRule ^wishlists/([0-9]+)$ /?page=wishlists&id=$1 [QSA,L]
|
||||||
RewriteRule ^(wishlists)/([0-9]+)/add$ /?page=$1&id=$2&wish_add=true [QSA,L]
|
RewriteRule ^wishlists/([0-9]+)/add$ /?page=wishlists&id=$1&wish_add=true [QSA,L]
|
||||||
|
|
||||||
# Wishlist
|
# Wishlist
|
||||||
RewriteRule ^(wishlist)/([0-9a-f]{40})$ /?page=$1&hash=$2 [QSA,L]
|
RewriteRule ^wishlist/([0-9a-f]{40})$ /?page=wishlist&hash=$1 [QSA,L]
|
||||||
|
|
||||||
# Blog Post
|
# Blog Post
|
||||||
RewriteRule ^blog/([a-z\-0-9]+)$ /?page=post&slug=$1 [QSA,L]
|
RewriteRule ^blog/([a-z\-0-9]+)$ /?page=post&slug=$1 [QSA,L]
|
||||||
|
|
|
@ -18,12 +18,13 @@ if (!isset($page)) {
|
||||||
switch ($_SERVER['REQUEST_METHOD']) {
|
switch ($_SERVER['REQUEST_METHOD']) {
|
||||||
case 'GET':
|
case 'GET':
|
||||||
if (isset($_GET['url'])) {
|
if (isset($_GET['url'])) {
|
||||||
$url = new URL(base64_decode($_GET['url']));
|
$url_old = base64_decode($_GET['url']);
|
||||||
|
$url = new URL($url_old);
|
||||||
|
|
||||||
$response['data'] = array(
|
$response['data'] = array(
|
||||||
'url' => $url->getPretty(),
|
'url' => $url_old,
|
||||||
'url_old' => $url->url,
|
'url_pretty' => $url->getPretty(),
|
||||||
'url_old_pretty' => $url->isPretty(),
|
'url_is_pretty' => $url->isPretty(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -81,7 +81,7 @@ $(function () {
|
||||||
.then(handleFetchError)
|
.then(handleFetchError)
|
||||||
.then(handleFetchResponse)
|
.then(handleFetchResponse)
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
window.history.pushState(null, document.title, response.data.url);
|
window.history.pushState(null, document.title, response.data.url_pretty);
|
||||||
|
|
||||||
$('.ui.dropdown.filter.priority')
|
$('.ui.dropdown.filter.priority')
|
||||||
.dropdown('restore default value')
|
.dropdown('restore default value')
|
||||||
|
|
|
@ -149,35 +149,26 @@ class Page
|
||||||
/**
|
/**
|
||||||
* Session
|
* Session
|
||||||
*/
|
*/
|
||||||
|
$user = isset($_SESSION['user']->id) ? $_SESSION['user'] : new User();
|
||||||
$user = isset($_SESSION['user']->id) ? $_SESSION['user'] : new User();
|
|
||||||
$ignorePower = array(
|
|
||||||
'blog',
|
|
||||||
'changelog',
|
|
||||||
'home',
|
|
||||||
'install',
|
|
||||||
'login',
|
|
||||||
'maintenance',
|
|
||||||
'post',
|
|
||||||
'register',
|
|
||||||
'wishlist',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
false === $user->isLoggedIn()
|
|
||||||
&& isset($_GET['page'])
|
|
||||||
&& false === in_array($_GET['page'], $ignorePower)
|
|
||||||
) {
|
|
||||||
redirect(Page::PAGE_LOGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Power
|
* Power
|
||||||
*/
|
*/
|
||||||
if (isset($user->power) && $user->power < $this->power) {
|
if (isset($user->power) && $user->power < $this->power && 0 !== $this->power) {
|
||||||
redirect(Page::PAGE_POWER . '&required=' . $this->power);
|
redirect(Page::PAGE_POWER . '&required=' . $this->power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
false === $user->isLoggedIn()
|
||||||
|
&& isset($_GET['page'])
|
||||||
|
&& 0 !== $this->power
|
||||||
|
) {
|
||||||
|
redirect(Page::PAGE_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update
|
* Update
|
||||||
*/
|
*/
|
||||||
|
@ -200,7 +191,7 @@ class Page
|
||||||
* Redirect
|
* Redirect
|
||||||
*/
|
*/
|
||||||
if ($options && $options->getOption('isInstalled') && isset($_GET)) {
|
if ($options && $options->getOption('isInstalled') && isset($_GET)) {
|
||||||
$url = new URL(http_build_query($_GET));
|
$url = new URL($_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
if ($url->url && false === $url->isPretty()) {
|
if ($url->url && false === $url->isPretty()) {
|
||||||
redirect($url->getPretty());
|
redirect($url->getPretty());
|
||||||
|
|
|
@ -11,7 +11,11 @@ namespace wishthis;
|
||||||
class URL
|
class URL
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Static
|
* Returns the HTTP status code of a URL.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public static function getResponseCode(string $url): int
|
public static function getResponseCode(string $url): int
|
||||||
{
|
{
|
||||||
|
@ -43,24 +47,41 @@ class URL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-Static
|
* The current URL. Can be pretty or not.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
*/
|
*/
|
||||||
public string $url;
|
public string $url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
*/
|
||||||
public function __construct(string $url)
|
public function __construct(string $url)
|
||||||
{
|
{
|
||||||
$this->url = urldecode($url);
|
$this->url = urldecode($url);
|
||||||
|
|
||||||
$_GET = $this->get_GET();
|
$_GET = $this->getGET();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current URL is pretty.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function isPretty(): bool
|
public function isPretty(): bool
|
||||||
{
|
{
|
||||||
$isPretty = 1 === preg_match('/^\/[a-z0-9\/]+/', $this->url);
|
$isPretty = 1 === preg_match('/^\/[a-z0-9\/\-]+$/', $this->url);
|
||||||
|
|
||||||
return $isPretty;
|
return $isPretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the original, un-pretty URL or an empty string on failure.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getPermalink(): string
|
public function getPermalink(): string
|
||||||
{
|
{
|
||||||
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
|
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
|
||||||
|
@ -95,10 +116,14 @@ class URL
|
||||||
return $permalink;
|
return $permalink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pretty version of the current URL.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getPretty(): string
|
public function getPretty(): string
|
||||||
{
|
{
|
||||||
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
|
$htaccess = preg_split('/\r\n|\r|\n/', file_get_contents(ROOT . '/.htaccess'));
|
||||||
$pretty_url = '';
|
|
||||||
|
|
||||||
if (!$this->url) {
|
if (!$this->url) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -121,63 +146,74 @@ class URL
|
||||||
explode('&', parse_url($target, PHP_URL_QUERY))
|
explode('&', parse_url($target, PHP_URL_QUERY))
|
||||||
);
|
);
|
||||||
$flags = explode(',', substr($parts[3], 1, -1)) ?? array();
|
$flags = explode(',', substr($parts[3], 1, -1)) ?? array();
|
||||||
parse_str($this->url, $getParameters);
|
|
||||||
|
|
||||||
uasort(
|
parse_str(ltrim($target, '/?'), $parameters);
|
||||||
$getParameters,
|
/** */
|
||||||
function ($a, $b) {
|
|
||||||
return strlen($a) <=> strlen($b);
|
/** Determine a potential URL. */
|
||||||
|
$potential_url = $rewriteRule;
|
||||||
|
|
||||||
|
preg_match_all('/\(.+?\)/', $rewriteRule, $groups);
|
||||||
|
$groups = $groups[0];
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($groups); $i++) {
|
||||||
|
foreach ($parameters as $key => $value) {
|
||||||
|
$replacement = '$' . $i + 1;
|
||||||
|
|
||||||
|
if ($replacement === $value && isset($_GET[$key])) {
|
||||||
|
$potential_url = str_replace(
|
||||||
|
$groups[$i],
|
||||||
|
$_GET[$key],
|
||||||
|
$potential_url
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$match = preg_match(
|
||||||
|
'/^' . str_replace(array('/'), array('\/'), $rewriteRule) . '$/',
|
||||||
|
$potential_url
|
||||||
);
|
);
|
||||||
$getParameters = array_reverse($getParameters, true);
|
|
||||||
|
|
||||||
preg_match_all('/\(.+?\)/', $rewriteRule, $regexes);
|
if (1 === $match && count($_GET) === count(explode('/', $rewriteRule))) {
|
||||||
|
return '/' . $potential_url;
|
||||||
$countMatches = 0;
|
|
||||||
|
|
||||||
foreach ($regexes as $matches) {
|
|
||||||
foreach ($matches as $match) {
|
|
||||||
foreach ($getParameters as $key => $value) {
|
|
||||||
if (
|
|
||||||
preg_match('/^' . $match . '$/', $value)
|
|
||||||
&& in_array($key, $keys)
|
|
||||||
&& count($getParameters) === 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $pretty_url ?: '/?' . $this->url;
|
if ('/?' === substr($this->url, 0, 2)) {
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '/?' . $this->url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_GET(): array
|
/**
|
||||||
|
* Returns the current URL parameters, even for pretty URLs.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getGET(): array
|
||||||
{
|
{
|
||||||
$queryString = parse_url($this->getPermalink(), PHP_URL_QUERY);
|
$queryString = $this->url;
|
||||||
$GET = array();
|
$GET = array();
|
||||||
|
|
||||||
if ($this->isPretty() && $queryString) {
|
if ($this->isPretty()) {
|
||||||
parse_str($queryString, $GET);
|
$queryString = parse_url($this->getPermalink(), PHP_URL_QUERY);
|
||||||
} else {
|
|
||||||
$GET = $_GET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $queryString) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('/?' === substr($queryString, 0, 2)) {
|
||||||
|
$queryString = substr($queryString, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_str($queryString, $GET);
|
||||||
|
|
||||||
return $GET;
|
return $GET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ $page->navigation();
|
||||||
<li>
|
<li>
|
||||||
<?php
|
<?php
|
||||||
/** TRANSLATORS: Changelog: Improved */
|
/** TRANSLATORS: Changelog: Improved */
|
||||||
echo __('Completely reworked the API');
|
echo __('Large parts of wishthis have been completely rewritten, such as the API and how pretty URLs work. The aim was to increase security and maintenability.');
|
||||||
?>
|
?>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in a new issue