Skip to content

Commit aec9328

Browse files
committed
Sync links.php
1 parent e11f4a5 commit aec9328

File tree

2 files changed

+59
-31
lines changed

2 files changed

+59
-31
lines changed

tools/links/links.config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,4 @@ function (string $url, string $file = null): bool {
113113
'[[= user_doc =]]' => 'https://doc.ibexa.co/projects/userguide/en/master',
114114
];
115115

116-
$find = true;
116+
$find = './docs/*/';

tools/links/links.php

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,48 @@ class TestableUrl
2323
/** @var null|array */
2424
private $replacements;
2525

26-
/** @var null|bool */
26+
/** @var null|bool|string */
2727
private $find;
2828

2929
/** @var null|bool */
30-
private $external = null;
30+
private $external;
31+
32+
/** @var null|string */
33+
private $transformedUrl;
34+
35+
/** @var null|string */
36+
private $solvedUrl;
3137

3238
/** @var bool */
3339
private $tested = false;
3440

3541
/** @var null|string[] */
36-
private $headers = null;
42+
private $headers;
3743

3844
/** @var null|int */
39-
private $code = null;
45+
private $code;
4046

4147
/** @var null|TestableUrl */
42-
private $location = null;
48+
private $location;
4349

4450
/** @var null|bool */
45-
private $fragmentFound = null;
51+
private $fragmentFound;
4652

4753
private const EXTERNAL_PATTERN = '^(https?:)?//';
4854
private const PATTERN_DELIMITER = '@';
4955
public const DEFAULT_SCHEME = 'https';
5056

