Refactor configuration check

This commit is contained in:
Romain Neutron
2013-07-12 18:40:12 +02:00
parent 1760dbce75
commit c4b977469d
13 changed files with 292 additions and 100 deletions

View File

@@ -0,0 +1,77 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Command;
use Alchemy\Phrasea\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
abstract class AbstractCheckCommand extends Command
{
const CHECK_OK = 0;
const CHECK_WARNING = 1;
const CHECK_ERROR = 2;
/**
* {@inheritdoc}
*/
protected function doExecute(InputInterface $input, OutputInterface $output)
{
$ret = static::CHECK_OK;
foreach($this->provideRequirements() as $collection) {
$output->writeln('');
$output->writeln($collection->getName() . ' requirements : ');
$output->writeln('');
foreach ($collection->getRequirements() as $requirement) {
$result = $requirement->isFulfilled() ? '<info>OK </info>' : ($requirement->isOptional() ? '<comment>WARNING</comment> ' : '<error>ERROR</error> ');
$output->write(' ' . $result);
$output->writeln($requirement->getTestMessage());
if (!$requirement->isFulfilled()) {
$ret = static::CHECK_ERROR;
$output->writeln(" " . $requirement->getHelpText());
$output->writeln('');
}
}
$output->writeln('');
$output->writeln($collection->getName() . ' recommendations : ');
$output->writeln('');
foreach ($collection->getRecommendations() as $requirement) {
$result = $requirement->isFulfilled() ? '<info>OK </info>' : ($requirement->isOptional() ? '<comment>WARNING</comment> ' : '<error>ERROR</error> ');
$output->write(' ' . $result);
$output->writeln($requirement->getTestMessage());
if (!$requirement->isFulfilled()) {
if ($ret === static::CHECK_OK) {
$ret = static::CHECK_WARNING;
}
$output->writeln(" " . $requirement->getHelpText());
$output->writeln('');
}
}
}
return $ret;
}
/**
* @return array An array of RequirementsCollection
*/
abstract protected function provideRequirements();
}

View File

@@ -11,11 +11,19 @@
namespace Alchemy\Phrasea\Command; namespace Alchemy\Phrasea\Command;
use Symfony\Component\Console\Input\InputInterface; use Alchemy\Phrasea\Setup\Probe\BinariesProbe;
use Symfony\Component\Console\Output\OutputInterface; use Alchemy\Phrasea\Setup\Probe\CacheServerProbe;
use Alchemy\Phrasea\Command\Setup\CheckEnvironment; use Alchemy\Phrasea\Setup\Probe\DataboxStructureProbe;
use Alchemy\Phrasea\Setup\Probe\FilesystemProbe;
use Alchemy\Phrasea\Setup\Probe\LocalesProbe;
use Alchemy\Phrasea\Setup\Probe\OpcodeCacheProbe;
use Alchemy\Phrasea\Setup\Probe\PhpProbe;
use Alchemy\Phrasea\Setup\Probe\PhraseaProbe;
use Alchemy\Phrasea\Setup\Probe\SearchEngineProbe;
use Alchemy\Phrasea\Setup\Probe\SubdefsPathsProbe;
use Alchemy\Phrasea\Setup\Probe\SystemProbe;
class CheckConfig extends CheckEnvironment class CheckConfig extends AbstractCheckCommand
{ {
const CHECK_OK = 0; const CHECK_OK = 0;
const CHECK_WARNING = 1; const CHECK_WARNING = 1;
@@ -30,45 +38,20 @@ class CheckConfig extends CheckEnvironment
return $this; return $this;
} }
/** protected function provideRequirements()
* {@inheritdoc}
*/
protected function doExecute(InputInterface $input, OutputInterface $output)
{ {
$ret = parent::doExecute($input, $output); return array(
BinariesProbe::create($this->container),
foreach ($this->container['phraseanet.appbox']->get_databoxes() as $databox) { CacheServerProbe::create($this->container),
$output->writeln("\nDatabox <info>".$databox->get_viewname()."</info> fields configuration\n"); DataboxStructureProbe::create($this->container),
foreach ($databox->get_meta_structure() as $field) { FilesystemProbe::create($this->container),
if ($field->get_original_source() !== $field->get_tag()->getTagname()) { LocalesProbe::create($this->container),
$status = ' <comment>WARNING</comment> '; OpcodeCacheProbe::create($this->container),
$info = sprintf(" (Described as '<comment>%s</comment>', this source does not seem to exist)", $field->get_original_source()); PhraseaProbe::create($this->container),
} else { PhpProbe::create($this->container),
$status = ' <info>OK</info> '; SearchEngineProbe::create($this->container),
$info = ''; SubdefsPathsProbe::create($this->container),
} SystemProbe::create($this->container),
$output->writeln($status.$databox->get_viewname() . "::".$field->get_name().$info); );
}
$output->writeln("\n");
}
$output->writeln("\nCache configuration\n");
$cache = str_replace('Alchemy\\Phrasea\\Cache\\', '', get_class($this->container['cache']));
$opCodeCache = str_replace('Alchemy\\Phrasea\\Cache\\', '', get_class($this->container['opcode-cache']));
if ('ArrayCache' === $cache) {
$output->writeln(' <comment>WARNING</comment> Current cache configuration uses <comment>ArrayCache</comment> (Or cache server is unreachable). Please check your cache configuration to use a cache server.');
} else {
$output->writeln(' <info>OK</info> Current cache configuration uses <info>'. $cache .'</info>');
}
if ('ArrayCache' === $opCodeCache) {
$output->writeln(' <comment>WARNING</comment> Current opcode cache configuration uses <comment>ArrayCache</comment>. Please check your cache configuration to use an opcode cache.');
} else {
$output->writeln(' <info>OK</info> Current opcode cache configuration uses <info>'. $opCodeCache .'</info>');
}
return $ret;
} }
} }

