Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
ValidationService
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
10 / 10
26
100.00% covered (success)
100.00%
1 / 1
 checks
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 run
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 check_validators_can_run
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 check_site_has_a_404_page
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 check_site_has_an_index_page
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 check_documentation_site_has_an_index_page
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 check_site_has_an_app_css_stylesheet
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 check_site_has_a_base_url_set
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 check_a_torchlight_api_token_is_set
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 check_for_conflicts_between_blade_and_markdown_pages
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Hyde\Framework\Services;
6
7use Hyde\Hyde;
8use Hyde\Enums\Feature;
9use Hyde\Facades\Config;
10use Hyde\Facades\Features;
11use Hyde\Pages\BladePage;
12use Hyde\Pages\MarkdownPage;
13use Hyde\Pages\DocumentationPage;
14use Hyde\Support\Models\ValidationResult as Result;
15
16use function count;
17use function get_class_methods;
18use function array_intersect;
19use function file_exists;
20use function implode;
21use function sprintf;
22use function str_starts_with;
23
24class ValidationService
25{
26    /** @return string[] */
27    public static function checks(): array
28    {
29        $service = new self();
30        $checks = [];
31        foreach (get_class_methods($service) as $method) {
32            if (str_starts_with($method, 'check_')) {
33                $checks[] = $method;
34            }
35        }
36
37        return $checks;
38    }
39
40    public function run(string $check): Result
41    {
42        $result = new Result;
43        $this->{$check}($result);
44
45        return $result;
46    }
47
48    public function check_validators_can_run(Result $result): Result
49    {
50        // Runs a rather useless check, but which forces the class to load, thus preventing skewed test results
51        // as the first test generally takes a little longer to run.
52        return $result->pass('Validators can run');
53    }
54
55    public function check_site_has_a_404_page(Result $result): Result
56    {
57        if (file_exists(MarkdownPage::path('404.md'))
58            || file_exists(BladePage::path('404.blade.php'))
59        ) {
60            return $result->pass('Your site has a 404 page');
61        }
62
63        return $result->fail('Could not find an 404.md or 404.blade.php file!')
64            ->withTip('You can publish the default one using `php hyde publish:views`');
65    }
66
67    public function check_site_has_an_index_page(Result $result): Result
68    {
69        if (file_exists(MarkdownPage::path('index.md'))
70            || file_exists(BladePage::path('index.blade.php'))
71        ) {
72            return $result->pass('Your site has an index page');
73        }
74
75        return $result->fail('Could not find an index.md or index.blade.php file!')
76            ->withTip('You can publish the one of the built in templates using `php hyde publish:homepage`');
77    }
78
79    public function check_documentation_site_has_an_index_page(Result $result): Result
80    {
81        if (! Features::hasDocumentationPages()) {
82            return $result->skip('Does documentation site have an index page?')
83                ->withTip('Skipped because: The documentation page feature is disabled in config');
84        }
85
86        if (count(DocumentationPage::files()) === 0) {
87            return $result->skip('Does documentation site have an index page?')
88                ->withTip('Skipped because: There are no documentation pages');
89        }
90
91        if (file_exists(DocumentationPage::path('index.md'))) {
92            return $result->pass('Your documentation site has an index page');
93        }
94
95        if (file_exists(DocumentationPage::path('README.md'))) {
96            return $result->fail('Could not find an index.md file in the _docs directory!')
97                ->withTip('However, a _docs/readme.md file was found. A suggestion would be to copy the _docs/readme.md to _docs/index.md.');
98        }
99
100        return $result->fail('Could not find an index.md file in the _docs directory!');
101    }
102
103    public function check_site_has_an_app_css_stylesheet(Result $result): Result
104    {
105        if (file_exists(Hyde::siteMediaPath('/app.css')) || file_exists(Hyde::mediaPath('app.css'))) {
106            return $result->pass('Your site has an app.css stylesheet');
107        }
108
109        return $result->fail(sprintf('Could not find an app.css file in the %s or %s directory!',
110            Hyde::pathToRelative(Hyde::siteMediaPath()), Hyde::getMediaDirectory()
111        ))->withTip('You may need to run `npm run dev`.`');
112    }
113
114    public function check_site_has_a_base_url_set(Result $result): Result
115    {
116        if (Hyde::hasSiteUrl()) {
117            return $result->pass('Your site has a base URL set')
118                ->withTip('This will allow Hyde to generate canonical URLs, sitemaps, RSS feeds, and more.');
119        }
120
121        return $result->fail('Could not find a site URL in the config or .env file!')
122            ->withTip('Adding it may improve SEO as it allows Hyde to generate canonical URLs, sitemaps, and RSS feeds');
123    }
124
125    public function check_a_torchlight_api_token_is_set(Result $result): Result
126    {
127        if (! Features::enabled(Feature::Torchlight)) {
128            return $result->skip('Check a Torchlight API token is set')
129                ->withTip('Torchlight is an API for code syntax highlighting. You can enable it in the Hyde config.');
130        }
131
132        if (Config::getNullableString('torchlight.token') !== null) {
133            return $result->pass('Your site has a Torchlight API token set');
134        }
135
136        return $result->fail('Torchlight is enabled in the config, but an API token could not be found in the .env file!')
137            ->withTip('Torchlight is an API for code syntax highlighting. You can get a free token at torchlight.dev.');
138    }
139
140    public function check_for_conflicts_between_blade_and_markdown_pages(Result $result): Result
141    {
142        $conflicts = array_intersect(
143            MarkdownPage::files(),
144            BladePage::files()
145        );
146
147        if (count($conflicts)) {
148            return $result->fail('Found naming conflicts between Markdown and Blade files: '.implode(', ', $conflicts))
149                ->withTip('This may cause on of them being immediately overwritten by the other.');
150        }
151
152        return $result->pass('No naming conflicts found between Blade and Markdown pages');
153    }
154}