Merge pull request #2500 from aynsix/PHRAS-1832-port-1776-to-master

PHRAS-1832 port 1776 to master - databox create
This commit is contained in:
Nicolas Maillat
2018-03-06 15:11:20 +01:00
committed by GitHub
18 changed files with 411 additions and 166 deletions

View File

@@ -75,7 +75,7 @@ $app->command(new PluginsReset());
$app->command(new EnablePlugin()); $app->command(new EnablePlugin());
$app->command(new DisablePlugin()); $app->command(new DisablePlugin());
$app->command(new CheckEnvironment('check:system')); $app->command(new CheckEnvironment('check:system'));
$app->command(new Install('system:install')); $app->command(new Install('system:install', $app['phraseanet.structure-template']));
$app->command(new CrossDomainGenerator()); $app->command(new CrossDomainGenerator());
$app->command(new FixAutoincrements('system:fix-autoincrements')); $app->command(new FixAutoincrements('system:fix-autoincrements'));

View File

@@ -47,7 +47,7 @@ database:
- mysql -u ubuntu -e 'CREATE DATABASE update39_test;CREATE DATABASE ab_test;CREATE DATABASE db_test;SET @@global.sql_mode=STRICT_ALL_TABLES;SET @@global.max_allowed_packet=33554432;SET @@global.wait_timeout=999999;'; - mysql -u ubuntu -e 'CREATE DATABASE update39_test;CREATE DATABASE ab_test;CREATE DATABASE db_test;SET @@global.sql_mode=STRICT_ALL_TABLES;SET @@global.max_allowed_packet=33554432;SET @@global.wait_timeout=999999;';
post: post:
- "./bin/developer system:uninstall -v" - "./bin/developer system:uninstall -v"
- "./bin/setup system:install -v --email=test@phraseanet.com --password=test --db-host=127.0.0.1 --db-user=ubuntu --db-template=fr --db-password= --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 -y;" - "./bin/setup system:install -v --email=test@phraseanet.com --password=test --db-host=127.0.0.1 --db-user=ubuntu --db-template=fr-simple --db-password= --databox=db_test --appbox=ab_test --server-name=http://127.0.0.1 -y;"
- "./bin/developer ini:setup-tests-dbs -v" - "./bin/developer ini:setup-tests-dbs -v"
- "./bin/console searchengine:index:create -v" - "./bin/console searchengine:index:create -v"
- "./bin/developer phraseanet:regenerate-sqlite -v" - "./bin/developer phraseanet:regenerate-sqlite -v"

View File

@@ -3,6 +3,7 @@
namespace Alchemy\Phrasea\Command\Databox; namespace Alchemy\Phrasea\Command\Databox;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
use Alchemy\Phrasea\Databox\DataboxConnectionSettings; use Alchemy\Phrasea\Databox\DataboxConnectionSettings;
use Alchemy\Phrasea\Databox\DataboxService; use Alchemy\Phrasea\Databox\DataboxService;
use Alchemy\Phrasea\Model\Repositories\UserRepository; use Alchemy\Phrasea\Model\Repositories\UserRepository;
@@ -10,6 +11,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\DialogHelper;
class CreateDataboxCommand extends Command class CreateDataboxCommand extends Command
{ {
@@ -18,7 +20,7 @@ class CreateDataboxCommand extends Command
{ {
$this->setName('databox:create') $this->setName('databox:create')
->addArgument('databox', InputArgument::REQUIRED, 'Database name for the databox', null) ->addArgument('databox', InputArgument::REQUIRED, 'Database name for the databox', null)
->addArgument('owner', InputArgument::REQUIRED, 'Email of the databox admin user', null) ->addArgument('owner', InputArgument::REQUIRED, 'Login of the databox admin user', null)
->addOption('connection', 'c', InputOption::VALUE_NONE, 'Flag to set new database settings') ->addOption('connection', 'c', InputOption::VALUE_NONE, 'Flag to set new database settings')
->addOption('db-host', null, InputOption::VALUE_OPTIONAL, 'MySQL server host', 'localhost') ->addOption('db-host', null, InputOption::VALUE_OPTIONAL, 'MySQL server host', 'localhost')
->addOption('db-port', null, InputOption::VALUE_OPTIONAL, 'MySQL server port', 3306) ->addOption('db-port', null, InputOption::VALUE_OPTIONAL, 'MySQL server port', 3306)
@@ -28,13 +30,16 @@ class CreateDataboxCommand extends Command
'db-template', 'db-template',
null, null,
InputOption::VALUE_OPTIONAL, InputOption::VALUE_OPTIONAL,
'Metadata structure language template (available are fr (french) and en (english))', 'Databox template',
'fr' null
); );
} }
protected function doExecute(InputInterface $input, OutputInterface $output) protected function doExecute(InputInterface $input, OutputInterface $output)
{ {
/** @var DialogHelper $dialog */
$dialog = $this->getHelperSet()->get('dialog');
$databoxName = $input->getArgument('databox'); $databoxName = $input->getArgument('databox');
$connectionSettings = $input->getOption('connection') == false ? null : new DataboxConnectionSettings( $connectionSettings = $input->getOption('connection') == false ? null : new DataboxConnectionSettings(
$input->getOption('db-host'), $input->getOption('db-host'),
@@ -45,18 +50,63 @@ class CreateDataboxCommand extends Command
/** @var UserRepository $userRepository */ /** @var UserRepository $userRepository */
$userRepository = $this->container['repo.users']; $userRepository = $this->container['repo.users'];
$owner = $userRepository->findByLogin($input->getArgument('owner'));
if(!$owner) {
$output->writeln(sprintf("<error>Unknown user \"%s\"</error>", $input->getArgument('owner')));
return 1;
}
/** @var DataboxService $databoxService */ /** @var DataboxService $databoxService */
$databoxService = $this->container['databox.service']; $databoxService = $this->container['databox.service'];
$owner = $userRepository->findByEmail($input->getArgument('owner')); if($databoxService->exists($databoxName, $connectionSettings)) {
$output->writeln(sprintf("<error>Database \"%s\" already exists</error>", $databoxName));
$databoxService->createDatabox( return 1;
$databoxName, }
$input->getOption('db-template') . '-simple',
$owner, /** @var StructureTemplate $templates */
$connectionSettings $templates = $this->container['phraseanet.structure-template'];
);
// if a template name is provided, check that this template exists
$templateName = $input->getOption('db-template');
if($templateName && !$templates->getByName($templateName)) {
throw new \Exception_InvalidArgument(sprintf("Databox template \"%s\" not found.", $templateName));
}
if(!$templateName) {
// propose a default template : the first available if "en-simple" does not exists.
$defaultDBoxTemplate = $templates->getDefault();
do {
$templateName = $dialog->ask($output, 'Choose a template from ('.$templates->toString().') for metadata structure <comment>[default: "'.$defaultDBoxTemplate.'"]</comment> : ', $defaultDBoxTemplate);
if(!$templates->getByName($templateName)){
$output->writeln(" <error>Data-Box template : Template not found, try again.</error>");
}
}
while (!$templates->getByName($templateName));
}
try {
$databoxService->createDatabox(
$databoxName,
$templateName,
$owner,
$connectionSettings
);
}
catch(\Exception $e) {
$output->writeln(sprintf("<error>Failed to create database \"%s\", error=\"%s\"</error>"
, $databoxName
, $e->getMessage()
));
return 1;
}
$output->writeln('Databox created'); $output->writeln('Databox created');
return 0;
} }
} }

