-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #541 from hydephp/develop
Merge pull request #45 from hydephp/recreate-validators
- Loading branch information
Showing
3 changed files
with
317 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?php | ||
|
||
namespace Hyde\Framework\Models; | ||
|
||
/** | ||
* @see \Hyde\Testing\Feature\Services\ValidationServiceTest | ||
* @see \Hyde\Testing\Feature\Commands\HydeValidateCommandTest | ||
*/ | ||
class ValidationResult | ||
{ | ||
public string $message; | ||
public string $tip; | ||
|
||
public bool $passed; | ||
public bool $skipped = false; | ||
|
||
public function __construct(string $defaultMessage = 'Generic check') | ||
{ | ||
$this->message = $defaultMessage; | ||
} | ||
|
||
public function pass(?string $withMessage = null): self | ||
{ | ||
$this->passed = true; | ||
if ($withMessage) { | ||
$this->message = $withMessage; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
public function fail(?string $withMessage = null): self | ||
{ | ||
$this->passed = false; | ||
if ($withMessage) { | ||
$this->message = $withMessage; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
public function skip(?string $withMessage = null): self | ||
{ | ||
$this->skipped = true; | ||
if ($withMessage) { | ||
$this->message = $withMessage; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
public function withTip(string $withTip): self | ||
{ | ||
$this->tip = $withTip; | ||
|
||
return $this; | ||
} | ||
|
||
public function tip(): string|false | ||
{ | ||
return $this->tip ?? false; | ||
} | ||
|
||
public function skipped(): bool | ||
{ | ||
return $this->skipped; | ||
} | ||
|
||
public function passed(): bool | ||
{ | ||
return $this->passed; | ||
} | ||
|
||
public function failed(): bool | ||
{ | ||
return ! $this->passed; | ||
} | ||
|
||
public function statusCode(): int | ||
{ | ||
if ($this->skipped) { | ||
return 1; | ||
} | ||
if ($this->passed()) { | ||
return 0; | ||
} | ||
|
||
return 2; | ||
} | ||
|
||
public function message(): string | ||
{ | ||
return $this->message; | ||
} | ||
|
||
public function formattedMessage(?string $withTimeString = null): string | ||
{ | ||
$string = ' '.$this->formatResult($this->message).$this->formatTimeString($withTimeString); | ||
if ($this->tip()) { | ||
$string .= "\n".str_repeat(' ', 9).$this->formatTip($this->tip); | ||
} | ||
|
||
return $string; | ||
} | ||
|
||
protected function formatResult(string $message): string | ||
{ | ||
if ($this->statusCode() === 0) { | ||
return $this->formatPassed($message); | ||
} | ||
if ($this->statusCode() === 2) { | ||
return $this->formatFailed($message); | ||
} | ||
|
||
return $this->formatSkipped($message); | ||
} | ||
|
||
protected function formatPassed(string $message): string | ||
{ | ||
return '<fg=white;bg=green> PASS <fg=green> '.$message.'</></>'; | ||
} | ||
|
||
protected function formatFailed(string $message): string | ||
{ | ||
return '<fg=gray;bg=yellow> FAIL <fg=yellow> '.$message.'</></>'; | ||
} | ||
|
||
protected function formatSkipped(string $message): string | ||
{ | ||
return '<fg=white;bg=gray> SKIP <fg=gray> '.$message.'</></>'; | ||
} | ||
|
||
protected function formatTimeString(string $time): string | ||
{ | ||
return '<fg=gray> ('.$time.'ms)</>'; | ||
} | ||
|
||
protected function formatTip(string $tip): string | ||
{ | ||
return '<fg=gray>'.$tip.'</>'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<?php | ||
|
||
namespace Hyde\Framework\Services; | ||
|
||
use Hyde\Framework\Helpers\Features; | ||
use Hyde\Framework\Hyde; | ||
use Hyde\Framework\Models\ValidationResult as Result; | ||
|
||
/** | ||
* @see \Hyde\Testing\Feature\Services\ValidationServiceTest | ||
* @see \Hyde\Testing\Feature\Commands\HydeValidateCommandTest | ||
*/ | ||
class ValidationService | ||
{ | ||
public static function checks(): array | ||
{ | ||
$service = new static(); | ||
$checks = []; | ||
foreach (get_class_methods($service) as $method) { | ||
if (str_starts_with($method, 'check_')) { | ||
$checks[] = $method; | ||
} | ||
} | ||
|
||
return $checks; | ||
} | ||
|
||
public function run(string $check): Result | ||
{ | ||
return $this->$check(new Result); | ||
} | ||
|
||
public function check_validators_can_run(Result $result): Result | ||
{ | ||
// Runs a rather useless check, but which forces the class to load, thus preventing skewed test results | ||
// as the first test generally takes a little longer to run. | ||
return $result->pass('Validators can run'); | ||
} | ||
|
||
public function check_site_has_a_404_page(Result $result): Result | ||
{ | ||
if (file_exists(Hyde::path('_pages/404.md')) | ||
|| file_exists(Hyde::path('_pages/404.blade.php')) | ||
) { | ||
return $result->pass('Your site has a 404 page'); | ||
} | ||
|
||
return $result->fail('Could not find an 404.md or 404.blade.php file!') | ||
->withTip('You can publish the default one using `php hyde publish:views`'); | ||
} | ||
|
||
public function check_site_has_an_index_page(Result $result): Result | ||
{ | ||
if (file_exists(Hyde::path('_pages/index.md')) | ||
|| file_exists('_pages/index.blade.php')) { | ||
return $result->pass('Your site has an index page'); | ||
} | ||
|
||
return $result->fail('Could not find an index.md or index.blade.php file!') | ||
->withTip('You can publish the one of the built in templates using `php hyde publish:homepage`'); | ||
} | ||
|
||
public function check_documentation_site_has_an_index_page(Result $result): Result | ||
{ | ||
if (! Features::hasDocumentationPages()) { | ||
return $result->skip('The documentation page feature is disabled in config'); | ||
} | ||
|
||
if (file_exists('_docs/index.md')) { | ||
return $result->pass('Your documentation site has an index page'); | ||
} | ||
|
||
if (file_exists('_docs/README.md')) { | ||
return $result->fail('Could not find an index.md file in the _docs directory!') | ||
->withTip('However, a _docs/readme.md file was found. A suggestion would be to copy the _docs/readme.md to _docs/index.md.'); | ||
} | ||
|
||
return $result->fail('Could not find an index.md file in the _docs directory!'); | ||
} | ||
|
||
public function check_site_has_an_app_css_stylesheet(Result $result): Result | ||
{ | ||
if (file_exists(Hyde::path('_site/media/app.css')) || file_exists(Hyde::path('_media/app.css'))) { | ||
return $result->pass('Your site has an app.css stylesheet'); | ||
} | ||
|
||
return $result->fail('Could not find an app.css file in the _site/media or _media directory!') | ||
->withTip('You may need to run `npm run dev`.`'); | ||
} | ||
|
||
public function check_site_has_a_base_url_set(Result $result): Result | ||
{ | ||
if ((bool) Hyde::uriPath() === true) { | ||
return $result->pass('Your site has a base URL set') | ||
->withTip('This will allow Hyde to generate canonical URLs, sitemaps, RSS feeds, and more.'); | ||
} | ||
|
||
return $result->fail('Could not find a site URL in the config or .env file!') | ||
->withTip('Adding it may improve SEO as it allows Hyde to generate canonical URLs, sitemaps, and RSS feeds'); | ||
} | ||
|
||
public function check_a_torchlight_api_token_is_set(Result $result): Result | ||
{ | ||
if (! Features::enabled(Features::torchlight())) { | ||
return $result->skip('Check a Torchlight API token is set') | ||
->withTip('Torchlight is an API for code syntax highlighting. You can enable it in the Hyde config.'); | ||
} | ||
|
||
if (config('torchlight.token') !== null) { | ||
return $result->pass('Your site has a Torchlight API token set'); | ||
} | ||
|
||
return $result->fail('Torchlight is enabled in the config, but an API token could not be found in the .env file!') | ||
->withTip('Torchlight is an API for code syntax highlighting. You can get a free token at torchlight.dev.'); | ||
} | ||
|
||
public function check_for_conflicts_between_blade_and_markdown_pages(Result $result): Result | ||
{ | ||
$conflicts = array_intersect( | ||
CollectionService::getMarkdownPageList(), | ||
CollectionService::getBladePageList() | ||
); | ||
|
||
if (count($conflicts)) { | ||
return $result->fail('Found naming conflicts between Markdown and Blade files: '.implode(', ', $conflicts)) | ||
->withTip('This may cause on of them being immediately overwritten by the other.'); | ||
} | ||
|
||
return $result->pass('No naming conflicts found between Blade and Markdown pages'); | ||
} | ||
} |