From 2ee90d35e4b234c7705490a69f8ed141aaccf9b7 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 14:27:45 +0100 Subject: [PATCH 01/17] create administrator update password event --- .../AdministratorUpdatePasswordEvent.php | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php new file mode 100644 index 000000000..70f92532b --- /dev/null +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -0,0 +1,84 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event\Administrator; +use Thelia\Core\Event\ActionEvent; + + +/** + * Class AdministratorUpdatePasswordEvent + * @package Thelia\Core\Event\Administrator + * @author Manuel Raynaud + */ +class AdministratorUpdatePasswordEvent extends ActionEvent +{ + + /** + * @var string administrator login + */ + protected $login; + + /** + * @var string new administrator password + */ + protected $password; + + public function __construct($login) + { + $this->login = $login; + } + + /** + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $login + */ + public function setLogin($login) + { + $this->login = $login; + } + + /** + * @return string + */ + public function getLogin() + { + return $this->login; + } + + +} \ No newline at end of file From 9d011eb5c67b40174eb5d8e89f1e80c8c5c96fa4 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 14:46:21 +0100 Subject: [PATCH 02/17] change command line for creating new administrator --- core/lib/Thelia/Command/CreateAdminUser.php | 2 +- reset_install.bat | 2 +- reset_install.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index 857790141..5ac62802a 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -38,7 +38,7 @@ class CreateAdminUser extends ContainerAwareCommand protected function configure() { $this - ->setName("thelia:create-admin") + ->setName("admin:create") ->setDescription("Create a new adminsitration user") ->setHelp("The thelia:create-admin command create a new administration user.") ->addOption( diff --git a/reset_install.bat b/reset_install.bat index 0a12c43d2..f8c0b35e2 100644 --- a/reset_install.bat +++ b/reset_install.bat @@ -26,7 +26,7 @@ if exist local\config\database.yml ( php install\faker.php echo [INFO] Adding admin - php Thelia thelia:create-admin + php Thelia admin:create echo [SUCCESS] Reset done ) diff --git a/reset_install.sh b/reset_install.sh index a91a2dc1c..83288a509 100755 --- a/reset_install.sh +++ b/reset_install.sh @@ -32,7 +32,7 @@ echo -e "\n\033[01;34m[INFO] Installing fixtures\033[00m\n" php install/faker.php echo -e "\n\033[01;34m[INFO] Adding admin\033[00m\n" -php Thelia thelia:create-admin --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 +php Thelia admin:create --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 echo -e "\n\033[01;34m[INFO] Clearing caches\033[00m\n" php Thelia cache:clear From b0f3ad69d2e9fbc89f9594535bc5b3c21b955ff9 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 15:01:18 +0100 Subject: [PATCH 03/17] start creating admin password recovery --- core/lib/Thelia/Action/Administrator.php | 16 ++++- .../Thelia/Command/AdminUpdatePassword.php | 63 +++++++++++++++++++ core/lib/Thelia/Command/CreateAdminUser.php | 4 +- .../AdministratorUpdatePasswordEvent.php | 2 +- core/lib/Thelia/Core/Event/TheliaEvents.php | 1 + 5 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 core/lib/Thelia/Command/AdminUpdatePassword.php diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php index 2bbfce8a8..23167dd40 100644 --- a/core/lib/Thelia/Action/Administrator.php +++ b/core/lib/Thelia/Action/Administrator.php @@ -25,6 +25,7 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\Administrator\AdministratorEvent; +use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Model\Admin as AdminModel; use Thelia\Model\AdminQuery; @@ -92,15 +93,24 @@ class Administrator extends BaseAction implements EventSubscriberInterface } } + public function updatePassword(AdministratorUpdatePasswordEvent $event) + { + if (null !== $admin = AdminQuery::create()->filterByLogin($event->getLogin())->findOne()) { + $admin->setPassword($event->getPassword()) + ->save(); + } + } + /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( - TheliaEvents::ADMINISTRATOR_CREATE => array("create", 128), - TheliaEvents::ADMINISTRATOR_UPDATE => array("update", 128), - TheliaEvents::ADMINISTRATOR_DELETE => array("delete", 128), + TheliaEvents::ADMINISTRATOR_CREATE => array('create', 128), + TheliaEvents::ADMINISTRATOR_UPDATE => array('update', 128), + TheliaEvents::ADMINISTRATOR_DELETE => array('delete', 128), + TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD => array('updatePassword', 128) ); } } diff --git a/core/lib/Thelia/Command/AdminUpdatePassword.php b/core/lib/Thelia/Command/AdminUpdatePassword.php new file mode 100644 index 000000000..6b0a0ec48 --- /dev/null +++ b/core/lib/Thelia/Command/AdminUpdatePassword.php @@ -0,0 +1,63 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + + +/** + * command line for updating admin password + * + * php Thelia admin:updatePassword + * + * Class AdminUpdatePassword + * @package Thelia\Command + * @author Manuel Raynaud + */ +class AdminUpdatePassword extends ContainerAwareCommand +{ + + /** + * Configures the current command. + */ + protected function configure() + { + $this + ->setName('admin:updatePassword') + ->setDescription('change administrator password') + ->setHelp('The admin:updatePassword command allows you to change the password for a given administrator') + ->addArgument( + 'login', + InputArgument::REQUIRED, + 'Login for administrator you want to change the password' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'Desired password. If this option is omitted, a random password is generated and shown in this prompt after' + ) + ; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index 5ac62802a..988122e7a 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -39,8 +39,8 @@ class CreateAdminUser extends ContainerAwareCommand { $this ->setName("admin:create") - ->setDescription("Create a new adminsitration user") - ->setHelp("The thelia:create-admin command create a new administration user.") + ->setDescription("Create a new administrator user") + ->setHelp("The admin:create command create a new administration user.") ->addOption( 'login_name', null, diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php index 70f92532b..cccb45cc4 100644 --- a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -80,5 +80,5 @@ class AdministratorUpdatePasswordEvent extends ActionEvent return $this->login; } - + } \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 42b20d8cd..ea3d7686a 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -565,6 +565,7 @@ final class TheliaEvents const ADMINISTRATOR_CREATE = "action.createAdministrator"; const ADMINISTRATOR_UPDATE = "action.updateAdministrator"; const ADMINISTRATOR_DELETE = "action.deleteAdministrator"; + const ADMINISTRATOR_UPDATEPASSWORD = 'action.generatePassword'; // -- Mailing System management --------------------------------------------- From e18c8992f82ecc5882803c1733cd09e2ecf970d8 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 15:33:25 +0100 Subject: [PATCH 04/17] finish admin update password command line --- core/lib/Thelia/Action/Administrator.php | 7 ++-- ...ord.php => AdminUpdatePasswordCommand.php} | 41 ++++++++++++++++++- core/lib/Thelia/Config/Resources/config.xml | 1 + .../AdministratorUpdatePasswordEvent.php | 23 ++++++----- local/modules/Cheque/Config/config.xml | 2 +- 5 files changed, 57 insertions(+), 17 deletions(-) rename core/lib/Thelia/Command/{AdminUpdatePassword.php => AdminUpdatePasswordCommand.php} (70%) diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php index 23167dd40..15940082a 100644 --- a/core/lib/Thelia/Action/Administrator.php +++ b/core/lib/Thelia/Action/Administrator.php @@ -95,10 +95,9 @@ class Administrator extends BaseAction implements EventSubscriberInterface public function updatePassword(AdministratorUpdatePasswordEvent $event) { - if (null !== $admin = AdminQuery::create()->filterByLogin($event->getLogin())->findOne()) { - $admin->setPassword($event->getPassword()) - ->save(); - } + $admin = $event->getAdmin(); + $admin->setPassword($event->getPassword()) + ->save(); } /** diff --git a/core/lib/Thelia/Command/AdminUpdatePassword.php b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php similarity index 70% rename from core/lib/Thelia/Command/AdminUpdatePassword.php rename to core/lib/Thelia/Command/AdminUpdatePasswordCommand.php index 6b0a0ec48..d4d0e5fc8 100644 --- a/core/lib/Thelia/Command/AdminUpdatePassword.php +++ b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php @@ -22,8 +22,15 @@ /*************************************************************************************/ 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 Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\AdminQuery; +use Thelia\Tools\Password; /** @@ -31,11 +38,11 @@ use Symfony\Component\Console\Input\InputOption; * * php Thelia admin:updatePassword * - * Class AdminUpdatePassword + * Class AdminUpdatePasswordCommand * @package Thelia\Command * @author Manuel Raynaud */ -class AdminUpdatePassword extends ContainerAwareCommand +class AdminUpdatePasswordCommand extends ContainerAwareCommand { /** @@ -60,4 +67,34 @@ class AdminUpdatePassword extends ContainerAwareCommand ) ; } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $login = $input->getArgument('login'); + + + if (null === $admin = AdminQuery::create()->filterByLogin($login)->findOne()) { + throw new \RuntimeException(sprintf('Admin with login %s does not exists', $login)); + } + + + $password = $input->getOption('password') ?: Password::generateRandom(); + + $event = new AdministratorUpdatePasswordEvent($admin); + $event->setPassword($password); + + + $this-> + getContainer() + ->get('event_dispatcher') + ->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event); + + $output->writeln(array( + '', + sprintf('admin %s password updated', $login), + sprintf('new password is : %s', $password), + '' + )); + + } } \ No newline at end of file diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index c0af99896..255f70dfd 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -182,6 +182,7 @@ + diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php index cccb45cc4..01a36a206 100644 --- a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -23,6 +23,7 @@ namespace Thelia\Core\Event\Administrator; use Thelia\Core\Event\ActionEvent; +use Thelia\Model\Admin; /** @@ -34,18 +35,18 @@ class AdministratorUpdatePasswordEvent extends ActionEvent { /** - * @var string administrator login + * @var \Thelia\Model\Admin */ - protected $login; + protected $admin; /** * @var string new administrator password */ protected $password; - public function __construct($login) + public function __construct(Admin $admin) { - $this->login = $login; + $this->admin = $admin; } /** @@ -65,20 +66,22 @@ class AdministratorUpdatePasswordEvent extends ActionEvent } /** - * @param string $login + * @param \Thelia\Model\Admin $admin */ - public function setLogin($login) + public function setAdmin(Admin $admin) { - $this->login = $login; + $this->admin = $admin; } /** - * @return string + * @return \Thelia\Model\Admin */ - public function getLogin() + public function getAdmin() { - return $this->login; + return $this->admin; } + + } \ No newline at end of file diff --git a/local/modules/Cheque/Config/config.xml b/local/modules/Cheque/Config/config.xml index 2430f5027..cac3f6b7b 100755 --- a/local/modules/Cheque/Config/config.xml +++ b/local/modules/Cheque/Config/config.xml @@ -1,4 +1,4 @@ - +string Date: Wed, 30 Oct 2013 14:27:45 +0100 Subject: [PATCH 05/17] create administrator update password event --- .../AdministratorUpdatePasswordEvent.php | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php new file mode 100644 index 000000000..b41b83a06 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -0,0 +1,84 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event\Administrator; +use Thelia\Core\Event\ActionEvent; + + +/** + * Class AdministratorUpdatePasswordEvent + * @package Thelia\Core\Event\Administrator + * @author Manuel Raynaud + */ +class AdministratorUpdatePasswordEvent extends ActionEvent +{ + + /** + * @var string administrator login + */ + protected $login; + + /** + * @var string new administrator password + */ + protected $password; + + public function __construct($login) + { + $this->login = $login; + } + + /** + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $login + */ + public function setLogin($login) + { + $this->login = $login; + } + + /** + * @return string + */ + public function getLogin() + { + return $this->login; + } + + +} \ No newline at end of file From c327b20fd640ffb694a81fd78be406d34f120747 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 14:46:21 +0100 Subject: [PATCH 06/17] change command line for creating new administrator --- core/lib/Thelia/Command/CreateAdminUser.php | 2 +- reset_install.bat | 2 +- reset_install.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index 857790141..5ac62802a 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -38,7 +38,7 @@ class CreateAdminUser extends ContainerAwareCommand protected function configure() { $this - ->setName("thelia:create-admin") + ->setName("admin:create") ->setDescription("Create a new adminsitration user") ->setHelp("The thelia:create-admin command create a new administration user.") ->addOption( diff --git a/reset_install.bat b/reset_install.bat index 0a12c43d2..f8c0b35e2 100644 --- a/reset_install.bat +++ b/reset_install.bat @@ -26,7 +26,7 @@ if exist local\config\database.yml ( php install\faker.php echo [INFO] Adding admin - php Thelia thelia:create-admin + php Thelia admin:create echo [SUCCESS] Reset done ) diff --git a/reset_install.sh b/reset_install.sh index a91a2dc1c..83288a509 100755 --- a/reset_install.sh +++ b/reset_install.sh @@ -32,7 +32,7 @@ echo -e "\n\033[01;34m[INFO] Installing fixtures\033[00m\n" php install/faker.php echo -e "\n\033[01;34m[INFO] Adding admin\033[00m\n" -php Thelia thelia:create-admin --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 +php Thelia admin:create --login_name thelia2 --password thelia2 --last_name thelia2 --first_name thelia2 echo -e "\n\033[01;34m[INFO] Clearing caches\033[00m\n" php Thelia cache:clear From 66c30a1b4c376f6b321638e39b20e76860805cb6 Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 15:01:18 +0100 Subject: [PATCH 07/17] start creating admin password recovery --- core/lib/Thelia/Action/Administrator.php | 16 ++++- .../Thelia/Command/AdminUpdatePassword.php | 63 +++++++++++++++++++ core/lib/Thelia/Command/CreateAdminUser.php | 4 +- core/lib/Thelia/Core/Event/TheliaEvents.php | 1 + 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 core/lib/Thelia/Command/AdminUpdatePassword.php diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php index 2bbfce8a8..23167dd40 100644 --- a/core/lib/Thelia/Action/Administrator.php +++ b/core/lib/Thelia/Action/Administrator.php @@ -25,6 +25,7 @@ namespace Thelia\Action; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Thelia\Core\Event\Administrator\AdministratorEvent; +use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; use Thelia\Core\Event\TheliaEvents; use Thelia\Model\Admin as AdminModel; use Thelia\Model\AdminQuery; @@ -92,15 +93,24 @@ class Administrator extends BaseAction implements EventSubscriberInterface } } + public function updatePassword(AdministratorUpdatePasswordEvent $event) + { + if (null !== $admin = AdminQuery::create()->filterByLogin($event->getLogin())->findOne()) { + $admin->setPassword($event->getPassword()) + ->save(); + } + } + /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( - TheliaEvents::ADMINISTRATOR_CREATE => array("create", 128), - TheliaEvents::ADMINISTRATOR_UPDATE => array("update", 128), - TheliaEvents::ADMINISTRATOR_DELETE => array("delete", 128), + TheliaEvents::ADMINISTRATOR_CREATE => array('create', 128), + TheliaEvents::ADMINISTRATOR_UPDATE => array('update', 128), + TheliaEvents::ADMINISTRATOR_DELETE => array('delete', 128), + TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD => array('updatePassword', 128) ); } } diff --git a/core/lib/Thelia/Command/AdminUpdatePassword.php b/core/lib/Thelia/Command/AdminUpdatePassword.php new file mode 100644 index 000000000..f6cf8ee64 --- /dev/null +++ b/core/lib/Thelia/Command/AdminUpdatePassword.php @@ -0,0 +1,63 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; + + +/** + * command line for updating admin password + * + * php Thelia admin:updatePassword + * + * Class AdminUpdatePassword + * @package Thelia\Command + * @author Manuel Raynaud + */ +class AdminUpdatePassword extends ContainerAwareCommand +{ + + /** + * Configures the current command. + */ + protected function configure() + { + $this + ->setName('admin:updatePassword') + ->setDescription('change administrator password') + ->setHelp('The admin:updatePassword command allows you to change the password for a given administrator') + ->addArgument( + 'login', + InputArgument::REQUIRED, + 'Login for administrator you want to change the password' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'Desired password. If this option is omitted, a random password is generated and shown in this prompt after' + ) + ; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Command/CreateAdminUser.php b/core/lib/Thelia/Command/CreateAdminUser.php index 5ac62802a..988122e7a 100644 --- a/core/lib/Thelia/Command/CreateAdminUser.php +++ b/core/lib/Thelia/Command/CreateAdminUser.php @@ -39,8 +39,8 @@ class CreateAdminUser extends ContainerAwareCommand { $this ->setName("admin:create") - ->setDescription("Create a new adminsitration user") - ->setHelp("The thelia:create-admin command create a new administration user.") + ->setDescription("Create a new administrator user") + ->setHelp("The admin:create command create a new administration user.") ->addOption( 'login_name', null, diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 42b20d8cd..ea3d7686a 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -565,6 +565,7 @@ final class TheliaEvents const ADMINISTRATOR_CREATE = "action.createAdministrator"; const ADMINISTRATOR_UPDATE = "action.updateAdministrator"; const ADMINISTRATOR_DELETE = "action.deleteAdministrator"; + const ADMINISTRATOR_UPDATEPASSWORD = 'action.generatePassword'; // -- Mailing System management --------------------------------------------- From 78cba61cd56938cdde781278a3c515daffdcd7ec Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 15:33:25 +0100 Subject: [PATCH 08/17] finish admin update password command line --- core/lib/Thelia/Action/Administrator.php | 7 ++-- ...ord.php => AdminUpdatePasswordCommand.php} | 41 ++++++++++++++++++- core/lib/Thelia/Config/Resources/config.xml | 1 + .../AdministratorUpdatePasswordEvent.php | 23 ++++++----- local/modules/Cheque/Config/config.xml | 2 +- 5 files changed, 57 insertions(+), 17 deletions(-) rename core/lib/Thelia/Command/{AdminUpdatePassword.php => AdminUpdatePasswordCommand.php} (70%) diff --git a/core/lib/Thelia/Action/Administrator.php b/core/lib/Thelia/Action/Administrator.php index 23167dd40..15940082a 100644 --- a/core/lib/Thelia/Action/Administrator.php +++ b/core/lib/Thelia/Action/Administrator.php @@ -95,10 +95,9 @@ class Administrator extends BaseAction implements EventSubscriberInterface public function updatePassword(AdministratorUpdatePasswordEvent $event) { - if (null !== $admin = AdminQuery::create()->filterByLogin($event->getLogin())->findOne()) { - $admin->setPassword($event->getPassword()) - ->save(); - } + $admin = $event->getAdmin(); + $admin->setPassword($event->getPassword()) + ->save(); } /** diff --git a/core/lib/Thelia/Command/AdminUpdatePassword.php b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php similarity index 70% rename from core/lib/Thelia/Command/AdminUpdatePassword.php rename to core/lib/Thelia/Command/AdminUpdatePasswordCommand.php index f6cf8ee64..035dc75e3 100644 --- a/core/lib/Thelia/Command/AdminUpdatePassword.php +++ b/core/lib/Thelia/Command/AdminUpdatePasswordCommand.php @@ -22,8 +22,15 @@ /*************************************************************************************/ 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 Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Model\AdminQuery; +use Thelia\Tools\Password; /** @@ -31,11 +38,11 @@ use Symfony\Component\Console\Input\InputOption; * * php Thelia admin:updatePassword * - * Class AdminUpdatePassword + * Class AdminUpdatePasswordCommand * @package Thelia\Command * @author Manuel Raynaud */ -class AdminUpdatePassword extends ContainerAwareCommand +class AdminUpdatePasswordCommand extends ContainerAwareCommand { /** @@ -60,4 +67,34 @@ class AdminUpdatePassword extends ContainerAwareCommand ) ; } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $login = $input->getArgument('login'); + + + if (null === $admin = AdminQuery::create()->filterByLogin($login)->findOne()) { + throw new \RuntimeException(sprintf('Admin with login %s does not exists', $login)); + } + + + $password = $input->getOption('password') ?: Password::generateRandom(); + + $event = new AdministratorUpdatePasswordEvent($admin); + $event->setPassword($password); + + + $this-> + getContainer() + ->get('event_dispatcher') + ->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event); + + $output->writeln(array( + '', + sprintf('admin %s password updated', $login), + sprintf('new password is : %s', $password), + '' + )); + + } } \ No newline at end of file diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index c0af99896..255f70dfd 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -182,6 +182,7 @@ + diff --git a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php index b41b83a06..e6a5894ac 100644 --- a/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php +++ b/core/lib/Thelia/Core/Event/Administrator/AdministratorUpdatePasswordEvent.php @@ -23,6 +23,7 @@ namespace Thelia\Core\Event\Administrator; use Thelia\Core\Event\ActionEvent; +use Thelia\Model\Admin; /** @@ -34,18 +35,18 @@ class AdministratorUpdatePasswordEvent extends ActionEvent { /** - * @var string administrator login + * @var \Thelia\Model\Admin */ - protected $login; + protected $admin; /** * @var string new administrator password */ protected $password; - public function __construct($login) + public function __construct(Admin $admin) { - $this->login = $login; + $this->admin = $admin; } /** @@ -65,20 +66,22 @@ class AdministratorUpdatePasswordEvent extends ActionEvent } /** - * @param string $login + * @param \Thelia\Model\Admin $admin */ - public function setLogin($login) + public function setAdmin(Admin $admin) { - $this->login = $login; + $this->admin = $admin; } /** - * @return string + * @return \Thelia\Model\Admin */ - public function getLogin() + public function getAdmin() { - return $this->login; + return $this->admin; } + + } \ No newline at end of file diff --git a/local/modules/Cheque/Config/config.xml b/local/modules/Cheque/Config/config.xml index 2430f5027..cac3f6b7b 100755 --- a/local/modules/Cheque/Config/config.xml +++ b/local/modules/Cheque/Config/config.xml @@ -1,4 +1,4 @@ - +string Date: Wed, 30 Oct 2013 15:44:32 +0100 Subject: [PATCH 09/17] Combination creation management --- core/lib/Thelia/Action/Attribute.php | 2 +- core/lib/Thelia/Action/Feature.php | 2 +- core/lib/Thelia/Action/ProductSaleElement.php | 90 +++++++- core/lib/Thelia/Config/Resources/config.xml | 2 + .../Thelia/Config/Resources/routing/admin.xml | 4 + .../Controller/Admin/FeatureController.php | 17 -- .../Controller/Admin/ProductController.php | 104 +++++++++ .../ProductCombinationGenerationEvent.php | 159 +++++++++++++ core/lib/Thelia/Core/Event/TheliaEvents.php | 2 + .../Template/Loop/AttributeAvailability.php | 19 +- .../Core/Template/Smarty/Plugins/Form.php | 29 ++- .../Form/ProductCombinationGenerationForm.php | 91 ++++++++ .../ProductDefaultSaleElementUpdateForm.php | 4 +- .../Form/ProductSaleElementUpdateForm.php | 4 +- core/lib/Thelia/Model/Attribute.php | 2 +- core/lib/Thelia/Model/Feature.php | 2 +- core/lib/Thelia/Model/Product.php | 15 +- .../default/assets/less/thelia/modals.less | 15 ++ .../default/includes/generic-js-dialog.html | 7 + .../default/includes/product-details-tab.html | 217 ++++++++++++++++-- templates/admin/default/product-edit.html | 56 +++++ 21 files changed, 766 insertions(+), 77 deletions(-) create mode 100644 core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php create mode 100644 core/lib/Thelia/Form/ProductCombinationGenerationForm.php diff --git a/core/lib/Thelia/Action/Attribute.php b/core/lib/Thelia/Action/Attribute.php index 7db04518a..30ceea0e8 100644 --- a/core/lib/Thelia/Action/Attribute.php +++ b/core/lib/Thelia/Action/Attribute.php @@ -63,7 +63,7 @@ class Attribute extends BaseAction implements EventSubscriberInterface // Add atribute to all product templates if required if ($event->getAddToAllTemplates() != 0) { - // TODO: add to all product template + $this->doAddToAllTemplates($attribute); } } diff --git a/core/lib/Thelia/Action/Feature.php b/core/lib/Thelia/Action/Feature.php index 6ae7645e3..36853f444 100644 --- a/core/lib/Thelia/Action/Feature.php +++ b/core/lib/Thelia/Action/Feature.php @@ -63,7 +63,7 @@ class Feature extends BaseAction implements EventSubscriberInterface // Add atribute to all product templates if required if ($event->getAddToAllTemplates() != 0) { - // TODO: add to all product template + $this->doAddToAllTemplates($feature); } } diff --git a/core/lib/Thelia/Action/ProductSaleElement.php b/core/lib/Thelia/Action/ProductSaleElement.php index 8349eb1bf..9c40025d8 100644 --- a/core/lib/Thelia/Action/ProductSaleElement.php +++ b/core/lib/Thelia/Action/ProductSaleElement.php @@ -40,6 +40,8 @@ use Thelia\Model\AttributeAvQuery; use Thelia\Model\Currency; use Thelia\Model\Map\AttributeCombinationTableMap; use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; +use Propel\Runtime\Connection\ConnectionInterface; class ProductSaleElement extends BaseAction implements EventSubscriberInterface { @@ -65,7 +67,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface if ($salesElement == null) { // Create a new default product sale element - $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true); + $salesElement = $event->getProduct()->createDefaultProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true); } else { // This (new) one is the default $salesElement->setIsDefault(true)->save($con); @@ -87,7 +89,7 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface ->setAttributeAvId($attributeAvId) ->setAttribute($attributeAv->getAttribute()) ->setProductSaleElements($salesElement) - ->save(); + ->save($con); } } } @@ -206,8 +208,9 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface if ($product->countSaleElements() <= 0) { // If we just deleted the last PSE, create a default one - $product->createDefaultProductSaleElement($con, 0, 0, $event->getCurrencyId(), true); - } elseif ($pse->getIsDefault()) { + $product->createProductSaleElement($con, 0, 0, 0, $event->getCurrencyId(), true); + } + elseif ($pse->getIsDefault()) { // If we deleted the default PSE, make the last created one the default $pse = ProductSaleElementsQuery::create() @@ -230,6 +233,83 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface } } + /** + * Generate combinations. All existing combinations for the product are deleted. + * + * @param ProductCombinationGenerationEvent $event + */ + public function generateCombinations(ProductCombinationGenerationEvent $event) { + + $con = Propel::getWriteConnection(ProductSaleElementsTableMap::DATABASE_NAME); + + $con->beginTransaction(); + + try { + + // Delete all product's productSaleElement + ProductSaleElementsQuery::create()->filterByProductId($event->product->getId())->delete(); + + $isDefault = true; + + // Create all combinations + foreach($event->getCombinations() as $combinationAttributesAvIds) { + + // Create the PSE + $saleElement = $event->getProduct()->createProductSaleElement( + $con, + $event->getWeight(), + $event->getPrice(), + $event->getSalePrice(), + $event->getCurrencyId(), + $isDefault, + $event->getOnsale(), + $event->getIsnew(), + $event->getQuantity(), + $event->getEanCode(), + $event->getReference() + ); + + $isDefault = false; + + $this->createCombination($con, $saleElement, $combinationAttributesAvIds); + } + + // Store all the stuff ! + $con->commit(); + } + catch (\Exception $ex) { + + $con->rollback(); + + throw $ex; + } + } + + /** + * Create a combination for a given product sale element + * + * @param ConnectionInterface $con the Propel connection + * @param ProductSaleElement $salesElement the product sale element + * @param unknown $combinationAttributes an array oif attributes av IDs + */ + protected function createCombination(ConnectionInterface $con, ProductSaleElements $salesElement, $combinationAttributes) + { + foreach ($combinationAttributes as $attributeAvId) { + + $attributeAv = AttributeAvQuery::create()->findPk($attributeAvId); + + if ($attributeAv !== null) { + $attributeCombination = new AttributeCombination(); + + $attributeCombination + ->setAttributeAvId($attributeAvId) + ->setAttribute($attributeAv->getAttribute()) + ->setProductSaleElements($salesElement) + ->save($con); + } + } + } + /** * {@inheritDoc} */ @@ -239,6 +319,8 @@ class ProductSaleElement extends BaseAction implements EventSubscriberInterface TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT => array("create", 128), TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT => array("update", 128), TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT => array("delete", 128), + TheliaEvents::PRODUCT_COMBINATION_GENERATION => array("generateCombinations", 128), + ); } } diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index c0af99896..84e9ef92e 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -90,6 +90,8 @@
+ + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index dc5a2c522..64bf37541 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -372,6 +372,10 @@ Thelia\Controller\Admin\ProductController::updateProductSaleElementsAction + + Thelia\Controller\Admin\ProductController::buildCombinationsAction + + Thelia\Controller\Admin\ProductController::updateProductDefaultSaleElementAction diff --git a/core/lib/Thelia/Controller/Admin/FeatureController.php b/core/lib/Thelia/Controller/Admin/FeatureController.php index 7696b9c6e..1be5dfeec 100644 --- a/core/lib/Thelia/Controller/Admin/FeatureController.php +++ b/core/lib/Thelia/Controller/Admin/FeatureController.php @@ -157,23 +157,6 @@ class FeatureController extends AbstractCrudController 'postscriptum' => $object->getPostscriptum() ); - // Setup features values - /* - * FIXME : doesn't work. "We get a This form should not contain extra fields." error - $attr_av_list = FeatureAvQuery::create() - ->joinWithI18n($this->getCurrentEditionLocale()) - ->filterByFeatureId($object->getId()) - ->find(); - - $attr_array = array(); - - foreach ($attr_av_list as $attr_av) { - $attr_array[$attr_av->getId()] = $attr_av->getTitle(); - } - - $data['feature_values'] = $attr_array; - */ - // Setup the object form return new FeatureModificationForm($this->getRequest(), "form", $data); } diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php index 84e16815d..5540c529b 100644 --- a/core/lib/Thelia/Controller/Admin/ProductController.php +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -64,6 +64,8 @@ use Thelia\Model\Country; use Thelia\Tools\NumberFormat; use Thelia\Model\Product; use Thelia\Model\CurrencyQuery; +use Thelia\Form\ProductCombinationGenerationForm; +use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; /** * Manages products @@ -1025,6 +1027,108 @@ class ProductController extends AbstractCrudController ); } + // Create combinations + protected function combine($input, &$output, &$tmp) { + $current = array_shift($input); + + if (count($input) > 0) { + foreach($current as $element) { + $tmp[] = $element; + $this->combine($input, $output, $tmp); + array_pop($tmp); + } + } else { + foreach($current as $element) { + $tmp[] = $element; + $output[] = $tmp; + array_pop($tmp); + } + } + } + + /** + * Build combinations from the combination output builder + */ + public function buildCombinationsAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth($this->resourceCode, AccessManager::UPDATE)) return $response; + + $error_msg = false; + + $changeForm = new ProductCombinationGenerationForm($this->getRequest()); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + // Rework attributes_av array, to build an array which contains all combinations, + // in the form combination[] = array of combination attributes av IDs + // + // First, create an array of attributes_av ID in the form $attributes_av_list[$attribute_id] = array of attributes_av ID + // from the list of attribute_id:attributes_av ID from the form. + $combinations = $attributes_av_list = array(); + + foreach($data['attribute_av'] as $item) { + list($attribute_id, $attribute_av_id) = explode(':', $item); + + if (! isset($attributes_av_list[$attribute_id])) + $attributes_av_list[$attribute_id] = array(); + + + $attributes_av_list[$attribute_id][] = $attribute_av_id; + } + + // Next, recursively combine array + $combinations = $tmp = array(); + + $this->combine($attributes_av_list, $combinations, $tmp); + + // Create event + $event = new ProductCombinationGenerationEvent( + $this->getExistingObject(), + $data['currency'], + $combinations + ); + + $event + ->setReference($data['reference'] == null ? '' : $data['reference']) + ->setPrice($data['price'] == null ? 0 : $data['price']) + ->setWeight($data['weight'] == null ? 0 : $data['weight']) + ->setQuantity($data['quantity'] == null ? 0 : $data['quantity']) + ->setSalePrice($data['sale_price'] == null ? 0 : $data['sale_price']) + ->setOnsale($data['onsale'] == null ? false : $data['onsale']) + ->setIsnew($data['isnew'] == null ? false : $data['isnew']) + ->setEanCode($data['ean_code'] == null ? '' : $data['ean_code']) + ; + + $this->dispatch(TheliaEvents::PRODUCT_COMBINATION_GENERATION, $event); + + // Log object modification + $this->adminLogAppend(sprintf("Combination generation for product reference %s", $event->getProduct()->getRef())); + + // Redirect to the success URL + $this->redirect($changeForm->getSuccessUrl()); + + } catch (FormValidationException $ex) { + // Form cannot be validated + $error_msg = $this->createStandardFormValidationErrorMessage($ex); + } catch (\Exception $ex) { + // Any other error + $error_msg = $ex->getMessage(); + } + + $this->setupFormErrorContext( + $this->getTranslator()->trans("Combination builder"), $error_msg, $changeForm, $ex); + + // At this point, the form has errors, and should be redisplayed. + return $this->renderEditionTemplate(); + } + /** * Invoked through Ajax; this method calculates the taxed price from the unaxed price, and * vice versa. diff --git a/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php new file mode 100644 index 000000000..05b55d733 --- /dev/null +++ b/core/lib/Thelia/Core/Event/Product/ProductCombinationGenerationEvent.php @@ -0,0 +1,159 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event\Product; +use Thelia\Model\Product; + +class ProductCombinationGenerationEvent extends ProductEvent +{ + protected $reference; + protected $price; + protected $currency_id; + protected $weight; + protected $quantity; + protected $sale_price; + protected $onsale; + protected $isnew; + protected $ean_code; + protected $combinations; + + public function __construct(Product $product, $currency_id, $combinations) + { + parent::__construct($product); + + $this->setCombinations($combinations); + $this->setCurrencyId($currency_id); + } + + public function getCurrencyId() + { + return $this->currency_id; + } + + public function setCurrencyId($currency_id) + { + $this->currency_id = $currency_id; + + return $this; + } + + public function getReference() + { + return $this->reference; + } + + public function setReference($reference) + { + $this->reference = $reference; + return $this; + } + + public function getPrice() + { + return $this->price; + } + + public function setPrice($price) + { + $this->price = $price; + return $this; + } + + public function getWeight() + { + return $this->weight; + } + + public function setWeight($weight) + { + $this->weight = $weight; + return $this; + } + + public function getQuantity() + { + return $this->quantity; + } + + public function setQuantity($quantity) + { + $this->quantity = $quantity; + return $this; + } + + public function getSalePrice() + { + return $this->sale_price; + } + + public function setSalePrice($sale_price) + { + $this->sale_price = $sale_price; + return $this; + } + + public function getOnsale() + { + return $this->onsale; + } + + public function setOnsale($onsale) + { + $this->onsale = $onsale; + return $this; + } + + public function getIsnew() + { + return $this->isnew; + } + + public function setIsnew($isnew) + { + $this->isnew = $isnew; + return $this; + } + + public function getEanCode() + { + return $this->ean_code; + } + + public function setEanCode($ean_code) + { + $this->ean_code = $ean_code; + return $this; + return $this; + } + + public function getCombinations() + { + return $this->combinations; + } + + public function setCombinations($combinations) + { + $this->combinations = $combinations; + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 42b20d8cd..dfd2d27aa 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -285,6 +285,8 @@ final class TheliaEvents const PRODUCT_DELETE_PRODUCT_SALE_ELEMENT = "action.deleteProductSaleElement"; const PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT = "action.updateProductSaleElement"; + const PRODUCT_COMBINATION_GENERATION = "action.productCombineationGeneration"; + const PRODUCT_SET_TEMPLATE = "action.productSetTemplate"; const PRODUCT_ADD_ACCESSORY = "action.productAddProductAccessory"; diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php index e9a7d9eb8..10c1dda00 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php @@ -128,14 +128,17 @@ class AttributeAvailability extends BaseI18nLoop foreach ($attributesAv as $attributeAv) { $loopResultRow = new LoopResultRow($loopResult, $attributeAv, $this->versionable, $this->timestampable, $this->countable); - $loopResultRow->set("ID", $attributeAv->getId()) - ->set("IS_TRANSLATED",$attributeAv->getVirtualColumn('IS_TRANSLATED')) - ->set("LOCALE",$locale) - ->set("TITLE",$attributeAv->getVirtualColumn('i18n_TITLE')) - ->set("CHAPO", $attributeAv->getVirtualColumn('i18n_CHAPO')) - ->set("DESCRIPTION", $attributeAv->getVirtualColumn('i18n_DESCRIPTION')) - ->set("POSTSCRIPTUM", $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set("POSITION", $attributeAv->getPosition()); + $loopResultRow + ->set("ID" , $attributeAv->getId()) + ->set("ATTRIBUTE_ID" , $attributeAv->getAttributeId()) + ->set("IS_TRANSLATED", $attributeAv->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE" , $locale) + ->set("TITLE" , $attributeAv->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO" , $attributeAv->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION" , $attributeAv->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM" , $attributeAv->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("POSITION" , $attributeAv->getPosition()) + ; $loopResult->addRow($loopResultRow); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index 494e219eb..ee49fe1ec 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -199,30 +199,29 @@ class Form extends AbstractSmartyPlugin { if ($repeat) { - $formFieldView = $this->getFormFieldView($params); - $formFieldConfig = $this->getFormFieldConfig($params); + $formFieldView = $this->getFormFieldView($params); + $formFieldConfig = $this->getFormFieldConfig($params); - $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView); + $this->assignFormTypeValues($template, $formFieldConfig, $formFieldView); $value = $formFieldView->vars["value"]; - // We have a collection - if (0 < $value_count = count($formFieldView->children)) { + $key = $this->getParam($params, 'value_key', null); - $key = $this->getParam($params, 'value_key', null); + // We (may) have a collection + if ($key !== null) { - if ($key !== null) { - // If the field is not found, use an empty value - $val = array_key_exists($key, $value) ? $value[$key] : ''; + // Force array + if (! is_array($value)) $value = array(); - $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key); + // If the field is not found, use an empty value + $val = array_key_exists($key, $value) ? $value[$key] : ''; - $val = $value[$key]; + $name = sprintf("%s[%s]", $formFieldView->vars["full_name"], $key); - $this->assignFieldValues($template, $name, $val, $formFieldView->vars, $value_count); - } else { - throw new \InvalidArgumentException(sprintf("Missing or empty parameter 'value_key' for field '%s'", $formFieldView->vars["name"])); - } + $val = $value[$key]; + + $this->assignFieldValues($template, $name, $val, $formFieldView->vars, count($formFieldView->children)); } else { $this->assignFieldValues($template, $formFieldView->vars["full_name"], $formFieldView->vars["value"], $formFieldView->vars); } diff --git a/core/lib/Thelia/Form/ProductCombinationGenerationForm.php b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php new file mode 100644 index 000000000..8e4b155b9 --- /dev/null +++ b/core/lib/Thelia/Form/ProductCombinationGenerationForm.php @@ -0,0 +1,91 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\GreaterThan; +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Model\Currency; +use Thelia\Core\Translation\Translator; + +class ProductCombinationGenerationForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add('product_id', 'integer', array( + 'label' => Translator::getInstance()->trans('Product ID'), + 'label_attr' => array('for' => 'combination_builder_id_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))) + )) + ->add('currency', 'integer', array( + 'label' => Translator::getInstance()->trans('Price currency *'), + 'label_attr' => array('for' => 'combination_builder_currency_field'), + 'constraints' => array(new GreaterThan(array('value' => 0))) + )) + ->add('reference', 'text', array( + 'label' => Translator::getInstance()->trans('Reference'), + 'label_attr' => array('for' => 'combination_builder_reference_field') + )) + ->add('price', 'number', array( + 'label' => Translator::getInstance()->trans('Product price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_field') + )) + ->add('weight', 'number', array( + 'label' => Translator::getInstance()->trans('Weight'), + 'label_attr' => array('for' => 'combination_builder_weight_field') + )) + ->add('quantity', 'number', array( + 'label' => Translator::getInstance()->trans('Available quantity'), + 'label_attr' => array('for' => 'combination_builder_quantity_field') + )) + ->add('sale_price', 'number', array( + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), + 'label_attr' => array('for' => 'combination_builder_price_with_tax_field') + )) + ->add('onsale', 'integer', array( + 'label' => Translator::getInstance()->trans('This product is on sale'), + 'label_attr' => array('for' => 'combination_builder_onsale_field') + )) + ->add('isnew', 'integer', array( + 'label' => Translator::getInstance()->trans('Advertise this product as new'), + 'label_attr' => array('for' => 'combination_builder_isnew_field') + )) + ->add('ean_code', 'text', array( + 'label' => Translator::getInstance()->trans('EAN Code'), + 'label_attr' => array('for' => 'combination_builder_ean_code_field') + )) + ->add('attribute_av', 'collection', array( + 'type' => 'text', + 'label' => Translator::getInstance()->trans('Attribute ID:Attribute AV ID'), + 'label_attr' => array('for' => 'combination_builder_attribute_av_id'), + 'allow_add' => true, + 'allow_delete' => true, + )) + ; + } + + public function getName() + { + return 'thelia_product_combination_generation_form'; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php index 2643692a2..54fb2fdc1 100644 --- a/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php +++ b/core/lib/Thelia/Form/ProductDefaultSaleElementUpdateForm.php @@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator; class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm { - use StandardDescriptionFieldsTrait; - protected function buildForm() { $this->formBuilder @@ -77,7 +75,7 @@ class ProductDefaultSaleElementUpdateForm extends ProductSaleElementUpdateForm "label_attr" => array("for" => "quantity_field") )) ->add("sale_price", "number", array( - "label" => Translator::getInstance()->trans("Sale price without taxes"), + "label" => Translator::getInstance()->trans("Sale price excluding taxes"), "label_attr" => array("for" => "price_with_tax_field") )) ->add("sale_price_with_tax", "number", array( diff --git a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php index da831545a..cda72cc72 100644 --- a/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php +++ b/core/lib/Thelia/Form/ProductSaleElementUpdateForm.php @@ -29,8 +29,6 @@ use Thelia\Core\Translation\Translator; class ProductSaleElementUpdateForm extends BaseForm { - use StandardDescriptionFieldsTrait; - protected function buildForm() { $this->formBuilder @@ -112,7 +110,7 @@ class ProductSaleElementUpdateForm extends BaseForm ) )) ->add('sale_price', 'collection', array( - 'label' => Translator::getInstance()->trans('Sale price without taxes'), + 'label' => Translator::getInstance()->trans('Sale price excluding taxes'), 'label_attr' => array('for' => 'price_with_tax_field'), 'allow_add' => true, 'allow_delete' => true, diff --git a/core/lib/Thelia/Model/Attribute.php b/core/lib/Thelia/Model/Attribute.php index 615fa643e..3439cac06 100755 --- a/core/lib/Thelia/Model/Attribute.php +++ b/core/lib/Thelia/Model/Attribute.php @@ -20,7 +20,7 @@ class Attribute extends BaseAttribute { $this->dispatchEvent(TheliaEvents::BEFORE_CREATEATTRIBUTE, new AttributeEvent($this)); // Set the current position for the new object - //$this->setPosition($this->getNextPosition()); + $this->setPosition($this->getNextPosition()); return true; } diff --git a/core/lib/Thelia/Model/Feature.php b/core/lib/Thelia/Model/Feature.php index 800ff832a..2627d5190 100755 --- a/core/lib/Thelia/Model/Feature.php +++ b/core/lib/Thelia/Model/Feature.php @@ -20,7 +20,7 @@ class Feature extends BaseFeature { $this->dispatchEvent(TheliaEvents::BEFORE_CREATEFEATURE, new FeatureEvent($this)); // Set the current position for the new object - //$this->setPosition($this->getNextPosition()); + $this->setPosition($this->getNextPosition()); return true; } diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index f16a8a776..1b3f1eefa 100755 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -167,7 +167,7 @@ class Product extends BaseProduct $this->setTaxRuleId($taxRuleId); // Create the default product sale element of this product - $sale_elements = $this->createDefaultProductSaleElement($con, $baseWeight, $basePrice, $priceCurrencyId, true); + $sale_elements = $this->createProductSaleElement($con, $baseWeight, $basePrice, $basePrice, $priceCurrencyId, true); // Store all the stuff ! $con->commit(); @@ -185,19 +185,20 @@ class Product extends BaseProduct /** * Create a basic product sale element attached to this product. */ - public function createDefaultProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $currencyId, $isDefault) { + public function createProductSaleElement(ConnectionInterface $con, $weight, $basePrice, $salePrice, $currencyId, $isDefault, $isPromo = false, $isNew = false, $quantity = 0, $eanCode = '', $ref = false) { // Create an empty product sale element $sale_elements = new ProductSaleElements(); $sale_elements ->setProduct($this) - ->setRef($this->getRef()) - ->setPromo(0) - ->setNewness(0) + ->setRef($ref == false ? $this->getRef() : $ref) + ->setPromo($isPromo) + ->setNewness($isNew) ->setWeight($weight) ->setIsDefault($isDefault) - ->setEanCode('') + ->setEanCode($eanCode) + ->setQuantity($quantity) ->save($con) ; @@ -206,7 +207,7 @@ class Product extends BaseProduct $product_price ->setProductSaleElements($sale_elements) - ->setPromoPrice($basePrice) + ->setPromoPrice($salePrice) ->setPrice($basePrice) ->setCurrencyId($currencyId) ->save($con) diff --git a/templates/admin/default/assets/less/thelia/modals.less b/templates/admin/default/assets/less/thelia/modals.less index 2d371e6c0..ee6b3c662 100755 --- a/templates/admin/default/assets/less/thelia/modals.less +++ b/templates/admin/default/assets/less/thelia/modals.less @@ -9,7 +9,22 @@ } } +.modal-header { + h3 { + margin-bottom: 0; + } +} + // Body (where all modal content resides) .modal-body { max-height: none; + .scrollable { + border: 1px solid @input-border; + border-radius: @input-border-radius; + height: 458px; + overflow: auto; + padding-bottom: 5px; + padding-left: 10px; + padding-top: 5px; + } } \ No newline at end of file diff --git a/templates/admin/default/includes/generic-js-dialog.html b/templates/admin/default/includes/generic-js-dialog.html index 891bb0957..f12a64664 100644 --- a/templates/admin/default/includes/generic-js-dialog.html +++ b/templates/admin/default/includes/generic-js-dialog.html @@ -30,6 +30,13 @@ $('#{$dialog_id}').on('hidden.bs.modal', function() { // Clear error status $("#{$dialog_id} .error").removeClass('error'); + $('#{$dialog_id} .form-group').removeClass('has-error') + // Empty field values $("#{$dialog_id} input[type=text], #{$dialog_id} select").val(''); + + // Uncheck boxes + $("#{$dialog_id} input[type=checkbox]").removeAttr('checked'); + + {$additionnal_js_code|default:''} }); \ No newline at end of file diff --git a/templates/admin/default/includes/product-details-tab.html b/templates/admin/default/includes/product-details-tab.html index 67b20ab77..096b0a7e7 100644 --- a/templates/admin/default/includes/product-details-tab.html +++ b/templates/admin/default/includes/product-details-tab.html @@ -26,9 +26,8 @@ close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" } - {* Be sure to get the product ID, even if the form could not be validated *} + {* Be sure to get the product ID and current tab, even if the form could not be validated *} - {form_hidden_fields form=$form} @@ -177,8 +176,6 @@ {/form_field} - {module_include location='product_details_shipping_form'} - {form_field form=$form field='quantity'}
@@ -189,7 +186,7 @@
{/form_field} - {module_include location='product_details_quantity_form'} + {module_include location='product_details_details_form'} @@ -268,9 +265,8 @@ close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}" } - {* Be sure to get the product ID, even if the form could not be validated *} + {* Be sure to get the product ID and current tab, even if the form could not be validated *} - {form_hidden_fields form=$form} @@ -340,7 +336,7 @@ {module_include location='product_combinations_list_caption'} {loop type="auth" name="can_create" role="ADMIN" resource="admin.product" access="UPDATE"} - + {intl l='Combination builder'} @@ -358,8 +354,8 @@ {intl l='Price
w/ taxes (%currency)' currency=$currency_symbol} {intl l='Weight
(Kg)'} {intl l='Default'} + {intl l='Sale'} {intl l='New'} - {intl l='Sale'} {intl l='Sale price
w/o taxes (%currency)' currency=$currency_symbol} {intl l='Sale price
w/ taxes (%currency)' currency=$currency_symbol}   @@ -375,18 +371,20 @@ {for $idx = 0 to $total_value_count-1} - + {form_field form=$form field='product_sale_element_id' value_key=$idx} {$current_pse_id = $value} - {$current_pse_id}: {loop name="product.sales.elements.combinations" type="attribute_combination" product_sale_elements=$current_pse_id backend_context="1"} + {loop name="product.sales.elements.combinations" type="attribute_combination" product_sale_elements=$current_pse_id backend_context="1"} {if $LOOP_COUNT > 1} - {/if}{$ATTRIBUTE_TITLE} {/loop} {/form_field} + + ID: {$current_pse_id} @@ -469,10 +467,16 @@

