mirror of
https://github.com/getgrav/grav.git
synced 2026-02-26 08:31:42 +01:00
Added bin/grav page-system-validator [-r|--record] [-c|--check] to test Flex Pages
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* Added new `Security::sanitizeSVG()` function
|
||||
1. [](#improved)
|
||||
* Several FlexObject loading improvements
|
||||
* Added `bin/grav page-system-validator [-r|--record] [-c|--check]` to test Flex Pages
|
||||
1. [](#bugfix)
|
||||
* Regression: Fixed language fallback
|
||||
* Regression: Fixed translations when language code is used for non-language purposes
|
||||
|
||||
27
bin/grav
27
bin/grav
@@ -3,7 +3,7 @@
|
||||
|
||||
use Grav\Common\Composer;
|
||||
use Grav\Common\Grav;
|
||||
use League\CLImate\CLImate;
|
||||
use Grav\Console\Cli;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
\define('GRAV_CLI', true);
|
||||
@@ -52,17 +52,18 @@ if (!file_exists(GRAV_ROOT . '/index.php')) {
|
||||
|
||||
$app = new Application('Grav CLI Application', GRAV_VERSION);
|
||||
$app->addCommands(array(
|
||||
new \Grav\Console\Cli\InstallCommand(),
|
||||
new \Grav\Console\Cli\ComposerCommand(),
|
||||
new \Grav\Console\Cli\SandboxCommand(),
|
||||
new \Grav\Console\Cli\CleanCommand(),
|
||||
new \Grav\Console\Cli\ClearCacheCommand(),
|
||||
new \Grav\Console\Cli\BackupCommand(),
|
||||
new \Grav\Console\Cli\NewProjectCommand(),
|
||||
new \Grav\Console\Cli\SchedulerCommand(),
|
||||
new \Grav\Console\Cli\SecurityCommand(),
|
||||
new \Grav\Console\Cli\LogViewerCommand(),
|
||||
new \Grav\Console\Cli\YamlLinterCommand(),
|
||||
new \Grav\Console\Cli\ServerCommand(),
|
||||
new Cli\InstallCommand(),
|
||||
new Cli\ComposerCommand(),
|
||||
new Cli\SandboxCommand(),
|
||||
new Cli\CleanCommand(),
|
||||
new Cli\ClearCacheCommand(),
|
||||
new Cli\BackupCommand(),
|
||||
new Cli\NewProjectCommand(),
|
||||
new Cli\SchedulerCommand(),
|
||||
new Cli\SecurityCommand(),
|
||||
new Cli\LogViewerCommand(),
|
||||
new Cli\YamlLinterCommand(),
|
||||
new Cli\ServerCommand(),
|
||||
new Cli\PageSystemValidatorCommand(),
|
||||
));
|
||||
$app->run();
|
||||
|
||||
276
system/src/Grav/Console/Cli/PageSystemValidatorCommand.php
Normal file
276
system/src/Grav/Console/Cli/PageSystemValidatorCommand.php
Normal file
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Console\Cli
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Console\Cli;
|
||||
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class PageSystemValidatorCommand extends ConsoleCommand
|
||||
{
|
||||
protected $tests = [
|
||||
// Content
|
||||
'header' => [[]],
|
||||
'summary' => [[], [200], [200, true]],
|
||||
'content' => [[]],
|
||||
'getRawContent' => [[]],
|
||||
'rawMarkdown' => [[]],
|
||||
'value' => [['content'], ['route'], ['order'], ['ordering'], ['folder'], ['slug'], ['name'], /*['frontmatter'],*/ ['header.menu'], ['header.slug']],
|
||||
'title' => [[]],
|
||||
'menu' => [[]],
|
||||
'visible' => [[]],
|
||||
'published' => [[]],
|
||||
'publishDate' => [[]],
|
||||
'unpublishDate' => [[]],
|
||||
'process' => [[]],
|
||||
'slug' => [[]],
|
||||
'order' => [[]],
|
||||
//'id' => [[]],
|
||||
'modified' => [[]],
|
||||
'lastModified' => [[]],
|
||||
'folder' => [[]],
|
||||
'date' => [[]],
|
||||
'dateformat' => [[]],
|
||||
'taxonomy' => [[]],
|
||||
'shouldProcess' => [['twig'], ['markdown']],
|
||||
'isPage' => [[]],
|
||||
'isDir' => [[]],
|
||||
'exists' => [[]],
|
||||
|
||||
// Forms
|
||||
'forms' => [[]],
|
||||
|
||||
// Routing
|
||||
'urlExtension' => [[]],
|
||||
'routable' => [[]],
|
||||
'link' => [[], [false], [true]],
|
||||
'permalink' => [[]],
|
||||
'canonical' => [[], [false], [true]],
|
||||
'url' => [[], [true], [true, true], [true, true, false], [false, false, true, false]],
|
||||
'route' => [[]],
|
||||
'rawRoute' => [[]],
|
||||
'routeAliases' => [[]],
|
||||
'routeCanonical' => [[]],
|
||||
'redirect' => [[]],
|
||||
'relativePagePath' => [[]],
|
||||
'path' => [[]],
|
||||
//'folder' => [[]],
|
||||
'parent' => [[]],
|
||||
'topParent' => [[]],
|
||||
'currentPosition' => [[]],
|
||||
'active' => [[]],
|
||||
'activeChild' => [[]],
|
||||
'home' => [[]],
|
||||
'root' => [[]],
|
||||
|
||||
// Translations
|
||||
//'translatedLanguages' => [[], [false], [true]],
|
||||
//'untranslatedLanguages' => [[], [false], [true]],
|
||||
//'language' => [[]],
|
||||
|
||||
// Legacy
|
||||
'raw' => [[]],
|
||||
'frontmatter' => [[]],
|
||||
'httpResponseCode' => [[]],
|
||||
'httpHeaders' => [[]],
|
||||
'blueprintName' => [[]],
|
||||
'name' => [[]],
|
||||
'childType' => [[]],
|
||||
'template' => [[]],
|
||||
'templateFormat' => [[]],
|
||||
'extension' => [[]],
|
||||
'expires' => [[]],
|
||||
'cacheControl' => [[]],
|
||||
'ssl' => [[]],
|
||||
'metadata' => [[]],
|
||||
'eTag' => [[]],
|
||||
'filePath' => [[]],
|
||||
'filePathClean' => [[]],
|
||||
'orderDir' => [[]],
|
||||
'orderBy' => [[]],
|
||||
'orderManual' => [[]],
|
||||
'maxCount' => [[]],
|
||||
'modular' => [[]],
|
||||
'modularTwig' => [[]],
|
||||
//'children' => [[]],
|
||||
'isFirst' => [[]],
|
||||
'isLast' => [[]],
|
||||
'prevSibling' => [[]],
|
||||
'nextSibling' => [[]],
|
||||
'adjacentSibling' => [[]],
|
||||
'ancestor' => [[]],
|
||||
//'inherited' => [[]],
|
||||
//'inheritedField' => [[]],
|
||||
'find' => [['/']],
|
||||
//'collection' => [[]],
|
||||
//'evaluate' => [[]],
|
||||
'folderExists' => [[]],
|
||||
//'getOriginal' => [[]],
|
||||
//'getAction' => [[]],
|
||||
];
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('page-system-validator')
|
||||
->setDescription('Page validator can be used to compare site before/after update and when migrating to Flex Pages.')
|
||||
->addOption('record', 'r', InputOption::VALUE_NONE, 'Record results')
|
||||
->addOption('check', 'c', InputOption::VALUE_NONE, 'Compare site against previously recorded results')
|
||||
->setHelp('The <info>page-system-validator</info> command can be used to test the pages before and after upgrade');
|
||||
}
|
||||
|
||||
protected function serve()
|
||||
{
|
||||
$this->output->writeln('');
|
||||
|
||||
$this->grav = $grav = Grav::instance();
|
||||
$grav->setup();
|
||||
|
||||
// Initialize
|
||||
$grav['uri']->init();
|
||||
/** @var Config $config */
|
||||
$config = $grav['config'];
|
||||
$config->init();
|
||||
$grav['plugins']->setup();
|
||||
$grav['debugger']->init();
|
||||
// Initialize the timezone.
|
||||
$timezone = $config->get('system.timezone');
|
||||
if ($timezone) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
/** @var Uri $uri */
|
||||
$uri = $grav['uri'];
|
||||
$uri->init();
|
||||
$grav->setLocale();
|
||||
$grav['language']->setActive('en');
|
||||
|
||||
// Plugins
|
||||
$grav['accounts'];
|
||||
$grav['plugins']->init();
|
||||
$grav->fireEvent('onPluginsInitialized');
|
||||
|
||||
// Themes
|
||||
$grav['themes']->init();
|
||||
|
||||
// Twig
|
||||
$grav['twig']->init();
|
||||
|
||||
// Pages
|
||||
$grav['pages']->init();
|
||||
$grav->fireEvent('onPagesInitialized', new Event(['pages' => $grav['pages']]));
|
||||
|
||||
if ($this->input->getOption('record')) {
|
||||
$this->output->writeln('Pages: ' . $config->get('system.pages.type', 'page'));
|
||||
|
||||
$this->output->writeln('<magenta>Record tests</magenta>');
|
||||
$this->output->writeln('');
|
||||
|
||||
$results = $this->record();
|
||||
$file = $this->getFile('pages-old');
|
||||
$file->save($results);
|
||||
|
||||
$this->output->writeln('Recorded tests to ' . $file->filename());
|
||||
} elseif ($this->input->getOption('check')) {
|
||||
$this->output->writeln('Pages: ' . $config->get('system.pages.type', 'page'));
|
||||
|
||||
$this->output->writeln('<magenta>Run tests</magenta>');
|
||||
$this->output->writeln('');
|
||||
|
||||
$new = $this->record();
|
||||
$file = $this->getFile('pages-new');
|
||||
$file->save($new);
|
||||
|
||||
$file = $this->getFile('pages-old');
|
||||
$old = $file->content();
|
||||
|
||||
$results = $this->check($old, $new);
|
||||
if (empty($results)) {
|
||||
$this->output->writeln('<green>Success!</green>');
|
||||
} else {
|
||||
$file = $this->getFile('diff');
|
||||
$file->save($results);
|
||||
$this->output->writeln('Recorded results to ' . $file->filename());
|
||||
}
|
||||
} else {
|
||||
$this->output->writeln('<green>page-system-validator [-r|--record] [-c|--check]</green>');
|
||||
}
|
||||
$this->output->writeln('');
|
||||
}
|
||||
|
||||
private function record()
|
||||
{
|
||||
$pages = $this->grav['pages'];
|
||||
$all = $pages->all();
|
||||
|
||||
$results = [];
|
||||
foreach ($all as $page) {
|
||||
foreach ($this->tests as $method => $params) {
|
||||
$params = $params ?: [[]];
|
||||
foreach ($params as $p) {
|
||||
$result = $page->$method(...$p);
|
||||
if (in_array($method, ['summary', 'content', 'getRawContent'], true)) {
|
||||
$result = preg_replace('/name="(form-nonce|__unique_form_id__)" value="[^"]+"/', 'name="\\1" value="DYNAMIC"', $result);
|
||||
$result = preg_replace('`src=("|\'|")/images/./././././[^"]+\\1`', 'src="\\1images/GENERATED\\1', $result);
|
||||
$result = preg_replace('/\?\d{10}/', '?1234567890', $result);
|
||||
} elseif ($method === 'httpHeaders' && isset($result['Expires'])) {
|
||||
$result['Expires'] = 'Thu, 19 Sep 2019 13:10:24 GMT (REPLACED AS DYNAMIC)';
|
||||
} elseif ($result instanceof PageInterface) {
|
||||
$result = $result->rawRoute();
|
||||
} elseif (is_object($result)) {
|
||||
$result = json_decode(json_encode($result), true);
|
||||
}
|
||||
|
||||
$ps = [];
|
||||
foreach ($p as $val) {
|
||||
$ps[] = (string)var_export($val, true);
|
||||
}
|
||||
$pstr = implode(', ', $ps);
|
||||
$call = "->{$method}({$pstr})";
|
||||
$results[$page->rawRoute()][$call] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json_decode(json_encode($results), true);
|
||||
}
|
||||
|
||||
private function check(array $old, array $new)
|
||||
{
|
||||
$errors = [];
|
||||
foreach ($old as $path => $page) {
|
||||
if (!isset($new[$path])) {
|
||||
$errors[$path] = 'PAGE REMOVED';
|
||||
continue;
|
||||
}
|
||||
foreach ($page as $method => $test) {
|
||||
if (($new[$path][$method] ?? null) !== $test) {
|
||||
$errors[$path][$method] = ['old' => $test, 'new' => $new[$path][$method]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return CompiledYamlFile
|
||||
*/
|
||||
private function getFile(string $name)
|
||||
{
|
||||
return CompiledYamlFile::instance('cache://tests/' . $name . '.yaml');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user