View File

@@ -11,17 +11,17 @@
namespace Alchemy\Phrasea\Command\Setup; namespace Alchemy\Phrasea\Command\Setup;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\AbstractCheckCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements; use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements;
use Alchemy\Phrasea\Setup\Requirements\CacheServerRequirement;
use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements; use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements;
use Alchemy\Phrasea\Setup\Requirements\LocalesRequirements; use Alchemy\Phrasea\Setup\Requirements\LocalesRequirements;
use Alchemy\Phrasea\Setup\Requirements\PhraseaRequirements; use Alchemy\Phrasea\Setup\Requirements\OpcodeCacheRequirement;
use Alchemy\Phrasea\Setup\Requirements\PhpRequirements; use Alchemy\Phrasea\Setup\Requirements\PhpRequirements;
use Alchemy\Phrasea\Setup\Requirements\PhraseaRequirements;
use Alchemy\Phrasea\Setup\Requirements\SystemRequirements; use Alchemy\Phrasea\Setup\Requirements\SystemRequirements;
class CheckEnvironment extends Command class CheckEnvironment extends AbstractCheckCommand
{ {
const CHECK_OK = 0; const CHECK_OK = 0;
const CHECK_WARNING = 1; const CHECK_WARNING = 1;
@@ -39,56 +39,17 @@ class CheckEnvironment extends Command
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function doExecute(InputInterface $input, OutputInterface $output) protected function provideRequirements()
{ {
$ret = static::CHECK_OK; return array(
new BinariesRequirements(),
foreach(array( new CacheServerRequirement(),
new BinariesRequirements(), new FilesystemRequirements(),
new FilesystemRequirements(), new LocalesRequirements(),
new LocalesRequirements(), new OpcodeCacheRequirement(),
new PhraseaRequirements(), new PhraseaRequirements(),
new PhpRequirements(), new PhpRequirements(),
new SystemRequirements(), new SystemRequirements(),
) as $collection) { );
$output->writeln('');
$output->writeln($collection->getName() . ' requirements : ');
$output->writeln('');
foreach ($collection->getRequirements() as $requirement) {
$result = $requirement->isFulfilled() ? '<info>OK </info>' : ($requirement->isOptional() ? '<comment>WARNING</comment> ' : '<error>ERROR</error> ');
$output->write(' ' . $result);
$output->writeln($requirement->getTestMessage());
if (!$requirement->isFulfilled()) {
$ret = static::CHECK_ERROR;
$output->writeln(" " . $requirement->getHelpText());
$output->writeln('');
}
}
$output->writeln('');
$output->writeln($collection->getName() . ' recommendations : ');
$output->writeln('');
foreach ($collection->getRecommendations() as $requirement) {
$result = $requirement->isFulfilled() ? '<info>OK </info>' : ($requirement->isOptional() ? '<comment>WARNING</comment> ' : '<error>ERROR</error> ');
$output->write(' ' . $result);
$output->writeln($requirement->getTestMessage());
if (!$requirement->isFulfilled()) {
if ($ret === static::CHECK_OK) {
$ret = static::CHECK_WARNING;
}
$output->writeln(" " . $requirement->getHelpText());
$output->writeln('');
}
}
}
return $ret;
} }
} }

