Skip to content

Commit

Permalink
Merge pull request #541 from hydephp/develop
Browse files Browse the repository at this point in the history
Merge pull request #45 from hydephp/recreate-validators
  • Loading branch information
caendesilva authored Jun 16, 2022
2 parents 1227f46 + c4157f2 commit 32e00f9
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 20 deletions.
64 changes: 44 additions & 20 deletions src/Commands/HydeValidateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,65 @@

namespace Hyde\Framework\Commands;

use Hyde\Framework\Hyde;
use Hyde\Framework\Services\ValidationService;
use LaravelZero\Framework\Commands\Command;

/**
* Runs the validation tests.
* @see \Hyde\Testing\Feature\Commands\HydeValidateCommandTest
*/
class HydeValidateCommand extends Command
{
/**
* The signature of the command.
*
* @var string
*/
protected $signature = 'validate';

/**
* The description of the command.
*
* @var string
*/
protected $description = 'Run a series of tests to validate your setup and help you optimize your site.';

/**
* Execute the console command.
*
* @return int
*/
protected float $time_start;
protected float $time_total = 0;

protected ValidationService $service;

public function __construct()
{
parent::__construct();

$this->service = new ValidationService();
}

public function handle(): int
{
$this->info('Running validation tests!');

$this->line(shell_exec(Hyde::path('vendor/bin/pest').' --group=validators'));
$this->newLine();

foreach (ValidationService::checks() as $check) {
$this->check($check);
}

$this->info('All done!');
$this->info('All done! '.$this->timeTotal());

return 0;
}

protected function check(string $check): void
{
$this->time_start = microtime(true);

$result = $this->service->run($check);

$this->line($result->formattedMessage($this->time()));

$this->newline();
}

protected function time(): string
{
$time = (microtime(true) - $this->time_start) * 1000;
$this->time_total += $time;

return number_format($time, 2);
}

protected function timeTotal(): string
{
return'<fg=gray>Ran '.sizeof(ValidationService::checks()).' checks in '.number_format($this->time_total, 2).'ms</>';
}
}
142 changes: 142 additions & 0 deletions src/Models/ValidationResult.php
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.'</>';
}
}
131 changes: 131 additions & 0 deletions src/Services/ValidationService.php
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');
}
}

0 comments on commit 32e00f9

Please sign in to comment.