{intl l='Attribute Combinations'}

- {intl - l='This product has no combination. The default price is used. Click here to create a new combination' - url='#combination_creation_dialog' - } +

{intl + l='This product has no combination. The default price is used. Click here to create a new combination.' + url='#combination_creation_dialog' + }

+

+ {intl + l='You may also quickly create combinations from products attributes using the Combination Builder.' + url='#combination_builder_dialog' + } +

@@ -494,7 +498,7 @@ @@ -583,3 +587,184 @@ form_action = {url path='/admin/product/combination/delete'} form_content = {$smarty.capture.combination_delete_dialog nofilter} } + +{* -- Combination builder dialog -------------------------------------------- *} + +{* Capture the dialog body, to pass it to the generic dialog *} + +{form name="thelia.admin.product_combination.build"} + +{capture "combination_builder_dialog"} + + {* Be sure to get the product ID and current tab, even if the form could not be validated *} + + + + {form_hidden_fields form=$form} + + {form_field form=$form field='product_id'} + + {/form_field} + + {if $form_error}
{$form_error_message}
{/if} + + {loop type="currency" name="get-currency-symbol" id=$edit_currency_id backend_context="1"} + {$currency_symbol = $SYMBOL} + + {form_field form=$form field='currency'} + + {/form_field} + {/loop} + + {form_field form=$form field='success_url'} + + {/form_field} + +
+ {intl l='Select attribute values to combine. You may enter a default value for some of the fields of the generated combinations.'} +
+ +
+
+
+
    + {$index = 0} + {loop name="product-attributes" type="attribute" order="manual" product=$product_id backend_context="1" lang=$edit_language_id} + {ifloop rel="product-attributes-av"} +
  • + {$TITLE} +
      + {loop name="product-attributes-av" type="attribute_availability" attribute="{$ID}" order="manual" backend_context="1" lang=$edit_language_id} +
    • +
      + +
      +
    • + {$index = $index + 1} + {/loop} +
    +
  • + {/ifloop} + {/loop} +
