Skip to content

Commit

Permalink
Update Route system (add route globbing and wildcard segments)
Browse files Browse the repository at this point in the history
  • Loading branch information
anthsnow committed May 19, 2022
1 parent fd5bbd0 commit aa42f25
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 27 deletions.
175 changes: 149 additions & 26 deletions src/Core/Routes/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,28 +91,85 @@ public function uriFull(): string {
* @return bool
*/
public function isRouteMatch(string $uri): bool {
$localUri = $this->uri();
$uri = $this->prepareUri($uri);
$localUri = $this->prepareUri($this->uri());
if (strcmp($localUri, $uri) === 0)
return true;
if (!preg_match('/\:([a-zA-Z0-9_]*)/i', $localUri))
if (!preg_match('/\:([a-zA-Z0-9_]*)/i', $localUri)
&& !preg_match('/\*([a-zA-Z0-9_]*)/i', $localUri))
return false;
// --- check ---
$localUriLst = explode('/', $localUri);
$uriLst = explode('/', $uri);
if (count($localUriLst) != count($uriLst))
return false;
for ($i = 0; $i < count($localUriLst); $i++) {
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$i];
if (empty($localPath) && empty($uriPath))
continue;
if (strcmp($localPath[0], ':') === 0) {
$constraint = $this->prepareConstraint($this->_constraints[substr($localPath, 1, strlen($localPath))] ?? "");
if (!empty($constraint) && !preg_match($constraint, $uriPath))
if (!preg_match('/\*([a-zA-Z0-9_]*)/i', $localUri)) {
if (count($localUriLst) != count($uriLst))
return false;
for ($i = 0; $i < count($localUriLst); $i++) {
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$i];
if (empty($localPath) && empty($uriPath))
continue;
if (strcmp($localPath[0], ':') === 0) {
$constraint = $this->prepareConstraint($this->_constraints[substr($localPath, 1, strlen($localPath))] ?? "");
if (!empty($constraint) && !preg_match($constraint, $uriPath))
return false;
continue; // skip
}
if (strcmp($localPath, $uriPath) !== 0)
return false;
}
} else {
if (count($localUriLst) > count($uriLst))
return false;
$uriPathCount = 0;
for ($i = 0; $i < count($localUriLst); $i++) {
// --- check uri-path-count ---
if ($uriPathCount >= count($uriLst))
return false;
// --- check ---
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$uriPathCount];
if (empty($localPath) && empty($uriPath)) {
$uriPathCount += 1;
continue;
}
if (strcmp($localPath[0], ':') === 0) {
$constraint = $this->prepareConstraint($this->_constraints[substr($localPath, 1, strlen($localPath))] ?? "");
if (!empty($constraint) && !preg_match($constraint, $uriPath))
return false;
$uriPathCount += 1;
continue; // skip
}
if (strcmp($localPath[0], '*') === 0) {
$isSuccess = false;
if ($i + 1 < count($localUriLst)) {
$localPathNext = $localUriLst[$i + 1];
for ($j = $uriPathCount + 1; $j < count($uriLst); $j++) {
$uriPath = $uriLst[$j];
if (strcmp($localPathNext, $uriPath) === 0
|| strcmp($localPathNext[0], ':') === 0 && strlen($localPathNext) > 1) {
$uriPathCount = $j - 1;
$isSuccess = true;
break;
}
}
} else {
$uriPathCount = count($uriLst) - 1;
$isSuccess = true;
}
if (!$isSuccess)
return false;

$uriPathCount += 1;
continue; // skip
}
if (strcmp($localPath, $uriPath) !== 0)
return false;
continue; // skip

$uriPathCount += 1;
}
if (strcmp($localPath, $uriPath) !== 0)
// --- check uri-path-count ---
if ($uriPathCount < count($uriLst))
return false;
}
return true;
Expand All @@ -124,22 +181,73 @@ public function isRouteMatch(string $uri): bool {
* @return array
*/
public function routeArgsFromUri(string $uri): array {
$localUri = $this->uri();
if (!preg_match('/\:([a-zA-Z0-9_]*)/i', $localUri))
$uri = $this->prepareUri($uri);
$localUri = $this->prepareUri($this->uri());
if (!preg_match('/\:([a-zA-Z0-9_]*)/i', $localUri)
&& !preg_match('/\*([a-zA-Z0-9_]*)/i', $localUri))
return [];
// --- select ---
$tmpArgs = [];
$localUriLst = explode('/', $localUri);
$uriLst = explode('/', $uri);
if (count($localUriLst) != count($uriLst))
return [];
for ($i = 0; $i < count($localUriLst); $i++) {
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$i];
if (empty($localPath) && empty($uriPath))
continue;
if (strcmp($localPath[0], ':') === 0 && strlen($localPath) > 1)
$tmpArgs[ltrim($localPath, ":")] = $uriPath;
if (!preg_match('/\*([a-zA-Z0-9_]*)/i', $localUri)) {
if (count($localUriLst) != count($uriLst))
return [];
for ($i = 0; $i < count($localUriLst); $i++) {
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$i];
if (empty($localPath) && empty($uriPath))
continue;
if (strcmp($localPath[0], ':') === 0 && strlen($localPath) > 1)
$tmpArgs[ltrim($localPath, ":")] = $uriPath;
}
} else {
if (count($localUriLst) > count($uriLst))
return [];
$uriPathCount = 0;
for ($i = 0; $i < count($localUriLst); $i++) {
// --- check uri-path-count ---
if ($uriPathCount >= count($uriLst))
return [];
// --- make args ---
$localPath = $localUriLst[$i];
$uriPath = $uriLst[$uriPathCount];
if (empty($localPath) && empty($uriPath)) {
$uriPathCount += 1;
continue;
}
if (strcmp($localPath[0], ':') === 0 && strlen($localPath) > 1) {
$tmpArgs[ltrim($localPath, ":")] = $uriPath;
} else if (strcmp($localPath[0], '*') === 0) {
$tmpUriPath = $uriPath;
if ($i + 1 < count($localUriLst)) {
$localPathNext = $localUriLst[$i + 1];
for ($j = $uriPathCount + 1; $j < count($uriLst); $j++) {
$uriPath = $uriLst[$j];
if (strcmp($localPathNext, $uriPath) === 0
|| strcmp($localPathNext[0], ':') === 0 && strlen($localPathNext) > 1) {
$uriPathCount = $j - 1;
break;
} else if (empty($tmpUriPath)) {
$tmpUriPath .= $uriPath;
} else {
$tmpUriPath .= "/$uriPath";
}
}
} else {
for ($j = $uriPathCount + 1; $j < count($uriLst); $j++) {
$uriPath = $uriLst[$j];
$tmpUriPath .= "/$uriPath";
}
$uriPathCount = count($uriLst) - 1;
}
$tmpArgs[ltrim($localPath, "*")] = $tmpUriPath;
}
$uriPathCount += 1;
}
// --- check uri-path-count ---
if ($uriPathCount < count($uriLst))
return [];
}
return $tmpArgs;
}
Expand All @@ -149,7 +257,9 @@ public function routeArgsFromUri(string $uri): array {
* @return bool
*/
public function hasUriArgs(): bool {
return (!empty($this->_uriArgs) || preg_match('/\:([a-zA-Z0-9_]*)/i', $this->uri()));
return (!empty($this->_uriArgs)
|| preg_match('/\:([a-zA-Z0-9_]*)/i', $this->uri())
|| preg_match('/\*([a-zA-Z0-9_]*)/i', $this->uri()));
}

/**
Expand Down Expand Up @@ -306,4 +416,17 @@ private function makeRedirectUri(string $currentUri): string {
}
return $tmpUri;
}

/**
* Подготовить URI
* @param string $uri
* @return string
*/
private function prepareUri(string $uri): string {
if (empty($uri))
return "";
if (strcmp($uri[0], '/') === 0)
$uri = substr($uri, 1, strlen($uri) - 1);
return $uri;
}
}
2 changes: 1 addition & 1 deletion src/Core/Routes/RoutesHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ function make_route(string $uri, array $args = []) {
if (empty($uri))
trigger_error("Make $tmpTypeStr route failed! Empty uri!", E_USER_ERROR);

$tmpUri = RouteCollector::makeValidRouteUrl($uri);
$tmpUri = (strcmp($uri[0], '*') === 0) ? $uri : RouteCollector::makeValidRouteUrl($uri);
if (empty($tmpUri))
trigger_error("Make $tmpTypeStr route failed! Invalid URI!", E_USER_ERROR);

Expand Down

0 comments on commit aa42f25

Please sign in to comment.