Skip to content

Commit ed129b4

Browse files
committed
Add doc linter to check related validators
This commit ensures that if validator A has a direct link to validator B, validator B will have a direct link to validator A too.
1 parent fc96faa commit ed129b4

4 files changed

Lines changed: 85 additions & 3 deletions

File tree

bin/console

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use Respect\Dev\Markdown\CompositeLinter;
1919
use Respect\Dev\Markdown\Differ as MarkdownDiffer;
2020
use Respect\Dev\Markdown\Linters\ValidatorHeaderLinter;
2121
use Respect\Dev\Markdown\Linters\ValidatorIndexLinter;
22+
use Respect\Dev\Markdown\Linters\ValidatorRelatedLinter;
2223
use SebastianBergmann\Diff\Differ;
2324
use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
2425
use Symfony\Component\Console\Application;
@@ -29,8 +30,9 @@ return (static function () {
2930
$application = new Application('Respect/Validation', '3.0');
3031
$application->addCommand(new CreateMixinCommand());
3132
$application->addCommand(new DocsLinterCommand($differ, new CompositeLinter(
32-
new ValidatorIndexLinter(),
3333
new ValidatorHeaderLinter(),
34+
new ValidatorIndexLinter(),
35+
new ValidatorRelatedLinter(),
3436
)));
3537
$application->addCommand(new UpdateDomainSuffixesCommand());
3638
$application->addCommand(new UpdateDomainToplevelCommand());

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,16 @@
7474
"scripts": {
7575
"docs:validators:headers": "bin/console docs:validators:headers",
7676
"docs:validators:index": "bin/console docs:validators:index",
77+
"docs:validators:related": "bin/console docs:validators:related",
7778
"docheader": "vendor/bin/docheader check library/ tests/",
7879
"phpcs": "vendor/bin/phpcs",
7980
"phpstan": "vendor/bin/phpstan analyze",
8081
"phpunit": "vendor/bin/phpunit --testsuite=unit",
8182
"pest": "vendor/bin/pest --testsuite=feature --compact",
8283
"docs": [
8384
"@docs:validators:headers",
84-
"@docs:validators:index"
85+
"@docs:validators:index",
86+
"@docs:validators:related"
8587
],
8688
"qa": [
8789
"@docheader",

docs/validators/IterableVal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ v::iterableVal()->isValid('string'); // false
1313

1414
## Note
1515

16-
This validator doesn't behave as PHP's [is_iterable() function because it considers that you can iterate over any object.
16+
This validator doesn't behave as PHP's [is_iterable()][] function because it considers that you can iterate over any object.
1717

1818
## Templates
1919

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Respect\Dev\Markdown\Linters;
6+
7+
use Respect\Dev\Markdown\Content;
8+
use Respect\Dev\Markdown\File;
9+
use Respect\Dev\Markdown\Linter;
10+
11+
use function array_keys;
12+
use function array_unique;
13+
use function basename;
14+
use function dirname;
15+
use function file_get_contents;
16+
use function in_array;
17+
use function preg_match_all;
18+
use function sort;
19+
use function sprintf;
20+
use function str_contains;
21+
use function str_ends_with;
22+
23+
final readonly class ValidatorRelatedLinter implements Linter
24+
{
25+
public function lint(File $file): File
26+
{
27+
if (!str_contains($file->filename, '/validators/') || str_ends_with($file->filename, '/validators/index.md')) {
28+
return $file;
29+
}
30+
31+
$validator = basename($file->filename, '.md');
32+
$relatedValidators = $this->getRelatedValidators($validator);
33+
34+
if ($relatedValidators === []) {
35+
return $file;
36+
}
37+
38+
$content = new Content();
39+
$content->paragraph('See also:');
40+
$content->emptyLine();
41+
foreach ($relatedValidators as $relatedValidator) {
42+
$content->anchorListItem($relatedValidator, $relatedValidator . '.md');
43+
}
44+
45+
$content->emptyLine();
46+
47+
return $file->withContent($file->content->withSection($content));
48+
}
49+
50+
/** @return array<string> */
51+
private function getRelatedValidators(string $validator): array
52+
{
53+
$docsDirectory = dirname(__DIR__, 3) . '/docs';
54+
$filename = sprintf('%s/validators/%s.md', $docsDirectory, $validator);
55+
$content = file_get_contents($filename);
56+
if ($content === false) {
57+
return [];
58+
}
59+
60+
$relatedValidators = [];
61+
62+
preg_match_all('/\[([^\]]+)\]\(([^\)]+\.md)\)/', $content, $matches);
63+
foreach (array_keys($matches[0]) as $key) {
64+
$related = $matches[1][$key];
65+
$document = $matches[2][$key];
66+
if (str_contains($document, '/') || in_array($related, $relatedValidators)) {
67+
continue;
68+
}
69+
70+
$relatedValidators[] = $related;
71+
}
72+
73+
$relatedValidators = array_unique($relatedValidators);
74+
sort($relatedValidators);
75+
76+
return $relatedValidators;
77+
}
78+
}

0 commit comments

Comments
 (0)