+
+
+ +
+ {form_field form=$form field='price'} +
+ + +
+ + {$currency_symbol} +
+
+ {/form_field} + + {form_field form=$form field='reference'} +
+ + +
+ +
+
+ {/form_field} + + {form_field form=$form field='ean_code'} +
+ + +
+ +
+
+ {/form_field} + +
+
+ {form_field form=$form field='weight'} +
+ + +
+ + {intl l="Kg"} +
+
+ {/form_field} +
+ +
+ {form_field form=$form field='quantity'} +
+ + +
+ +
+
+ {/form_field} +
+
+ + {form_field form=$form field='sale_price'} +
+ +
+ + {$currency_symbol} +
+
+ {/form_field} + + {form_field form=$form field='onsale'} +
+
+ +
+
+ {/form_field} + + {form_field form=$form field='isnew'} +
+
+ +
+
+ {/form_field} + +
{intl l='0 combinations'}
+
+
+ +{/capture} + +{include + file = "includes/generic-create-dialog.html" + + dialog_id = "combination_builder_dialog" + dialog_title = {intl l="Create combinations"} + dialog_body = {$smarty.capture.combination_builder_dialog nofilter} + + dialog_ok_label = {intl l="Create combinations"} + + form_action = {url path='/admin/product/combination/build'} + form_enctype = {form_enctype form=$form} + form_error_message = '' + + ok_button_id = "combination_builder_dialog_ok" +} + +{/form} diff --git a/templates/admin/default/product-edit.html b/templates/admin/default/product-edit.html index 446e1fd7f..184fb916b 100644 --- a/templates/admin/default/product-edit.html +++ b/templates/admin/default/product-edit.html @@ -344,6 +344,21 @@ $(function() { } } + // -- Combination builder stuff -------------------------------------------- + + $('#open_combination_builder').click(function(ev) { + if (! confirm("{intl l='Existing combiations will be deleted. Do you want to continue ?'}'")) { + ev.preventDefault(); + ev.stopPropagation(); + } + }); + + {include + file = "includes/generic-js-dialog.html" + dialog_id = "combination_builder_dialog" + form_name = "thelia.admin.product_combination.build" + } + // Automatic update of price fields: any change in the taxed (resp. untaxed) price // will update the untaxed (resp. taxed) one $('.automatic_price_field').typeWatch({ @@ -353,6 +368,47 @@ $(function() { update_price($(this).val(), $(this).data('price-type'), $(this).data('rel-price')); } }); + + // Count generated combinations in real time + function countGeneratedCombinations() { + + var total = 0; + + var counter = {}; + + var list = $('.attribute_av_value:checked'); + + if (list.length > 0) { + console.log("ok !"); + + list.each(function() { + var attr_id = $(this).data('attribute-id'); + + console.log("att="+attr_id); + + if (undefined != counter[attr_id]) + counter[attr_id]++; + else + counter[attr_id] = 1; + }); + + console.log(counter); + + total = 1; + + for(var count in counter) { + total *= counter[count]; + } + } + + return total; + } + + $('.attribute_av_value').change(function(ev) { + var total = countGeneratedCombinations(); + + $('#number_of_generated_combinations').text(total); + }); }); From 9f11f475eeaf3d7b95a579f1e605779fc3536e46 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Wed, 30 Oct 2013 15:47:21 +0100 Subject: [PATCH 10/17] Typo --- templates/admin/default/product-edit.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/admin/default/product-edit.html b/templates/admin/default/product-edit.html index 184fb916b..e05bc7434 100644 --- a/templates/admin/default/product-edit.html +++ b/templates/admin/default/product-edit.html @@ -347,7 +347,7 @@ $(function() { // -- Combination builder stuff -------------------------------------------- $('#open_combination_builder').click(function(ev) { - if (! confirm("{intl l='Existing combiations will be deleted. Do you want to continue ?'}'")) { + if (! confirm("{intl l='Existing combinations will be deleted. Do you want to continue ?'}'")) { ev.preventDefault(); ev.stopPropagation(); } From 86d84462adb9432bb144a132fab66112341e661e Mon Sep 17 00:00:00 2001 From: Manuel Raynaud Date: Wed, 30 Oct 2013 16:13:06 +0100 Subject: [PATCH 11/17] clean some code in FileController --- .../Controller/Admin/FileController.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/lib/Thelia/Controller/Admin/FileController.php b/core/lib/Thelia/Controller/Admin/FileController.php index 38b8d74fb..ced780181 100755 --- a/core/lib/Thelia/Controller/Admin/FileController.php +++ b/core/lib/Thelia/Controller/Admin/FileController.php @@ -136,9 +136,9 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Saving images for %parentName% parent id %parentId% (%parentType%)', array( - '%parentName%' => $event->getParentName(), - '%parentId%' => $event->getParentId(), - '%parentType%' => $event->getImageType() + '%parentName%' => $imageCreateOrUpdateEvent->getParentName(), + '%parentId%' => $imageCreateOrUpdateEvent->getParentId(), + '%parentType%' => $imageCreateOrUpdateEvent->getImageType() ), 'image' ) @@ -214,9 +214,9 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Saving documents for %parentName% parent id %parentId% (%parentType%)', array( - '%parentName%' => $event->getParentName(), - '%parentId%' => $event->getParentId(), - '%parentType%' => $event->getDocumentType() + '%parentName%' => $documentCreateOrUpdateEvent->getParentName(), + '%parentId%' => $documentCreateOrUpdateEvent->getParentId(), + '%parentType%' => $documentCreateOrUpdateEvent->getDocumentType() ), 'document' ) @@ -549,8 +549,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Deleting image for %id% with parent id %parentId%', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $imageDeleteEvent->getImageToDelete()->getId(), + '%parentId%' => $imageDeleteEvent->getImageToDelete()->getParentId(), ), 'image' ) @@ -562,8 +562,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Fail to delete image for %id% with parent id %parentId% (Exception : %e%)', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $imageDeleteEvent->getImageToDelete()->getId(), + '%parentId%' => $imageDeleteEvent->getImageToDelete()->getParentId(), '%e%' => $e->getMessage() ), 'image' @@ -621,8 +621,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Deleting document for %id% with parent id %parentId%', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $documentDeleteEvent->getDocumentToDelete()->getId(), + '%parentId%' => $documentDeleteEvent->getDocumentToDelete()->getParentId(), ), 'document' ) @@ -634,8 +634,8 @@ class FileController extends BaseAdminController $this->container->get('thelia.translator')->trans( 'Fail to delete document for %id% with parent id %parentId% (Exception : %e%)', array( - '%id%' => $event->getDocumentToDelete()->getId(), - '%parentId%' => $event->getDocumentToDelete()->getParentId(), + '%id%' => $documentDeleteEvent->getDocumentToDelete()->getId(), + '%parentId%' => $documentDeleteEvent->getDocumentToDelete()->getParentId(), '%e%' => $e->getMessage() ), 'document' From c7835758e5efe45cdf591e88c45f885267d00ff2 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Wed, 30 Oct 2013 16:32:36 +0100 Subject: [PATCH 12/17] Minor css tuning, renamed "details" tab of categories edition to associaitons --- .../default/assets/less/thelia/thelia.less | 23 ++++++++++++------- templates/admin/default/category-edit.html | 10 ++++---- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/templates/admin/default/assets/less/thelia/thelia.less b/templates/admin/default/assets/less/thelia/thelia.less index 0d42273e9..00ab43a74 100644 --- a/templates/admin/default/assets/less/thelia/thelia.less +++ b/templates/admin/default/assets/less/thelia/thelia.less @@ -338,7 +338,7 @@ // -- Drag & drop -- .take{ - + .draggable{ border: 2px dashed @gray-light; margin-bottom: 10px; @@ -346,9 +346,9 @@ &:last-child{ margin-bottom: 0; - } + } } - + .over{ .drop-message{ border-color: @brand-primary; @@ -358,8 +358,8 @@ } -.place{ - +.place{ + .over{ .drop-message{ border-color: @brand-primary; @@ -368,10 +368,10 @@ } .panel-body{ - + .draggable, .drag{ margin: 5px 0; - padding: 10px; + padding: 10px; border: 1px dashed @gray-light; } @@ -390,7 +390,7 @@ } .take, .place{ - + .drop-message{ width: 50%; margin: 10px auto; @@ -410,4 +410,11 @@ .ui-draggable-dragging{ z-index: 100; } +} + +// -- File Upoload drop zone --------------------------------------------------- + +.dropzone { + border: 1px dashed #ddd; + padding: 20px; } \ No newline at end of file diff --git a/templates/admin/default/category-edit.html b/templates/admin/default/category-edit.html index 340e7cbbd..200098d69 100755 --- a/templates/admin/default/category-edit.html +++ b/templates/admin/default/category-edit.html @@ -42,7 +42,7 @@