gl-website-deployer/vendor/doctrine/rst-parser/lib/UrlGenerator.php
2024-11-19 08:02:04 +01:00

157 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Doctrine\RST;
use function array_pop;
use function basename;
use function count;
use function explode;
use function implode;
use function ltrim;
use function preg_match;
use function rtrim;
use function strpos;
use function substr;
final class UrlGenerator
{
/** @var Configuration */
private $configuration;
public function __construct(Configuration $configuration)
{
$this->configuration = $configuration;
}
public function generateUrl(string $path, string $currentFileName, string $dirName): string
{
$canonicalPath = (string) $this->canonicalUrl($dirName, $path);
if ($this->configuration->isBaseUrlEnabled($canonicalPath)) {
$baseUrl = $this->configuration->getBaseUrl();
return rtrim($baseUrl, '/') . '/' . ltrim($canonicalPath, '/');
}
return (string) $this->relativeUrl($path, $currentFileName);
}
public function absoluteUrl(string $dirName, string $url): string
{
// if $url is already an absolute path, just return it
if ($url[0] === '/') {
return $url;
}
// $url is a relative path so join it together with the
// current $dirName to produce an absolute url
return rtrim($dirName, '/') . '/' . $url;
}
/**
* Resolves a relative URL using directories, for instance, if the
* current directory is "path/to/something", and you want to get the
* relative URL to "path/to/something/else.html", the result will
* be else.html. Else, "../" will be added to go to the upper directory
*/
public function relativeUrl(?string $url, string $currentFileName): ?string
{
if ($url === null) {
return null;
}
// If string contains ://, it is considered as absolute
if (preg_match('/:\\/\\//mUsi', $url) > 0) {
return $url;
}
// If string begins with "/", the "/" is removed to resolve the
// relative path
if ($url !== '' && $url[0] === '/') {
$url = substr($url, 1);
if ($this->samePrefix($url, $currentFileName)) {
// If the prefix is the same, simply returns the file name
$relative = basename($url);
} else {
// Else, returns enough ../ to get upper
$relative = '';
$depth = count(explode('/', $currentFileName)) - 1;
for ($k = 0; $k < $depth; $k++) {
$relative .= '../';
}
$relative .= $url;
}
} else {
$relative = $url;
}
return $relative;
}
public function canonicalUrl(string $dirName, string $url): ?string
{
if ($url !== '') {
if ($url[0] === '/') {
// If the URL begins with a "/", the following is the
// canonical URL
return substr($url, 1);
}
// Else, the canonical name is under the current dir
if ($dirName !== '') {
$path = $url;
// the url is already a canonical url
if (strpos($url, $dirName . '/') === 0) {
return $url;
}
return $this->canonicalize($dirName . '/' . $path);
}
return $this->canonicalize($url);
}
return null;
}
private function canonicalize(string $url): string
{
$parts = explode('/', $url);
$stack = [];
foreach ($parts as $part) {
if ($part === '..') {
array_pop($stack);
} else {
$stack[] = $part;
}
}
return implode('/', $stack);
}
private function samePrefix(string $url, string $currentFileName): bool
{
$partsA = explode('/', $url);
$partsB = explode('/', $currentFileName);
$n = count($partsA);
if ($n !== count($partsB)) {
return false;
}
unset($partsA[$n - 1]);
unset($partsB[$n - 1]);
return $partsA === $partsB;
}
}