View File

@@ -13,6 +13,8 @@ namespace Alchemy\Phrasea\Command\Developer;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Core\Version; use Alchemy\Phrasea\Core\Version;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Utilities\StringHelper;
use Doctrine\DBAL\Connection;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -112,11 +114,15 @@ class IniReset extends Command
// get data paths // get data paths
$dataPath = $this->container['conf']->get(['main', 'storage', 'subdefs'], $this->container['root.path'].'/datas'); $dataPath = $this->container['conf']->get(['main', 'storage', 'subdefs'], $this->container['root.path'].'/datas');
$schema = $this->container['orm.em']->getConnection()->getSchemaManager(); /** @var Connection $connection */
$connection = $this->container['orm.em']->getConnection();
$schema = $connection->getSchemaManager();
$output->writeln('Creating database "'.$dbs['ab'].'"...<info>OK</info>'); $output->writeln('Creating database "'.$dbs['ab'].'"...<info>OK</info>');
$schema->dropAndCreateDatabase($dbs['ab']); $schema->dropAndCreateDatabase(StringHelper::SqlQuote($dbs['ab'], StringHelper::SQL_IDENTIFIER));
$output->writeln('Creating database "'.$dbName.'"...<info>OK</info>'); $output->writeln('Creating database "'.$dbName.'"...<info>OK</info>');
$schema->dropAndCreateDatabase($dbName); $schema->dropAndCreateDatabase(StringHelper::SqlQuote($dbName, StringHelper::SQL_IDENTIFIER));
// inject v3.1 fixtures // inject v3.1 fixtures
if ($input->getOption('run-patches')) { if ($input->getOption('run-patches')) {
@@ -212,7 +218,7 @@ class IniReset extends Command
} else { } else {
$output->write(sprintf('Upgrading... from version <info>%s</info> to <info>%s</info>', $this->app->getApplicationBox()->get_version(), $version->getNumber()), true); $output->write(sprintf('Upgrading... from version <info>%s</info> to <info>%s</info>', $this->app->getApplicationBox()->get_version(), $version->getNumber()), true);
} }
$cmd = 'php ' . __DIR__ . '/../../../../../bin/setup system:upgrade -y -f -v'; $cmd = 'php ' . __DIR__ . '/../../../../../bin/setup system:upgrade -y -f -v';
$process = new Process($cmd); $process = new Process($cmd);
$process->setTimeout(600); $process->setTimeout(600);

View File

