Inital commit
This commit is contained in:
@@ -16,8 +16,12 @@ use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\HttpFoundation\Session\Session;
|
||||
use Thelia\Model\AdminQuery;
|
||||
use Thelia\Tools\Password;
|
||||
|
||||
@@ -28,10 +32,21 @@ use Thelia\Tools\Password;
|
||||
*
|
||||
* Class AdminUpdatePasswordCommand
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class AdminUpdatePasswordCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
|
||||
$request = new Request();
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
|
||||
/** @var RequestStack $requestStack */
|
||||
$requestStack = $container->get('request_stack');
|
||||
$requestStack->push($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the current command.
|
||||
@@ -58,6 +73,8 @@ class AdminUpdatePasswordCommand extends ContainerAwareCommand
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
$login = $input->getArgument('login');
|
||||
|
||||
if (null === $admin = AdminQuery::create()->filterByLogin($login)->findOne()) {
|
||||
@@ -69,10 +86,7 @@ class AdminUpdatePasswordCommand extends ContainerAwareCommand
|
||||
$event = new AdministratorUpdatePasswordEvent($admin);
|
||||
$event->setPassword($password);
|
||||
|
||||
$this->
|
||||
getContainer()
|
||||
->get('event_dispatcher')
|
||||
->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event);
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event);
|
||||
|
||||
$output->writeln(array(
|
||||
'',
|
||||
@@ -80,7 +94,5 @@ class AdminUpdatePasswordCommand extends ContainerAwareCommand
|
||||
sprintf('<info>new password is : %s</info>', $password),
|
||||
''
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,25 +12,23 @@
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Thelia\Model\Module;
|
||||
|
||||
/**
|
||||
* base class for module commands
|
||||
*
|
||||
* Class BaseModuleGenerate
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
abstract class BaseModuleGenerate extends ContainerAwareCommand
|
||||
{
|
||||
protected $module;
|
||||
protected $moduleDirectory;
|
||||
protected $module;
|
||||
protected $moduleDirectory;
|
||||
|
||||
protected $reservedKeyWords = array(
|
||||
protected $reservedKeyWords = array(
|
||||
'thelia'
|
||||
);
|
||||
|
||||
protected $neededDirectories = array(
|
||||
protected $neededDirectories = array(
|
||||
'Config',
|
||||
'Model',
|
||||
'Loop',
|
||||
@@ -38,23 +36,37 @@ abstract class BaseModuleGenerate extends ContainerAwareCommand
|
||||
'Controller',
|
||||
'EventListeners',
|
||||
'I18n',
|
||||
Module::ADMIN_INCLUDES_DIRECTORY_NAME,
|
||||
'templates',
|
||||
'Hook',
|
||||
);
|
||||
|
||||
protected function verifyExistingModule()
|
||||
{
|
||||
if (file_exists($this->moduleDirectory)) {
|
||||
throw new \RuntimeException(sprintf("%s module already exists", $this->module));
|
||||
}
|
||||
}
|
||||
protected function verifyExistingModule()
|
||||
{
|
||||
if (file_exists($this->moduleDirectory)) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"%s module already exists. Use --force option to force generation.",
|
||||
$this->module
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatModuleName($name)
|
||||
{
|
||||
if (in_array(strtolower($name), $this->reservedKeyWords)) {
|
||||
throw new \RuntimeException(sprintf("%s module name is a reserved keyword", $name));
|
||||
}
|
||||
protected function formatModuleName($name)
|
||||
{
|
||||
if (in_array(strtolower($name), $this->reservedKeyWords)) {
|
||||
throw new \RuntimeException(sprintf("%s module name is a reserved keyword", $name));
|
||||
}
|
||||
|
||||
return ucfirst($name);
|
||||
}
|
||||
return ucfirst($name);
|
||||
}
|
||||
|
||||
protected function validModuleName($name)
|
||||
{
|
||||
if (!preg_match('#^[A-Z]([A-Za-z\d])+$#', $name)) {
|
||||
throw new \RuntimeException(
|
||||
sprintf("%s module name is not a valid name, it must be in CamelCase. (ex: MyModuleName)", $name)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,18 +15,17 @@ namespace Thelia\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
/**
|
||||
* clear the cache
|
||||
*
|
||||
* Class CacheClear
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*
|
||||
*/
|
||||
class CacheClear extends ContainerAwareCommand
|
||||
@@ -46,26 +45,46 @@ class CacheClear extends ContainerAwareCommand
|
||||
'with-images',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'clear images generated in web/cache directory'
|
||||
'clear images generated in `image_cache_dir_from_web_root` or web/cache/images directory'
|
||||
)
|
||||
->addOption(
|
||||
'with-documents',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'clear documents generated in `document_cache_dir_from_web_root` or web/cache/documents directory'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
||||
$cacheDir = $this->getContainer()->getParameter("kernel.cache_dir");
|
||||
|
||||
$this->clearCache($cacheDir, $output);
|
||||
|
||||
if (!$input->getOption("without-assets")) {
|
||||
$this->clearCache(THELIA_WEB_DIR . "assets", $output);
|
||||
if (!$input->getOption('without-assets')) {
|
||||
$this->clearCache(THELIA_WEB_DIR . ConfigQuery::read('asset_dir_from_web_root', 'assets'), $output);
|
||||
}
|
||||
|
||||
if ($input->getOption('with-images')) {
|
||||
$this->clearCache(THELIA_CACHE_DIR, $output);
|
||||
$this->clearCache(
|
||||
THELIA_WEB_DIR . ConfigQuery::read(
|
||||
'image_cache_dir_from_web_root',
|
||||
'cache' . DS . 'images'
|
||||
),
|
||||
$output
|
||||
);
|
||||
}
|
||||
|
||||
if ($input->getOption('with-documents')) {
|
||||
$this->clearCache(
|
||||
THELIA_WEB_DIR . ConfigQuery::read(
|
||||
'document_cache_dir_from_web_root',
|
||||
'cache' . DS . 'documents'
|
||||
),
|
||||
$output
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function clearCache($dir, OutputInterface $output)
|
||||
@@ -74,10 +93,7 @@ class CacheClear extends ContainerAwareCommand
|
||||
|
||||
try {
|
||||
$cacheEvent = new CacheEvent($dir);
|
||||
$this->
|
||||
getContainer()
|
||||
->get('event_dispatcher')
|
||||
->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
// throws same exception code for does not exist and permission denied ...
|
||||
if (!file_exists($dir)) {
|
||||
@@ -92,6 +108,5 @@ class CacheClear extends ContainerAwareCommand
|
||||
}
|
||||
|
||||
$output->writeln(sprintf("<info>%s cache directory cleared successfully</info>", $dir));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ class ClearImageCache extends ContainerAwareCommand
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dispatcher = $this->getContainer()->get('event_dispatcher');
|
||||
|
||||
$request = new Request();
|
||||
|
||||
try {
|
||||
@@ -41,13 +39,15 @@ class ClearImageCache extends ContainerAwareCommand
|
||||
|
||||
$subdir = $input->getArgument('subdir');
|
||||
|
||||
if (! is_null($subdir)) $event->setCacheSubdirectory($subdir);
|
||||
if (! is_null($subdir)) {
|
||||
$event->setCacheSubdirectory($subdir);
|
||||
}
|
||||
|
||||
$dispatcher->dispatch(TheliaEvents::IMAGE_CLEAR_CACHE, $event);
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::IMAGE_CLEAR_CACHE, $event);
|
||||
|
||||
$output->writeln(sprintf('%s image cache successfully cleared.', is_null($subdir) ? 'Entire' : ucfirst($subdir)));
|
||||
} catch (\Exception $ex) {
|
||||
$output->writeln(sprintf("Failed to clear image cache: %s", $ex->getMessage()));
|
||||
$output->writeln(sprintf("Failed to clear image cache: %s", $ex->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
225
core/lib/Thelia/Command/ConfigCommand.php
Normal file
225
core/lib/Thelia/Command/ConfigCommand.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/*******************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Model\Config;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
|
||||
/**
|
||||
* command line for managing configuration variables
|
||||
*
|
||||
* php Thelia thelia:config COMMAND [name] [value] [--secured] [--visible]
|
||||
*
|
||||
* Where COMMAND is list, get, set or delete.
|
||||
*
|
||||
* For command get and delete, you should also set the name attribute.
|
||||
*
|
||||
* For command set, you should set the name and value attributes and optionally add
|
||||
* --secured and/or --visible arguments.
|
||||
*
|
||||
* Class ConfigCommand
|
||||
* @package Thelia\Command
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class ConfigCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName("thelia:config")
|
||||
->setDescription("Manage configuration variables")
|
||||
->addArgument(
|
||||
'COMMAND',
|
||||
InputArgument::REQUIRED,
|
||||
'Command : list, get, set, delete'
|
||||
)
|
||||
->addArgument(
|
||||
'name',
|
||||
InputArgument::OPTIONAL,
|
||||
'The variable name'
|
||||
)
|
||||
->addArgument(
|
||||
'value',
|
||||
InputArgument::OPTIONAL,
|
||||
'The variable value'
|
||||
)
|
||||
->addOption(
|
||||
'secured',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'When setting a new variable tell variable is secured.'
|
||||
)
|
||||
->addOption(
|
||||
'visible',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'When setting a new variable tell variable is visible.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$command = $input->getArgument("COMMAND");
|
||||
|
||||
switch ($command) {
|
||||
case "list":
|
||||
$this->listConfig($input, $output);
|
||||
break;
|
||||
|
||||
case "get":
|
||||
$this->getConfig($input, $output);
|
||||
break;
|
||||
|
||||
case "set":
|
||||
$this->setConfig($input, $output);
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
$this->deleteConfig($input, $output);
|
||||
break;
|
||||
|
||||
default:
|
||||
$output->writeln(
|
||||
"<error>Unknown argument 'COMMAND' : list, get, set, delete</error>"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function listConfig(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln([
|
||||
"",
|
||||
"<error>Variables list</error>",
|
||||
""
|
||||
]);
|
||||
|
||||
$vars = ConfigQuery::create()
|
||||
->orderByName()
|
||||
->find()
|
||||
;
|
||||
|
||||
$rows = [];
|
||||
|
||||
/** @var Config $var */
|
||||
foreach ($vars as $var) {
|
||||
$rows[] = [
|
||||
$var->getName(),
|
||||
$var->getValue(),
|
||||
$var->getSecured() !== 0 ? "yes" : "no",
|
||||
$var->getHidden() !== 0 ? "yes" : "no"
|
||||
];
|
||||
}
|
||||
|
||||
$table = new Table($output);
|
||||
$table
|
||||
->setHeaders(['Name', 'Value', 'secured', 'hidden'])
|
||||
->setRows($rows)
|
||||
;
|
||||
$table->render();
|
||||
}
|
||||
|
||||
private function getConfig(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$varName = $input->getArgument("name");
|
||||
|
||||
if (null === $varName) {
|
||||
$output->writeln(
|
||||
"<error>Need argument 'name' for get command</error>"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$var = ConfigQuery::create()->findOneByName($varName);
|
||||
|
||||
$out = [];
|
||||
|
||||
if (null === $var) {
|
||||
$out[] = sprintf(
|
||||
"<error>Unknown variable '%s'</error>",
|
||||
$varName
|
||||
);
|
||||
} else {
|
||||
$out = [
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Name", $var->getName(), "info"),
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Value", $var->getValue(), "info"),
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Secured", $var->getSecured() ? "yes" : "no", "info"),
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Hidden", $var->getHidden() ? "yes" : "no", "info"),
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Title", $var->getTitle(), "info"),
|
||||
sprintf('%12s: <%3$s>%s</%3$s>', "Description", $var->getDescription(), "info"),
|
||||
];
|
||||
}
|
||||
|
||||
$output->writeln($out);
|
||||
}
|
||||
|
||||
|
||||
private function setConfig(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$varName = $input->getArgument("name");
|
||||
$varValue = $input->getArgument("value");
|
||||
|
||||
if (null === $varName || null === $varValue) {
|
||||
$output->writeln(
|
||||
"<error>Need argument 'name' and 'value' for set command</error>"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigQuery::write(
|
||||
$varName,
|
||||
$varValue,
|
||||
$input->getOption("secured"),
|
||||
!$input->getOption("visible")
|
||||
);
|
||||
|
||||
$output->writeln("<info>Variable has been set</info>");
|
||||
}
|
||||
|
||||
private function deleteConfig(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$varName = $input->getArgument("name");
|
||||
|
||||
if (null === $varName) {
|
||||
$output->writeln(
|
||||
"<error>Need argument 'name' for get command</error>"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$var = ConfigQuery::create()->findOneByName($varName);
|
||||
|
||||
if (null === $var) {
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
"<error>Unknown variable '%s'</error>",
|
||||
$varName
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$var->delete();
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
"<info>Variable '%s' has been deleted</info>",
|
||||
$varName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,23 @@ namespace Thelia\Command;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
use Thelia\Core\Application;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\HttpFoundation\Session\Session;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Lang;
|
||||
use Thelia\Model\LangQuery;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
/**
|
||||
* Command.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Gilles Bourgeat <gbourgeat@openstudio.fr>
|
||||
*/
|
||||
class ContainerAwareCommand extends Command implements ContainerAwareInterface
|
||||
{
|
||||
@@ -34,7 +46,9 @@ class ContainerAwareCommand extends Command implements ContainerAwareInterface
|
||||
protected function getContainer()
|
||||
{
|
||||
if (null === $this->container) {
|
||||
$this->container = $this->getApplication()->getKernel()->getContainer();
|
||||
/** @var Application $application */
|
||||
$application = $this->getApplication();
|
||||
$this->container = $application->getKernel()->getContainer();
|
||||
}
|
||||
|
||||
return $this->container;
|
||||
@@ -42,9 +56,78 @@ class ContainerAwareCommand extends Command implements ContainerAwareInterface
|
||||
|
||||
/**
|
||||
* @see ContainerAwareInterface::setContainer()
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\EventDispatcher\EventDispatcher
|
||||
*/
|
||||
public function getDispatcher()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
|
||||
// Initialize Thelia translator, if not already done.
|
||||
try {
|
||||
Translator::getInstance();
|
||||
} catch (\Exception $ex) {
|
||||
$this->container->get('thelia.translator');
|
||||
}
|
||||
|
||||
return $container->get('event_dispatcher');
|
||||
}
|
||||
|
||||
/**
|
||||
* For init an Request, if your command has need an Request
|
||||
* @param Lang|null $lang
|
||||
* @since 2.3
|
||||
*/
|
||||
protected function initRequest(Lang $lang = null)
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
|
||||
$request = Request::create($this->getBaseUrl($lang));
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$container->set("request_stack", new RequestStack());
|
||||
$container->get('request_stack')->push($request);
|
||||
|
||||
$requestContext = new RequestContext();
|
||||
$requestContext->fromRequest($request);
|
||||
$url = $container->get('thelia.url.manager');
|
||||
$url->setRequestContext($requestContext);
|
||||
$this->getContainer()->get('router.admin')->setContext($requestContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Lang|null $lang
|
||||
* @return string
|
||||
* @since 2.3
|
||||
*/
|
||||
protected function getBaseUrl(Lang $lang = null)
|
||||
{
|
||||
$baseUrl = '';
|
||||
|
||||
if ((int) ConfigQuery::read('one_domain_foreach_lang') === 1) {
|
||||
if ($lang === null) {
|
||||
$lang = LangQuery::create()->findOneByByDefault(true);
|
||||
}
|
||||
|
||||
$baseUrl = $lang->getUrl();
|
||||
}
|
||||
|
||||
$baseUrl = trim($baseUrl);
|
||||
|
||||
if (empty($baseUrl)) {
|
||||
$baseUrl = ConfigQuery::read('url_site');
|
||||
}
|
||||
|
||||
if (empty($baseUrl)) {
|
||||
$baseUrl = 'http://localhost';
|
||||
}
|
||||
|
||||
return $baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Thelia\Model\Admin;
|
||||
use Thelia\Model\AdminQuery;
|
||||
|
||||
class CreateAdminUser extends ContainerAwareCommand
|
||||
{
|
||||
@@ -50,6 +52,13 @@ class CreateAdminUser extends ContainerAwareCommand
|
||||
'User last name',
|
||||
null
|
||||
)
|
||||
->addOption(
|
||||
"email",
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'Admin email address',
|
||||
null
|
||||
)
|
||||
->addOption(
|
||||
"locale",
|
||||
null,
|
||||
@@ -65,13 +74,13 @@ class CreateAdminUser extends ContainerAwareCommand
|
||||
null
|
||||
)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln('Please enter the admin user information:');
|
||||
|
||||
/** @var Admin $admin */
|
||||
$admin = $this->getAdminInfo($input, $output);
|
||||
|
||||
$admin->save();
|
||||
@@ -83,22 +92,30 @@ class CreateAdminUser extends ContainerAwareCommand
|
||||
));
|
||||
}
|
||||
|
||||
protected function enterData($dialog, $output, $label, $error_message, $hidden = false)
|
||||
{
|
||||
$command = $hidden ? 'askHiddenResponse' : 'askAndValidate';
|
||||
protected function enterData(
|
||||
QuestionHelper $helper,
|
||||
InputInterface $input,
|
||||
OutputInterface $output,
|
||||
$label,
|
||||
$errorMessage,
|
||||
$hidden = false
|
||||
) {
|
||||
$question = new Question($this->decorateInfo($label));
|
||||
|
||||
return $dialog->$command(
|
||||
$output,
|
||||
$this->decorateInfo($label),
|
||||
function ($answer) {
|
||||
$answer = trim($answer);
|
||||
if (empty($answer)) {
|
||||
throw new \RuntimeException("This information is mandatory.");
|
||||
}
|
||||
if ($hidden) {
|
||||
$question->setHidden(true);
|
||||
$question->setHiddenFallback(false);
|
||||
}
|
||||
|
||||
return $answer;
|
||||
$question->setValidator(function ($value) use (&$errorMessage) {
|
||||
if (trim($value) == '') {
|
||||
throw new \Exception($errorMessage);
|
||||
}
|
||||
);
|
||||
|
||||
return $value;
|
||||
});
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,21 +127,23 @@ class CreateAdminUser extends ContainerAwareCommand
|
||||
*/
|
||||
protected function getAdminInfo(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
$admin = new Admin();
|
||||
|
||||
$admin->setLogin($input->getOption("login_name") ?: $this->enterData($dialog, $output, "Admin login name : ", "Please enter a login name."));
|
||||
$admin->setFirstname($input->getOption("first_name") ?: $this->enterData($dialog, $output, "User first name : ", "Please enter user first name."));
|
||||
$admin->setLastname($input->getOption("last_name") ?: $this->enterData($dialog, $output, "User last name : ", "Please enter user last name."));
|
||||
$admin->setLogin($input->getOption("login_name") ?: $this->enterLogin($helper, $input, $output));
|
||||
$admin->setFirstname($input->getOption("first_name") ?: $this->enterData($helper, $input, $output, "User first name : ", "Please enter user first name."));
|
||||
$admin->setLastname($input->getOption("last_name") ?: $this->enterData($helper, $input, $output, "User last name : ", "Please enter user last name."));
|
||||
|
||||
$admin->setLocale($input->getOption("locale") ?: 'en_US');
|
||||
$admin->setEmail($input->getOption("email") ?: $this->enterEmail($helper, $input, $output));
|
||||
|
||||
do {
|
||||
$password = $input->getOption("password") ?: $this->enterData($dialog, $output, "Password : ", "Please enter a password.", true);
|
||||
$password_again = $input->getOption("password") ?: $this->enterData($dialog, $output, "Password (again): ", "Please enter the password again.", true);
|
||||
$password = $input->getOption("password") ?: $this->enterData($helper, $input, $output, "Password : ", "Please enter a password.", true);
|
||||
$password_again = $input->getOption("password") ?: $this->enterData($helper, $input, $output, "Password (again): ", "Please enter the password again.", true);
|
||||
|
||||
if (! empty($password) && $password == $password_again) {
|
||||
|
||||
$admin->setPassword($password);
|
||||
|
||||
break;
|
||||
@@ -143,4 +162,44 @@ class CreateAdminUser extends ContainerAwareCommand
|
||||
return sprintf("<info>%s</info>", $text);
|
||||
}
|
||||
|
||||
|
||||
protected function enterLogin(QuestionHelper $helper, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$question = new Question($this->decorateInfo("Admin login name : "));
|
||||
|
||||
$question->setValidator(function ($answer) {
|
||||
$answer = trim($answer);
|
||||
if (empty($answer)) {
|
||||
throw new \RuntimeException("Please enter a login name.");
|
||||
}
|
||||
|
||||
if (AdminQuery::create()->findOneByLogin($answer)) {
|
||||
throw new \RuntimeException("An administrator with this login already exists.");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
});
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
protected function enterEmail(QuestionHelper $helper, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$question = new Question($this->decorateInfo("Admin email or empty value : "));
|
||||
|
||||
$question->setValidator(function ($answer) {
|
||||
$answer = trim($answer);
|
||||
if (!empty($answer) && !filter_var($answer, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new \RuntimeException("Please enter an email or an empty value.");
|
||||
}
|
||||
|
||||
if (AdminQuery::create()->findOneByEmail($answer)) {
|
||||
throw new \RuntimeException("An administrator with this email already exists.");
|
||||
}
|
||||
|
||||
return !empty($answer) ? $answer : uniqid('CHANGE_ME_');
|
||||
});
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
}
|
||||
|
||||
241
core/lib/Thelia/Command/ExportCommand.php
Normal file
241
core/lib/Thelia/Command/ExportCommand.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Core\Archiver\ArchiverInterface;
|
||||
use Thelia\Core\Archiver\ArchiverManager;
|
||||
use Thelia\Core\DependencyInjection\Compiler\RegisterArchiverPass;
|
||||
use Thelia\Core\DependencyInjection\Compiler\RegisterSerializerPass;
|
||||
use Thelia\Core\Serializer\SerializerInterface;
|
||||
use Thelia\Core\Serializer\SerializerManager;
|
||||
use Thelia\Model\ExportQuery;
|
||||
use Thelia\Model\LangQuery;
|
||||
|
||||
/**
|
||||
* Class ExportCommand
|
||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||
*/
|
||||
class ExportCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('export')
|
||||
->setDescription('Export data')
|
||||
->setHelp('The <info>export</info> command run selected export')
|
||||
->addArgument(
|
||||
'ref',
|
||||
InputArgument::OPTIONAL,
|
||||
'Export reference.'
|
||||
)
|
||||
->addArgument(
|
||||
'serializer',
|
||||
InputArgument::OPTIONAL,
|
||||
'Serializer identifier.'
|
||||
)
|
||||
->addArgument(
|
||||
'archiver',
|
||||
InputArgument::OPTIONAL,
|
||||
'Archiver identifier.'
|
||||
)
|
||||
->addOption(
|
||||
'locale',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Locale for export',
|
||||
'en_US'
|
||||
)
|
||||
->addOption(
|
||||
'list-export',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'List available exports and exit.'
|
||||
)
|
||||
->addOption(
|
||||
'list-serializer',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'List available serializers and exit.'
|
||||
)
|
||||
->addOption(
|
||||
'list-archiver',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'List available archivers and exit.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($input->getOption('list-export')) {
|
||||
$this->listExport($output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->getOption('list-serializer')) {
|
||||
$this->listSerializer($output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->getOption('list-archiver')) {
|
||||
$this->listArchiver($output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$exportRef = $input->getArgument('ref');
|
||||
$serializer = $input->getArgument('serializer');
|
||||
if ($exportRef === null || $serializer === null) {
|
||||
throw new \RuntimeException(
|
||||
'Not enough arguments.' . PHP_EOL . 'If no options are provided, ref and serializer arguments are required.'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var \Thelia\Handler\ExportHandler $exportHandler */
|
||||
$exportHandler = $this->getContainer()->get('thelia.export.handler');
|
||||
|
||||
$export = $exportHandler->getExportByRef($exportRef);
|
||||
if ($export === null) {
|
||||
throw new \RuntimeException(
|
||||
$exportRef . ' export doesn\'t exist.'
|
||||
);
|
||||
}
|
||||
|
||||
$serializerManager = $this->getContainer()->get(RegisterSerializerPass::MANAGER_SERVICE_ID);
|
||||
$serializer = $serializerManager->get($serializer);
|
||||
|
||||
$archiver = null;
|
||||
if ($input->getArgument('archiver')) {
|
||||
/** @var \Thelia\Core\Archiver\ArchiverManager $archiverManager */
|
||||
$archiverManager = $this->getContainer()->get(RegisterArchiverPass::MANAGER_SERVICE_ID);
|
||||
$archiver = $archiverManager->get($input->getArgument('archiver'));
|
||||
}
|
||||
|
||||
$exportEvent = $exportHandler->export(
|
||||
$export,
|
||||
$serializer,
|
||||
$archiver,
|
||||
(new LangQuery)->findOneByLocale($input->getOption('locale'))
|
||||
);
|
||||
|
||||
$formattedLine = $this->getHelper('formatter')->formatBlock(
|
||||
'Export finish',
|
||||
'fg=black;bg=green',
|
||||
true
|
||||
);
|
||||
$output->writeln($formattedLine);
|
||||
$output->writeln('<info>Export available at path:</info>');
|
||||
$output->writeln('<comment>' . $exportEvent->getFilePath() . '</comment>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Output available exports
|
||||
*
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output An output interface
|
||||
*/
|
||||
protected function listExport(OutputInterface $output)
|
||||
{
|
||||
$table = new Table($output);
|
||||
|
||||
foreach ((new ExportQuery)->find() as $export) {
|
||||
$table->addRow([
|
||||
$export->getRef(),
|
||||
$export->getTitle(),
|
||||
$export->getDescription()
|
||||
]);
|
||||
}
|
||||
|
||||
$table
|
||||
->setHeaders([
|
||||
'Reference',
|
||||
'Title',
|
||||
'Description'
|
||||
])
|
||||
->render()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output available serializers
|
||||
*
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output An output interface
|
||||
*/
|
||||
protected function listSerializer(OutputInterface $output)
|
||||
{
|
||||
$table = new Table($output);
|
||||
|
||||
/** @var SerializerManager $serializerManager */
|
||||
$serializerManager = $this->getContainer()->get(RegisterSerializerPass::MANAGER_SERVICE_ID);
|
||||
|
||||
/** @var SerializerInterface $serializer */
|
||||
foreach ($serializerManager->getSerializers() as $serializer) {
|
||||
$table->addRow([
|
||||
$serializer->getId(),
|
||||
$serializer->getName(),
|
||||
$serializer->getExtension(),
|
||||
$serializer->getMimeType()
|
||||
]);
|
||||
}
|
||||
|
||||
$table
|
||||
->setHeaders([
|
||||
'Id',
|
||||
'Name',
|
||||
'Extension',
|
||||
'MIME type'
|
||||
])
|
||||
->render()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output available archivers
|
||||
*
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output An output interface
|
||||
*/
|
||||
protected function listArchiver(OutputInterface $output)
|
||||
{
|
||||
$table = new Table($output);
|
||||
|
||||
/** @var ArchiverManager $archiverManager */
|
||||
$archiverManager = $this->getContainer()->get(RegisterArchiverPass::MANAGER_SERVICE_ID);
|
||||
|
||||
/** @var ArchiverInterface $archiver */
|
||||
foreach ($archiverManager->getArchivers(true) as $archiver) {
|
||||
$table->addRow([
|
||||
$archiver->getId(),
|
||||
$archiver->getName(),
|
||||
$archiver->getExtension(),
|
||||
$archiver->getMimeType()
|
||||
]);
|
||||
}
|
||||
|
||||
$table
|
||||
->setHeaders([
|
||||
'Id',
|
||||
'Name',
|
||||
'Extension',
|
||||
'MIME type'
|
||||
])
|
||||
->render()
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,7 @@ namespace Thelia\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Thelia\Core\Security\Resource\AdminResources;
|
||||
|
||||
use Thelia\Model\Map\ResourceI18nTableMap;
|
||||
use Thelia\Model\Map\ResourceTableMap;
|
||||
|
||||
@@ -40,7 +38,6 @@ class GenerateResources extends ContainerAwareCommand
|
||||
null
|
||||
)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
@@ -65,7 +62,7 @@ class GenerateResources extends ContainerAwareCommand
|
||||
}
|
||||
$compteur++;
|
||||
$output->writeln(
|
||||
"($compteur, '$value', NOW(), NOW())" . ($constant === key( array_slice( $constants, -1, 1, true ) ) ? ';' : ',')
|
||||
"($compteur, '$value', NOW(), NOW())" . ($constant === key(array_slice($constants, -1, 1, true)) ? ';' : ',')
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -81,17 +78,17 @@ class GenerateResources extends ContainerAwareCommand
|
||||
|
||||
$compteur++;
|
||||
|
||||
$title = ucwords( str_replace('.', ' / ', str_replace('admin.', '', $value) ) );
|
||||
$title = ucwords(str_replace('.', ' / ', str_replace('admin.', '', $value)));
|
||||
|
||||
$output->writeln(
|
||||
"($compteur, 'en_US', '$title'),"
|
||||
);
|
||||
$output->writeln(
|
||||
"($compteur, 'fr_FR', '$title')" . ($constant === key( array_slice( $constants, -1, 1, true ) ) ? ';' : ',')
|
||||
"($compteur, 'fr_FR', '$title')" . ($constant === key(array_slice($constants, -1, 1, true)) ? ';' : ',')
|
||||
);
|
||||
}
|
||||
break;
|
||||
default :
|
||||
default:
|
||||
foreach ($constants as $constant => $value) {
|
||||
if ($constant == AdminResources::SUPERADMINISTRATOR) {
|
||||
continue;
|
||||
@@ -101,5 +98,4 @@ class GenerateResources extends ContainerAwareCommand
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
221
core/lib/Thelia/Command/GenerateSQLCommand.php
Normal file
221
core/lib/Thelia/Command/GenerateSQLCommand.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Imagine\Exception\RuntimeException;
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Model\CustomerQuery;
|
||||
use Thelia\Model\Map\ProductTableMap;
|
||||
use Thelia\Tools\URL;
|
||||
use Thelia\Tools\Version\Version;
|
||||
use TheliaSmarty\Template\SmartyParser;
|
||||
|
||||
/**
|
||||
* Class GenerateSQLCommand
|
||||
* @package Thelia\Command
|
||||
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
|
||||
*/
|
||||
class GenerateSQLCommand extends ContainerAwareCommand
|
||||
{
|
||||
/** @var Translator $translator */
|
||||
protected $translator = null;
|
||||
|
||||
/** @var SmartyParser $parser */
|
||||
protected $parser = null;
|
||||
|
||||
/** @var \PDO */
|
||||
protected $con;
|
||||
|
||||
/** @var array */
|
||||
protected $locales;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName("generate:sql")
|
||||
->setDescription("Generate SQL files (insert.sql, update*.sql)")
|
||||
->addOption(
|
||||
"locales",
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"generate only for only specific locales (separated by a ,) : fr_FR,es_ES or es_ES"
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->init($input);
|
||||
|
||||
// Main insert.sql file
|
||||
$content = file_get_contents(THELIA_SETUP_DIRECTORY . 'insert.sql.tpl');
|
||||
$version = Version::parse();
|
||||
$content = $this->parser->renderString($content, $version, false);
|
||||
|
||||
if (false === file_put_contents(THELIA_SETUP_DIRECTORY . 'insert.sql', $content)) {
|
||||
$output->writeln("Can't write file " . THELIA_SETUP_DIRECTORY . 'insert.sql');
|
||||
} else {
|
||||
$output->writeln("File " . THELIA_SETUP_DIRECTORY . 'insert.sql generated successfully.');
|
||||
}
|
||||
|
||||
// sql update files
|
||||
$finder = Finder::create()
|
||||
->name('*.tpl')
|
||||
->depth(0)
|
||||
->in(THELIA_SETUP_DIRECTORY . 'update' . DS . 'tpl');
|
||||
|
||||
/** @var \SplFileInfo $file */
|
||||
foreach ($finder as $file) {
|
||||
$content = file_get_contents($file->getRealPath());
|
||||
$content = $this->parser->renderString($content, [], false);
|
||||
|
||||
$destination = THELIA_SETUP_DIRECTORY . 'update' . DS . 'sql' . DS . $file->getBasename('.tpl');
|
||||
|
||||
if (false === file_put_contents($destination, $content)) {
|
||||
$output->writeln("Can't write file " . $destination);
|
||||
} else {
|
||||
$output->writeln("File " . $destination . ' generated successfully.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function init(InputInterface $input)
|
||||
{
|
||||
$this->initRequest();
|
||||
|
||||
$container = $this->getContainer();
|
||||
|
||||
$this->translator = $container->get('thelia.translator');
|
||||
$this->parser = $container->get('thelia.parser');
|
||||
|
||||
$this->con = Propel::getConnection(ProductTableMap::DATABASE_NAME);
|
||||
|
||||
$this->initLocales($input);
|
||||
|
||||
$this->initParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @return array
|
||||
*/
|
||||
protected function initLocales(InputInterface $input)
|
||||
{
|
||||
$this->locales = [];
|
||||
$availableLocales = [];
|
||||
|
||||
$finder = Finder::create()
|
||||
->name('*.php')
|
||||
->depth(0)
|
||||
->sortByName()
|
||||
->in(THELIA_SETUP_DIRECTORY . 'I18n');
|
||||
|
||||
// limit to only some locale(s)
|
||||
$localesToKeep = $input->getOption("locales");
|
||||
if (!empty($localesToKeep)) {
|
||||
$localesToKeep = explode(',', $localesToKeep);
|
||||
} else {
|
||||
$localesToKeep = null;
|
||||
}
|
||||
|
||||
/** @var \SplFileInfo $file */
|
||||
foreach ($finder as $file) {
|
||||
$locale = $file->getBasename('.php');
|
||||
$availableLocales[] = $locale;
|
||||
|
||||
if (empty($localesToKeep) || in_array($locale, $localesToKeep)) {
|
||||
$this->locales[] = $locale;
|
||||
$this->translator->addResource(
|
||||
'php',
|
||||
$file->getRealPath(),
|
||||
$locale,
|
||||
'install'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->locales)) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"You should at least generate sql for one locale. Available locales : %s",
|
||||
implode(', ', $availableLocales)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the smarty parser.
|
||||
*
|
||||
* The intl function is replaced, and locales are assigned.
|
||||
*
|
||||
* @throws \SmartyException
|
||||
*/
|
||||
protected function initParser()
|
||||
{
|
||||
$this->parser->unregisterPlugin('function', 'intl');
|
||||
$this->parser->registerPlugin('function', 'intl', [$this, 'translate']);
|
||||
$this->parser->assign("locales", $this->locales);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smarty function that replace the classic `intl` function.
|
||||
*
|
||||
* The attributes of the function are:
|
||||
* - `l`: the key
|
||||
* - `locale`: the locale. eg.: fr_FR
|
||||
* - `in_string`: set to 1 not add simple quote around the string. (default = 0)
|
||||
* - `use_default`: set to 1 to use the `l` string as a fallback. (default = 0)
|
||||
*
|
||||
* @param $params
|
||||
* @param $smarty
|
||||
* @return string
|
||||
*/
|
||||
public function translate($params, $smarty)
|
||||
{
|
||||
$translation = '';
|
||||
|
||||
if (empty($params["l"])) {
|
||||
throw new RuntimeException('Translation Error. Key is empty.');
|
||||
} elseif (empty($params["locale"])) {
|
||||
throw new RuntimeException('Translation Error. Locale is empty.');
|
||||
} else {
|
||||
$inString = (0 !== intval($params["in_string"]));
|
||||
$useDefault = (0 !== intval($params["use_default"]));
|
||||
|
||||
$translation = $this->translator->trans(
|
||||
$params["l"],
|
||||
[],
|
||||
'install',
|
||||
$params["locale"],
|
||||
$useDefault
|
||||
);
|
||||
|
||||
if (empty($translation)) {
|
||||
$translation = ($inString) ? '' : "NULL";
|
||||
} else {
|
||||
$translation = $this->con->quote($translation);
|
||||
// remove quote
|
||||
if ($inString) {
|
||||
$translation = substr($translation, 1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $translation;
|
||||
}
|
||||
}
|
||||
157
core/lib/Thelia/Command/HookCleanCommand.php
Normal file
157
core/lib/Thelia/Command/HookCleanCommand.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Thelia\Core\Event\Cache\CacheEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\IgnoredModuleHookQuery;
|
||||
use Thelia\Model\Module;
|
||||
use Thelia\Model\ModuleHookQuery;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
|
||||
/**
|
||||
* Clean hook
|
||||
*
|
||||
* Class HookCleanCommand
|
||||
* @package Thelia\Command
|
||||
*
|
||||
* @author Julien Chanséaume <julien@thelia.net>
|
||||
*
|
||||
*/
|
||||
class HookCleanCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName("hook:clean")
|
||||
->setDescription("Clean hooks. It will delete all hooks, then recreate it.")
|
||||
->addOption(
|
||||
"assume-yes",
|
||||
'y',
|
||||
InputOption::VALUE_NONE,
|
||||
'Assume to answer yes to all questions'
|
||||
)
|
||||
->addArgument(
|
||||
"module",
|
||||
InputArgument::OPTIONAL,
|
||||
"The module code to clean up"
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$module = $this->getModule($input);
|
||||
|
||||
if (!$this->askConfirmation($input, $output)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->deleteHooks($module);
|
||||
|
||||
$output->writeln("<info>Hooks have been successfully deleted</info>");
|
||||
|
||||
$this->clearCache($output);
|
||||
} catch (\Exception $ex) {
|
||||
$output->writeln(sprintf("<error>%s</error>", $ex->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private function getModule(InputInterface $input)
|
||||
{
|
||||
$module = null;
|
||||
$moduleCode = $input->getArgument("module");
|
||||
|
||||
if (!empty($moduleCode)) {
|
||||
if (null === $module = ModuleQuery::create()->findOneByCode($moduleCode)) {
|
||||
throw new \RuntimeException(sprintf("Module %s does not exist.", $moduleCode));
|
||||
}
|
||||
}
|
||||
|
||||
return $module;
|
||||
}
|
||||
|
||||
private function askConfirmation(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$assumeYes = $input->getOption("assume-yes");
|
||||
$moduleCode = $input->getArgument("module");
|
||||
|
||||
if (!$assumeYes) {
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
$questionText = "Would you like to delete all hooks ";
|
||||
$questionText .= (empty($moduleCode))
|
||||
? "of all modules"
|
||||
: "of module " . $moduleCode;
|
||||
$questionText .= " ? (yes, or no) ";
|
||||
|
||||
$question = new ConfirmationQuestion($questionText, false);
|
||||
|
||||
if (!$helper->ask($input, $output, $question)) {
|
||||
$output->writeln("<info>No hooks deleted</info>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete module hooks
|
||||
*
|
||||
* @param Module|null $module if specified it will only delete hooks related to this module.
|
||||
* @throws \Exception
|
||||
* @throws \Propel\Runtime\Exception\PropelException
|
||||
*/
|
||||
protected function deleteHooks($module)
|
||||
{
|
||||
$query = ModuleHookQuery::create();
|
||||
if (null !== $module) {
|
||||
$query
|
||||
->filterByModule($module)
|
||||
->delete();
|
||||
} else {
|
||||
$query->deleteAll();
|
||||
}
|
||||
|
||||
$query = IgnoredModuleHookQuery::create();
|
||||
if (null !== $module) {
|
||||
$query
|
||||
->filterByModule($module)
|
||||
->delete();
|
||||
} else {
|
||||
$query->deleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function clearCache(OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$cacheDir = $this->getContainer()->getParameter("kernel.cache_dir");
|
||||
$cacheEvent = new CacheEvent($cacheDir);
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::CACHE_CLEAR, $cacheEvent);
|
||||
} catch (\Exception $ex) {
|
||||
throw new \Exception(sprintf("Error during clearing of cache : %s", $ex->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
141
core/lib/Thelia/Command/ImportCommand.php
Normal file
141
core/lib/Thelia/Command/ImportCommand.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Thelia\Model\ImportQuery;
|
||||
use Thelia\Model\LangQuery;
|
||||
|
||||
/**
|
||||
* Class ImportCommand
|
||||
* @author Jérôme Billiras <jbilliras@openstudio.fr>
|
||||
*/
|
||||
class ImportCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('import')
|
||||
->setDescription('Import data')
|
||||
->setHelp('The <info>import</info> command run selected import')
|
||||
->addArgument(
|
||||
'ref',
|
||||
InputArgument::OPTIONAL,
|
||||
'Import reference.'
|
||||
)
|
||||
->addArgument(
|
||||
'filePath',
|
||||
InputArgument::OPTIONAL,
|
||||
'File path to import'
|
||||
)
|
||||
->addOption(
|
||||
'locale',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Locale for export',
|
||||
'en_US'
|
||||
)
|
||||
->addOption(
|
||||
'list',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'List available imports and exit.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($input->getOption('list')) {
|
||||
$this->listImport($output);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$importRef = $input->getArgument('ref');
|
||||
$path = $input->getArgument('filePath');
|
||||
if ($importRef === null || $path === null) {
|
||||
throw new \RuntimeException(
|
||||
'Not enough arguments.' . PHP_EOL . 'If no options are provided, ref and filePath arguments are required.'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var \Thelia\Handler\ImportHandler $importHandler */
|
||||
$importHandler = $this->getContainer()->get('thelia.import.handler');
|
||||
|
||||
$import = $importHandler->getImportByRef($importRef);
|
||||
if ($import === null) {
|
||||
throw new \RuntimeException(
|
||||
$importRef . ' import doesn\'t exist.'
|
||||
);
|
||||
}
|
||||
|
||||
$importEvent = $importHandler->import(
|
||||
$import,
|
||||
new File($input->getArgument('filePath')),
|
||||
(new LangQuery)->findOneByLocale($input->getOption('locale'))
|
||||
);
|
||||
|
||||
$formattedLine = $this->getHelper('formatter')->formatBlock(
|
||||
'Successfully import ' . $importEvent->getImport()->getImportedRows() . ' row(s)',
|
||||
'fg=black;bg=green',
|
||||
true
|
||||
);
|
||||
$output->writeln($formattedLine);
|
||||
|
||||
if (count($importEvent->getErrors()) > 0) {
|
||||
$formattedLine = $this->getHelper('formatter')->formatBlock(
|
||||
'With error',
|
||||
'fg=black;bg=yellow',
|
||||
true
|
||||
);
|
||||
$output->writeln($formattedLine);
|
||||
|
||||
foreach ($importEvent->getErrors() as $error) {
|
||||
$output->writeln('<comment>' . $error . '</comment>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output available imports
|
||||
*
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output An output interface
|
||||
*/
|
||||
protected function listImport(OutputInterface $output)
|
||||
{
|
||||
$table = new Table($output);
|
||||
|
||||
foreach ((new ImportQuery)->find() as $import) {
|
||||
$table->addRow([
|
||||
$import->getRef(),
|
||||
$import->getTitle(),
|
||||
$import->getDescription()
|
||||
]);
|
||||
}
|
||||
|
||||
$table
|
||||
->setHeaders([
|
||||
'Reference',
|
||||
'Title',
|
||||
'Description'
|
||||
])
|
||||
->render()
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -12,20 +12,23 @@
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use Thelia\Install\CheckPermission;
|
||||
use Thelia\Install\Database;
|
||||
use Thelia\Tools\TokenProvider;
|
||||
|
||||
/**
|
||||
* try to install a new instance of Thelia
|
||||
*
|
||||
* Class Install
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class Install extends ContainerAwareCommand
|
||||
{
|
||||
@@ -42,7 +45,8 @@ class Install extends ContainerAwareCommand
|
||||
"db_host",
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"host for your database"
|
||||
"host for your database",
|
||||
"localhost"
|
||||
)
|
||||
->addOption(
|
||||
"db_username",
|
||||
@@ -62,8 +66,14 @@ class Install extends ContainerAwareCommand
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"database name"
|
||||
)
|
||||
->addOption(
|
||||
"db_port",
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"database port",
|
||||
"3306"
|
||||
)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
@@ -84,11 +94,12 @@ class Install extends ContainerAwareCommand
|
||||
"host" => $input->getOption("db_host"),
|
||||
"dbName" => $input->getOption("db_name"),
|
||||
"username" => $input->getOption("db_username"),
|
||||
"password" => $input->getOption("db_password")
|
||||
"password" => $input->getOption("db_password"),
|
||||
"port" => $input->getOption("db_port")
|
||||
);
|
||||
|
||||
while (false === $connection = $this->tryConnection($connectionInfo, $output)) {
|
||||
$connectionInfo = $this->getConnectionInfo($input, $output);
|
||||
$connectionInfo = $this->getConnectionInfo($input, $output);
|
||||
}
|
||||
|
||||
$database = new Database($connection);
|
||||
@@ -101,6 +112,7 @@ class Install extends ContainerAwareCommand
|
||||
""
|
||||
));
|
||||
$database->insertSql($connectionInfo["dbName"]);
|
||||
$this->manageSecret($database);
|
||||
|
||||
$output->writeln(array(
|
||||
"",
|
||||
@@ -118,6 +130,13 @@ class Install extends ContainerAwareCommand
|
||||
));
|
||||
}
|
||||
|
||||
protected function manageSecret(Database $database)
|
||||
{
|
||||
$secret = TokenProvider::generateToken();
|
||||
$sql = "UPDATE `config` SET `value`=? WHERE `name`='form.secret'";
|
||||
$database->execute($sql, [$secret]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if needed directories have write permission
|
||||
*
|
||||
@@ -129,26 +148,32 @@ class Install extends ContainerAwareCommand
|
||||
"Checking some permissions"
|
||||
));
|
||||
|
||||
$permissions = new CheckPermission(false, $this->getContainer()->get('thelia.translator'));
|
||||
/** @var Translator $translator */
|
||||
$translator = $this->getContainer()->get('thelia.translator');
|
||||
|
||||
$permissions = new CheckPermission(false, $translator);
|
||||
$isValid = $permissions->exec();
|
||||
|
||||
foreach ($permissions->getValidationMessages() as $item => $data) {
|
||||
if ($data['status']) {
|
||||
$output->writeln(array(
|
||||
sprintf("<info>%s ...</info> %s",
|
||||
$data['text'],
|
||||
"<info>Ok</info>")
|
||||
$output->writeln(
|
||||
array(
|
||||
sprintf(
|
||||
"<info>%s ...</info> %s",
|
||||
$data['text'],
|
||||
"<info>Ok</info>"
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$output->writeln(array(
|
||||
sprintf("<error>%s </error>%s",
|
||||
sprintf(
|
||||
"<error>%s </error>%s",
|
||||
$data['text'],
|
||||
sprintf("<error>%s</error>", $data["hint"])
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (false === $isValid) {
|
||||
@@ -177,14 +202,13 @@ class Install extends ContainerAwareCommand
|
||||
$configContent = str_replace("%PASSWORD%", $connectionInfo["password"], $configContent);
|
||||
$configContent = str_replace(
|
||||
"%DSN%",
|
||||
sprintf("mysql:host=%s;dbname=%s", $connectionInfo["host"], $connectionInfo["dbName"]),
|
||||
sprintf("mysql:host=%s;dbname=%s;port=%s", $connectionInfo["host"], $connectionInfo["dbName"], $connectionInfo['port']),
|
||||
$configContent
|
||||
);
|
||||
|
||||
file_put_contents($configFile, $configContent);
|
||||
|
||||
$fs->remove($this->getContainer()->getParameter("kernel.cache_dir"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,16 +220,15 @@ class Install extends ContainerAwareCommand
|
||||
*/
|
||||
protected function tryConnection($connectionInfo, OutputInterface $output)
|
||||
{
|
||||
|
||||
if (is_null($connectionInfo["dbName"])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dsn = "mysql:host=%s";
|
||||
$dsn = "mysql:host=%s;port=%s";
|
||||
|
||||
try {
|
||||
$connection = new \PDO(
|
||||
sprintf($dsn, $connectionInfo["host"]),
|
||||
sprintf($dsn, $connectionInfo["host"], $connectionInfo["port"]),
|
||||
$connectionInfo["username"],
|
||||
$connectionInfo["password"]
|
||||
);
|
||||
@@ -230,62 +253,93 @@ class Install extends ContainerAwareCommand
|
||||
*/
|
||||
protected function getConnectionInfo(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
$connectionInfo = array();
|
||||
|
||||
$connectionInfo["host"] = $dialog->askAndValidate(
|
||||
$connectionInfo['host'] = $this->enterData(
|
||||
$helper,
|
||||
$input,
|
||||
$output,
|
||||
$this->decorateInfo("Database host : "),
|
||||
function ($answer) {
|
||||
$answer = trim($answer);
|
||||
if (is_null($answer)) {
|
||||
throw new \RuntimeException("You must specify a database host");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
"Database host [default: localhost] : ",
|
||||
"You must specify a database host",
|
||||
false,
|
||||
"localhost"
|
||||
);
|
||||
|
||||
$connectionInfo["dbName"] = $dialog->askAndValidate(
|
||||
$connectionInfo['port'] = $this->enterData(
|
||||
$helper,
|
||||
$input,
|
||||
$output,
|
||||
$this->decorateInfo("Database name (if database does not exist, Thelia will try to create it) : "),
|
||||
function ($answer) {
|
||||
$answer = trim($answer);
|
||||
|
||||
if (is_null($answer)) {
|
||||
throw new \RuntimeException("You must specify a database name");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
"Database port [default: 3306] : ",
|
||||
"You must specify a database port",
|
||||
false,
|
||||
"3306"
|
||||
);
|
||||
|
||||
$connectionInfo["username"] = $dialog->askAndValidate(
|
||||
$connectionInfo['dbName'] = $this->enterData(
|
||||
$helper,
|
||||
$input,
|
||||
$output,
|
||||
$this->decorateInfo("Database username : "),
|
||||
function ($answer) {
|
||||
$answer = trim($answer);
|
||||
|
||||
if (is_null($answer)) {
|
||||
throw new \RuntimeException("You must specify a database username");
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
"Database name (if database does not exist, Thelia will try to create it) : ",
|
||||
"You must specify a database name"
|
||||
);
|
||||
|
||||
$connectionInfo["password"] = $dialog->askHiddenResponse(
|
||||
$connectionInfo['username'] = $this->enterData(
|
||||
$helper,
|
||||
$input,
|
||||
$output,
|
||||
$this->decorateInfo("Database password : ")
|
||||
"Database username : ",
|
||||
"You must specify a database username"
|
||||
);
|
||||
|
||||
$connectionInfo['password'] = $this->enterData(
|
||||
$helper,
|
||||
$input,
|
||||
$output,
|
||||
"Database password : ",
|
||||
"You must specify a database username",
|
||||
true,
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
return $connectionInfo;
|
||||
}
|
||||
|
||||
protected function enterData(
|
||||
QuestionHelper $helper,
|
||||
InputInterface $input,
|
||||
OutputInterface $output,
|
||||
$label,
|
||||
$errorMessage,
|
||||
$hidden = false,
|
||||
$defaultValue = null,
|
||||
$beEmpty = false
|
||||
) {
|
||||
$question = new Question($label, $defaultValue);
|
||||
|
||||
if ($hidden) {
|
||||
$question->setHidden(true);
|
||||
$question->setHiddenFallback(false);
|
||||
}
|
||||
|
||||
$question->setValidator(function ($value) use (&$errorMessage, &$beEmpty) {
|
||||
if (trim($value) == '') {
|
||||
if (is_null($value) && !$beEmpty) {
|
||||
throw new \Exception($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
});
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
protected function decorateInfo($text)
|
||||
{
|
||||
return sprintf("<info>%s</info>", $text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@ namespace Thelia\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
/**
|
||||
* activates a module
|
||||
@@ -33,12 +36,17 @@ class ModuleActivateCommand extends BaseModuleGenerate
|
||||
$this
|
||||
->setName("module:activate")
|
||||
->setDescription("Activates a module")
|
||||
->addOption(
|
||||
"with-dependencies",
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'activate module recursively'
|
||||
)
|
||||
->addArgument(
|
||||
"module" ,
|
||||
"module",
|
||||
InputArgument::REQUIRED,
|
||||
"module to activate"
|
||||
)
|
||||
;
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
@@ -51,12 +59,26 @@ class ModuleActivateCommand extends BaseModuleGenerate
|
||||
throw new \RuntimeException(sprintf("module %s not found", $moduleCode));
|
||||
}
|
||||
|
||||
try {
|
||||
$moduleInstance = $module->createInstance();
|
||||
if ($module->getActivate() == BaseModule::IS_ACTIVATED) {
|
||||
throw new \RuntimeException(sprintf("module %s is already actived", $moduleCode));
|
||||
}
|
||||
|
||||
$moduleInstance->activate();
|
||||
|
||||
try {
|
||||
$event = new ModuleToggleActivationEvent($module->getId());
|
||||
if ($input->getOption("with-dependencies")) {
|
||||
$event->setRecursive(true);
|
||||
}
|
||||
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf("Activation fail with Exception : [%d] %s", $e->getCode(), $e->getMessage()));
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"Activation fail with Exception : [%d] %s",
|
||||
$e->getCode(),
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//impossible to change output class in CommandTester...
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Thelia\Action\Module;
|
||||
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
/**
|
||||
* Deactivates a module
|
||||
@@ -33,11 +39,23 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
||||
$this
|
||||
->setName("module:deactivate")
|
||||
->setDescription("Deactivate a module")
|
||||
->addOption(
|
||||
"with-dependencies",
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'activate module recursively'
|
||||
)
|
||||
->addArgument(
|
||||
"module" ,
|
||||
"module",
|
||||
InputArgument::REQUIRED,
|
||||
"module to deactivate"
|
||||
)
|
||||
->addOption(
|
||||
"assume-yes",
|
||||
'y',
|
||||
InputOption::VALUE_NONE,
|
||||
'Assume to deactivate a mandatory module'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -51,10 +69,26 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
||||
throw new \RuntimeException(sprintf("module %s not found", $moduleCode));
|
||||
}
|
||||
|
||||
try {
|
||||
$moduleInstance = $module->createInstance();
|
||||
if ($module->getActivate() == BaseModule::IS_NOT_ACTIVATED) {
|
||||
throw new \RuntimeException(sprintf("module %s is already deactivated", $moduleCode));
|
||||
}
|
||||
|
||||
$moduleInstance->deActivate();
|
||||
|
||||
try {
|
||||
$event = new ModuleToggleActivationEvent($module->getId());
|
||||
|
||||
$module = ModuleQuery::create()->findPk($module->getId());
|
||||
if ($module->getMandatory() == BaseModule::IS_MANDATORY) {
|
||||
if (!$this->askConfirmation($input, $output)) {
|
||||
return;
|
||||
}
|
||||
$event->setAssumeDeactivate(true);
|
||||
}
|
||||
|
||||
if ($input->getOption("with-dependencies")) {
|
||||
$event->setRecursive(true);
|
||||
}
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf("Deactivation fail with Exception : [%d] %s", $e->getCode(), $e->getMessage()));
|
||||
}
|
||||
@@ -68,4 +102,33 @@ class ModuleDeactivateCommand extends BaseModuleGenerate
|
||||
), "bg=green;fg=black");
|
||||
}
|
||||
}
|
||||
|
||||
private function askConfirmation(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$assumeYes = $input->getOption("assume-yes");
|
||||
$moduleCode = $input->getArgument("module");
|
||||
|
||||
if (!$assumeYes) {
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
$questionText = "Module ";
|
||||
$questionText .= (empty($moduleCode))
|
||||
? ""
|
||||
: $moduleCode;
|
||||
$questionText .= " is mandatory.\n";
|
||||
$questionText .= "Would you like to deactivate the module ";
|
||||
$questionText .= (empty($moduleCode))
|
||||
? ""
|
||||
: $moduleCode;
|
||||
$questionText .= " ? (yes, or no) ";
|
||||
|
||||
$question = new ConfirmationQuestion($questionText, false);
|
||||
|
||||
if (!$helper->ask($input, $output, $question)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
@@ -22,7 +23,7 @@ use Symfony\Component\Filesystem\Filesystem;
|
||||
*
|
||||
* Class ModuleGenerateCommand
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class ModuleGenerateCommand extends BaseModuleGenerate
|
||||
{
|
||||
@@ -32,23 +33,38 @@ class ModuleGenerateCommand extends BaseModuleGenerate
|
||||
->setName("module:generate")
|
||||
->setDescription("generate all needed files for creating a new Module")
|
||||
->addArgument(
|
||||
"name" ,
|
||||
"name",
|
||||
InputArgument::REQUIRED,
|
||||
"name wanted for your Module"
|
||||
)
|
||||
->addOption(
|
||||
'force',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'If defined, it will update the module with missing directories and files (no overrides).'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->module = $this->formatModuleName($input->getArgument("name"));
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . DIRECTORY_SEPARATOR . $this->module;
|
||||
$this->verifyExistingModule();
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . $this->module;
|
||||
|
||||
$this->validModuleName($this->module);
|
||||
|
||||
try {
|
||||
$this->verifyExistingModule();
|
||||
} catch (\RuntimeException $ex) {
|
||||
if (false === $input->getOption('force')) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
$this->createDirectories();
|
||||
$this->createFiles();
|
||||
if (method_exists($this, "renderBlock")) {
|
||||
//impossible to change output class in CommandTester...
|
||||
if (method_exists($output, "renderBlock")) {
|
||||
// impossible to change output class in CommandTester...
|
||||
$output->renderBlock(array(
|
||||
'',
|
||||
sprintf("module %s create with success", $this->module),
|
||||
@@ -56,19 +72,38 @@ class ModuleGenerateCommand extends BaseModuleGenerate
|
||||
''
|
||||
), "bg=green;fg=black");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function createDirectories()
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
|
||||
$fs->mkdir($this->moduleDirectory);
|
||||
|
||||
foreach ($this->neededDirectories as $directory) {
|
||||
$fs->mkdir($this->moduleDirectory . DIRECTORY_SEPARATOR . $directory);
|
||||
if (!$fs->exists($this->moduleDirectory)) {
|
||||
$fs->mkdir($this->moduleDirectory);
|
||||
}
|
||||
|
||||
foreach ($this->neededDirectories as $directory) {
|
||||
if (!$fs->exists($this->moduleDirectory . DIRECTORY_SEPARATOR . $directory)) {
|
||||
$fs->mkdir($this->moduleDirectory . DIRECTORY_SEPARATOR . $directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function copyConfigFile($filename, $skeletonDir, Filesystem $fs)
|
||||
{
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $filename;
|
||||
if (!$fs->exists($filename)) {
|
||||
$configContent = file_get_contents($skeletonDir . "config.xml");
|
||||
|
||||
$configContent = str_replace("%%CLASSNAME%%", $this->module, $configContent);
|
||||
$configContent = str_replace("%%NAMESPACE%%", $this->module, $configContent);
|
||||
$configContent = str_replace("%%NAMESPACE_LOWER%%", strtolower($this->module), $configContent);
|
||||
|
||||
file_put_contents(
|
||||
$filename,
|
||||
$configContent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function createFiles()
|
||||
@@ -76,56 +111,116 @@ class ModuleGenerateCommand extends BaseModuleGenerate
|
||||
$fs = new Filesystem();
|
||||
|
||||
try {
|
||||
$skeletonDir = str_replace("/", DIRECTORY_SEPARATOR, THELIA_ROOT . "/core/lib/Thelia/Command/Skeleton/Module/");
|
||||
$skeletonDir = str_replace("/", DIRECTORY_SEPARATOR, __DIR__ . "/Skeleton/Module/");
|
||||
|
||||
// config.xml file
|
||||
$fs->copy($skeletonDir . "config.xml", $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "config.xml");
|
||||
$this->copyConfigFile("config.xml", $skeletonDir, $fs);
|
||||
$this->copyConfigFile("config_prod.xml", $skeletonDir, $fs);
|
||||
$this->copyConfigFile("config_dev.xml", $skeletonDir, $fs);
|
||||
$this->copyConfigFile("config_test.xml", $skeletonDir, $fs);
|
||||
|
||||
$moduleContent = file_get_contents($skeletonDir . "module.xml");
|
||||
// Readme.md file
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Readme.md";
|
||||
if (!$fs->exists($filename)) {
|
||||
$readmeContent = file_get_contents($skeletonDir . "Readme.md");
|
||||
|
||||
$moduleContent = str_replace("%%CLASSNAME%%", $this->module, $moduleContent);
|
||||
$moduleContent = str_replace("%%NAMESPACE%%", $this->module, $moduleContent);
|
||||
// generate title for readme
|
||||
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $this->module, $readmeTitle);
|
||||
$composerFinalName = strtolower(implode("-", $readmeTitle[0]));
|
||||
|
||||
file_put_contents($this->moduleDirectory . DIRECTORY_SEPARATOR . "Config". DIRECTORY_SEPARATOR . "module.xml", $moduleContent);
|
||||
$readmeContent = str_replace("%%MODULENAME%%", $this->module, $readmeContent);
|
||||
$readmeContent = str_replace("%%MODULENAMETITLE%%", implode(" ", $readmeTitle[0]), $readmeContent);
|
||||
$readmeContent = str_replace("%%COMPOSERNAME%%", $composerFinalName, $readmeContent);
|
||||
|
||||
file_put_contents($filename, $readmeContent);
|
||||
}
|
||||
|
||||
// composer.json file
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "composer.json";
|
||||
if (!$fs->exists($filename)) {
|
||||
$composerContent = file_get_contents($skeletonDir . "composer.json");
|
||||
|
||||
// generate composer module name
|
||||
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $this->module, $composerName);
|
||||
|
||||
$composerContent = str_replace("%%MODULENAME%%", $this->module, $composerContent);
|
||||
$composerContent = str_replace("%%COMPOSERNAME%%", strtolower(implode("-", $composerName[0])), $composerContent);
|
||||
|
||||
file_put_contents($filename, $composerContent);
|
||||
}
|
||||
|
||||
// module.xml file
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config". DIRECTORY_SEPARATOR . "module.xml";
|
||||
if (!$fs->exists($filename)) {
|
||||
$moduleContent = file_get_contents($skeletonDir . "module.xml");
|
||||
|
||||
$moduleContent = str_replace("%%CLASSNAME%%", $this->module, $moduleContent);
|
||||
$moduleContent = str_replace("%%NAMESPACE%%", $this->module, $moduleContent);
|
||||
|
||||
file_put_contents($filename, $moduleContent);
|
||||
}
|
||||
|
||||
// PHP Class template
|
||||
$classContent = file_get_contents($skeletonDir . "Class.php.template");
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . $this->module . ".php";
|
||||
if (!$fs->exists($filename)) {
|
||||
$classContent = file_get_contents($skeletonDir . "Class.php.template");
|
||||
|
||||
$classContent = str_replace("%%CLASSNAME%%", $this->module, $classContent);
|
||||
$classContent = str_replace("%%NAMESPACE%%", $this->module, $classContent);
|
||||
$classContent = str_replace("%%CLASSNAME%%", $this->module, $classContent);
|
||||
$classContent = str_replace("%%NAMESPACE%%", $this->module, $classContent);
|
||||
$classContent = str_replace("%%DOMAINNAME%%", strtolower($this->module), $classContent);
|
||||
|
||||
file_put_contents($this->moduleDirectory . DIRECTORY_SEPARATOR . $this->module.".php", $classContent);
|
||||
file_put_contents($filename, $classContent);
|
||||
}
|
||||
|
||||
// schema.xml file
|
||||
$schemaContent = file_get_contents($skeletonDir . "schema.xml");
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "schema.xml";
|
||||
if (!$fs->exists($filename)) {
|
||||
$schemaContent = file_get_contents($skeletonDir . "schema.xml");
|
||||
|
||||
$schemaContent = str_replace("%%NAMESPACE%%", $this->module, $schemaContent);
|
||||
$schemaContent = str_replace("%%NAMESPACE%%", $this->module, $schemaContent);
|
||||
$schemaContent = str_replace(
|
||||
'%%XSD_LOCATION%%',
|
||||
$fs->makePathRelative(
|
||||
THELIA_VENDOR . 'propel/propel/resources/xsd/',
|
||||
$this->moduleDirectory
|
||||
) . 'database.xsd',
|
||||
$schemaContent
|
||||
);
|
||||
|
||||
file_put_contents($this->moduleDirectory . DIRECTORY_SEPARATOR . "Config". DIRECTORY_SEPARATOR . "schema.xml", $schemaContent);
|
||||
file_put_contents($filename, $schemaContent);
|
||||
}
|
||||
|
||||
// routing.xml file
|
||||
$routingContent = file_get_contents($skeletonDir . "routing.xml");
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "routing.xml";
|
||||
if (!$fs->exists($filename)) {
|
||||
$routingContent = file_get_contents($skeletonDir . "routing.xml");
|
||||
|
||||
$routingContent = str_replace("%%NAMESPACE%%", $this->module, $routingContent);
|
||||
$routingContent = str_replace("%%CLASSNAME_LOWER%%", strtolower($this->module), $routingContent);
|
||||
$routingContent = str_replace("%%NAMESPACE%%", $this->module, $routingContent);
|
||||
$routingContent = str_replace("%%CLASSNAME_LOWER%%", strtolower($this->module), $routingContent);
|
||||
|
||||
file_put_contents($this->moduleDirectory . DIRECTORY_SEPARATOR . "Config". DIRECTORY_SEPARATOR . "routing.xml", $routingContent);
|
||||
file_put_contents($filename, $routingContent);
|
||||
}
|
||||
|
||||
// I18n sample files
|
||||
$fs->copy(
|
||||
$skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php",
|
||||
$this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php"
|
||||
);
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php";
|
||||
if (!$fs->exists($filename)) {
|
||||
$fs->copy(
|
||||
$skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "fr_FR.php",
|
||||
$filename
|
||||
);
|
||||
}
|
||||
|
||||
$fs->copy(
|
||||
$skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php",
|
||||
$this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php"
|
||||
);
|
||||
$filename = $this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php";
|
||||
if (!$fs->exists($filename)) {
|
||||
$fs->copy(
|
||||
$skeletonDir . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php",
|
||||
$this->moduleDirectory . DIRECTORY_SEPARATOR . "I18n" . DIRECTORY_SEPARATOR . "en_US.php"
|
||||
);
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$fs->remove($this->moduleDirectory);
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Propel\Generator\Command\ModelBuildCommand;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@@ -25,7 +26,7 @@ use Symfony\Component\Filesystem\Filesystem;
|
||||
*
|
||||
* Class ModuleGenerateModelCommand
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
{
|
||||
@@ -46,13 +47,12 @@ class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
"with this option generate sql file at the same time"
|
||||
)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->module = $this->formatModuleName($input->getArgument("name"));
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . DS . $this->module;
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . $this->module;
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
@@ -66,11 +66,13 @@ class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
|
||||
$this->generateModel($output);
|
||||
|
||||
$output->renderBlock(array(
|
||||
'',
|
||||
'Model generated successfuly',
|
||||
''
|
||||
), 'bg=green;fg=black');
|
||||
/** @var FormatterHelper $formatter */
|
||||
$formatter = $this->getHelper('formatter');
|
||||
$formattedBlock = $formatter->formatBlock(
|
||||
'Model generated successfully',
|
||||
'bg=green;fg=black'
|
||||
);
|
||||
$output->writeln($formattedBlock);
|
||||
|
||||
if ($input->getOption("generate-sql")) {
|
||||
$output->writeln(' ');
|
||||
@@ -80,7 +82,6 @@ class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
|
||||
protected function generateSql(OutputInterface $output)
|
||||
{
|
||||
|
||||
$command = $this->getApplication()->find("module:generate:sql");
|
||||
|
||||
$command->run(
|
||||
@@ -108,7 +109,7 @@ class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
);
|
||||
|
||||
$verifyDirectories = array(
|
||||
THELIA_MODULE_DIR . DS . "Thelia",
|
||||
THELIA_MODULE_DIR . "Thelia",
|
||||
$this->moduleDirectory . DS . "Model" . DS . "Thelia"
|
||||
);
|
||||
|
||||
@@ -117,7 +118,5 @@ class ModuleGenerateModelCommand extends BaseModuleGenerate
|
||||
$fs->remove($directory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Propel\Generator\Command\SqlBuildCommand;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@@ -24,7 +25,7 @@ use Symfony\Component\Filesystem\Filesystem;
|
||||
*
|
||||
* Class ModuleGenerateSqlCommand
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class ModuleGenerateSqlCommand extends BaseModuleGenerate
|
||||
{
|
||||
@@ -44,7 +45,7 @@ class ModuleGenerateSqlCommand extends BaseModuleGenerate
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->module = $this->formatModuleName($input->getArgument("name"));
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . DS . $this->module;
|
||||
$this->moduleDirectory = THELIA_MODULE_DIR . $this->module;
|
||||
|
||||
$fs = new Filesystem();
|
||||
|
||||
@@ -68,12 +69,15 @@ class ModuleGenerateSqlCommand extends BaseModuleGenerate
|
||||
$output
|
||||
);
|
||||
|
||||
$output->renderBlock(array(
|
||||
'',
|
||||
'Sql generated successfuly',
|
||||
'File available in your module config directory',
|
||||
''
|
||||
), 'bg=green;fg=black');
|
||||
|
||||
/** @var FormatterHelper $formatter */
|
||||
$formatter = $this->getHelper('formatter');
|
||||
$formattedBlock = $formatter->formatBlock(
|
||||
[
|
||||
'Sql generated successfully',
|
||||
'File available in your module config directory',
|
||||
],
|
||||
'bg=green;fg=black'
|
||||
);
|
||||
$output->writeln($formattedBlock);
|
||||
}
|
||||
}
|
||||
|
||||
87
core/lib/Thelia/Command/ModuleListCommand.php
Normal file
87
core/lib/Thelia/Command/ModuleListCommand.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Model\Map\ModuleTableMap;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
/**
|
||||
* Class ModuleListCommand
|
||||
* @package Thelia\Command
|
||||
* @author Benjamin Perche <bperche@openstudio.fr>
|
||||
*/
|
||||
class ModuleListCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('module:list')
|
||||
->setDescription('List the modules')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int|null|void
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$helper = new Table($output);
|
||||
$helper->addRows($this->getModulesData());
|
||||
|
||||
$helper
|
||||
->setHeaders(["Code", "Active", "Type", "Version"])
|
||||
->render()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getModulesData()
|
||||
{
|
||||
$moduleData = ModuleQuery::create()
|
||||
->orderByType()
|
||||
->addAsColumn("code", ModuleTableMap::CODE)
|
||||
->addAsColumn("active", "IF(".ModuleTableMap::ACTIVATE.", \"Yes\", \"No\")")
|
||||
->addAsColumn("type", ModuleTableMap::TYPE)
|
||||
->addAsColumn("version", ModuleTableMap::VERSION)
|
||||
->select([
|
||||
"code",
|
||||
"active",
|
||||
"type",
|
||||
"version",
|
||||
])
|
||||
->find()
|
||||
->toArray()
|
||||
;
|
||||
|
||||
foreach ($moduleData as &$row) {
|
||||
switch ($row["type"]) {
|
||||
case BaseModule::CLASSIC_MODULE_TYPE:
|
||||
$row["type"] = "classic";
|
||||
break;
|
||||
case BaseModule::DELIVERY_MODULE_TYPE:
|
||||
$row["type"] = "delivery";
|
||||
break;
|
||||
case BaseModule::PAYMENT_MODULE_TYPE:
|
||||
$row["type"] = "payment";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $moduleData;
|
||||
}
|
||||
}
|
||||
219
core/lib/Thelia/Command/ModulePositionCommand.php
Normal file
219
core/lib/Thelia/Command/ModulePositionCommand.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\Event\UpdatePositionEvent;
|
||||
use Thelia\Model\ModuleQuery;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
|
||||
/**
|
||||
* Class ModulePositionCommand
|
||||
* Set modules position
|
||||
*
|
||||
* @package Thelia\Command
|
||||
* @author Jérôme Billiras <jerome.billiras+github@gmail.com>
|
||||
*/
|
||||
class ModulePositionCommand extends ContainerAwareCommand
|
||||
{
|
||||
/**
|
||||
* @var \Thelia\Model\ModuleQuery
|
||||
*/
|
||||
protected $moduleQuery;
|
||||
|
||||
/**
|
||||
* @var array Modules list
|
||||
*/
|
||||
protected $modulesList = [];
|
||||
|
||||
/**
|
||||
* @var array Modules positions list
|
||||
*/
|
||||
protected $positionsList = [];
|
||||
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->moduleQuery = new ModuleQuery;
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('module:position')
|
||||
->setDescription('Set module(s) position')
|
||||
->addArgument(
|
||||
'modules',
|
||||
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
|
||||
'Module in format moduleName:[+|-]position where position is an integer or up or down.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$argsList = $input->getArgument('modules');
|
||||
array_walk($argsList, [$this, 'checkModuleArgument']);
|
||||
|
||||
if (!$this->checkPositions($input, $output, $isAbsolute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($isAbsolute) {
|
||||
array_multisort($this->positionsList, SORT_ASC, SORT_REGULAR, $this->modulesList);
|
||||
}
|
||||
|
||||
$maxPositionByType = $this->cleanPosition();
|
||||
|
||||
foreach ($this->modulesList as $moduleIdx => $moduleName) {
|
||||
$this->moduleQuery->clear();
|
||||
$module = $this->moduleQuery->findOneByCode($moduleName);
|
||||
$position = $this->positionsList[$moduleIdx];
|
||||
|
||||
if ($position === 'up') {
|
||||
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_UP);
|
||||
} elseif ($position === 'down') {
|
||||
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_DOWN);
|
||||
} else {
|
||||
if ($position[0] === '+' || $position[0] === '-') {
|
||||
$position = $module->getPosition() + $position;
|
||||
}
|
||||
|
||||
if ($position < 1) {
|
||||
$position = 1;
|
||||
}
|
||||
|
||||
$maxPosition = $maxPositionByType[$module->getType()];
|
||||
if ($position > $maxPosition) {
|
||||
$position = $maxPosition;
|
||||
}
|
||||
|
||||
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_ABSOLUTE, $position);
|
||||
}
|
||||
|
||||
$this->getDispatcher()->dispatch(TheliaEvents::MODULE_UPDATE_POSITION, $event);
|
||||
}
|
||||
|
||||
/** @var FormatterHelper $formatter */
|
||||
$formatter = $this->getHelper('formatter');
|
||||
$formattedBlock = $formatter->formatBlock('Module position(s) updated', 'bg=green;fg=black', true);
|
||||
$output->writeln($formattedBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a module argument format
|
||||
*
|
||||
* @param string $paramValue
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function checkModuleArgument($paramValue)
|
||||
{
|
||||
if (!preg_match('#^([a-z0-9]+):([\+-]?[0-9]+|up|down)$#i', $paramValue, $matches)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Arguments must be in format moduleName:[+|-]position where position is an integer or up or down.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->moduleQuery->clear();
|
||||
$module = $this->moduleQuery->findOneByCode($matches[1]);
|
||||
if ($module === null) {
|
||||
throw new \RuntimeException(sprintf('%s module does not exists. Try to refresh first.', $matches[1]));
|
||||
}
|
||||
|
||||
$this->modulesList[] = $matches[1];
|
||||
$this->positionsList[] = $matches[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder modules positions (without holes)
|
||||
*
|
||||
* @return array Maximum position by type
|
||||
*/
|
||||
protected function cleanPosition()
|
||||
{
|
||||
$modulesType = [];
|
||||
|
||||
$this->moduleQuery->clear();
|
||||
$modules = $this->moduleQuery->orderByPosition(Criteria::ASC);
|
||||
|
||||
/** @var \Thelia\Model\Module $module */
|
||||
foreach ($modules as $module) {
|
||||
if (!isset($modulesType[$module->getType()])) {
|
||||
$modulesType[$module->getType()] = 0;
|
||||
}
|
||||
|
||||
$module
|
||||
->setPosition(++$modulesType[$module->getType()])
|
||||
->save()
|
||||
;
|
||||
}
|
||||
|
||||
return $modulesType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check positions consistency
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param bool $isAbsolute Set to true or false according to position values
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return bool Continue or stop command
|
||||
*/
|
||||
protected function checkPositions(InputInterface $input, OutputInterface $output, &$isAbsolute = false)
|
||||
{
|
||||
$isRelative = false;
|
||||
foreach (array_count_values($this->positionsList) as $value => $count) {
|
||||
if (is_int($value) && $value[0] !== '+' && $value[0] !== '-') {
|
||||
$isAbsolute = true;
|
||||
|
||||
if ($count > 1) {
|
||||
throw new \InvalidArgumentException('Two (or more) absolute positions are identical.');
|
||||
}
|
||||
} else {
|
||||
$isRelative = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isAbsolute && $isRelative) {
|
||||
/** @var FormatterHelper $formatter */
|
||||
$formatter = $this->getHelper('formatter');
|
||||
$formattedBlock = $formatter->formatBlock(
|
||||
'Mix absolute and relative positions may produce unexpected results !',
|
||||
'bg=yellow;fg=black',
|
||||
true
|
||||
);
|
||||
$output->writeln($formattedBlock);
|
||||
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
$question = new ConfirmationQuestion('<question>Do you want to continue ? y/[n]<question>', false);
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Exception\InvalidModuleException;
|
||||
use Thelia\Module\ModuleManagement;
|
||||
|
||||
/**
|
||||
@@ -36,13 +37,20 @@ class ModuleRefreshCommand extends ContainerAwareCommand
|
||||
{
|
||||
try {
|
||||
$moduleManagement = new ModuleManagement;
|
||||
$moduleManagement->updateModules();
|
||||
$moduleManagement->updateModules($this->getContainer());
|
||||
} catch (InvalidModuleException $ime) {
|
||||
throw new \RuntimeException(
|
||||
sprintf('One or more modules could not be refreshed : %s', $ime->getErrorsAsString("\n"))
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Refresh modules list fail with Exception : [%d] %s', $e->getCode(), $e->getMessage()));
|
||||
throw new \RuntimeException(
|
||||
sprintf('Refresh modules list fail with Exception : [%d] %s', $e->getCode(), $e->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
if (method_exists($output, 'renderBlock')) {
|
||||
$output->renderBlock([
|
||||
$output->renderBlock(
|
||||
[
|
||||
'',
|
||||
'Modules list successfully refreshed',
|
||||
''
|
||||
|
||||
@@ -40,5 +40,4 @@ class TheliaConsoleOutput extends ConsoleOutput
|
||||
|
||||
$this->writeln($output);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,18 @@
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Propel\Runtime\Connection\ConnectionWrapper;
|
||||
use \Thelia\Model\Map\ProductTableMap;
|
||||
use Propel\Runtime\Propel;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Install\Database;
|
||||
|
||||
/**
|
||||
* Class ReloadDatabasesCommand
|
||||
* @package Thelia\Command
|
||||
* @author Manuel Raynaud <mraynaud@openstudio.fr>
|
||||
* @author Manuel Raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class ReloadDatabaseCommand extends BaseModuleGenerate
|
||||
{
|
||||
@@ -40,7 +42,8 @@ class ReloadDatabaseCommand extends BaseModuleGenerate
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$connection = Propel::getConnection(\Thelia\Model\Map\ProductTableMap::DATABASE_NAME);
|
||||
/** @var ConnectionWrapper $connection */
|
||||
$connection = Propel::getConnection(ProductTableMap::DATABASE_NAME);
|
||||
$connection = $connection->getWrappedConnection();
|
||||
|
||||
$tables = $connection->query("SHOW TABLES");
|
||||
|
||||
47
core/lib/Thelia/Command/SaleCheckActivationCommand.php
Normal file
47
core/lib/Thelia/Command/SaleCheckActivationCommand.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace Thelia\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Thelia\Core\Event\Sale\SaleActiveStatusCheckEvent;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
|
||||
/**
|
||||
* Class SaleCheckActivationCommand
|
||||
* @package Thelia\Command
|
||||
* @author manuel raynaud <manu@raynaud.io>
|
||||
*/
|
||||
class SaleCheckActivationCommand extends ContainerAwareCommand
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this
|
||||
->setName("sale:check-activation")
|
||||
->setDescription("check the activation and deactivation dates of sales, and perform the required action depending on the current date.");
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$this->getDispatcher()->dispatch(
|
||||
TheliaEvents::CHECK_SALE_ACTIVATION_EVENT,
|
||||
new SaleActiveStatusCheckEvent()
|
||||
);
|
||||
|
||||
$output->writeln("<info>Sale verification processed successfully</info>");
|
||||
} catch (\Exception $ex) {
|
||||
$output->writeln(sprintf("<error>Error : %s</error>", $ex->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ use Thelia\Module\BaseModule;
|
||||
|
||||
class %%CLASSNAME%% extends BaseModule
|
||||
{
|
||||
/** @var string */
|
||||
const DOMAIN_NAME = '%%DOMAINNAME%%';
|
||||
|
||||
/*
|
||||
* You may now override BaseModuleInterface methods, such as:
|
||||
* install, destroy, preActivation, postActivation, preDeactivation, postDeactivation
|
||||
|
||||
55
core/lib/Thelia/Command/Skeleton/Module/Readme.md
Normal file
55
core/lib/Thelia/Command/Skeleton/Module/Readme.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# %%MODULENAMETITLE%%
|
||||
|
||||
Add a short description here. You can also add a screenshot if needed.
|
||||
|
||||
## Installation
|
||||
|
||||
### Manually
|
||||
|
||||
* Copy the module into ```<thelia_root>/local/modules/``` directory and be sure that the name of the module is %%MODULENAME%%.
|
||||
* Activate it in your thelia administration panel
|
||||
|
||||
### Composer
|
||||
|
||||
Add it in your main thelia composer.json file
|
||||
|
||||
```
|
||||
composer require your-vendor/%%COMPOSERNAME%%-module:~1.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Explain here how to use your module, how to configure it, etc.
|
||||
|
||||
## Hook
|
||||
|
||||
If your module use one or more hook, fill this part. Explain which hooks are used.
|
||||
|
||||
|
||||
## Loop
|
||||
|
||||
If your module declare one or more loop, describe them here like this :
|
||||
|
||||
[loop name]
|
||||
|
||||
### Input arguments
|
||||
|
||||
|Argument |Description |
|
||||
|--- |--- |
|
||||
|**arg1** | describe arg1 with an exemple. |
|
||||
|**arg2** | describe arg2 with an exemple. |
|
||||
|
||||
### Output arguments
|
||||
|
||||
|Variable |Description |
|
||||
|--- |--- |
|
||||
|$VAR1 | describe $VAR1 variable |
|
||||
|$VAR2 | describe $VAR2 variable |
|
||||
|
||||
### Exemple
|
||||
|
||||
Add a complete exemple of your loop
|
||||
|
||||
## Other ?
|
||||
|
||||
If you have other think to put, feel free to complete your readme as you want.
|
||||
11
core/lib/Thelia/Command/Skeleton/Module/composer.json
Normal file
11
core/lib/Thelia/Command/Skeleton/Module/composer.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "your-vendor/%%COMPOSERNAME%%-module",
|
||||
"license": "LGPL-3.0+",
|
||||
"type": "thelia-module",
|
||||
"require": {
|
||||
"thelia/installer": "~1.1"
|
||||
},
|
||||
"extra": {
|
||||
"installer-name": "%%MODULENAME%%"
|
||||
}
|
||||
}
|
||||
@@ -6,19 +6,19 @@
|
||||
|
||||
<loops>
|
||||
<!-- sample definition
|
||||
<loop name="MySuperLoop" class="MyModule\Loop\MySuperLoop" />
|
||||
<loop name="MySuperLoop" class="%%NAMESPACE%%\Loop\MySuperLoop" />
|
||||
-->
|
||||
</loops>
|
||||
|
||||
<forms>
|
||||
<!--
|
||||
<form name="MyFormName" class="MyModule\Form\MySuperForm" />
|
||||
<form name="MyFormName" class="%%NAMESPACE%%\Form\MySuperForm" />
|
||||
-->
|
||||
</forms>
|
||||
|
||||
<commands>
|
||||
<!--
|
||||
<command class="MyModule\Command\MySuperCommand" />
|
||||
<command class="%%NAMESPACE%%\Command\MySuperCommand" />
|
||||
-->
|
||||
</commands>
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
</services>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<hooks>
|
||||
<hook id="%%NAMESPACE_LOWER%%.hook" class="%%NAMESPACE%%\Hook\MySuperHook">
|
||||
<tag name="hook.event_listener" event="main.body.bottom" type="front|back|pdf|email" method="onMainBodyBottom" />
|
||||
</hook>
|
||||
</hooks>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<exports>
|
||||
|
||||
|
||||
50
core/lib/Thelia/Command/Skeleton/Module/config_dev.xml
Normal file
50
core/lib/Thelia/Command/Skeleton/Module/config_dev.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<loops>
|
||||
<!-- sample definition
|
||||
<loop name="MySuperLoop" class="%%NAMESPACE%%\Loop\MySuperLoop" />
|
||||
-->
|
||||
</loops>
|
||||
|
||||
<forms>
|
||||
<!--
|
||||
<form name="MyFormName" class="%%NAMESPACE%%\Form\MySuperForm" />
|
||||
-->
|
||||
</forms>
|
||||
|
||||
<commands>
|
||||
<!--
|
||||
<command class="%%NAMESPACE%%\Command\MySuperCommand" />
|
||||
-->
|
||||
</commands>
|
||||
|
||||
<!--
|
||||
<services>
|
||||
|
||||
</services>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<hooks>
|
||||
<hook id="%%NAMESPACE_LOWER%%.hook" class="%%NAMESPACE%%\Hook\MySuperHook">
|
||||
<tag name="hook.event_listener" event="main.body.bottom" type="front|back|pdf|email" method="onMainBodyBottom" />
|
||||
</hook>
|
||||
</hooks>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<exports>
|
||||
|
||||
</exports>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<imports>
|
||||
|
||||
</imports>
|
||||
-->
|
||||
</config>
|
||||
50
core/lib/Thelia/Command/Skeleton/Module/config_prod.xml
Normal file
50
core/lib/Thelia/Command/Skeleton/Module/config_prod.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<loops>
|
||||
<!-- sample definition
|
||||
<loop name="MySuperLoop" class="%%NAMESPACE%%\Loop\MySuperLoop" />
|
||||
-->
|
||||
</loops>
|
||||
|
||||
<forms>
|
||||
<!--
|
||||
<form name="MyFormName" class="%%NAMESPACE%%\Form\MySuperForm" />
|
||||
-->
|
||||
</forms>
|
||||
|
||||
<commands>
|
||||
<!--
|
||||
<command class="%%NAMESPACE%%\Command\MySuperCommand" />
|
||||
-->
|
||||
</commands>
|
||||
|
||||
<!--
|
||||
<services>
|
||||
|
||||
</services>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<hooks>
|
||||
<hook id="%%NAMESPACE_LOWER%%.hook" class="%%NAMESPACE%%\Hook\MySuperHook">
|
||||
<tag name="hook.event_listener" event="main.body.bottom" type="front|back|pdf|email" method="onMainBodyBottom" />
|
||||
</hook>
|
||||
</hooks>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<exports>
|
||||
|
||||
</exports>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<imports>
|
||||
|
||||
</imports>
|
||||
-->
|
||||
</config>
|
||||
50
core/lib/Thelia/Command/Skeleton/Module/config_test.xml
Normal file
50
core/lib/Thelia/Command/Skeleton/Module/config_test.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<loops>
|
||||
<!-- sample definition
|
||||
<loop name="MySuperLoop" class="%%NAMESPACE%%\Loop\MySuperLoop" />
|
||||
-->
|
||||
</loops>
|
||||
|
||||
<forms>
|
||||
<!--
|
||||
<form name="MyFormName" class="%%NAMESPACE%%\Form\MySuperForm" />
|
||||
-->
|
||||
</forms>
|
||||
|
||||
<commands>
|
||||
<!--
|
||||
<command class="%%NAMESPACE%%\Command\MySuperCommand" />
|
||||
-->
|
||||
</commands>
|
||||
|
||||
<!--
|
||||
<services>
|
||||
|
||||
</services>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<hooks>
|
||||
<hook id="%%NAMESPACE_LOWER%%.hook" class="%%NAMESPACE%%\Hook\MySuperHook">
|
||||
<tag name="hook.event_listener" event="main.body.bottom" type="front|back|pdf|email" method="onMainBodyBottom" />
|
||||
</hook>
|
||||
</hooks>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<exports>
|
||||
|
||||
</exports>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<imports>
|
||||
|
||||
</imports>
|
||||
-->
|
||||
</config>
|
||||
@@ -1,18 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module>
|
||||
<module xmlns="http://thelia.net/schema/dic/module"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/module http://thelia.net/schema/dic/module/module-2_2.xsd">
|
||||
<fullnamespace>%%NAMESPACE%%\%%CLASSNAME%%</fullnamespace>
|
||||
<descriptive locale="en_US">
|
||||
<title>Automatically generated module - please update module.xml file</title>
|
||||
<!--
|
||||
<subtitle></subtitle>
|
||||
<description></description>
|
||||
<postscriptum></postscriptum>
|
||||
-->
|
||||
</descriptive>
|
||||
<descriptive locale="fr_FR">
|
||||
<title>Module généré autromatiquement - editez le fichier module.xml</title>
|
||||
<title>Module généré automatiquement - éditez le fichier module.xml</title>
|
||||
</descriptive>
|
||||
<!-- <logo></logo> -->
|
||||
<!--<images-folder>images</images-folder>-->
|
||||
<languages>
|
||||
<language>en_US</language>
|
||||
<language>fr_FR</language>
|
||||
</languages>
|
||||
<version></version>
|
||||
<author>
|
||||
<name></name>
|
||||
<email></email>
|
||||
</author>
|
||||
<authors>
|
||||
<author>
|
||||
<name></name>
|
||||
<email></email>
|
||||
</author>
|
||||
</authors>
|
||||
<type>classic</type>
|
||||
<thelia>2.0.0</thelia>
|
||||
<!--
|
||||
module dependencies
|
||||
<required>
|
||||
<module version=">=0.1">Front</module>
|
||||
<module version="~1.0">HookCart</module>
|
||||
<module version=">0.2">HookSearch</module>
|
||||
</required>
|
||||
-->
|
||||
<thelia>2.2.0</thelia>
|
||||
<stability>other</stability>
|
||||
<mandatory>0</mandatory>
|
||||
<hidden>0</hidden>
|
||||
</module>
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<database defaultIdMethod="native" name="thelia" namespace="%%NAMESPACE%%\Model">
|
||||
<database defaultIdMethod="native" name="thelia"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="%%XSD_LOCATION%%" >
|
||||
<!--
|
||||
See propel documentation on http://propelorm.org for all information about schema file
|
||||
|
||||
<table name="product_rel" namespace="%%NAMESPACE%%\Model">
|
||||
<column autoIncrement="true" name="id" primaryKey="true" required="true" type="INTEGER" />
|
||||
<column defaultValue="0" name="visible" required="true" type="TINYINT" />
|
||||
<column defaultValue="0" name="position" required="true" type="INTEGER" />
|
||||
<column name="title" size="255" type="VARCHAR" />
|
||||
<column name="description" type="CLOB" />
|
||||
<column name="chapo" type="LONGVARCHAR" />
|
||||
<column name="postscriptum" type="LONGVARCHAR" />
|
||||
<foreign-key foreignTable="product" name="fk_product_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="product_id" />
|
||||
</foreign-key>
|
||||
<behavior name="timestampable" />
|
||||
<behavior name="i18n">
|
||||
<parameter name="i18n_columns" value="title, description, chapo, postscriptum" />
|
||||
</behavior>
|
||||
<behavior name="versionable">
|
||||
<parameter name="log_created_at" value="true" />
|
||||
<parameter name="log_created_by" value="true" />
|
||||
</behavior>
|
||||
</table>
|
||||
-->
|
||||
<external-schema filename="local/config/schema.xml" referenceOnly="true" />
|
||||
</database>
|
||||
|
||||
Reference in New Issue
Block a user