View File

@@ -18,12 +18,14 @@ use Alchemy\Phrasea\Setup\Version\Probe\Probe38;
use Alchemy\Phrasea\Setup\Version\Probe\ProbeInterface as VersionProbeInterface; use Alchemy\Phrasea\Setup\Version\Probe\ProbeInterface as VersionProbeInterface;
use Alchemy\Phrasea\Setup\Probe\BinariesProbe; use Alchemy\Phrasea\Setup\Probe\BinariesProbe;
use Alchemy\Phrasea\Setup\Probe\CacheServerProbe; use Alchemy\Phrasea\Setup\Probe\CacheServerProbe;
use Alchemy\Phrasea\Setup\Probe\OpcodeCacheProbe; use Alchemy\Phrasea\Setup\Probe\DataboxStructureProbe;
use Alchemy\Phrasea\Setup\Probe\FilesystemProbe; use Alchemy\Phrasea\Setup\Probe\FilesystemProbe;
use Alchemy\Phrasea\Setup\Probe\LocalesProbe; use Alchemy\Phrasea\Setup\Probe\LocalesProbe;
use Alchemy\Phrasea\Setup\Probe\OpcodeCacheProbe;
use Alchemy\Phrasea\Setup\Probe\PhpProbe; use Alchemy\Phrasea\Setup\Probe\PhpProbe;
use Alchemy\Phrasea\Setup\Probe\PhraseaProbe; use Alchemy\Phrasea\Setup\Probe\PhraseaProbe;
use Alchemy\Phrasea\Setup\Probe\SearchEngineProbe; use Alchemy\Phrasea\Setup\Probe\SearchEngineProbe;
use Alchemy\Phrasea\Setup\Probe\SubdefsPathsProbe;
use Alchemy\Phrasea\Setup\Probe\SystemProbe; use Alchemy\Phrasea\Setup\Probe\SystemProbe;
class ConfigurationTester class ConfigurationTester
@@ -52,12 +54,14 @@ class ConfigurationTester
$this->requirements = array( $this->requirements = array(
BinariesProbe::create($this->app), BinariesProbe::create($this->app),
CacheServerProbe::create($this->app), CacheServerProbe::create($this->app),
DataboxStructureProbe::create($this->app),
OpcodeCacheProbe::create($this->app), OpcodeCacheProbe::create($this->app),
FilesystemProbe::create($this->app), FilesystemProbe::create($this->app),
LocalesProbe::create($this->app), LocalesProbe::create($this->app),
PhpProbe::create($this->app), PhpProbe::create($this->app),
PhraseaProbe::create($this->app), PhraseaProbe::create($this->app),
SearchEngineProbe::create($this->app), SearchEngineProbe::create($this->app),
SubdefsPathsProbe::create($this->app),
SystemProbe::create($this->app), SystemProbe::create($this->app),
); );

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Setup\Probe;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Setup\RequirementCollection;
class DataboxStructureProbe extends RequirementCollection implements ProbeInterface
{
public function __construct(\appbox $appbox)
{
$this->setName('Databoxes structure');
foreach ($appbox->get_databoxes() as $databox) {
foreach ($databox->get_meta_structure() as $field) {
$this->verifyDataboxField($databox->get_dbname(), $field->get_name(), $field->get_original_source(), $field->get_tag()->getTagname());
}
}
}
private function verifyDataboxField($dbName, $field, $original, $tagname)
{
$this->addRequirement(
$original === $tagname,
"$dbName::$field must be be set to a valid metadata source",
"Source \"<strong>$original</strong>\" is not a valid one, please fix it."
);
}
/**
* {@inheritdoc}
*
* @return DataboxStructureProbe
*/
public static function create(Application $app)
{
return new static($app['phraseanet.appbox']);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2013 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Setup\Probe;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Setup\RequirementCollection;
class SubdefsPathsProbe extends RequirementCollection implements ProbeInterface
{
public function __construct(\appbox $appbox)
{
$this->setName('Subdefs Paths');
foreach ($appbox->get_databoxes() as $databox) {
$this->ensureWriteableSubdefsPath($databox->get_dbname(), 'document', (string) $databox->get_sxml_structure()->path);
foreach ($databox->get_subdef_structure() as $group => $subdefs) {
foreach ($subdefs as $subdef) {
$this->ensureWriteableSubdefsPath($databox->get_dbname(), $group . '/' . $subdef->get_name(), (string) $databox->get_sxml_structure()->path);
}
}
}
}
private function ensureWriteableSubdefsPath($dbName, $sdName, $path)
{
$this->addRequirement(
is_dir($path),
"$path ($dbName - $sdName) must be a directory",
"Create directory \"<strong>$path</strong>\" directory so that the subdef could be stored."
);
$this->addRequirement(
is_readable($path),
"$path ($dbName - $sdName) directory must be readable",
"Change the permissions of the \"<strong>$path</strong>\" directory so that the web server can read it."
);
$this->addRequirement(
is_writable($path),
"$path ($dbName - $sdName) directory must be writable",
"Change the permissions of the \"<strong>$path</strong>\" directory so that the web server can write into it."
);
}
/**
* {@inheritdoc}
*
* @return SubdefsPathsProbe
*/
public static function create(Application $app)
{
return new static($app['phraseanet.appbox']);
}
}

View File

@@ -1,5 +1,10 @@
<?php <?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
return call_user_func(function () { return call_user_func(function () {
return require __DIR__ . '/../vendor/autoload.php'; $loader = require __DIR__ . '/../vendor/autoload.php';
return $loader;
}); });

View File

@@ -1,7 +1,11 @@
<?php <?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
use Alchemy\Phrasea\CLI; use Alchemy\Phrasea\CLI;
return call_user_func(function (CLI $cli) { return call_user_func(function (CLI $cli) {
return $cli; return $cli;
}, $cli); }, $cli);

View File

@@ -1,7 +1,11 @@
<?php <?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
return call_user_func(function (Application $app) { return call_user_func(function (Application $app) {
return $app; return $app;
}, $app); }, $app);

View File

@@ -1,4 +1,7 @@
<?php <?php
// This file is automatically generated, please do not edit it.
// To update configuration, use bin/console plugins:* commands.
return array( return array(
); );

View File

@@ -0,0 +1,18 @@
<?php
namespace Alchemy\Tests\Phrasea\Command;
use Alchemy\Phrasea\Command\CheckConfig;
class CheckConfigTest extends \PhraseanetPHPUnitAbstract
{
public function testRunWithoutProblems()
{
$input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
$command = new CheckConfig('check:config');
$command->setContainer(self::$DI['app']);
$this->assertLessThan(2, $command->execute($input, $output));
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Alchemy\Tests\Phrasea\Setup\Probe;
class DataboxStructureProbeTest extends ProbeTestCase
{
protected function getClassName()
{
return 'Alchemy\Phrasea\Setup\Probe\DataboxStructureProbe';
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Alchemy\Tests\Phrasea\Setup\Probe;
class SubdefsPathsProbeTest extends ProbeTestCase
{
protected function getClassName()
{
return 'Alchemy\Phrasea\Setup\Probe\SubdefsPathsProbe';
}
}