@@ -13,6 +13,8 @@ namespace Alchemy\Phrasea\Command\Developer;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Utilities\StringHelper;
use Doctrine\DBAL\Connection;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -44,20 +46,30 @@ class SetupTestsDbs extends Command
$dbs[] = $settings['database']['ab_name']; $dbs[] = $settings['database']['ab_name'];
$dbs[] = $settings['database']['db_name']; $dbs[] = $settings['database']['db_name'];
$schema = $this->container['orm.em']->getConnection()->getSchemaManager(); /** @var Connection $connection */
$connection = $this->container['orm.em']->getConnection();
$schema = $connection->getSchemaManager();
foreach($dbs as $name) { foreach($dbs as $name) {
$output->writeln('Creating database "'.$name.'"...<info>OK</info>'); $output->writeln('Creating database "'.$name.'"...<info>OK</info>');
$name = StringHelper::SqlQuote($name, StringHelper::SQL_IDENTIFIER); // quote as `identifier`
$schema->dropAndCreateDatabase($name); $schema->dropAndCreateDatabase($name);
} }
$this->container['orm.em']->getConnection()->executeUpdate(' $user = StringHelper::SqlQuote($settings['database']['user'], StringHelper::SQL_VALUE); // quote as 'value'
GRANT ALL PRIVILEGES ON '.$settings['database']['ab_name'].'.* TO \''.$settings['database']['user'].'\'@\''.$settings['database']['host'].'\' IDENTIFIED BY \''.$settings['database']['password'].'\' WITH GRANT OPTION $host = StringHelper::SqlQuote($settings['database']['host'], StringHelper::SQL_VALUE);
'); $pass = StringHelper::SqlQuote($settings['database']['password'], StringHelper::SQL_VALUE);
$this->container['orm.em']->getConnection()->executeUpdate(' $ab_name = StringHelper::SqlQuote($settings['database']['ab_name'], StringHelper::SQL_IDENTIFIER);
GRANT ALL PRIVILEGES ON '.$settings['database']['db_name'].'.* TO \''.$settings['database']['user'].'\'@\''.$settings['database']['host'].'\' IDENTIFIED BY \''.$settings['database']['password'].'\' WITH GRANT OPTION $db_name = StringHelper::SqlQuote($settings['database']['db_name'], StringHelper::SQL_IDENTIFIER);
');
$this->container['orm.em']->getConnection()->executeUpdate(
'GRANT ALL PRIVILEGES ON '.$ab_name.'.* TO '.$user.'@'.$host.' IDENTIFIED BY '.$pass.' WITH GRANT OPTION'
);
$this->container['orm.em']->getConnection()->executeUpdate(
'GRANT ALL PRIVILEGES ON '.$db_name.'.* TO '.$user.'@'.$host.' IDENTIFIED BY '.$pass.' WITH GRANT OPTION'
);
$this->container['orm.em']->getConnection()->executeUpdate('SET @@global.sql_mode= ""'); $this->container['orm.em']->getConnection()->executeUpdate('SET @@global.sql_mode= ""');

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\Command\Setup; namespace Alchemy\Phrasea\Command\Setup;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Connection;
use Symfony\Component\Console\Helper\DialogHelper; use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\ArrayInput;
@@ -23,11 +24,18 @@ use Symfony\Component\Process\ExecutableFinder;
class Install extends Command class Install extends Command
{ {
private $executableFinder; private $executableFinder;
/** @var StructureTemplate StructureTemplate */
private $structureTemplate;
public function __construct($name = null) /**
* @param null|string $name
* @param StructureTemplate $structureTemplate
*/
public function __construct($name, $structureTemplate)
{ {
parent::__construct($name); parent::__construct($name);
$this->structureTemplate = $structureTemplate;
$this->executableFinder = new ExecutableFinder(); $this->executableFinder = new ExecutableFinder();
$this $this
@@ -38,9 +46,9 @@ class Install extends Command
->addOption('db-port', null, InputOption::VALUE_OPTIONAL, 'MySQL server port', 3306) ->addOption('db-port', null, InputOption::VALUE_OPTIONAL, 'MySQL server port', 3306)
->addOption('db-user', null, InputOption::VALUE_OPTIONAL, 'MySQL server user', 'phrasea') ->addOption('db-user', null, InputOption::VALUE_OPTIONAL, 'MySQL server user', 'phrasea')
->addOption('db-password', null, InputOption::VALUE_OPTIONAL, 'MySQL server password', null) ->addOption('db-password', null, InputOption::VALUE_OPTIONAL, 'MySQL server password', null)
->addOption('db-template', null, InputOption::VALUE_OPTIONAL, 'Metadata structure language template (available are fr (french) and en (english))', null)
->addOption('databox', null, InputOption::VALUE_OPTIONAL, 'Database name for the DataBox', null)
->addOption('appbox', null, InputOption::VALUE_OPTIONAL, 'Database name for the ApplicationBox', null) ->addOption('appbox', null, InputOption::VALUE_OPTIONAL, 'Database name for the ApplicationBox', null)
->addOption('databox', null, InputOption::VALUE_OPTIONAL, 'Database name for the DataBox', null)
->addOption('db-template', null, InputOption::VALUE_OPTIONAL, 'Databox template (' . $this->structureTemplate->toString() . ')', null)
->addOption('data-path', null, InputOption::VALUE_OPTIONAL, 'Path to data repository', realpath(__DIR__ . '/../../../../../datas')) ->addOption('data-path', null, InputOption::VALUE_OPTIONAL, 'Path to data repository', realpath(__DIR__ . '/../../../../../datas'))
->addOption('server-name', null, InputOption::VALUE_OPTIONAL, 'Server name') ->addOption('server-name', null, InputOption::VALUE_OPTIONAL, 'Server name')
->addOption('indexer', null, InputOption::VALUE_OPTIONAL, 'Path to Phraseanet Indexer', 'auto') ->addOption('indexer', null, InputOption::VALUE_OPTIONAL, 'Path to Phraseanet Indexer', 'auto')
@@ -49,11 +57,22 @@ class Install extends Command
return $this; return $this;
} }
private function serverNameToAppBoxName($serverName)
{
return "ab_" . $serverName;
}
private function serverNameToDataBoxName($serverName)
{
return "db_" . $serverName;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function doExecute(InputInterface $input, OutputInterface $output) protected function doExecute(InputInterface $input, OutputInterface $output)
{ {
/** @var DialogHelper $dialog */
$dialog = $this->getHelperSet()->get('dialog'); $dialog = $this->getHelperSet()->get('dialog');
$output->writeln("<comment> $output->writeln("<comment>
@@ -91,12 +110,16 @@ class Install extends Command
} }
} }
$abConn = $this->getABConn($input, $output, $dialog); $serverName = $this->getServerName($input, $output, $dialog);
list($dbConn, $template) = $this->getDBConn($input, $output, $abConn, $dialog); $abConn = $this->getABConn($input, $output, $dialog, $serverName);
if(!$abConn) {
return 1; // no ab is fatal
}
list($dbConn, $templateName) = $this->getDBConn($input, $output, $abConn, $dialog);
list($email, $password) = $this->getCredentials($input, $output, $dialog); list($email, $password) = $this->getCredentials($input, $output, $dialog);
$dataPath = $this->getDataPath($input, $output, $dialog); $dataPath = $this->getDataPath($input, $output, $dialog);
$serverName = $this->getServerName($input, $output, $dialog);
if (!$input->getOption('yes')) { if (!$input->getOption('yes')) {
$continue = $dialog->askConfirmation($output, "<question>Phraseanet is going to be installed, continue ? (N/y)</question>", false); $continue = $dialog->askConfirmation($output, "<question>Phraseanet is going to be installed, continue ? (N/y)</question>", false);
@@ -108,32 +131,32 @@ class Install extends Command
} }
} }
$this->container['phraseanet.installer']->install($email, $password, $abConn, $serverName, $dataPath, $dbConn, $template, $this->detectBinaries()); $this->container['phraseanet.installer']->install($email, $password, $abConn, $serverName, $dataPath, $dbConn, $templateName, $this->detectBinaries());
if (null !== $this->getApplication()) { if (null !== $this->getApplication()) {
$command = $this->getApplication()->find('crossdomain:generate'); $command = $this->getApplication()->find('crossdomain:generate');
$command->run(new ArrayInput(array( $command->run(new ArrayInput([
'command' => 'crossdomain:generate' 'command' => 'crossdomain:generate'
)), $output); ]), $output);
} }
$output->writeln("<info>Install successful !</info>"); $output->writeln("<info>Install successful !</info>");
return; return 0;
} }
private function getABConn(InputInterface $input, OutputInterface $output, DialogHelper $dialog) private function getABConn(InputInterface $input, OutputInterface $output, DialogHelper $dialog)
{ {
$abConn = $info = null; $abConn = $info = null;
if (!$input->getOption('appbox')) { if (!$input->getOption('appbox')) {
$output->writeln("\n<info>--- Database credentials ---</info>\n"); $output->writeln("<info>--- Database credentials ---</info>");
do { do {
$hostname = $dialog->ask($output, "DB hostname (localhost) : ", 'localhost'); $hostname = $dialog->ask($output, 'DB hostname <comment>[default: "localhost"]</comment> : ', 'localhost');
$port = $dialog->ask($output, "DB port (3306) : ", 3306); $port = $dialog->ask($output, 'DB port <comment>[default: "3306"]</comment> : ', '3306');
$dbUser = $dialog->ask($output, "DB user : "); $dbUser = $dialog->ask($output, 'DB user : ');
$dbPassword = $dialog->askHiddenResponse($output, "DB password (hidden) : "); $dbPassword = $dialog->askHiddenResponse($output, 'DB password (hidden) : ');
$abName = $dialog->ask($output, "DB name (phraseanet) : ", 'phraseanet'); $abName = $dialog->ask($output, 'ApplicationBox name <comment>[default: "phraseanet"]</comment> : ', 'phraseanet');
$info = [ $info = [
'host' => $hostname, 'host' => $hostname,
@@ -145,9 +168,10 @@ class Install extends Command
try { try {
$abConn = $this->container['dbal.provider']($info); $abConn = $this->container['dbal.provider']($info);
$abConn->connect(); $abConn->connect();
$output->writeln("\n\t<info>Application-Box : Connection successful !</info>\n"); $output->writeln("<info>Application-Box : Connection successful !</info>");
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln("\n\t<error>Invalid connection parameters</error>\n"); $output->writeln("<error>Application-Box : Failed to connect, try again.</error>");
$abConn = null;
} }
} while (!$abConn); } while (!$abConn);
} else { } else {
@@ -161,7 +185,7 @@ class Install extends Command
$abConn = $this->container['dbal.provider']($info); $abConn = $this->container['dbal.provider']($info);
$abConn->connect(); $abConn->connect();
$output->writeln("\n\t<info>Application-Box : Connection successful !</info>\n"); $output->writeln("<info>Application-Box : Connection successful !</info>");
} }
// add dbs.option & orm.options services to use orm.em later // add dbs.option & orm.options services to use orm.em later
@@ -175,12 +199,13 @@ class Install extends Command
private function getDBConn(InputInterface $input, OutputInterface $output, Connection $abConn, DialogHelper $dialog) private function getDBConn(InputInterface $input, OutputInterface $output, Connection $abConn, DialogHelper $dialog)
{ {
$dbConn = $template = $info = null; $dbConn = $info = null;
$templates = $this->container['phraseanet.structure-template']->getAvailable(); $templateName = null;
if (!$input->getOption('databox')) { if (!$input->getOption('databox')) {
do { do {
$retry = false; $retry = false;
$dbName = $dialog->ask($output, 'DataBox name, will not be created if empty : ', null); $dbName = $dialog->ask($output, 'Data-Box name, will not be created if empty : ', null);
if ($dbName) { if ($dbName) {
try { try {
@@ -194,19 +219,13 @@ class Install extends Command
$dbConn = $this->container['dbal.provider']($info); $dbConn = $this->container['dbal.provider']($info);
$dbConn->connect(); $dbConn->connect();
$output->writeln("\n\t<info>Data-Box : Connection successful !</info>\n"); $output->writeln("<info>Data-Box : Connection successful !</info>");
do {
$template = $dialog->ask($output, "Choose a language template for metadata structure, available are {$templates->__toString()} : ", 'en');
}
while (!in_array($template, array_keys($templates->getTemplates())));
$output->writeln("\n\tLanguage selected is <info>'$template'</info>\n");
} catch (\Exception $e) { } catch (\Exception $e) {
$output->writeln(" <error>Data-Box : Failed to connect, try again.</error>");
$retry = true; $retry = true;
} }
} else { } else {
$output->writeln("\n\tNo databox will be created\n"); $output->writeln("No databox will be created");
} }
} while ($retry); } while ($retry);
} else { } else {
@@ -220,17 +239,37 @@ class Install extends Command
$dbConn = $this->container['dbal.provider']($info); $dbConn = $this->container['dbal.provider']($info);
$dbConn->connect(); $dbConn->connect();
$output->writeln("\n\t<info>Data-Box : Connection successful !</info>\n"); $output->writeln("<info>Data-Box : Connection successful !</info>");
$template = $input->getOption('db-template') ? : 'en';
} }
// add dbs.option & orm.options services to use orm.em later // add dbs.option & orm.options services to use orm.em later
if ($dbConn && $info) { if ($dbConn && $info) {
/** @var StructureTemplate $templates */
$templates = $this->container['phraseanet.structure-template'];
// if a template name is provided, check that this template exists
$templateName = $input->getOption('db-template');
if($templateName && !$templates->getByName($templateName)) {
throw new \Exception_InvalidArgument(sprintf("Databox template \"%s\" not found.", $templateName));
}
if(!$templateName) {
// propose a default template : the first available if "en-simple" does not exists.
$defaultDBoxTemplate = $this->structureTemplate->getDefault();
do {
$templateName = $dialog->ask($output, 'Choose a template from ('.$templates->toString().') for metadata structure <comment>[default: "'.$defaultDBoxTemplate.'"]</comment> : ', $defaultDBoxTemplate);
if(!$templates->getByName($templateName)) {
$output->writeln("<error>Data-Box template : Template not found, try again.</error>");
}
}
while (!$templates->getByName($templateName));
}
$this->container['dbs.options'] = array_merge($this->container['db.options.from_info']($info), $this->container['dbs.options']); $this->container['dbs.options'] = array_merge($this->container['db.options.from_info']($info), $this->container['dbs.options']);
$this->container['orm.ems.options'] = array_merge($this->container['orm.em.options.from_info']($info), $this->container['orm.ems.options']); $this->container['orm.ems.options'] = array_merge($this->container['orm.em.options.from_info']($info), $this->container['orm.ems.options']);
} }
return [$dbConn, $template]; return [$dbConn, $templateName];
} }
private function getCredentials(InputInterface $input, OutputInterface $output, DialogHelper $dialog) private function getCredentials(InputInterface $input, OutputInterface $output, DialogHelper $dialog)
@@ -238,7 +277,7 @@ class Install extends Command
$email = $password = null; $email = $password = null;
if (!$input->getOption('email') && !$input->getOption('password')) { if (!$input->getOption('email') && !$input->getOption('password')) {
$output->writeln("\n<info>--- Account Informations ---</info>\n"); $output->writeln("<info>--- Account Informations ---</info>");
do { do {
$email = $dialog->ask($output, 'Please provide a valid e-mail address : '); $email = $dialog->ask($output, 'Please provide a valid e-mail address : ');
@@ -248,7 +287,7 @@ class Install extends Command
$password = $dialog->askHiddenResponse($output, 'Please provide a password (hidden, 6 character min) : '); $password = $dialog->askHiddenResponse($output, 'Please provide a password (hidden, 6 character min) : ');
} while (strlen($password) < 6); } while (strlen($password) < 6);
$output->writeln("\n\t<info>Email / Password successfully set</info>\n"); $output->writeln("<info>Email / Password successfully set</info>");
} elseif ($input->getOption('email') && $input->getOption('password')) { } elseif ($input->getOption('email') && $input->getOption('password')) {
if (!\Swift_Validate::email($input->getOption('email'))) { if (!\Swift_Validate::email($input->getOption('email'))) {
throw new \RuntimeException('Invalid email addess'); throw new \RuntimeException('Invalid email addess');

View File

@@ -11,6 +11,7 @@
namespace Alchemy\Phrasea\Controller; namespace Alchemy\Phrasea\Controller;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
use Alchemy\Phrasea\Setup\RequirementCollectionInterface; use Alchemy\Phrasea\Setup\RequirementCollectionInterface;
use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements; use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements;
use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements; use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements;
@@ -74,10 +75,13 @@ class SetupController extends Controller
$warnings[] = $this->app->trans('It is not recommended to install Phraseanet without HTTPS support'); $warnings[] = $this->app->trans('It is not recommended to install Phraseanet without HTTPS support');
} }
/** @var StructureTemplate $st */
$st = $this->app['phraseanet.structure-template'];
return $this->render('/setup/step2.html.twig', [ return $this->render('/setup/step2.html.twig', [
'locale' => $this->app['locale'], 'locale' => $this->app['locale'],
'available_locales' => Application::getAvailableLanguages(), 'available_locales' => Application::getAvailableLanguages(),
'available_templates' => $this->app['phraseanet.structure-template']->getAvailable()->getTemplates(), 'available_templates' => $st->getNames(),
'warnings' => $warnings, 'warnings' => $warnings,
'error' => $request->query->get('error'), 'error' => $request->query->get('error'),
'current_servername' => $request->getScheme() . '://' . $request->getHttpHost() . '/', 'current_servername' => $request->getScheme() . '://' . $request->getHttpHost() . '/',
@@ -92,7 +96,7 @@ class SetupController extends Controller
$servername = $request->getScheme() . '://' . $request->getHttpHost() . '/'; $servername = $request->getScheme() . '://' . $request->getHttpHost() . '/';
$dbConn = null; $dbConn = null;
$database_host = $request->request->get('hostname'); $database_host = $request->request->get('hostname');
$database_port = $request->request->get('port'); $database_port = $request->request->get('port');

View File

@@ -10,8 +10,6 @@
namespace Alchemy\Phrasea\Core\Configuration; namespace Alchemy\Phrasea\Core\Configuration;
use Alchemy\Phrasea\Application;
/** /**
* Class StructureTemplate * Class StructureTemplate
* @package Alchemy\Phrasea\Core\Configuration * @package Alchemy\Phrasea\Core\Configuration
@@ -19,25 +17,36 @@ use Alchemy\Phrasea\Application;
class StructureTemplate class StructureTemplate
{ {
const TEMPLATE_EXTENSION = 'xml'; const TEMPLATE_EXTENSION = 'xml';
private $templates; const DEFAULT_TEMPLATE = 'en-simple';
public function __construct(Application $app) /** @var string */
{ private $rootPath;
$this->app = $app;
} /** @var \SplFileInfo[] */
private $templates;
/** @var string[] */
private $names;
/** /**
* @return $this * @param string $rootPath
* @throws \Exception
*/ */
public function getAvailable() public function __construct($rootPath)
{ {
$templateList = new \DirectoryIterator($this->app['root.path'] . '/lib/conf.d/data_templates'); $this->rootPath = $rootPath;
if (empty($templateList)) { $this->names = $this->templates = null; // lazy loaded, not yet set
throw new \Exception('No available structure template'); }
private function load()
{
if(!is_null($this->templates)) {
return; // already loaded
} }
$templates = [];
$abbreviationLength = 2; $templateList = new \DirectoryIterator($this->rootPath . '/lib/conf.d/data_templates');
$this->templates = [];
$this->names = [];
foreach ($templateList as $template) { foreach ($templateList as $template) {
if ($template->isDot() if ($template->isDot()
|| !$template->isFile() || !$template->isFile()
@@ -45,65 +54,64 @@ class StructureTemplate
) { ) {
continue; continue;
} }
$name = $template->getFilename();
$abbreviation = strtolower(substr($name, 0, $abbreviationLength));
if (array_key_exists($abbreviation, $templates)) {
$abbreviation = strtolower(substr($name, 0, ++$abbreviationLength));
}
$templates[$abbreviation] = $template->getBasename('.' . self::TEMPLATE_EXTENSION);
}
$this->templates = $templates;
return $this; $name = $template->getBasename('.' . self::TEMPLATE_EXTENSION);
// beware that the directoryiterator returns a reference on a static, so clone()
$this->templates[$name] = clone($template);
$this->names[] = $name;
}
}
/**
* @param $templateName
* @return null|\SplFileInfo
*/
public function getByName($templateName)
{
$this->load();
if (!array_key_exists($templateName, $this->templates)) {
return null;
}
return $this->templates[$templateName];
}
/**
* @param $index
* @return null|\SplFileInfo
*/
public function getNameByIndex($index)
{
$this->load();
return $this->names[$index];
}
/**
* @return \string[]
*/
public function getNames()
{
$this->load();
return $this->names;
}
public function toString()
{
$this->load();
return implode(', ', $this->names);
} }
/** /**
* @return string * @return string
*/ */
public function __toString() public function getDefault()
{ {
if (!$this->templates) { $this->load();
return '';
}
$templateToString = '';
$cpt = 1;
$templateLength = count($this->templates);
foreach ($this->templates as $key => $value) {
if (($templateLength - 1) == $cpt) {
$separator = ' and ';
}
elseif (end($this->templates) == $value) {
$separator = '';
}
else {
$separator = ', ';
}
$templateToString .= $key . ' (' . $value . ')' . $separator;
$cpt++;
}
return $templateToString; return $this->getByName(self::DEFAULT_TEMPLATE) ? self::DEFAULT_TEMPLATE : $this->getNameByIndex(0);
}
/**
* @param $template
* @return mixed
* @throws \Exception
*/
public function getTemplateName($template = 'en')
{
if (!array_key_exists($template, $this->templates)) {
throw new \Exception('Not found template : ' . $template);
}
return $this->templates[$template];
}
/**
* @return mixed
*/
public function getTemplates()
{
return $this->templates;
} }
} }

View File

@@ -75,7 +75,7 @@ class ConfigurationServiceProvider implements ServiceProviderInterface
}); });
$app['phraseanet.structure-template'] = $app->share(function (Application $app) { $app['phraseanet.structure-template'] = $app->share(function (Application $app) {
return new StructureTemplate($app); return new StructureTemplate($app['root.path']);
}); });
} }

View File

@@ -4,7 +4,9 @@ namespace Alchemy\Phrasea\Databox;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess; use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Utilities\StringHelper;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
/** /**
@@ -72,26 +74,101 @@ class DataboxService
} }
/** /**
* @param $databaseName
* @param DataboxConnectionSettings|null $connectionSettings
* @return bool
*/
public function exists($databaseName, DataboxConnectionSettings $connectionSettings = null)
{
$connectionSettings = $connectionSettings ?: DataboxConnectionSettings::fromArray(
$this->configuration->get(['main', 'database'])
);
$factory = $this->connectionFactory;
// do not simply try to connect to the database, list
/** @var Connection $connection */
$connection = $factory([
'host' => $connectionSettings->getHost(),
'port' => $connectionSettings->getPort(),
'user' => $connectionSettings->getUser(),
'password' => $connectionSettings->getPassword(),
'dbname' => null,
]);
$ret = false;
$databaseName = strtolower($databaseName);
$sm = $connection->getSchemaManager();
$databases = $sm->listDatabases();
foreach($databases as $database) {
if(strtolower($database) == $databaseName) {
$ret = true;
break;
}
}
return $ret;
}
/**
* @param Connection $connection
* @param \SplFileInfo $template
* @return \databox
*/
public function createDataboxFromConnection($connection, $template)
{
return \databox::create($this->app, $connection, $template);
}
/**
* @param $databaseName
* @param $templateName
* @param User $owner * @param User $owner
* @param string $databaseName
* @param string $dataTemplate
* @param DataboxConnectionSettings|null $connectionSettings * @param DataboxConnectionSettings|null $connectionSettings
* @return \databox * @return \databox
* @throws \Exception_InvalidArgument
*/ */
public function createDatabox( public function createDatabox(
$databaseName, $databaseName,
$dataTemplate, $templateName,
User $owner, User $owner,
DataboxConnectionSettings $connectionSettings = null DataboxConnectionSettings $connectionSettings = null
) { ) {
$this->validateDatabaseName($databaseName); $this->validateDatabaseName($databaseName);
$dataTemplate = new \SplFileInfo($this->rootPath . '/lib/conf.d/data_templates/' . $dataTemplate . '.xml'); /** @var StructureTemplate $st */
$st = $this->app['phraseanet.structure-template'];
$template = $st->getByName($templateName);
if(is_null($template)) {
throw new \Exception_InvalidArgument(sprintf('Databox template "%s" not found.', $templateName));
}
// if no connectionSettings (host, user, ...) are provided, create dbox beside appBox
$connectionSettings = $connectionSettings ?: DataboxConnectionSettings::fromArray( $connectionSettings = $connectionSettings ?: DataboxConnectionSettings::fromArray(
$this->configuration->get(['main', 'database']) $this->configuration->get(['main', 'database'])
); );
$factory = $this->connectionFactory; $factory = $this->connectionFactory;
if(!$this->exists($databaseName, $connectionSettings)) {
// use a tmp connection to create the database
/** @var Connection $connection */
$connection = $factory([
'host' => $connectionSettings->getHost(),
'port' => $connectionSettings->getPort(),
'user' => $connectionSettings->getUser(),
'password' => $connectionSettings->getPassword(),
'dbname' => null
]);
// the schemeManager does NOT quote identifiers, we MUST do it
// see : http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-manager.html
$connection->getSchemaManager()->createDatabase(StringHelper::SqlQuote($databaseName, StringHelper::SQL_IDENTIFIER));
$connection->close();
unset($connection);
}
/** @var Connection $connection */ /** @var Connection $connection */
$connection = $factory([ $connection = $factory([
'host' => $connectionSettings->getHost(), 'host' => $connectionSettings->getHost(),
@@ -103,7 +180,8 @@ class DataboxService
$connection->connect(); $connection->connect();
$databox = \databox::create($this->app, $connection, $dataTemplate); $databox = $this->createDataboxFromConnection($connection, $template);
$databox->registerAdmin($owner); $databox->registerAdmin($owner);
$connection->close(); $connection->close();

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\Setup; namespace Alchemy\Phrasea\Setup;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Core\Event\InstallFinishEvent; use Alchemy\Phrasea\Core\Event\InstallFinishEvent;
use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Model\Entities\User;
@@ -29,7 +30,7 @@ class Installer
$this->app = $app; $this->app = $app;
} }
public function install($email, $password, Connection $abConn, $serverName, $dataPath, Connection $dbConn = null, $template = null, array $binaryData = []) public function install($email, $password, Connection $abConn, $serverName, $dataPath, Connection $dbConn = null, $templateName = null, array $binaryData = [])
{ {
$this->rollbackInstall($abConn, $dbConn); $this->rollbackInstall($abConn, $dbConn);
@@ -39,7 +40,7 @@ class Installer
$user = $this->createUser($email, $password); $user = $this->createUser($email, $password);
$this->createDefaultUsers(); $this->createDefaultUsers();
if (null !== $dbConn) { if (null !== $dbConn) {
$this->createDB($dbConn, $template, $user); $this->createDB($dbConn, $templateName, $user);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$this->rollbackInstall($abConn, $dbConn); $this->rollbackInstall($abConn, $dbConn);
@@ -51,9 +52,15 @@ class Installer
return $user; return $user;
} }
private function createDB(Connection $dbConn = null, $template, User $admin) private function createDB(Connection $dbConn = null, $templateName, User $admin)
{ {
$template = new \SplFileInfo(__DIR__ . '/../../../conf.d/data_templates/' . $this->app['phraseanet.structure-template']->getAvailable()->getTemplateName($template) . '.xml'); /** @var StructureTemplate $st */
$st = $this->app['phraseanet.structure-template'];
$template = $st->getByName($templateName);
if(is_null($template)) {
throw new \Exception_InvalidArgument(sprintf('Databox template "%s" not found.', $templateName));
}
$databox = \databox::create($this->app, $dbConn, $template); $databox = \databox::create($this->app, $dbConn, $template);
$this->app->getAclForUser($admin) $this->app->getAclForUser($admin)
@@ -66,7 +73,7 @@ class Installer
\ACL::BAS_MODIF_TH => true, \ACL::BAS_MODIF_TH => true,
\ACL::BAS_CHUPUB => true \ACL::BAS_CHUPUB => true
] ]
); );
$collection = \collection::create($this->app, $databox, $this->app['phraseanet.appbox'], 'test', $admin); $collection = \collection::create($this->app, $databox, $this->app['phraseanet.appbox'], 'test', $admin);

View File

@@ -13,6 +13,9 @@ namespace Alchemy\Phrasea\Utilities;
class StringHelper class StringHelper
{ {
const SQL_VALUE = '\'';
const SQL_IDENTIFIER = '`';
/** /**
* @param string $str * @param string $str
* @return string * @return string
@@ -35,4 +38,14 @@ class StringHelper
return $pascalCase ? $transformStr : lcfirst($transformStr); return $pascalCase ? $transformStr : lcfirst($transformStr);
} }
/**
* @param $s
* @param $quote
* @return string
*/
public static function SqlQuote($s, $quote)
{
return $quote . str_replace($quote, $quote.$quote, $s) . $quote;
}
} }

View File

@@ -63,14 +63,15 @@ class databox extends base implements ThumbnailedElement
/** /**
* @param Application $app * @param Application $app
* @param Connection $databoxConnection * @param Connection $databoxConnection
* @param SplFileInfo $data_template * @param SplFileInfo $template
* @return databox * @return databox
* @throws \Doctrine\DBAL\DBALException * @throws \Doctrine\DBAL\DBALException
*/ */
public static function create(Application $app, Connection $databoxConnection, \SplFileInfo $data_template) public static function create(Application $app, Connection $databoxConnection, \SplFileInfo $template)
{ {
if ( ! file_exists($data_template->getRealPath())) { $rp = $template->getRealPath();
throw new \InvalidArgumentException($data_template->getRealPath() . " does not exist"); if (!$rp || !file_exists($rp)) {
throw new \InvalidArgumentException(sprintf('Databox template "%s" not found.', $template->getFilename()));
} }
$host = $databoxConnection->getHost(); $host = $databoxConnection->getHost();
@@ -113,7 +114,7 @@ class databox extends base implements ThumbnailedElement
$databox->insert_datas(); $databox->insert_datas();
$databox->setNewStructure( $databox->setNewStructure(
$data_template, $app['conf']->get(['main', 'storage', 'subdefs']) $template, $app['conf']->get(['main', 'storage', 'subdefs'])
); );
$app['dispatcher']->dispatch(DataboxEvents::CREATED, new CreatedEvent($databox)); $app['dispatcher']->dispatch(DataboxEvents::CREATED, new CreatedEvent($databox));
@@ -371,9 +372,9 @@ class databox extends base implements ThumbnailedElement
DataboxEvents::STRUCTURE_CHANGED, DataboxEvents::STRUCTURE_CHANGED,
new StructureChangedEvent( new StructureChangedEvent(
$this, $this,
array( [
'dom_before'=>$old_structure 'dom_before'=>$old_structure
) ]
) )
); );
@@ -441,13 +442,13 @@ class databox extends base implements ThumbnailedElement
$type = isset($field['type']) ? $field['type'] : 'string'; $type = isset($field['type']) ? $field['type'] : 'string';
$type = in_array($type $type = in_array($type
, [ , [
databox_field::TYPE_DATE databox_field::TYPE_DATE
, databox_field::TYPE_NUMBER , databox_field::TYPE_NUMBER
, databox_field::TYPE_STRING , databox_field::TYPE_STRING
, databox_field::TYPE_TEXT , databox_field::TYPE_TEXT
] ]
) ? $type : databox_field::TYPE_STRING; ) ? $type : databox_field::TYPE_STRING;
$multi = isset($field['multi']) ? (Boolean) (string) $field['multi'] : false; $multi = isset($field['multi']) ? (Boolean) (string) $field['multi'] : false;
@@ -769,14 +770,14 @@ class databox extends base implements ThumbnailedElement
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC); $rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor(); $stmt->closeCursor();
$ret = array( $ret = [
'records' => 0, 'records' => 0,
'records_indexed' => 0, // jetons = 0;0 'records_indexed' => 0, // jetons = 0;0
'records_to_index' => 0, // jetons = 0;1 'records_to_index' => 0, // jetons = 0;1
'records_not_indexed' => 0, // jetons = 1;0 'records_not_indexed' => 0, // jetons = 1;0
'records_indexing' => 0, // jetons = 1;1 'records_indexing' => 0, // jetons = 1;1
'subdefs_todo' => array() // by type "image", "video", ... 'subdefs_todo' => [] // by type "image", "video", ...
); ];
foreach ($rs as $row) { foreach ($rs as $row) {
$ret['records'] += ($n = (int)($row['n'])); $ret['records'] += ($n = (int)($row['n']));
$status = $row['status']; $status = $row['status'];
@@ -870,9 +871,9 @@ class databox extends base implements ThumbnailedElement
DataboxEvents::UNMOUNTED, DataboxEvents::UNMOUNTED,
new UnmountedEvent( new UnmountedEvent(
null, null,
array( [
'dbname'=>$old_dbname 'dbname'=>$old_dbname
) ]
) )
); );
@@ -935,9 +936,9 @@ class databox extends base implements ThumbnailedElement
DataboxEvents::DELETED, DataboxEvents::DELETED,
new DeletedEvent( new DeletedEvent(
null, null,
array( [
'dbname'=>$old_dbname 'dbname'=>$old_dbname
) ]
) )
); );
@@ -1141,7 +1142,7 @@ class databox extends base implements ThumbnailedElement
\ACL::BAS_MODIF_TH => true, \ACL::BAS_MODIF_TH => true,
\ACL::BAS_CHUPUB => true \ACL::BAS_CHUPUB => true
] ]
); );
$sql = "SELECT * FROM coll"; $sql = "SELECT * FROM coll";
$stmt = $this->get_connection()->prepare($sql); $stmt = $this->get_connection()->prepare($sql);
@@ -1363,9 +1364,9 @@ class databox extends base implements ThumbnailedElement
DataboxEvents::TOU_CHANGED, DataboxEvents::TOU_CHANGED,
new TouChangedEvent( new TouChangedEvent(
$this, $this,
array( [
'tou_before'=>$old_tou, 'tou_before'=>$old_tou,
) ]
) )
); );
@@ -1481,6 +1482,7 @@ class databox extends base implements ThumbnailedElement
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC); $rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor(); $stmt->closeCursor();
$TOU = [];
foreach ($rs as $row) { foreach ($rs as $row) {
$TOU[$row['locale']] = ['updated_on' => $row['updated_on'], 'value' => $row['value']]; $TOU[$row['locale']] = ['updated_on' => $row['updated_on'], 'value' => $row['value']];
} }

