Code Coverage  | 
      ||||||||||
Lines  | 
       Functions and Methods  | 
       Classes and Traits  | 
      ||||||||
| Total |         | 
       100.00%  | 
       57 / 57  | 
               | 
       100.00%  | 
       10 / 10  | 
       CRAP |         | 
       100.00%  | 
       1 / 1  | 
      
| ValidationService |         | 
       100.00%  | 
       57 / 57  | 
               | 
       100.00%  | 
       10 / 10  | 
       26 |         | 
       100.00%  | 
       1 / 1  | 
      
| checks |         | 
       100.00%  | 
       6 / 6  | 
               | 
       100.00%  | 
       1 / 1  | 
       3 | |||
| run |         | 
       100.00%  | 
       3 / 3  | 
               | 
       100.00%  | 
       1 / 1  | 
       1 | |||
| check_validators_can_run |         | 
       100.00%  | 
       1 / 1  | 
               | 
       100.00%  | 
       1 / 1  | 
       1 | |||
| check_site_has_a_404_page |         | 
       100.00%  | 
       5 / 5  | 
               | 
       100.00%  | 
       1 / 1  | 
       3 | |||
| check_site_has_an_index_page |         | 
       100.00%  | 
       5 / 5  | 
               | 
       100.00%  | 
       1 / 1  | 
       3 | |||
| check_documentation_site_has_an_index_page |         | 
       100.00%  | 
       12 / 12  | 
               | 
       100.00%  | 
       1 / 1  | 
       5 | |||
| check_site_has_an_app_css_stylesheet |         | 
       100.00%  | 
       5 / 5  | 
               | 
       100.00%  | 
       1 / 1  | 
       3 | |||
| check_site_has_a_base_url_set |         | 
       100.00%  | 
       5 / 5  | 
               | 
       100.00%  | 
       1 / 1  | 
       2 | |||
| check_a_torchlight_api_token_is_set |         | 
       100.00%  | 
       7 / 7  | 
               | 
       100.00%  | 
       1 / 1  | 
       3 | |||
| check_for_conflicts_between_blade_and_markdown_pages |         | 
       100.00%  | 
       8 / 8  | 
               | 
       100.00%  | 
       1 / 1  | 
       2 | |||
| 1 | <?php | 
| 2 | |
| 3 | declare(strict_types=1); | 
| 4 | |
| 5 | namespace Hyde\Framework\Services; | 
| 6 | |
| 7 | use Hyde\Hyde; | 
| 8 | use Hyde\Enums\Feature; | 
| 9 | use Hyde\Facades\Config; | 
| 10 | use Hyde\Facades\Features; | 
| 11 | use Hyde\Pages\BladePage; | 
| 12 | use Hyde\Pages\MarkdownPage; | 
| 13 | use Hyde\Pages\DocumentationPage; | 
| 14 | use Hyde\Support\Models\ValidationResult as Result; | 
| 15 | |
| 16 | use function count; | 
| 17 | use function get_class_methods; | 
| 18 | use function array_intersect; | 
| 19 | use function file_exists; | 
| 20 | use function implode; | 
| 21 | use function sprintf; | 
| 22 | use function str_starts_with; | 
| 23 | |
| 24 | class 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 | } |