diff --git a/lib/Alchemy/Phrasea/Command/AbstractCheckCommand.php b/lib/Alchemy/Phrasea/Command/AbstractCheckCommand.php new file mode 100644 index 0000000000..0b21b7b48a --- /dev/null +++ b/lib/Alchemy/Phrasea/Command/AbstractCheckCommand.php @@ -0,0 +1,77 @@ +provideRequirements() as $collection) { + + $output->writeln(''); + $output->writeln($collection->getName() . ' requirements : '); + $output->writeln(''); + + foreach ($collection->getRequirements() as $requirement) { + $result = $requirement->isFulfilled() ? 'OK ' : ($requirement->isOptional() ? 'WARNING ' : '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() ? 'OK ' : ($requirement->isOptional() ? 'WARNING ' : '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(); +} diff --git a/lib/Alchemy/Phrasea/Command/CheckConfig.php b/lib/Alchemy/Phrasea/Command/CheckConfig.php index 7a23670bff..0ba508dc71 100644 --- a/lib/Alchemy/Phrasea/Command/CheckConfig.php +++ b/lib/Alchemy/Phrasea/Command/CheckConfig.php @@ -11,11 +11,19 @@ namespace Alchemy\Phrasea\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Alchemy\Phrasea\Command\Setup\CheckEnvironment; +use Alchemy\Phrasea\Setup\Probe\BinariesProbe; +use Alchemy\Phrasea\Setup\Probe\CacheServerProbe; +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_WARNING = 1; @@ -30,45 +38,20 @@ class CheckConfig extends CheckEnvironment return $this; } - /** - * {@inheritdoc} - */ - protected function doExecute(InputInterface $input, OutputInterface $output) + protected function provideRequirements() { - $ret = parent::doExecute($input, $output); - - foreach ($this->container['phraseanet.appbox']->get_databoxes() as $databox) { - $output->writeln("\nDatabox ".$databox->get_viewname()." fields configuration\n"); - foreach ($databox->get_meta_structure() as $field) { - if ($field->get_original_source() !== $field->get_tag()->getTagname()) { - $status = ' WARNING '; - $info = sprintf(" (Described as '%s', this source does not seem to exist)", $field->get_original_source()); - } else { - $status = ' OK '; - $info = ''; - } - $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(' WARNING Current cache configuration uses ArrayCache (Or cache server is unreachable). Please check your cache configuration to use a cache server.'); - } else { - $output->writeln(' OK Current cache configuration uses '. $cache .''); - } - - if ('ArrayCache' === $opCodeCache) { - $output->writeln(' WARNING Current opcode cache configuration uses ArrayCache. Please check your cache configuration to use an opcode cache.'); - } else { - $output->writeln(' OK Current opcode cache configuration uses '. $opCodeCache .''); - } - - return $ret; + return array( + BinariesProbe::create($this->container), + CacheServerProbe::create($this->container), + DataboxStructureProbe::create($this->container), + FilesystemProbe::create($this->container), + LocalesProbe::create($this->container), + OpcodeCacheProbe::create($this->container), + PhraseaProbe::create($this->container), + PhpProbe::create($this->container), + SearchEngineProbe::create($this->container), + SubdefsPathsProbe::create($this->container), + SystemProbe::create($this->container), + ); } } diff --git a/lib/Alchemy/Phrasea/Command/Setup/CheckEnvironment.php b/lib/Alchemy/Phrasea/Command/Setup/CheckEnvironment.php index 2ba63db427..df74f47997 100644 --- a/lib/Alchemy/Phrasea/Command/Setup/CheckEnvironment.php +++ b/lib/Alchemy/Phrasea/Command/Setup/CheckEnvironment.php @@ -11,17 +11,17 @@ namespace Alchemy\Phrasea\Command\Setup; -use Alchemy\Phrasea\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; +use Alchemy\Phrasea\Command\AbstractCheckCommand; use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements; +use Alchemy\Phrasea\Setup\Requirements\CacheServerRequirement; use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements; 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\PhraseaRequirements; use Alchemy\Phrasea\Setup\Requirements\SystemRequirements; -class CheckEnvironment extends Command +class CheckEnvironment extends AbstractCheckCommand { const CHECK_OK = 0; const CHECK_WARNING = 1; @@ -39,56 +39,17 @@ class CheckEnvironment extends Command /** * {@inheritdoc} */ - protected function doExecute(InputInterface $input, OutputInterface $output) + protected function provideRequirements() { - $ret = static::CHECK_OK; - - foreach(array( - new BinariesRequirements(), - new FilesystemRequirements(), - new LocalesRequirements(), - new PhraseaRequirements(), - new PhpRequirements(), - new SystemRequirements(), - ) as $collection) { - - $output->writeln(''); - $output->writeln($collection->getName() . ' requirements : '); - $output->writeln(''); - - foreach ($collection->getRequirements() as $requirement) { - $result = $requirement->isFulfilled() ? 'OK ' : ($requirement->isOptional() ? 'WARNING ' : '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() ? 'OK ' : ($requirement->isOptional() ? 'WARNING ' : '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( + new BinariesRequirements(), + new CacheServerRequirement(), + new FilesystemRequirements(), + new LocalesRequirements(), + new OpcodeCacheRequirement(), + new PhraseaRequirements(), + new PhpRequirements(), + new SystemRequirements(), + ); } } diff --git a/lib/Alchemy/Phrasea/Setup/ConfigurationTester.php b/lib/Alchemy/Phrasea/Setup/ConfigurationTester.php index 8751b79f03..8ff79f22a1 100644 --- a/lib/Alchemy/Phrasea/Setup/ConfigurationTester.php +++ b/lib/Alchemy/Phrasea/Setup/ConfigurationTester.php @@ -18,12 +18,14 @@ use Alchemy\Phrasea\Setup\Version\Probe\Probe38; use Alchemy\Phrasea\Setup\Version\Probe\ProbeInterface as VersionProbeInterface; use Alchemy\Phrasea\Setup\Probe\BinariesProbe; 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\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 ConfigurationTester @@ -52,12 +54,14 @@ class ConfigurationTester $this->requirements = array( BinariesProbe::create($this->app), CacheServerProbe::create($this->app), + DataboxStructureProbe::create($this->app), OpcodeCacheProbe::create($this->app), FilesystemProbe::create($this->app), LocalesProbe::create($this->app), PhpProbe::create($this->app), PhraseaProbe::create($this->app), SearchEngineProbe::create($this->app), + SubdefsPathsProbe::create($this->app), SystemProbe::create($this->app), ); diff --git a/lib/Alchemy/Phrasea/Setup/Probe/DataboxStructureProbe.php b/lib/Alchemy/Phrasea/Setup/Probe/DataboxStructureProbe.php new file mode 100644 index 0000000000..d111ed4ceb --- /dev/null +++ b/lib/Alchemy/Phrasea/Setup/Probe/DataboxStructureProbe.php @@ -0,0 +1,48 @@ +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 \"$original\" is not a valid one, please fix it." + ); + } + + /** + * {@inheritdoc} + * + * @return DataboxStructureProbe + */ + public static function create(Application $app) + { + return new static($app['phraseanet.appbox']); + } +} diff --git a/lib/Alchemy/Phrasea/Setup/Probe/SubdefsPathsProbe.php b/lib/Alchemy/Phrasea/Setup/Probe/SubdefsPathsProbe.php new file mode 100644 index 0000000000..0b2e71f95e --- /dev/null +++ b/lib/Alchemy/Phrasea/Setup/Probe/SubdefsPathsProbe.php @@ -0,0 +1,63 @@ +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 \"$path\" 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 \"$path\" 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 \"$path\" 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']); + } +} diff --git a/plugins/autoload.php b/plugins/autoload.php index e914fb7f97..7c242765f2 100644 --- a/plugins/autoload.php +++ b/plugins/autoload.php @@ -1,5 +1,10 @@ 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)); + } +} diff --git a/tests/Alchemy/Tests/Phrasea/Setup/Probe/DataboxStructureProbeTest.php b/tests/Alchemy/Tests/Phrasea/Setup/Probe/DataboxStructureProbeTest.php new file mode 100644 index 0000000000..fdb1682ff8 --- /dev/null +++ b/tests/Alchemy/Tests/Phrasea/Setup/Probe/DataboxStructureProbeTest.php @@ -0,0 +1,11 @@ +