51-
public function __construct(string $url, string $text = null, string $file = null, string $line = null, array $replacements = null, bool $find = false, bool $test = false)
57+
/**
58+
* Represent a URL, potentially extracted from a file, which can be tested
59+
* @param string $url The URL itself
60+
* @param string|null $text The text of the link to the URL
61+
* @param string|null $file The file in which the URL has been found
62+
* @param string|null $line The file line the URL has been found at
63+
* @param string[]|null $replacements Some replacements to execute on the URL before testing it, like variables to replace by their values
64+
* @param bool|string|null $find By default, URL is considered absolute or relative; If true, the URL will be considered partial and the target must be searched to solve the URL; If a string is given, this string will be used as a search prefix
65+
* @param bool $test Set to true to test the URL immediately at construction time
66+
*/
67+
public function __construct(string $url, string $text = null, string $file = null, string $line = null, array $replacements = null, mixed $find = false, bool $test = false)
5268
{
5369
$this->url = $url;
5470
$this->text = $text;
@@ -102,10 +118,15 @@ public function getUrl(): string
102118

103119
public function getTransformedUrl(): string
104120
{
105-
if (is_array($this->replacements)) {
106-
return str_replace(array_keys($this->replacements), array_values($this->replacements), $this->getUrl());
121+
if (null === $this->transformedUrl) {
122+
if (is_array($this->replacements)) {
123+
$this->transformedUrl = str_replace(array_keys($this->replacements), array_values($this->replacements), $this->getUrl());
124+
} else {
125+
$this->transformedUrl = $this->getUrl();
126+
}
107127
}
108-
return $this->getUrl();
128+
129+
return $this->transformedUrl;
109130
}
110131

111132
public static function getRelativePath($sourcePath, $targetPath): string
@@ -170,24 +191,29 @@ public static function solveRelativePath(string $sourcePath, string $targetPath)
170191
*/
171192
public function getSolvedUrl(): string
172193
{
173-
$url = $this->getTransformedUrl();
174-
if ($this->isFragment()) {
175-
return $this->getFile() . $url;
176-
} else if (!$this->isExternal() && $this->hasFile() && !$this->find) {
177-
return self::solveRelativePath($this->getFile(), $url);
178-
} else if (!$this->isExternal() && $this->find) {
179-
$urlWithoutFragment = self::getUrlWithoutFragment($url);
180-
$candidates = (new Finder('.'))->includeWholeName("*/$urlWithoutFragment")->find();
181-
if (1 === count($candidates)) {
182-
return $candidates[0] . ($this->hasFragment() ? '#' . $this->getFragment() : '');
183-
} else if ($this->hasFile()) {
194+
if (null === $this->solvedUrl) {
195+
$url = $this->getTransformedUrl();
196+
if ($this->isFragment()) {
197+
return $this->solvedUrl = $this->getFile() . $url;
198+
} else if (!$this->isExternal() && $this->hasFile() && !$this->find) {
184199
return self::solveRelativePath($this->getFile(), $url);
200+
} else if (!$this->isExternal() && $this->find) {
201+
$findPrefix = is_string($this->find) ? $this->find : '*/';
202+
$urlWithoutFragment = self::getUrlWithoutFragment($url);
203+
$candidates = (new Finder('.'))->includeWholeName("{$findPrefix}{$urlWithoutFragment}")->find();
204+
if (1 === count($candidates)) {
205+
return $this->solvedUrl = $candidates[0] . ($this->hasFragment() ? '#' . $this->getFragment() : '');
206+
} else if ($this->hasFile()) {
207+
return $this->solvedUrl = self::solveRelativePath($this->getFile(), $url);
208+
} else {
209+
return $this->solvedUrl = $url;
210+
}
185211
} else {
186-
return $url;
212+
return $this->solvedUrl = $url;
187213
}
188-
} else {
189-
return $url;
190214
}
215+
216+
return $this->solvedUrl;
191217
}
192218

193219

@@ -290,7 +316,7 @@ public static function testUrl(string $url, bool $external = null, bool $testFra
290316
$fragmentFound = $contents && 1 === preg_match("@(id|name)=\"$fragment\"@", $contents);
291317
if (!$fragmentFound && !self::isExternalUrl($url)) {
292318
if ('md' === pathinfo(TestableUrl::getUrlWithoutFragment($url), PATHINFO_EXTENSION)) {
293-
$pattern = '@^#+ *' . str_replace('-', '.+', $fragment) . ' *$@mi';
319+
$pattern = '@^#+\W*' . str_replace('-', '\W+', $fragment) . '\W*$@mi';
294320
$fragmentFound = (bool)preg_match($pattern, $contents);
295321
}
296322
}
@@ -330,7 +356,7 @@ public static function testUrl(string $url, bool $external = null, bool $testFra
330356
case 522: // Connection Timed Out
331357
if ($tryNumber <= $retryCount+1) {
332358
sleep($retryDelay);
333-
return testUrl($url, $external, $testFragment, $retryCount, $retryDelay, $tryNumber++);
359+
return self::testUrl($url, $external, $testFragment, $retryCount, $retryDelay, $tryNumber++);
334360
}
335361
case 400: // Bad Request
336362
case 401: // Unauthorized
@@ -453,10 +479,10 @@ class UrlExtractor
453479
/**
454480
* @param array[]|null $patterns A map of file extensions and pattern lists.
455481
* @param string[]|null $replacements A map of replacements ['what_to_replace'=>'by_what_to replace']
456-
* @param bool $find If the file must be searched for instead of just being considered as a relative path.
482+
* @param bool|string $find If the URL target must be searched for instead of just being considered as a relative path; If a string is given, it will be used as search prefix
457483
* @see UrlExtractor::getDefaultPatterns For an example of pattern map.
458484
*/
459-
public function __construct(array $patterns = null, array $replacements = null, bool $find = false)
485+
public function __construct(array $patterns = null, array $replacements = null, mixed $find = false)
460486
{
461487
$this->patterns = null === $patterns ? self::getDefaultPatterns() : $patterns;
462488
$this->flattenPatterns();
@@ -783,10 +809,12 @@ class UrlTester
783809
* @param string[] $usageFiles The list of files to extract URLs from
784810
* @param string[] $resourceFiles The list of files that should be used by those URLs
785811
* @param array[]|null $exclusionTests An associative array of arrays of functions testing if a URL should be excluded from test
812+
* @param array|null $replacements A replacement map to apply on each URL
813+
* @param bool|string $find If the URL target must be searched for instead of just being considered as a relative path; If a string is given, it will be used as search prefix
786814
* @param $output
787815
* @param $error
788816
*/
789-
public function __construct(array $usageFiles = [], array $resourceFiles = [], array $exclusionTests = null, array $replacements = null, bool $find = false, $output = null, $error = null)
817+
public function __construct(array $usageFiles = [], array $resourceFiles = [], array $exclusionTests = null, array $replacements = null, mixed $find = false, $output = null, $error = null)
790818
{
791819
$this->setUsageFiles($usageFiles);
792820
$this->setResourceFiles($resourceFiles);
@@ -1342,7 +1370,7 @@ private static function buildFinder($where, $minDepth = null, $maxDepth = null,
13421370
return $finder;
13431371
}
13441372

1345-
static function newUrlTesterFromCommand(array $argv, array $exclusionTests = null, array $replacements = null, bool $find = false): UrlTester
1373+
static function newUrlTesterFromCommand(array $argv, array $exclusionTests = null, array $replacements = null, mixed $find = false): UrlTester
13461374
{
13471375
$finders = [
13481376
'usage' => [],

0 commit comments

Comments
 (0)