View File

@@ -32,7 +32,7 @@
- name: Run application setup - name: Run application setup
become: yes become: yes
become_user: vagrant become_user: vagrant
shell: 'bin/setup system:install --email=admin@{{ hostname }}.vb --password=admin --db-host=127.0.0.1 --db-port=3306 --db-user={{ mariadb.user }} --db-password={{ mariadb.password }} --db-template=fr --appbox={{ mariadb.appbox_db }} --databox={{ mariadb.databox_db }} --server-name=www.{{ hostname }}.vb --data-path=/vagrant/datas -y' shell: 'bin/setup system:install --email=admin@{{ hostname }}.vb --password=admin --db-host=127.0.0.1 --db-port=3306 --db-user={{ mariadb.user }} --db-password={{ mariadb.password }} --db-template=en-simple --appbox={{ mariadb.appbox_db }} --databox={{ mariadb.databox_db }} --server-name=www.{{ hostname }}.vb --data-path=/vagrant/datas -y'
args: args:
chdir: /vagrant/ chdir: /vagrant/

View File

@@ -738,8 +738,8 @@
<td><label>{{ 'Modele de donnees' | trans }}</label></td> <td><label>{{ 'Modele de donnees' | trans }}</label></td>
<td> <td>
<select name="db_template" class="databox_creation_input"> <select name="db_template" class="databox_creation_input">
{% for key,template in available_templates %} {% for name in available_templates %}
<option value="{{ key }}">{{ template }}</option> <option value="{{ name|escape('js') }}">{{ name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>

View File

@@ -4,6 +4,7 @@ namespace Alchemy\Tests\Phrasea\Command\Setup;
use Alchemy\Phrasea\Command\Setup\Install; use Alchemy\Phrasea\Command\Setup\Install;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
/** /**
* @group functional * @group functional
@@ -20,7 +21,7 @@ class InstallTest extends \PhraseanetTestCase
$password = 'sup4ssw0rd'; $password = 'sup4ssw0rd';
$serverName = 'http://phrasea.io'; $serverName = 'http://phrasea.io';
$dataPath = '/tmp'; $dataPath = '/tmp';
$template = 'fr'; $template = 'fr-simple';
$infoDb = Yaml::parse(file_get_contents(__DIR__ . '/../../../../../../resources/hudson/InstallDBs.yml')); $infoDb = Yaml::parse(file_get_contents(__DIR__ . '/../../../../../../resources/hudson/InstallDBs.yml'));
@@ -81,7 +82,7 @@ class InstallTest extends \PhraseanetTestCase
return true; return true;
break; break;
default: default:
return; return '';
} }
})); }));
@@ -93,7 +94,9 @@ class InstallTest extends \PhraseanetTestCase
->method('install') ->method('install')
->with($email, $password, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $serverName, $dataPath, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $template, $this->anything()); ->with($email, $password, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $serverName, $dataPath, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $template, $this->anything());
$command = new Install('system:check'); $structureTemplate = self::$DI['cli']['phraseanet.structure-template'];
$command = new Install('system:check', $structureTemplate);
$command->setHelperSet($helperSet); $command->setHelperSet($helperSet);
$command->setContainer(self::$DI['cli']); $command->setContainer(self::$DI['cli']);
$this->assertEquals(0, $command->execute($input, $output)); $this->assertEquals(0, $command->execute($input, $output));

View File

@@ -75,7 +75,7 @@ class InstallerTest extends \PhraseanetTestCase
$dataPath = __DIR__ . '/../../../../../datas/'; $dataPath = __DIR__ . '/../../../../../datas/';
$installer = new Installer($app); $installer = new Installer($app);
$installer->install(uniqid('admin') . '@example.com', 'sdfsdsd', $abConn, 'http://local.phrasea.test.installer/', $dataPath, $dbConn, 'en'); $installer->install(uniqid('admin') . '@example.com', 'sdfsdsd', $abConn, 'http://local.phrasea.test.installer/', $dataPath, $dbConn, 'en-simple');
$this->assertTrue($app['configuration.store']->isSetup()); $this->assertTrue($app['configuration.store']->isSetup());
$this->assertTrue($app['phraseanet.configuration-tester']->isUpToDate()); $this->assertTrue($app['phraseanet.configuration-tester']->isUpToDate());

View File

@@ -52,4 +52,27 @@ class StringHelperTest extends \PhraseanetTestCase
["ABC\n\rDEF", "ABC\n\nDEF"], ["ABC\n\rDEF", "ABC\n\nDEF"],
]; ];
} }
/**
* @dataProvider provideStringsForSqlQuote
* @covers Alchemy\Phrasea\Utilities\StringHelper::SqlQuote
*/
public function testSqlQuote($string, $mode, $expected)
{
$result = StringHelper::SqlQuote($string, $mode);
$this->assertEquals($expected, $result);
}
public function provideStringsForSqlQuote()
{
return [
["azerty", StringHelper::SQL_VALUE, "'azerty'"],
["aze'rty", StringHelper::SQL_VALUE, "'aze''rty'"],
["aze`rty", StringHelper::SQL_VALUE, "'aze`rty'"],
["azerty", StringHelper::SQL_IDENTIFIER, "`azerty`"],
["aze'rty", StringHelper::SQL_IDENTIFIER, "`aze'rty`"],
["aze`rty", StringHelper::SQL_IDENTIFIER, "`aze``rty`"],
];
}
} }