diff --git a/composer.json b/composer.json index 3597db33d..3c09ecca5 100755 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "php": ">=5.4", "ezyang/htmlpurifier": "dev-master", "ircmaxell/password-compat": "dev-master", - "propel/propel": "2.0.0-alpha1", + "propel/propel": "dev-master", "psr/log" : "1.0", "symfony/class-loader": "2.2.*", "symfony/config" : "2.2.*", @@ -27,7 +27,7 @@ "symfony-cmf/routing": "1.0.0", "symfony/form": "2.2.*", - "symfony/validator": "2.3.*@dev", + "symfony/validator": "2.3.*", "smarty/smarty": "v3.1.14", "kriswallsmith/assetic": "1.2.*@dev", diff --git a/composer.lock b/composer.lock index efa62a9f2..9af980224 100755 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "458aeccc06b7394d7653a9063b6fd981", + "hash": "050e3da6bd52d5743a46e09992cf67c0", "packages": [ { "name": "ezyang/htmlpurifier", @@ -254,16 +254,16 @@ }, { "name": "propel/propel", - "version": "2.0.0-alpha1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/propelorm/Propel2.git", - "reference": "3b9ea45a6e1b9fb3903cb910a31fbbac4a66c184" + "reference": "58a25ded43c3d04313cad2b738342d307988b1b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/propelorm/Propel2/zipball/3b9ea45a6e1b9fb3903cb910a31fbbac4a66c184", - "reference": "3b9ea45a6e1b9fb3903cb910a31fbbac4a66c184", + "url": "https://api.github.com/repos/propelorm/Propel2/zipball/58a25ded43c3d04313cad2b738342d307988b1b5", + "reference": "58a25ded43c3d04313cad2b738342d307988b1b5", "shasum": "" }, "require": { @@ -310,7 +310,7 @@ "orm", "persistence" ], - "time": "2013-06-05 06:46:14" + "time": "2013-09-01 13:29:51" }, { "name": "psr/log", @@ -397,12 +397,12 @@ "source": { "type": "git", "url": "https://github.com/simplepie/simplepie.git", - "reference": "f5436d69a8efa9d4ab3a9abc65d17317eb24b7f4" + "reference": "f97c8ef9be655c35e6fecdb608bdf5af05a4374a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplepie/simplepie/zipball/f5436d69a8efa9d4ab3a9abc65d17317eb24b7f4", - "reference": "f5436d69a8efa9d4ab3a9abc65d17317eb24b7f4", + "url": "https://api.github.com/repos/simplepie/simplepie/zipball/f97c8ef9be655c35e6fecdb608bdf5af05a4374a", + "reference": "f97c8ef9be655c35e6fecdb608bdf5af05a4374a", "shasum": "" }, "require": { @@ -443,7 +443,7 @@ "feeds", "rss" ], - "time": "2013-04-29 06:13:26" + "time": "2013-08-31 01:38:46" }, { "name": "smarty/smarty", @@ -1066,22 +1066,23 @@ }, { "name": "symfony/icu", - "version": "v1.0.0", + "version": "v1.2.0", "target-dir": "Symfony/Component/Icu", "source": { "type": "git", "url": "https://github.com/symfony/Icu.git", - "reference": "v1.0.0" + "reference": "7299cd3d8d6602103d1ebff5d0a9917b7bc6de72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Icu/zipball/v1.0.0", - "reference": "v1.0.0", + "url": "https://api.github.com/repos/symfony/Icu/zipball/7299cd3d8d6602103d1ebff5d0a9917b7bc6de72", + "reference": "7299cd3d8d6602103d1ebff5d0a9917b7bc6de72", "shasum": "" }, "require": { + "lib-icu": ">=4.4", "php": ">=5.3.3", - "symfony/intl": ">=2.3,<3.0" + "symfony/intl": "~2.3" }, "type": "library", "autoload": { @@ -1109,7 +1110,7 @@ "icu", "intl" ], - "time": "2013-06-03 18:32:07" + "time": "2013-06-03 18:32:58" }, { "name": "symfony/intl", @@ -1508,7 +1509,7 @@ }, { "name": "symfony/validator", - "version": "2.3.x-dev", + "version": "v2.3.4", "target-dir": "Symfony/Component/Validator", "source": { "type": "git", @@ -1622,12 +1623,12 @@ "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "feb6492762a77db946bc13cc44a20a01546be0e6" + "reference": "77a4e394d99a67e7fb611e8b402c2da4b80fa4f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/feb6492762a77db946bc13cc44a20a01546be0e6", - "reference": "feb6492762a77db946bc13cc44a20a01546be0e6", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/77a4e394d99a67e7fb611e8b402c2da4b80fa4f8", + "reference": "77a4e394d99a67e7fb611e8b402c2da4b80fa4f8", "shasum": "" }, "require": { @@ -1660,7 +1661,7 @@ "faker", "fixtures" ], - "time": "2013-08-12 10:05:47" + "time": "2013-08-29 19:11:59" }, { "name": "phpunit/php-code-coverage", @@ -2037,8 +2038,7 @@ "stability-flags": { "ezyang/htmlpurifier": 20, "ircmaxell/password-compat": 20, - "propel/propel": 15, - "symfony/validator": 20, + "propel/propel": 20, "kriswallsmith/assetic": 20, "leafo/lessphp": 20, "ptachoire/cssembed": 20, diff --git a/core/lib/Thelia/Action/BaseAction.php b/core/lib/Thelia/Action/BaseAction.php index ab8f4abb8..2984ddbd6 100755 --- a/core/lib/Thelia/Action/BaseAction.php +++ b/core/lib/Thelia/Action/BaseAction.php @@ -49,34 +49,4 @@ class BaseAction { return $this->container->get('event_dispatcher'); } - - /** - * Check current user authorisations. - * - * @param mixed $roles a single role or an array of roles. - * @param mixed $permissions a single permission or an array of permissions. - * - * @throws AuthenticationException if permissions are not granted to the current user. - */ - protected function checkAuth($roles, $permissions) { - - if (! $this->getSecurityContext()->isGranted( - is_array($roles) ? $roles : array($roles), - is_array($permissions) ? $permissions : array($permissions)) ) { - - Tlog::getInstance()->addAlert("Authorization roles:", $roles, " permissions:", $permissions, " refused."); - - throw new AuthorizationException("Sorry, you're not allowed to perform this action"); - } - } - - /** - * Return the security context - * - * @return Thelia\Core\Security\SecurityContext - */ - protected function getSecurityContext() - { - return $this->container->get('thelia.securityContext'); - } } \ No newline at end of file diff --git a/core/lib/Thelia/Action/Cart.php b/core/lib/Thelia/Action/Cart.php index 86674aedf..019911265 100755 --- a/core/lib/Thelia/Action/Cart.php +++ b/core/lib/Thelia/Action/Cart.php @@ -41,6 +41,7 @@ use Thelia\Model\ConfigQuery; * * Class Cart * @package Thelia\Action + * @author Manuel Raynaud */ class Cart extends BaseAction implements EventSubscriberInterface { diff --git a/core/lib/Thelia/Action/Category.php b/core/lib/Thelia/Action/Category.php index d411d2a51..59604bab9 100755 --- a/core/lib/Thelia/Action/Category.php +++ b/core/lib/Thelia/Action/Category.php @@ -42,28 +42,19 @@ class Category extends BaseAction implements EventSubscriberInterface { public function create(CategoryCreateEvent $event) { - $this->checkAuth("ADMIN", "admin.category.create"); - $category = new CategoryModel(); - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event); - - $category->create( - $event->getTitle(), - $event->getParent(), - $event->getLocale() + $category + ->setDispatcher($this->getDispatcher()) + ->create( + $event->getTitle(), + $event->getParent(), + $event->getLocale() ); - - $event->setCreatedCategory($category); - - $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $event); } public function modify(CategoryChangeEvent $event) { - $this->checkAuth("ADMIN", "admin.category.change"); - - // TODO !! } /** @@ -73,19 +64,11 @@ class Category extends BaseAction implements EventSubscriberInterface */ public function delete(CategoryDeleteEvent $event) { - $this->checkAuth("ADMIN", "admin.category.delete"); - - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { - $event->setDeletedCategory($category); - - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $event); - - $category->delete(); - - $event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $event); + $category->setDispatcher($this->getDispatcher())->delete(); } } @@ -96,21 +79,15 @@ class Category extends BaseAction implements EventSubscriberInterface */ public function toggleVisibility(CategoryToggleVisibilityEvent $event) { - $this->checkAuth("ADMIN", "admin.category.edit"); - - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event); - - $category->setVisible($category->getVisible() ? false : true); - - $category->save(); - - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event); + $category + ->setDispatcher($this->getDispatcher()) + ->setVisible($category->getVisible() ? false : true) + ->save() + ; } } @@ -121,8 +98,6 @@ class Category extends BaseAction implements EventSubscriberInterface */ public function changePosition(CategoryChangePositionEvent $event) { - $this->checkAuth("ADMIN", "admin.category.edit"); - if ($event->getMode() == CategoryChangePositionEvent::POSITION_ABSOLUTE) return $this->changeAbsolutePosition($event); else @@ -136,13 +111,10 @@ class Category extends BaseAction implements EventSubscriberInterface */ protected function exchangePosition(CategoryChangePositionEvent $event) { - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event); - // The current position of the category $my_position = $category->getPosition(); @@ -171,7 +143,11 @@ class Category extends BaseAction implements EventSubscriberInterface $cnx->beginTransaction(); try { - $category->setPosition($result->getPosition())->save(); + $category + ->setDispatcher($this->getDispatcher()) + ->setPosition($result->getPosition()) + ->save() + ; $result->setPosition($my_position)->save(); @@ -180,9 +156,6 @@ class Category extends BaseAction implements EventSubscriberInterface $cnx->rollback(); } } - - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event); } } @@ -193,15 +166,10 @@ class Category extends BaseAction implements EventSubscriberInterface */ protected function changeAbsolutePosition(CategoryChangePositionEvent $event) { - $this->checkAuth("ADMIN", "admin.category.edit"); - - $category = CategoryQuery::create()->findPk($event->getId()); + $category = CategoryQuery::create()->findPk($event->getCategoryId()); if ($category !== null) { - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event); - // The required position $new_position = $event->getPosition(); @@ -236,16 +204,17 @@ class Category extends BaseAction implements EventSubscriberInterface $result->setPosition($result->getPosition() + $delta)->save($cnx); } - $category->setPosition($new_position)->save($cnx); + $category + ->setDispatcher($this->getDispatcher()) + ->setPosition($new_position) + ->save($cnx) + ; $cnx->commit(); } catch (Exception $e) { $cnx->rollback(); } } - - $event->setCategory($category); - $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event); } } diff --git a/core/lib/Thelia/Action/Config.php b/core/lib/Thelia/Action/Config.php new file mode 100644 index 000000000..fa683f1d4 --- /dev/null +++ b/core/lib/Thelia/Action/Config.php @@ -0,0 +1,155 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Action; + + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +use Thelia\Model\ConfigQuery; +use Thelia\Model\Config as ConfigModel; + +use Thelia\Core\Event\TheliaEvents; + +use Thelia\Core\Event\ConfigChangeEvent; +use Thelia\Core\Event\ConfigCreateEvent; +use Thelia\Core\Event\ConfigDeleteEvent; + +class Config extends BaseAction implements EventSubscriberInterface +{ + /** + * Create a new configuration entry + * + * @param ConfigCreateEvent $event + */ + public function create(ConfigCreateEvent $event) + { + $config = new ConfigModel(); + + $config + ->setDispatcher($this->getDispatcher()) + + ->setName($event->getEventName()) + ->setValue($event->getValue()) + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setHidden($event->getHidden()) + ->setSecured($event->getSecured()) + + ->save() + ; + + $event->setConfig($config); + } + + /** + * Change a configuration entry value + * + * @param ConfigChangeEvent $event + */ + public function setValue(ConfigChangeEvent $event) + { + $search = ConfigQuery::create(); + + if (null !== $config = $search->findOneById($event->getConfigId())) { + + if ($event->getValue() !== $config->getValue()) { + + $config + ->setDispatcher($this->getDispatcher()) + + ->setValue($event->getValue()) + ->save() + ; + + $event->setConfig($config); + } + } + } + + /** + * Change a configuration entry + * + * @param ConfigChangeEvent $event + */ + public function modify(ConfigChangeEvent $event) + { + $search = ConfigQuery::create(); + + if (null !== $config = ConfigQuery::create()->findOneById($event->getConfigId())) { + + $config + ->setDispatcher($this->getDispatcher()) + + ->setName($event->getEventName()) + ->setValue($event->getValue()) + ->setHidden($event->getHidden()) + ->setSecured($event->getSecured()) + + ->setLocale($event->getLocale()) + ->setTitle($event->getTitle()) + ->setDescription($event->getDescription()) + ->setChapo($event->getChapo()) + ->setPostscriptum($event->getPostscriptum()) + + ->save(); + + $event->setConfig($config); + } + } + + /** + * Delete a configuration entry + * + * @param ConfigDeleteEvent $event + */ + public function delete(ConfigDeleteEvent $event) + { + + if (null !== ($config = ConfigQuery::create()->findOneById($event->getConfigId()))) { + + if (! $config->getSecured()) { + + $config + ->setDispatcher($this->getDispatcher()) + ->delete() + ; + + $event->setConfig($config); + } + } + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + TheliaEvents::CONFIG_CREATE => array("create", 128), + TheliaEvents::CONFIG_SETVALUE => array("setValue", 128), + TheliaEvents::CONFIG_MODIFY => array("modify", 128), + TheliaEvents::CONFIG_DELETE => array("delete", 128), + ); + } +} diff --git a/core/lib/Thelia/Action/Customer.php b/core/lib/Thelia/Action/Customer.php index 4c7a71d5e..962e2e2cf 100755 --- a/core/lib/Thelia/Action/Customer.php +++ b/core/lib/Thelia/Action/Customer.php @@ -38,7 +38,16 @@ use Symfony\Component\Validator\Exception\ValidatorException; use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\UsernameNotFoundException; use Propel\Runtime\Exception\PropelException; +use Thelia\Core\Event\CustomerLoginEvent; +/** + * + * customer class where all actions are managed + * + * Class Customer + * @package Thelia\Action + * @author Manuel Raynaud + */ class Customer extends BaseAction implements EventSubscriberInterface { @@ -46,7 +55,6 @@ class Customer extends BaseAction implements EventSubscriberInterface { $customer = new CustomerModel(); - $customer->setDispatcher($this->getDispatcher()); $this->createOrUpdateCustomer($customer, $event); @@ -56,7 +64,6 @@ class Customer extends BaseAction implements EventSubscriberInterface { $customer = $event->getCustomer(); - $customer->setDispatcher($this->getDispatcher()); $this->createOrUpdateCustomer($customer, $event); @@ -64,6 +71,8 @@ class Customer extends BaseAction implements EventSubscriberInterface private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event) { + $customer->setDispatcher($this->getDispatcher()); + $customer->createOrUpdate( $event->getTitle(), $event->getFirstname(), @@ -87,6 +96,12 @@ class Customer extends BaseAction implements EventSubscriberInterface $event->setCustomer($customer); } + + public function login(CustomerLoginEvent $event) + { + $this->getSecurityContext()->setCustomerUser($event->getCustomer()); + } + /** * Perform user logout. The user is redirected to the provided view, if any. * @@ -94,8 +109,6 @@ class Customer extends BaseAction implements EventSubscriberInterface */ public function logout(ActionEvent $event) { - $event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event); - $this->getSecurityContext()->clearCustomerUser(); } @@ -104,6 +117,16 @@ class Customer extends BaseAction implements EventSubscriberInterface // TODO } + /** + * Return the security context + * + * @return Thelia\Core\Security\SecurityContext + */ + protected function getSecurityContext() + { + return $this->container->get('thelia.securityContext'); + } + /** * Returns an array of event names this subscriber wants to listen to. * @@ -129,6 +152,8 @@ class Customer extends BaseAction implements EventSubscriberInterface return array( TheliaEvents::CUSTOMER_CREATEACCOUNT => array("create", 128), TheliaEvents::CUSTOMER_UPDATEACCOUNT => array("modify", 128), + TheliaEvents::CUSTOMER_LOGOUT => array("logout", 128), + TheliaEvents::CUSTOMER_LOGIN => array("login" , 128), ); } } diff --git a/core/lib/Thelia/Cart/CartTrait.php b/core/lib/Thelia/Cart/CartTrait.php index 901263a32..527867d5d 100755 --- a/core/lib/Thelia/Cart/CartTrait.php +++ b/core/lib/Thelia/Cart/CartTrait.php @@ -31,6 +31,13 @@ use Thelia\Core\HttpFoundation\Session\Session; use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Event\CartEvent; +/** + * managed cart + * + * Trait CartTrait + * @package Thelia\Cart + * @author Manuel Raynaud + */ trait CartTrait { /** diff --git a/core/lib/Thelia/Command/BaseModuleGenerate.php b/core/lib/Thelia/Command/BaseModuleGenerate.php index fab1b7707..b26db435b 100755 --- a/core/lib/Thelia/Command/BaseModuleGenerate.php +++ b/core/lib/Thelia/Command/BaseModuleGenerate.php @@ -22,6 +22,13 @@ /*************************************************************************************/ namespace Thelia\Command; +/** + * base class for module commands + * + * Class BaseModuleGenerate + * @package Thelia\Command + * @author Manuel Raynaud + */ abstract class BaseModuleGenerate extends ContainerAwareCommand { protected $module; diff --git a/core/lib/Thelia/Command/CacheClear.php b/core/lib/Thelia/Command/CacheClear.php index ed1cca8a6..82a7cbd7f 100755 --- a/core/lib/Thelia/Command/CacheClear.php +++ b/core/lib/Thelia/Command/CacheClear.php @@ -30,6 +30,14 @@ use Symfony\Component\Filesystem\Exception\IOException; use Thelia\Command\ContainerAwareCommand; +/** + * clear the cache + * + * Class CacheClear + * @package Thelia\Command + * @author Manuel Raynaud + * + */ class CacheClear extends ContainerAwareCommand { protected function configure() diff --git a/core/lib/Thelia/Command/Install.php b/core/lib/Thelia/Command/Install.php index edf459086..2e10d77ee 100755 --- a/core/lib/Thelia/Command/Install.php +++ b/core/lib/Thelia/Command/Install.php @@ -29,6 +29,13 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; use Thelia\Command\ContainerAwareCommand; +/** + * try to install a new instance of Thelia + * + * Class Install + * @package Thelia\Command + * @author Manuel Raynaud + */ class Install extends ContainerAwareCommand { /** diff --git a/core/lib/Thelia/Command/ModuleGenerateCommand.php b/core/lib/Thelia/Command/ModuleGenerateCommand.php index 842d421af..b34e43dc1 100755 --- a/core/lib/Thelia/Command/ModuleGenerateCommand.php +++ b/core/lib/Thelia/Command/ModuleGenerateCommand.php @@ -27,6 +27,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; +/** + * generate a new Module + * + * Class ModuleGenerateCommand + * @package Thelia\Command + * @author Manuel Raynaud + */ class ModuleGenerateCommand extends BaseModuleGenerate { protected function configure() diff --git a/core/lib/Thelia/Command/ModuleGenerateModelCommand.php b/core/lib/Thelia/Command/ModuleGenerateModelCommand.php index 28e96fa52..fbbe9be6c 100755 --- a/core/lib/Thelia/Command/ModuleGenerateModelCommand.php +++ b/core/lib/Thelia/Command/ModuleGenerateModelCommand.php @@ -31,6 +31,13 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; +/** + * generate class model for a specific module + * + * Class ModuleGenerateModelCommand + * @package Thelia\Command + * @author Manuel Raynaud + */ class ModuleGenerateModelCommand extends BaseModuleGenerate { protected function configure() diff --git a/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php b/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php index 89d87cb6f..2c6b310a5 100755 --- a/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php +++ b/core/lib/Thelia/Command/ModuleGenerateSqlCommand.php @@ -30,6 +30,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Filesystem; +/** + * generate sql for a specific module + * + * Class ModuleGenerateSqlCommand + * @package Thelia\Command + * @author Manuel Raynaud + */ class ModuleGenerateSqlCommand extends BaseModuleGenerate { public function configure() diff --git a/core/lib/Thelia/Config/Resources/action.xml b/core/lib/Thelia/Config/Resources/action.xml index 2bd31ce3e..9ecfad939 100755 --- a/core/lib/Thelia/Config/Resources/action.xml +++ b/core/lib/Thelia/Config/Resources/action.xml @@ -22,12 +22,17 @@ - + - + + + + + + diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 45c763830..2da8a3eea 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -32,6 +32,7 @@ + @@ -45,6 +46,9 @@
+ + + diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index cd7af7aef..607514fa1 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -53,10 +53,38 @@ read + + + + Thelia\Controller\Admin\ConfigController::defaultAction + + + + Thelia\Controller\Admin\ConfigController::changeValuesAction + + + + Thelia\Controller\Admin\ConfigController::createAction + + + + Thelia\Controller\Admin\ConfigController::changeAction + + + + Thelia\Controller\Admin\ConfigController::saveChangeAction + + + + Thelia\Controller\Admin\ConfigController::deleteAction + + + Thelia\Controller\Admin\AdminController::processTemplateAction .* + diff --git a/core/lib/Thelia/Config/Resources/routing/front.xml b/core/lib/Thelia/Config/Resources/routing/front.xml index c420e1550..9329b22ad 100755 --- a/core/lib/Thelia/Config/Resources/routing/front.xml +++ b/core/lib/Thelia/Config/Resources/routing/front.xml @@ -18,10 +18,14 @@ Thelia\Controller\Front\CustomerController::updateAction - + Thelia\Controller\Front\CustomerController::loginAction + + Thelia\Controller\Front\CustomerController::logoutAction + + Thelia\Controller\Front\CartController::addItem cart diff --git a/core/lib/Thelia/Controller/Admin/AdminController.php b/core/lib/Thelia/Controller/Admin/AdminController.php index 570bbec99..fdb6b13ac 100755 --- a/core/lib/Thelia/Controller/Admin/AdminController.php +++ b/core/lib/Thelia/Controller/Admin/AdminController.php @@ -29,10 +29,4 @@ class AdminController extends BaseAdminController { return $this->render("home"); } - - public function processAction() - { - echo "not yet coded !"; - exit(); - } } diff --git a/core/lib/Thelia/Controller/Admin/BaseAdminController.php b/core/lib/Thelia/Controller/Admin/BaseAdminController.php index 271ce3c05..c4b4c44b0 100755 --- a/core/lib/Thelia/Controller/Admin/BaseAdminController.php +++ b/core/lib/Thelia/Controller/Admin/BaseAdminController.php @@ -32,6 +32,8 @@ use Thelia\Tools\URL; use Thelia\Tools\Redirect; use Thelia\Core\Security\SecurityContext; use Thelia\Model\AdminLog; +use Thelia\Model\Lang; +use Thelia\Model\LangQuery; class BaseAdminController extends BaseController { @@ -46,17 +48,25 @@ class BaseAdminController extends BaseController AdminLog::append($message, $this->getRequest(), $this->getSecurityContext()->getAdminUser()); } + /** + * This method process the rendering of view called from an admin page + * + * @param unknown $template + * @return Response the reponse which contains the rendered view + */ public function processTemplateAction($template) { try { if (! empty($template)) { // If we have a view in the URL, render this view return $this->render($template); - } elseif (null != $view = $this->getRequest()->get('view')) { + } + elseif (null != $view = $this->getRequest()->get('view')) { return $this->render($view); } - } catch (\Exception $ex) { - // Nothing special + } + catch (\Exception $ex) { + return new Response($this->errorPage($ex->getMessage())); } return $this->pageNotFound(); @@ -87,19 +97,31 @@ class BaseAdminController extends BaseController /** * Check current admin user authorisations. An ADMIN role is assumed. * - * @param unknown $permissions a single permission or an array of permissions. + * @param mixed $permissions a single permission or an array of permissions. + * + * @return mixed null if authorization is granted, or a Response object which contains the error page otherwise * - * @throws AuthenticationException if permissions are not granted ti the current user. */ protected function checkAuth($permissions) { - if (! $this->getSecurityContext()->isGranted(array("ADMIN"), is_array($permissions) ? $permissions : array($permissions))) { - throw new AuthorizationException("Sorry, you're not allowed to perform this action"); - } + $permArr = is_array($permissions) ? $permissions : array($permissions); + + if ($this->getSecurityContext()->isGranted(array("ADMIN"), $permArr)) { + // Okay ! + return null; + } + + // Log the problem + $this->adminLogAppend("User is not granted for permissions %s", implode(", ", $permArr)); + + // Generate the proper response + $response = new Response(); + + return $response->setContent($this->errorPage("Sorry, you're not allowed to perform this action")); } /** - * @return a ParserInterfac instance parser + * @return a ParserInterface instance parser */ protected function getParser() { @@ -128,6 +150,23 @@ class BaseAdminController extends BaseController return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); } + /** + * Get the current edition lang ID, checking if a change was requested in the current request + */ + protected function getCurrentEditionLangId() { + return $this->getRequest()->get( + 'edition_language', + $this->getSession()->getAdminEditionLangId() + ); + } + + /** + * A simple helper to get the current edition locale, from the session edition language ID + */ + protected function getCurrentEditionLocale() { + return LangQuery::create()->findOneById($this->getCurrentEditionLangId())->getLocale(); + } + /** * Render the given template, and returns the result as an Http Response. * @@ -151,26 +190,41 @@ class BaseAdminController extends BaseController */ protected function renderRaw($templateName, $args = array()) { + // Add the template standard extension $templateName .= '.html'; $session = $this->getSession(); + // Find the current edit language ID + $edition_language = $this->getCurrentEditionLangId(); + + // Prepare common template variables $args = array_merge($args, array( - 'locale' => $session->getLocale(), - 'lang' => $session->getLang() + 'locale' => $session->getLocale(), + 'lang_code' => $session->getLang(), + 'lang_id' => $session->getLangId(), + 'edition_language' => $edition_language, + 'current_url' => htmlspecialchars($this->getRequest()->getUri()) )); + // Update the current edition language in session + $this->getSession()->setAdminEditionLangId($edition_language); + + // Render the template. try { $data = $this->getParser()->render($templateName, $args); return $data; - } catch (AuthenticationException $ex) { - + } + catch (AuthenticationException $ex) { // User is not authenticated, and templates requires authentication -> redirect to login page // We user login_tpl as a path, not a template. - Redirect::exec(URL::absoluteUrl($ex->getLoginTemplate())); } + catch (AuthorizationException $ex) { + // User is not allowed to perform the required action. Return the error page instead of the requested page. + return $this->errorPage("Sorry, you are not allowed to perform this action."); + } } } diff --git a/core/lib/Thelia/Controller/Admin/CategoryController.php b/core/lib/Thelia/Controller/Admin/CategoryController.php index 4e798d683..9966034f8 100755 --- a/core/lib/Thelia/Controller/Admin/CategoryController.php +++ b/core/lib/Thelia/Controller/Admin/CategoryController.php @@ -33,6 +33,7 @@ use Thelia\Core\Event\CategoryDeleteEvent; use Thelia\Core\Event\CategoryToggleVisibilityEvent; use Thelia\Core\Event\CategoryChangePositionEvent; use Thelia\Form\CategoryDeletionForm; +use Thelia\Model\Lang; class CategoryController extends BaseAdminController { @@ -65,7 +66,7 @@ class CategoryController extends BaseAdminController } catch (FormValidationException $e) { $categoryCreationForm->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($categoryCreationForm); + $this->getParserContext()->addForm($categoryCreationForm); } catch (Exception $e) { Tlog::getInstance()->error(sprintf("Failed to create category: %s", $e->getMessage())); @@ -78,7 +79,7 @@ class CategoryController extends BaseAdminController protected function editCategory($args) { - $this->checkAuth("ADMIN", "admin.category.edit"); + if (null !== $response = $this->checkAuth("admin.category.edit")) return $response; return $this->render('edit_category', $args); } @@ -99,14 +100,14 @@ class CategoryController extends BaseAdminController $this->adminLogAppend(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId())); // Substitute _ID_ in the URL with the ID of the created category - $successUrl = str_replace('_ID_', $categoryDeleteEvent->getDeletedCategory()->getId(), $categoryDeletionForm->getSuccessUrl()); + $successUrl = str_replace('_ID_', $categoryDeleteEvent->getDeletedCategory()->getParent(), $categoryDeletionForm->getSuccessUrl()); // Redirect to the success URL $this->redirect($successUrl); } catch (FormValidationException $e) { $categoryDeletionForm->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($categoryDeletionForm); + $this->getParserContext()->addForm($categoryDeletionForm); } catch (Exception $e) { Tlog::getInstance()->error(sprintf("Failed to delete category: %s", $e->getMessage())); @@ -119,7 +120,7 @@ class CategoryController extends BaseAdminController protected function browseCategory($args) { - $this->checkAuth("AMIN", "admin.catalog.view"); + if (null !== $response = $this->checkAuth("admin.catalog.view")) return $response; return $this->render('categories', $args); } @@ -185,11 +186,31 @@ class CategoryController extends BaseAdminController // Get the category ID $id = $this->getRequest()->get('id', 0); + // Find the current order + $category_order = $this->getRequest()->get( + 'category_order', + $this->getSession()->get('admin.category_order', 'manual') + ); + + // Find the current edit language ID + $edition_language = $this->getRequest()->get( + 'edition_language', + $this->getSession()->get('admin.edition_language', Lang::getDefaultLanguage()->getId()) + ); + $args = array( 'action' => $action, - 'current_category_id' => $id + 'current_category_id' => $id, + 'category_order' => $category_order, + 'edition_language' => $edition_language, ); + // Store the current sort order in session + $this->getSession()->set('admin.category_order', $category_order); + + // Store the current edition language in session + $this->getSession()->set('admin.edition_language', $edition_language); + try { switch ($action) { case 'browse' : // Browse categories diff --git a/core/lib/Thelia/Controller/Admin/ConfigController.php b/core/lib/Thelia/Controller/Admin/ConfigController.php new file mode 100644 index 000000000..ab6327e0e --- /dev/null +++ b/core/lib/Thelia/Controller/Admin/ConfigController.php @@ -0,0 +1,299 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Controller\Admin; + +use Thelia\Core\Event\ConfigDeleteEvent; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Tools\URL; +use Thelia\Core\Event\ConfigChangeEvent; +use Thelia\Core\Event\ConfigCreateEvent; +use Thelia\Log\Tlog; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Core\Security\Exception\AuthorizationException; +use Thelia\Model\ConfigQuery; +use Thelia\Form\ConfigModificationForm; +use Thelia\Form\ConfigCreationForm; + +/** + * Manages Thelmia system variables, aka Config objects. + * + * @author Franck Allimant + */ +class ConfigController extends BaseAdminController +{ + /** + * The default action is displaying the variables list. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function defaultAction() { + + if (null !== $response = $this->checkAuth("admin.configuration.variables.view")) return $response; + + return $this->render('variables'); + } + + /** + * Create a new config object + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function createAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.variables.create")) return $response; + + $message = false; + + // Create the Creation Form + $creationForm = new ConfigCreationForm($this->getRequest()); + + try { + + // Validate the form, create the ConfigCreation event and dispatch it. + $form = $this->validateForm($creationForm, "POST"); + + $data = $form->getData(); + + $createEvent = new ConfigCreateEvent(); + + $createEvent + ->setEventName($data['name']) + ->setValue($data['value']) + ->setLocale($data["locale"]) + ->setTitle($data['title']) + ->setHidden($data['hidden']) + ->setSecured($data['secured']) + ; + + $this->dispatch(TheliaEvents::CONFIG_CREATE, $createEvent); + + $createdObject = $createEvent->getConfig(); + + // Log config creation + $this->adminLogAppend(sprintf("Variable %s (ID %s) created", $createdObject->getName(), $createdObject->getId())); + + // Substitute _ID_ in the URL with the ID of the created object + $successUrl = str_replace('_ID_', $createdObject->getId(), $creationForm->getSuccessUrl()); + + // Redirect to the success URL + $this->redirect($successUrl); + } + catch (FormValidationException $ex) { + // Form cannot be validated + $message = sprintf("Please check your input: %s", $ex->getMessage()); + } + catch (\Exception $ex) { + // Any other error + $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + } + + if ($message !== false) { + // An error has been detected: log it + Tlog::getInstance()->error(sprintf("Error during variable creation process : %s. Exception was %s", $message, $ex->getMessage())); + + // Mark the form as errored + $creationForm->setErrorMessage($message); + + // Pass it to the parser, along with the error message + $this->getParserContext() + ->addForm($creationForm) + ->setGeneralError($message) + ; + } + + // At this point, the form has error, and should be redisplayed. + return $this->render('variables'); + } + + /** + * Load a config object for modification, and display the edit template. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function changeAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response; + + // Load the config object + $config = ConfigQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->findOneById($this->getRequest()->get('variable_id')); + + if ($config != null) { + + // Prepare the data that will hydrate the form + $data = array( + 'id' => $config->getId(), + 'name' => $config->getName(), + 'value' => $config->getValue(), + 'hidden' => $config->getHidden(), + 'secured' => $config->getSecured(), + 'locale' => $config->getLocale(), + 'title' => $config->getTitle(), + 'chapo' => $config->getChapo(), + 'description' => $config->getDescription(), + 'postscriptum' => $config->getPostscriptum() + ); + + // Setup the object form + $changeForm = new ConfigModificationForm($this->getRequest(), "form", $data); + + // Pass it to the parser + $this->getParserContext()->addForm($changeForm); + } + + // Render the edition template. + return $this->render('variable-edit', array('variable_id' => $this->getRequest()->get('variable_id'))); + } + + /** + * Save changes on a modified config object, and either go back to the variable list, or stay on the edition page. + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function saveChangeAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response; + + $message = false; + + // Create the form from the request + $changeForm = new ConfigModificationForm($this->getRequest()); + + // Get the variable ID + $variable_id = $this->getRequest()->get('variable_id'); + + try { + + // Check the form against constraints violations + $form = $this->validateForm($changeForm, "POST"); + + // Get the form field values + $data = $form->getData(); + + $changeEvent = new ConfigChangeEvent($data['id']); + + // Create and dispatch the change event + $changeEvent + ->setEventName($data['name']) + ->setValue($data['value']) + ->setHidden($data['hidden']) + ->setSecured($data['secured']) + ->setLocale($data["locale"]) + ->setTitle($data['title']) + ->setChapo($data['chapo']) + ->setDescription($data['description']) + ->setPostscriptum($data['postscriptum']) + ; + + $this->dispatch(TheliaEvents::CONFIG_MODIFY, $changeEvent); + + // Log config modification + $changedObject = $changeEvent->getConfig(); + + $this->adminLogAppend(sprintf("Variable %s (ID %s) modified", $changedObject->getName(), $changedObject->getId())); + + // If we have to stay on the same page, do not redirect to the succesUrl, + // just redirect to the edit page again. + if ($this->getRequest()->get('save_mode') == 'stay') { + $this->redirect(URL::absoluteUrl( + "admin/configuration/variables/change", + array('variable_id' => $variable_id) + )); + } + + // Redirect to the success URL + $this->redirect($changeForm->getSuccessUrl()); + } + catch (FormValidationException $ex) { + // Invalid data entered + $message = sprintf("Please check your input: %s", $ex->getMessage()); + } + catch (\Exception $ex) { + // Any other error + $message = sprintf("Sorry, an error occured: %s", $ex->getMessage()); + } + + if ($message !== false) { + // Log error message + Tlog::getInstance()->error(sprintf("Error during variable creation process : %s. Exception was %s", $message, $ex->getMessage())); + + // Mark the form as errored + $changeForm->setErrorMessage($message); + + // Pas the form and the error to the parser + $this->getParserContext() + ->addForm($changeForm) + ->setGeneralError($message) + ; + } + + // At this point, the form has errors, and should be redisplayed. + return $this->render('variable-edit', array('variable_id' => $variable_id)); + } + + /** + * Change values modified directly from the variable list + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function changeValuesAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response; + + $variables = $this->getRequest()->get('variable', array()); + + // Process all changed variables + foreach($variables as $id => $value) { + $event = new ConfigChangeEvent($id); + $event->setValue($value); + + $this->dispatch(TheliaEvents::CONFIG_SETVALUE, $event); + } + + $this->redirect(URL::adminViewUrl('variables')); + } + + /** + * Delete a config object + * + * @return Symfony\Component\HttpFoundation\Response the response + */ + public function deleteAction() { + + // Check current user authorization + if (null !== $response = $this->checkAuth("admin.configuration.variables.delete")) return $response; + + // Get the config id, and dispatch the delet request + $event = new ConfigDeleteEvent($this->getRequest()->get('variable_id')); + + $this->dispatch(TheliaEvents::CONFIG_DELETE, $event); + + $this->redirect(URL::adminViewUrl('variables')); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Controller/Admin/SessionController.php b/core/lib/Thelia/Controller/Admin/SessionController.php index 39dbc1205..552fea8eb 100755 --- a/core/lib/Thelia/Controller/Admin/SessionController.php +++ b/core/lib/Thelia/Controller/Admin/SessionController.php @@ -51,13 +51,16 @@ class SessionController extends BaseAdminController public function checkLoginAction() { - $adminLoginForm = new AdminLogin($this->getRequest()); - $request = $this->getRequest(); - $authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm); + $adminLoginForm = new AdminLogin($request); try { + + $form = $this->validateForm($adminLoginForm, "post"); + + $authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm); + $user = $authenticator->getAuthentifiedUser(); // Success -> store user in security context @@ -85,7 +88,7 @@ class SessionController extends BaseAdminController // Log authentication failure AdminLog::append(sprintf("Undefined error: %s", $ex->getMessage()), $request); - $message = "Unable to process your request. Please try again."; + $message = "Unable to process your request. Please try again.".$ex->getMessage(); } // Store error information in the form @@ -93,7 +96,7 @@ class SessionController extends BaseAdminController $adminLoginForm->setErrorMessage($message); // Store the form name in session (see Form Smarty plugin to find usage of this parameter) - $this->getParserContext()->setErrorForm($adminLoginForm); + $this->getParserContext()->addForm($adminLoginForm); // Display the login form again return $this->render("login"); diff --git a/core/lib/Thelia/Controller/BaseController.php b/core/lib/Thelia/Controller/BaseController.php index 1a610768d..c7c9f6f14 100755 --- a/core/lib/Thelia/Controller/BaseController.php +++ b/core/lib/Thelia/Controller/BaseController.php @@ -35,6 +35,7 @@ use Thelia\Core\Factory\ActionEventFactory; use Thelia\Form\BaseForm; use Thelia\Form\Exception\FormValidationException; use Symfony\Component\EventDispatcher\Event; +use Thelia\Core\Event\DefaultActionEvent; /** * @@ -60,10 +61,12 @@ class BaseController extends ContainerAware * Dispatch a Thelia event * * @param string $eventName a TheliaEvent name, as defined in TheliaEvents class - * @param Event $event the event + * @param Event $event the action event, or null (a DefaultActionEvent will be dispatched) */ - protected function dispatch($eventName, Event $event = null) + protected function dispatch($eventName, ActionEvent $event = null) { + if ($event == null) $event = new DefaultActionEvent(); + $this->getDispatcher()->dispatch($eventName, $event); } @@ -117,6 +120,29 @@ class BaseController extends ContainerAware return $request->getSession(); } + /** + * Get all errors that occured in a form + * + * @param \Symfony\Component\Form\Form $form + * @return string the error string + */ + private function getErrorMessages(\Symfony\Component\Form\Form $form) { + + $errors = ''; + + foreach ($form->getErrors() as $key => $error) { + $errors .= $error->getMessage() . ', '; + } + + foreach ($form->all() as $child) { + if (!$child->isValid()) { + $errors .= $this->getErrorMessages($child) . ', '; + } + } + + return rtrim($errors, ', '); + } + /** * Validate a BaseForm * @@ -135,17 +161,20 @@ class BaseController extends ContainerAware if ($form->isValid()) { return $form; - } else { - throw new FormValidationException("Missing or invalid data"); } - } else { + else { + throw new FormValidationException(sprintf("Missing or invalid data: %s", $this->getErrorMessages($form))); + } + } + else { throw new FormValidationException(sprintf("Wrong form method, %s expected.", $expectedMethod)); } } /** * - * redirect request to specify url + * redirect request to the specified url + * * @param string $url */ public function redirect($url) @@ -154,12 +183,21 @@ class BaseController extends ContainerAware } /** - * If success_url param is present in request, follow this link. + * If success_url param is present in request or in the provided form, redirect to this URL. + * + * @param BaseForm $form a base form, which may contains the success URL */ - protected function redirectSuccess() + protected function redirectSuccess(BaseForm $form = null) { - if (null !== $url = $this->getRequest()->get("success_url")) { - $this->redirect($url); + if ($form != null) { + $url = $form->getSuccessUrl(); } + else { + $url = $this->getRequest()->get("success_url"); + } + + echo "url=$url"; + + if (null !== $url) $this->redirect($url); } } diff --git a/core/lib/Thelia/Controller/Front/CartController.php b/core/lib/Thelia/Controller/Front/CartController.php index 62b68a3fc..8f2cdd036 100755 --- a/core/lib/Thelia/Controller/Front/CartController.php +++ b/core/lib/Thelia/Controller/Front/CartController.php @@ -63,7 +63,7 @@ class CartController extends BaseFrontController if ($message) { $cartAdd->setErrorMessage($message); - $this->getParserContext()->setErrorForm($cartAdd); + $this->getParserContext()->addForm($cartAdd); } } diff --git a/core/lib/Thelia/Controller/Front/CustomerController.php b/core/lib/Thelia/Controller/Front/CustomerController.php index 698c69d70..7ff7cb496 100755 --- a/core/lib/Thelia/Controller/Front/CustomerController.php +++ b/core/lib/Thelia/Controller/Front/CustomerController.php @@ -22,8 +22,6 @@ /*************************************************************************************/ namespace Thelia\Controller\Front; -use Propel\Runtime\Exception\PropelException; -use Symfony\Component\Validator\Exception\ValidatorException; use Thelia\Core\Event\CustomerCreateOrUpdateEvent; use Thelia\Core\Event\CustomerLoginEvent; use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator; @@ -37,65 +35,101 @@ use Thelia\Form\Exception\FormValidationException; use Thelia\Model\Customer; use Thelia\Core\Event\TheliaEvents; use Thelia\Core\Event\CustomerEvent; +use Thelia\Core\Factory\ActionEventFactory; +use Thelia\Tools\URL; +use Thelia\Log\Tlog; +use Thelia\Core\Security\Exception\WrongPasswordException; class CustomerController extends BaseFrontController { /** - * create a new Customer. Retrieve data in form and dispatch a action.createCustomer event - * - * if error occurs, message is set in the parserContext + * Create a new customer. + * On success, redirect to success_url if exists, otherwise, display the same view again. */ public function createAction() { - $request = $this->getRequest(); - $customerCreation = new CustomerCreation($request); - try { - $form = $this->validateForm($customerCreation, "post"); + if (! $this->getSecurityContext()->hasCustomerUser()) { - $customerCreateEvent = $this->createEventInstance($form->getData()); + $message = false; - $this->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $customerCreateEvent); + $customerCreation = new CustomerCreation($this->getRequest()); - $this->processLogin($customerCreateEvent->getCustomer()); + try { + $form = $this->validateForm($customerCreation, "post"); - $this->redirectSuccess(); + $customerCreateEvent = $this->createEventInstance($form->getData()); - } catch (FormValidationException $e) { - $customerCreation->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($customerCreation); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during customer creation process in front context with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); + $this->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $customerCreateEvent); + + $this->processLogin($customerCreateEvent->getCustomer()); + + $this->redirectSuccess($customerCreation); + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer creation process : %s. Exception was %s", $message, $e->getMessage())); + + $customerCreation->setErrorMessage($message); + + $this->getParserContext() + ->addForm($customerCreation) + ->setGeneralError($message) + ; + } } - } + /** + * Update customer data. On success, redirect to success_url if exists. + * Otherwise, display the same view again. + */ public function updateAction() { - $request = $this->getRequest(); - $customerModification = new CustomerModification($request); + if ($this->getSecurityContext()->hasCustomerUser()) { - try { + $message = false; - $customer = $this->getSecurityContext()->getCustomerUser(); + $customerModification = new CustomerModification($this->getRequest()); - $form = $this->validateForm($customerModification, "post"); + try { - $customerChangeEvent = $this->createEventInstance($form->getData()); - $customerChangeEvent->setCustomer($customer); + $customer = $this->getSecurityContext()->getCustomerUser(); - $this->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_UPDATEACCOUNT, $customerChangeEvent); + $form = $this->validateForm($customerModification, "post"); - $this->processLogin($customerChangeEvent->getCustomer()); + $customerChangeEvent = $this->createEventInstance($form->getData()); + $customerChangeEvent->setCustomer($customer); - $this->redirectSuccess(); + $this->dispatch(TheliaEvents::CUSTOMER_UPDATEACCOUNT, $customerChangeEvent); - } catch (FormValidationException $e) { - $customerModification->setErrorMessage($e->getMessage()); - $this->getParserContext()->setErrorForm($customerModification); - } catch (PropelException $e) { - \Thelia\Log\Tlog::getInstance()->error(sprintf("error during updating customer in front context with message : %s", $e->getMessage())); - $this->getParserContext()->setGeneralError($e->getMessage()); + $this->processLogin($customerChangeEvent->getCustomer()); + + $this->redirectSuccess($customerModification); + + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer modification process : %s. Exception was %s", $message, $e->getMessage())); + + $customerModification->setErrorMessage($message); + + $this->getParserContext() + ->addForm($customerModification) + ->setGeneralError($message) + ; + } } } @@ -103,39 +137,75 @@ class CustomerController extends BaseFrontController * Perform user login. On a successful login, the user is redirected to the URL * found in the success_url form parameter, or / if none was found. * - * If login is not successfull, the same view is dispolyed again. + * If login is not successfull, the same view is displayed again. * */ public function loginAction() { - $request = $this->getRequest(); + if (! $this->getSecurityContext()->hasCustomerUser()) { + $message = false; - $customerLoginForm = new CustomerLogin($request); + $request = $this->getRequest(); - $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); + try { - try { - $customer = $authenticator->getAuthentifiedUser(); + $customerLoginForm = new CustomerLogin($request); - $this->processLogin($customer); + $form = $this->validateForm($customerLoginForm, "post"); - $this->redirectSuccess(); - } catch (ValidatorException $e) { + $authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm); - } catch(UsernameNotFoundException $e) { + $customer = $authenticator->getAuthentifiedUser(); - } catch(AuthenticationException $e) { + $this->processLogin($customer); - } catch (\Exception $e) { + $this->redirectSuccess($customerLoginForm); + } + catch (FormValidationException $e) { + $message = "Invalid or missing data. Please check your input"; + } + catch(UsernameNotFoundException $e) { + $message = "This customer email was not found."; + } + catch (WrongPasswordException $e) { + $message = "Wrong password. Please try again."; + } + catch(AuthenticationException $e) { + $message = "Sorry, we failed to authentify you. Please try again."; + } + catch (\Exception $e) { + $message = "Sorry, an unknown error occured."; + } + + if ($message !== false) { + Tlog::getInstance()->error(sprintf("Error during customer login process : %s. Exception was %s", $message, $e->getMessage())); + + $customerLoginForm->setErrorMessage($message); + + $this->getParserContext()->addForm($customerLoginForm); + } } } - public function processLogin(Customer $customer) + /** + * Perform customer logout. + * + * @param Customer $customer + */ + public function logoutAction() { - $this->getSecurityContext()->setCustomerUser($customer); + if ($this->getSecurityContext()->hasCustomerUser()) { + $this->dispatch(TheliaEvents::CUSTOMER_LOGOUT); + } - if($event) $this->dispatch(TheliaEvents::CUSTOMER_LOGIN, new CustomerLoginEvent($customer)); + // Redirect to home page + $this->redirect(URL::getIndexPage()); + } + + protected function processLogin(Customer $customer) + { + $this->dispatch(TheliaEvents::CUSTOMER_LOGIN, new CustomerLoginEvent($customer)); } /** @@ -161,10 +231,9 @@ class CustomerController extends BaseFrontController $this->getRequest()->getSession()->getLang(), isset($data["reseller"])?$data["reseller"]:null, isset($data["sponsor"])?$data["sponsor"]:null, - isset($data["discount"])?$data["discount"]:nullsch + isset($data["discount"])?$data["discount"]:null ); return $customerCreateEvent; } - } diff --git a/core/lib/Thelia/Core/Application.php b/core/lib/Thelia/Core/Application.php index 531d8802c..bb0eec79a 100755 --- a/core/lib/Thelia/Core/Application.php +++ b/core/lib/Thelia/Core/Application.php @@ -29,6 +29,12 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\HttpKernel\KernelInterface; +/** + * cli application for Thelia + * Class Application + * @package Thelia\Core + * mfony\Component\HttpFoundation\Session\Session + */ class Application extends BaseApplication { diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterListenersPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterListenersPass.php index 9f7e9f31f..08fcd777b 100755 --- a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterListenersPass.php +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterListenersPass.php @@ -31,6 +31,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; * @package Thelia\Core\DependencyInjection\Compiler * * Source code come from Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass class + * @author Manuel Raynaud */ class RegisterListenersPass implements CompilerPassInterface { diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php index 80c3ba933..71d96ca40 100755 --- a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterParserPluginPass.php @@ -31,7 +31,7 @@ use Symfony\Component\DependencyInjection\Reference; * Register parser plugins. These plugins shouild be tagged thelia.parser.register_plugin * in the configuration. * - * + * @author Manuel Raynaud */ class RegisterParserPluginPass implements CompilerPassInterface { diff --git a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php index 2bd902e64..2d7110ee5 100755 --- a/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php +++ b/core/lib/Thelia/Core/DependencyInjection/Compiler/RegisterRouterPass.php @@ -28,6 +28,14 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; +/** + * + * this compiler can add many router to symfony-cms routing + * + * Class RegisterRouterPass + * @package Thelia\Core\DependencyInjection\Compiler + * @author Manuel Raynaud + */ class RegisterRouterPass implements CompilerPassInterface { diff --git a/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php b/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php index a95e7d668..294c9b671 100755 --- a/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php +++ b/core/lib/Thelia/Core/DependencyInjection/Loader/XmlFileLoader.php @@ -36,6 +36,14 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Loader\FileLoader; +/** + * + * Load, read and validate config xml files + * + * Class XmlFileLoader + * @package Thelia\Core\DependencyInjection\Loader + * @author Manuel Raynaud + */ class XmlFileLoader extends FileLoader { /** diff --git a/core/lib/Thelia/Core/Event/CategoryChangeEvent.php b/core/lib/Thelia/Core/Event/CategoryChangeEvent.php new file mode 100644 index 000000000..e8e183b3f --- /dev/null +++ b/core/lib/Thelia/Core/Event/CategoryChangeEvent.php @@ -0,0 +1,44 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +use Thelia\Model\Category; + +class CategoryCreateEvent extends ActionEvent +{ + protected $category_id; + protected $locale; + protected $title; + protected $chapo; + protected $description; + protected $postscriptum; + protected $url; + protected $visibility; + protected $parent; + + public function __construct($category_id) + { + $this->category_id = $category_id; + } +} diff --git a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php b/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php index 141fc8182..94f131626 100644 --- a/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryChangePositionEvent.php @@ -30,28 +30,18 @@ class CategoryChangePositionEvent extends ActionEvent const POSITION_DOWN = 2; const POSITION_ABSOLUTE = 3; - protected $id; + protected $category_id; protected $mode; protected $position; protected $category; - public function __construct($id, $mode, $position = null) + public function __construct($category_id, $mode, $position = null) { - $this->id = $id; + $this->category_id = $category_id; $this->mode = $mode; $this->position = $position; } - public function getId() - { - return $this->id; - } - - public function setId($id) - { - $this->id = $id; - } - public function getMode() { return $this->mode; @@ -81,4 +71,15 @@ class CategoryChangePositionEvent extends ActionEvent { $this->category = $category; } -} \ No newline at end of file + + public function getCategoryId() + { + return $this->category_id; + } + + public function setCategoryId($category_id) + { + $this->category_id = $category_id; + } + +} diff --git a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php index 558b04277..f4d5a45ee 100644 --- a/core/lib/Thelia/Core/Event/CategoryCreateEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryCreateEvent.php @@ -77,6 +77,5 @@ class CategoryCreateEvent extends ActionEvent public function setCreatedCategory(Category $created_category) { $this->created_category = $created_category; -var_dump($this->created_category); } } diff --git a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php index c53cb7e10..3e863be8e 100644 --- a/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryDeleteEvent.php @@ -26,22 +26,22 @@ use Thelia\Model\Category; class CategoryDeleteEvent extends ActionEvent { - protected $id; + protected $category_id; protected $deleted_category; - public function __construct($id) + public function __construct($category_id) { - $this->id = $id; + $this->category_id = $category_id; } - public function getId() + public function getCategoryId() { - return $this->id; + return $this->category_id; } - public function setId($id) + public function setCategoryId($category_id) { - $this->id = $id; + $this->category_id = $category_id; } public function getDeletedCategory() diff --git a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php index b7237924e..ef921a0de 100644 --- a/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php +++ b/core/lib/Thelia/Core/Event/CategoryToggleVisibilityEvent.php @@ -26,22 +26,22 @@ use Thelia\Model\Category; class CategoryToggleVisibilityEvent extends ActionEvent { - protected $id; + protected $category_id; protected $category; - public function __construct($id) + public function __construct($category_id) { - $this->id = $id; + $this->category_id = $category_id; } - public function getId() + public function getCategoryId() { - return $this->id; + return $this->category_id; } - public function setId($id) + public function setCategoryId($category_id) { - $this->id = $id; + $this->category_id = $category_id; } public function getCategory() diff --git a/core/lib/Thelia/Core/Event/ConfigChangeEvent.php b/core/lib/Thelia/Core/Event/ConfigChangeEvent.php new file mode 100644 index 000000000..e7da059ee --- /dev/null +++ b/core/lib/Thelia/Core/Event/ConfigChangeEvent.php @@ -0,0 +1,88 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +use Thelia\Model\Config; + +class ConfigChangeEvent extends ConfigCreateEvent +{ + protected $config_id; + + protected $description; + protected $chapo; + protected $postscriptum; + + public function __construct($config_id) + { + $this->setConfigId($config_id); + } + + public function getConfigId() + { + return $this->config_id; + } + + public function setConfigId($config_id) + { + $this->config_id = $config_id; + + return $this; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + public function getChapo() + { + return $this->chapo; + } + + public function setChapo($chapo) + { + $this->chapo = $chapo; + + return $this; + } + + public function getPostscriptum() + { + return $this->postscriptum; + } + + public function setPostscriptum($postscriptum) + { + $this->postscriptum = $postscriptum; + + return $this; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Event/ConfigCreateEvent.php b/core/lib/Thelia/Core/Event/ConfigCreateEvent.php new file mode 100644 index 000000000..79440c491 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ConfigCreateEvent.php @@ -0,0 +1,108 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; +use Thelia\Model\Config; + +class ConfigCreateEvent extends ConfigEvent +{ + protected $event_name; + protected $value; + protected $locale; + protected $title; + protected $hidden; + protected $secured; + + // Use event_name to prevent conflict with Event::name property. + public function getEventName() + { + return $this->event_name; + } + + public function setEventName($event_name) + { + $this->event_name = $event_name; + + return $this; + } + + public function getValue() + { + return $this->value; + } + + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + public function getHidden() + { + return $this->hidden; + } + + public function setHidden($hidden) + { + $this->hidden = $hidden; + + return $this; + } + + public function getSecured() + { + return $this->secured; + } + + public function setSecured($secured) + { + $this->secured = $secured; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ConfigDeleteEvent.php b/core/lib/Thelia/Core/Event/ConfigDeleteEvent.php new file mode 100644 index 000000000..6cc39438c --- /dev/null +++ b/core/lib/Thelia/Core/Event/ConfigDeleteEvent.php @@ -0,0 +1,48 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; + +use Thelia\Model\Config; + +class ConfigDeleteEvent extends ConfigEvent +{ + protected $config_id; + + public function __construct($config_id) + { + $this->setConfigId($config_id); + } + + public function getConfigId() + { + return $this->config_id; + } + + public function setConfigId($config_id) + { + $this->config_id = $config_id; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/ConfigEvent.php b/core/lib/Thelia/Core/Event/ConfigEvent.php new file mode 100644 index 000000000..eb5ec57c7 --- /dev/null +++ b/core/lib/Thelia/Core/Event/ConfigEvent.php @@ -0,0 +1,47 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Event; +use Thelia\Model\Config; + +class ConfigEvent extends ActionEvent +{ + protected $config; + + public function __construct(Config $config = null) + { + $this->config = $config; + } + + public function getConfig() + { + return $this->config; + } + + public function setConfig($config) + { + $this->config = $config; + + return $this; + } +} diff --git a/core/lib/Thelia/Core/Event/CustomerLoginEvent.php b/core/lib/Thelia/Core/Event/CustomerLoginEvent.php index cc363790d..9a26bba3f 100755 --- a/core/lib/Thelia/Core/Event/CustomerLoginEvent.php +++ b/core/lib/Thelia/Core/Event/CustomerLoginEvent.php @@ -26,7 +26,7 @@ namespace Thelia\Core\Event; use Thelia\Model\Customer; -class CustomerLoginEvent { +class CustomerLoginEvent extends ActionEvent { protected $customer; diff --git a/core/lib/Thelia/Core/Event/TheliaEvents.php b/core/lib/Thelia/Core/Event/TheliaEvents.php index 8460efda9..8eefe2735 100755 --- a/core/lib/Thelia/Core/Event/TheliaEvents.php +++ b/core/lib/Thelia/Core/Event/TheliaEvents.php @@ -249,4 +249,20 @@ final class TheliaEvents * Sent just after an attempt to use a Coupon */ const AFTER_USE_COUPON = "action.after_use_coupon"; + + // -- Configuration management --------------------------------------------- + + const CONFIG_CREATE = "action.createConfig"; + const CONFIG_SETVALUE = "action.setConfigValue"; + const CONFIG_MODIFY = "action.changeConfig"; + const CONFIG_DELETE = "action.deleteConfig"; + + const BEFORE_CREATECONFIG = "action.before_createConfig"; + const AFTER_CREATECONFIG = "action.after_createConfig"; + + const BEFORE_CHANGECONFIG = "action.before_changeConfig"; + const AFTER_CHANGECONFIG = "action.after_changeConfig"; + + const BEFORE_DELETECONFIG = "action.before_deleteConfig"; + const AFTER_DELETECONFIG = "action.after_deleteConfig"; } diff --git a/core/lib/Thelia/Core/EventListener/ControllerListener.php b/core/lib/Thelia/Core/EventListener/ControllerListener.php index 9bb432e6a..097afb189 100755 --- a/core/lib/Thelia/Core/EventListener/ControllerListener.php +++ b/core/lib/Thelia/Core/EventListener/ControllerListener.php @@ -36,6 +36,7 @@ use Thelia\Core\Template\ParserContext; * * Class ControllerListener * @package Thelia\Core\EventListener + * @author Manuel Raynaud */ class ControllerListener implements EventSubscriberInterface { @@ -59,12 +60,7 @@ class ControllerListener implements EventSubscriberInterface $event = new ActionEventFactory($request, $action, $event->getKernel()->getContainer()->getParameter("thelia.actionEvent")); $actionEvent = $event->createActionEvent(); $dispatcher->dispatch("action.".$action, $actionEvent); - - // Process form errors - if ($actionEvent->hasErrorForm()) { - $this->parserContext->setErrorForm($actionEvent->getErrorForm()); - } - } + } } public static function getSubscribedEvents() diff --git a/core/lib/Thelia/Core/Factory/ActionEventFactory.php b/core/lib/Thelia/Core/Factory/ActionEventFactory.php index 9ef0644ff..cbbb7caf8 100755 --- a/core/lib/Thelia/Core/Factory/ActionEventFactory.php +++ b/core/lib/Thelia/Core/Factory/ActionEventFactory.php @@ -25,6 +25,14 @@ namespace Thelia\Core\Factory; use Symfony\Component\HttpFoundation\Request; +/** + * * + * try to instanciate the good action class + * + * Class ActionEventFactory + * @package Thelia\Core\Factory + * @author Manuel Raynaud + */ class ActionEventFactory { diff --git a/core/lib/Thelia/Core/HttpFoundation/Request.php b/core/lib/Thelia/Core/HttpFoundation/Request.php index a30806a4b..e86ce8b65 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Request.php +++ b/core/lib/Thelia/Core/HttpFoundation/Request.php @@ -24,6 +24,13 @@ namespace Thelia\Core\HttpFoundation; use Symfony\Component\HttpFoundation\Request as BaseRequest; +/** + * extends Symfony\Component\HttpFoundation\Request for adding some helpers + * + * Class Request + * @package Thelia\Core\HttpFoundation + * @author Manuel Raynaud + */ class Request extends BaseRequest { diff --git a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php index 784258ad3..738cb531d 100755 --- a/core/lib/Thelia/Core/HttpFoundation/Session/Session.php +++ b/core/lib/Thelia/Core/HttpFoundation/Session/Session.php @@ -29,7 +29,16 @@ use Thelia\Exception\InvalidCartException; use Thelia\Model\CartQuery; use Thelia\Model\Cart; use Thelia\Tools\URL; +use Thelia\Model\Lang; +/** + * + * extends mfony\Component\HttpFoundation\Session\Session for adding some helpers + * + * Class Session + * @package Thelia\Core\HttpFoundation\Session + * Symfony\Component\HttpFoundation\Request + */ class Session extends BaseSession { // -- Language ------------------------------------------------------------ @@ -39,9 +48,47 @@ class Session extends BaseSession return $this->get("locale", "en_US"); } + public function setLocale($locale) + { + $this->set("locale", $locale); + + return $this; + } + public function getLang() { - return substr($this->getLocale(), 0, 2); + return $this->get("lang", substr($this->getLocale(), 0, 2)); + } + + public function setLang($lang) + { + $this->set("lang", $lang); + + return $this; + } + + public function getLangId() + { + return $this->get("lang_id", Lang::getDefaultLanguage()->getId()); + } + + public function setLangId($langId) + { + $this->set("lang_id", $langId); + + return $this; + } + + public function getAdminEditionLangId() + { + return $this->get('admin.edition_language', Lang::getDefaultLanguage()->getId()); + } + + public function setAdminEditionLangId($langId) + { + $this->set('admin.edition_language', $langId); + + return $this; } // -- Customer user -------------------------------------------------------- @@ -49,6 +96,7 @@ class Session extends BaseSession public function setCustomerUser(UserInterface $user) { $this->set('customer_user', $user); + return $this; } public function getCustomerUser() @@ -66,6 +114,7 @@ class Session extends BaseSession public function setAdminUser(UserInterface $user) { $this->set('admin_user', $user); + return $this; } public function getAdminUser() @@ -83,6 +132,7 @@ class Session extends BaseSession public function setReturnToUrl($url) { $this->set('return_to_url', $url); + return $this; } /** @@ -141,6 +191,6 @@ class Session extends BaseSession public function setCart($cart_id) { $this->set("cart_id", $cart_id); + return $this; } - } diff --git a/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php index 6dc938d88..d9a223430 100755 --- a/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php +++ b/core/lib/Thelia/Core/Security/Authentication/UsernamePasswordFormAuthenticator.php @@ -55,8 +55,6 @@ class UsernamePasswordFormAuthenticator implements AuthenticatorInterface ); $this->options = array_merge($defaults, $options); - - $this->loginForm->bind($this->request); } /** diff --git a/core/lib/Thelia/Core/Security/SecurityContext.php b/core/lib/Thelia/Core/Security/SecurityContext.php index c09945f61..6ddb47f00 100755 --- a/core/lib/Thelia/Core/Security/SecurityContext.php +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -60,6 +60,16 @@ class SecurityContext return $this->getSession()->getAdminUser(); } + /** + * Check if an admin user is logged in. + * + * @return true if an admin user is logged in, false otherwise. + */ + public function hasAdminUser() + { + return $this->getSession()->getAdminUser() != null; + } + /** * Gets the currently authenticated customer, or null if none is defined * @@ -70,6 +80,16 @@ class SecurityContext return $this->getSession()->getCustomerUser(); } + /** + * Check if a customer user is logged in. + * + * @return true if a customer is logged in, false otherwise. + */ + public function hasCustomerUser() + { + return $this->getSession()->getCustomerUser() != null; + } + /** * Check if a user has at least one of the required roles * diff --git a/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php new file mode 100644 index 000000000..ef51d51b8 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Element/BaseI18nLoop.php @@ -0,0 +1,79 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Element; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Thelia\Core\Template\Loop\Argument\Argument; +use Propel\Runtime\ActiveQuery\ModelCriteria; +use Thelia\Core\Security\SecurityContext; +use Thelia\Model\Tools\ModelCriteriaTools; + +/** + * + * Class BaseI18nLoop, imlplemented by loops providing internationalized data, such as title, description, etc. + * + * @package Thelia\Core\Template\Element + */ +abstract class BaseI18nLoop extends BaseLoop +{ + /** + * Define common loop arguments + * + * @return Argument[] + */ + protected function getDefaultArgs() + { + $args = parent::getDefaultArgs(); + + $args[] = Argument::createIntTypeArgument('lang'); + + return $args; + } + + /** + * Setup ModelCriteria for proper i18n processing + * + * @param ModelCriteria $search the Propel Criteria to configure + * @param array $columns the i18n columns + * @param string $foreignTable the specified table (default to criteria table) + * @param string $foreignKey the foreign key in this table (default to criteria table) + * + * @return mixed the locale + */ + protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false) { + + /* manage translations */ + return ModelCriteriaTools::getI18n( + $this->getBackend_context(), + $this->getLang(), + $search, + $this->request->getSession()->getLocale(), + $columns, + $foreignTable, + $foreignKey, + $forceReturn + ); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Element/BaseLoop.php b/core/lib/Thelia/Core/Template/Element/BaseLoop.php index 8861022e9..befb53dc7 100755 --- a/core/lib/Thelia/Core/Template/Element/BaseLoop.php +++ b/core/lib/Thelia/Core/Template/Element/BaseLoop.php @@ -138,7 +138,7 @@ abstract class BaseLoop } elseif ($value !== null && !$argument->type->isValid($value)) { /* check type */ $faultActor[] = $argument->name; - $faultDetails[] = sprintf('Invalid value for "%s" argument in loop type: %s, name: %s', $argument->name, $loopType, $loopName); + $faultDetails[] = sprintf('Invalid value "%s" for "%s" argument in loop type: %s, name: %s', $value, $argument->name, $loopType, $loopName); } else { /* set default */ /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ @@ -219,10 +219,10 @@ abstract class BaseLoop } /** - * @param \ModelCriteria $search - * @param $pagination + * @param ModelCriteria $search + * @param $pagination * - * @return array|\PropelModelPager + * @return array|\Propel\Runtime\Util\PropelModelPager */ protected function searchWithPagination(ModelCriteria $search, &$pagination) { @@ -242,18 +242,21 @@ abstract class BaseLoop * @param array $columns the i18n columns * @param string $foreignTable the specified table (default to criteria table) * @param string $foreignKey the foreign key in this table (default to criteria table) + * + * @return mixed the locale */ - protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') { + protected function configureI18nProcessing(ModelCriteria $search, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID', $forceReturn = false) { /* manage translations */ - ModelCriteriaTools::getI18n( + return ModelCriteriaTools::getI18n( $this->getBackend_context(), $this->getLang(), $search, $this->request->getSession()->getLocale(), $columns, $foreignTable, - $foreignKey + $foreignKey, + $forceReturn ); } diff --git a/core/lib/Thelia/Core/Template/Loop/Attribute.php b/core/lib/Thelia/Core/Template/Loop/Attribute.php index 0608732a4..79ffd4677 100755 --- a/core/lib/Thelia/Core/Template/Loop/Attribute.php +++ b/core/lib/Thelia/Core/Template/Loop/Attribute.php @@ -25,7 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -53,7 +53,7 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Attribute extends BaseLoop +class Attribute extends BaseI18nLoop { /** * @return ArgumentCollection @@ -66,7 +66,6 @@ class Attribute extends BaseLoop Argument::createIntListTypeArgument('category'), Argument::createBooleanOrBothTypeArgument('visible', 1), Argument::createIntListTypeArgument('exclude'), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -91,7 +90,7 @@ class Attribute extends BaseLoop $lang = $this->getLang(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -157,6 +156,7 @@ class Attribute extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $attribute->getId()) ->set("IS_TRANSLATED",$attribute->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$attribute->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $attribute->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $attribute->getVirtualColumn('i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php index 0664c7d56..13e905670 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeAvailability.php @@ -25,7 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -46,7 +46,7 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class AttributeAvailability extends BaseLoop +class AttributeAvailability extends BaseI18nLoop { /** * @return ArgumentCollection @@ -57,7 +57,6 @@ class AttributeAvailability extends BaseLoop Argument::createIntListTypeArgument('id'), Argument::createIntListTypeArgument('attribute'), Argument::createIntListTypeArgument('exclude'), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -78,7 +77,7 @@ class AttributeAvailability extends BaseLoop $search = AttributeAvQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -126,6 +125,7 @@ class AttributeAvailability extends BaseLoop $loopResultRow = new LoopResultRow(); $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')) diff --git a/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php index 556a5a1fd..53566c053 100755 --- a/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php +++ b/core/lib/Thelia/Core/Template/Loop/AttributeCombination.php @@ -25,7 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -48,7 +48,7 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class AttributeCombination extends BaseLoop +class AttributeCombination extends BaseI18nLoop { /** * @return ArgumentCollection @@ -57,7 +57,6 @@ class AttributeCombination extends BaseLoop { return new ArgumentCollection( Argument::createIntTypeArgument('product_sale_elements', null, true), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -78,7 +77,7 @@ class AttributeCombination extends BaseLoop $search = AttributeCombinationQuery::create(); /* manage attribute translations */ - $this->configureI18nProcessing( + $locale = $this->configureI18nProcessing( $search, array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), AttributeTableMap::TABLE_NAME, @@ -86,7 +85,7 @@ class AttributeCombination extends BaseLoop ); /* manage attributeAv translations */ - $this->configureI18nProcessing( + $locale = $this->configureI18nProcessing( $search, array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), AttributeAvTableMap::TABLE_NAME, @@ -118,6 +117,7 @@ class AttributeCombination extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow + ->set("LOCALE",$locale) ->set("ATTRIBUTE_TITLE", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_TITLE')) ->set("ATTRIBUTE_CHAPO", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_CHAPO')) ->set("ATTRIBUTE_DESCRIPTION", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/Category.php b/core/lib/Thelia/Core/Template/Loop/Category.php index e01ce3df4..9d4a2b4ec 100755 --- a/core/lib/Thelia/Core/Template/Loop/Category.php +++ b/core/lib/Thelia/Core/Template/Loop/Category.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -62,7 +62,7 @@ use Thelia\Type\BooleanOrBothType; * @author Manuel Raynaud * @author Etienne Roudeix */ -class Category extends BaseLoop +class Category extends BaseI18nLoop { /** * @return ArgumentCollection @@ -75,11 +75,10 @@ class Category extends BaseLoop Argument::createBooleanTypeArgument('current'), Argument::createBooleanTypeArgument('not_empty', 0), Argument::createBooleanOrBothTypeArgument('visible', 1), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( - new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'random')) + new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse', 'visible', 'visible_reverse', 'random')) ), 'manual' ), @@ -97,7 +96,7 @@ class Category extends BaseLoop $search = CategoryQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -146,6 +145,12 @@ class Category extends BaseLoop case "manual": $search->orderByPosition(Criteria::ASC); break; + case "visible": + $search->orderByVisible(Criteria::ASC); + break; + case "visible_reverse": + $search->orderByVisible(Criteria::DESC); + break; case "random": $search->clearOrderByColumns(); $search->addAscendingOrderByColumn('RAND()'); @@ -173,12 +178,13 @@ class Category extends BaseLoop $loopResultRow ->set("ID", $category->getId()) ->set("IS_TRANSLATED",$category->getVirtualColumn('IS_TRANSLATED')) - ->set("TITLE",$category->getVirtualColumn('i18n_TITLE')) + ->set("LOCALE",$locale) + ->set("TITLE", $category->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $category->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $category->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $category->getVirtualColumn('i18n_POSTSCRIPTUM')) ->set("PARENT", $category->getParent()) - ->set("URL", $category->getUrl()) + ->set("URL", $category->getUrl($locale)) ->set("PRODUCT_COUNT", $category->countChild()) ->set("VISIBLE", $category->getVisible() ? "1" : "0") ->set("POSITION", $category->getPosition()) diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php index 30238c26d..0582ad3ee 100755 --- a/core/lib/Thelia/Core/Template/Loop/CategoryPath.php +++ b/core/lib/Thelia/Core/Template/Loop/CategoryPath.php @@ -23,7 +23,7 @@ namespace Thelia\Core\Template\Loop; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -54,7 +54,7 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Franck Allimant */ -class CategoryPath extends BaseLoop +class CategoryPath extends BaseI18nLoop { /** * @return ArgumentCollection @@ -65,8 +65,7 @@ class CategoryPath extends BaseLoop Argument::createIntTypeArgument('category', null, true), Argument::createIntTypeArgument('depth'), Argument::createIntTypeArgument('level'), - Argument::createBooleanOrBothTypeArgument('visible', true, false), - Argument::createIntTypeArgument('lang') + Argument::createBooleanOrBothTypeArgument('visible', true, false) ); } @@ -82,7 +81,7 @@ class CategoryPath extends BaseLoop $search = CategoryQuery::create(); - $this->configureI18nProcessing($search, array('TITLE')); + $locale = $this->configureI18nProcessing($search, array('TITLE')); $search->filterById($id); if ($visible != BooleanOrBothType::ANY) $search->filterByVisible($visible); @@ -100,8 +99,9 @@ class CategoryPath extends BaseLoop $loopResultRow ->set("TITLE",$category->getVirtualColumn('i18n_TITLE')) - ->set("URL", $category->getUrl()) + ->set("URL", $category->getUrl($locale)) ->set("ID", $category->getId()) + ->set("LOCALE",$locale) ; $results[] = $loopResultRow; diff --git a/core/lib/Thelia/Core/Template/Loop/CategoryTree.php b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php index 330466f49..63f1e9cfb 100755 --- a/core/lib/Thelia/Core/Template/Loop/CategoryTree.php +++ b/core/lib/Thelia/Core/Template/Loop/CategoryTree.php @@ -22,9 +22,7 @@ /*************************************************************************************/ namespace Thelia\Core\Template\Loop; - use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -34,6 +32,7 @@ use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Model\CategoryQuery; use Thelia\Type; use Thelia\Type\BooleanOrBothType; +use Thelia\Core\Template\Element\BaseI18nLoop; /** * @@ -46,19 +45,17 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Franck Allimant */ -class CategoryTree extends BaseLoop +class CategoryTree extends BaseI18nLoop { /** * @return ArgumentCollection */ protected function getArgDefinitions() { - return new ArgumentCollection( - Argument::createIntTypeArgument('category', null, true), - Argument::createIntTypeArgument('depth', PHP_INT_MAX), - Argument::createBooleanOrBothTypeArgument('visible', true, false), - Argument::createIntListTypeArgument('exclude', array()) - ); + return new ArgumentCollection(Argument::createIntTypeArgument('category', null, true), + Argument::createIntTypeArgument('depth', PHP_INT_MAX), + Argument::createBooleanOrBothTypeArgument('visible', true, false), + Argument::createIntListTypeArgument('exclude', array())); } // changement de rubrique @@ -66,7 +63,11 @@ class CategoryTree extends BaseLoop { if ($level > $max_level) return; - $search = CategoryQuery::create(); + $search = CategoryQuery::create(); + + $locale = $this->configureI18nProcessing($search, array( + 'TITLE' + )); $search->filterByParent($parent); @@ -82,18 +83,15 @@ class CategoryTree extends BaseLoop $loopResultRow = new LoopResultRow(); - $loopResultRow - ->set("ID", $result->getId()) - ->set("TITLE",$result->getTitle()) - ->set("PARENT", $result->getParent()) - ->set("URL", $result->getUrl()) - ->set("VISIBLE", $result->getVisible() ? "1" : "0") - ->set("LEVEL", $level) + $loopResultRow + ->set("ID", $result->getId())->set("TITLE", $result->getVirtualColumn('i18n_TITLE')) + ->set("PARENT", $result->getParent())->set("URL", $result->getUrl($locale)) + ->set("VISIBLE", $result->getVisible() ? "1" : "0")->set("LEVEL", $level) ; - $loopResult->addRow($loopResultRow); + $loopResult->addRow($loopResultRow); - $this->buildCategoryTree($result->getId(), $visible, 1 + $level, $max_level, $exclude, $loopResult); + $this->buildCategoryTree($result->getId(), $visible, 1 + $level, $max_level, $exclude, $loopResult); } } @@ -105,7 +103,7 @@ class CategoryTree extends BaseLoop public function exec(&$pagination) { $id = $this->getCategory(); - $depth = $this->getDepth(); + $depth = $this->getDepth(); $visible = $this->getVisible(); $exclude = $this->getExclude(); diff --git a/core/lib/Thelia/Core/Template/Loop/Config.php b/core/lib/Thelia/Core/Template/Loop/Config.php new file mode 100644 index 000000000..02f39510d --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Config.php @@ -0,0 +1,128 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Core\Template\Element\BaseI18nLoop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; + +use Thelia\Core\Template\Loop\Argument\Argument; + +use Thelia\Model\LangQuery; +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Model\ConfigQuery; +use Thelia\Type\BooleanOrBothType; + +/** + * Config loop, to access configuration variables + * + * - id is the config id + * - name is the config name + * - hidden filters by hidden status (yes, no, both) + * - secured filters by secured status (yes, no, both) + * - exclude is a comma separated list of config IDs that will be excluded from output + * + * @package Thelia\Core\Template\Loop + * @author Franck Allimant + */ +class Config extends BaseI18nLoop +{ + /** + * @return ArgumentCollection + */ + protected function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createIntTypeArgument('id'), + Argument::createIntListTypeArgument('exclude'), + Argument::createAnyTypeArgument('variable'), + Argument::createBooleanOrBothTypeArgument('hidden'), + Argument::createBooleanOrBothTypeArgument('secured') + ); + } + + /** + * @param $pagination (ignored) + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $id = $this->getId(); + $name = $this->getVariable(); + $secured = $this->getSecured(); + + $search = ConfigQuery::create(); + + $locale = $this->configureI18nProcessing($search); + + if (! is_null($id)) + $search->filterById($id); + + if (! is_null($name)) + $search->filterByName($name); + + if (! is_null($exclude)) { + $search->filterById($exclude, Criteria::NOT_IN); + } + + if ($this->getHidden() != BooleanOrBothType::ANY) + $search->filterByHidden($this->getHidden() ? 1 : 0); + + if (! is_null($secured) && $secured != BooleanOrBothType::ANY) + $search->filterBySecured($secured ? 1 : 0); + + $search->orderByName(Criteria::ASC); + + $results = $this->search($search, $pagination); + + $loopResult = new LoopResult(); + + foreach ($results as $result) { + + $loopResultRow = new LoopResultRow(); + + $loopResultRow + ->set("ID" , $result->getId()) + ->set("NAME" , $result->getName()) + ->set("VALUE" , $result->getValue()) + ->set("IS_TRANSLATED", $result->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) + ->set("TITLE" , $result->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO" , $result->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION" , $result->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM" , $result->getVirtualColumn('i18n_POSTSCRIPTUM')) + ->set("HIDDEN" , $result->getHidden()) + ->set("SECURED" , $result->getSecured()) + ->set("CREATE_DATE" , $result->getCreatedAt()) + ->set("UPDATE_DATE" , $result->getUpdatedAt()) + ; + + $loopResult->addRow($loopResultRow); + } + + return $loopResult; + } +} diff --git a/core/lib/Thelia/Core/Template/Loop/Content.php b/core/lib/Thelia/Core/Template/Loop/Content.php index 701206ea8..58836daa7 100755 --- a/core/lib/Thelia/Core/Template/Loop/Content.php +++ b/core/lib/Thelia/Core/Template/Loop/Content.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -49,7 +49,7 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Content extends BaseLoop +class Content extends BaseI18nLoop { /** * @return ArgumentCollection @@ -63,7 +63,6 @@ class Content extends BaseLoop Argument::createBooleanTypeArgument('current_folder'), Argument::createIntTypeArgument('depth', 1), Argument::createBooleanOrBothTypeArgument('visible', 1), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -87,7 +86,7 @@ class Content extends BaseLoop $search = ContentQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -215,12 +214,13 @@ class Content extends BaseLoop $loopResultRow->set("ID", $content->getId()) ->set("IS_TRANSLATED",$content->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$content->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $content->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $content->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $content->getVirtualColumn('i18n_POSTSCRIPTUM')) ->set("POSITION", $content->getPosition()) - ->set("URL", $content->getUrl()) + ->set("URL", $content->getUrl($locale)) ; $loopResult->addRow($loopResultRow); diff --git a/core/lib/Thelia/Core/Template/Loop/Country.php b/core/lib/Thelia/Core/Template/Loop/Country.php index d93d94cb4..d031e135d 100755 --- a/core/lib/Thelia/Core/Template/Loop/Country.php +++ b/core/lib/Thelia/Core/Template/Loop/Country.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -43,7 +43,7 @@ use Thelia\Model\ConfigQuery; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Country extends BaseLoop +class Country extends BaseI18nLoop { /** * @return ArgumentCollection @@ -54,8 +54,7 @@ class Country extends BaseLoop Argument::createIntListTypeArgument('id'), Argument::createIntListTypeArgument('area'), Argument::createBooleanTypeArgument('with_area'), - Argument::createIntListTypeArgument('exclude'), - Argument::createIntTypeArgument('lang') + Argument::createIntListTypeArgument('exclude') ); } @@ -69,7 +68,7 @@ class Country extends BaseLoop $search = CountryQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -108,6 +107,7 @@ class Country extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $country->getId()) ->set("IS_TRANSLATED",$country->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$country->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $country->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $country->getVirtualColumn('i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/Currency.php b/core/lib/Thelia/Core/Template/Loop/Currency.php index b793b86fd..8076e2276 100755 --- a/core/lib/Thelia/Core/Template/Loop/Currency.php +++ b/core/lib/Thelia/Core/Template/Loop/Currency.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -43,7 +43,7 @@ use Thelia\Model\ConfigQuery; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Currency extends BaseLoop +class Currency extends BaseI18nLoop { /** * @return ArgumentCollection @@ -53,8 +53,7 @@ class Currency extends BaseLoop return new ArgumentCollection( Argument::createIntListTypeArgument('id'), Argument::createIntListTypeArgument('exclude'), - Argument::createBooleanTypeArgument('default_only', false), - Argument::createIntTypeArgument('lang') + Argument::createBooleanTypeArgument('default_only', false) ); } @@ -68,7 +67,7 @@ class Currency extends BaseLoop $search = CurrencyQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search, array('NAME')); + $locale = $this->configureI18nProcessing($search, array('NAME')); $id = $this->getId(); @@ -99,6 +98,7 @@ class Currency extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $currency->getId()) ->set("IS_TRANSLATED",$currency->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("NAME",$currency->getVirtualColumn('i18n_NAME')) ->set("ISOCODE", $currency->getCode()) ->set("SYMBOL", $currency->getSymbol()) diff --git a/core/lib/Thelia/Core/Template/Loop/Feature.php b/core/lib/Thelia/Core/Template/Loop/Feature.php index e2de85dbc..4a631dda8 100755 --- a/core/lib/Thelia/Core/Template/Loop/Feature.php +++ b/core/lib/Thelia/Core/Template/Loop/Feature.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -49,7 +49,7 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Feature extends BaseLoop +class Feature extends BaseI18nLoop { /** * @return ArgumentCollection @@ -62,7 +62,6 @@ class Feature extends BaseLoop Argument::createIntListTypeArgument('category'), Argument::createBooleanOrBothTypeArgument('visible', 1), Argument::createIntListTypeArgument('exclude'), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -83,7 +82,7 @@ class Feature extends BaseLoop $search = FeatureQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -149,6 +148,7 @@ class Feature extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $feature->getId()) ->set("IS_TRANSLATED",$feature->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$feature->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $feature->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $feature->getVirtualColumn('i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php index c04d70031..d298a5234 100755 --- a/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php +++ b/core/lib/Thelia/Core/Template/Loop/FeatureAvailability.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -44,7 +44,7 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class FeatureAvailability extends BaseLoop +class FeatureAvailability extends BaseI18nLoop { /** * @return ArgumentCollection @@ -55,7 +55,6 @@ class FeatureAvailability extends BaseLoop Argument::createIntListTypeArgument('id'), Argument::createIntListTypeArgument('feature'), Argument::createIntListTypeArgument('exclude'), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -76,7 +75,7 @@ class FeatureAvailability extends BaseLoop $search = FeatureAvQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -124,6 +123,7 @@ class FeatureAvailability extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $featureAv->getId()) ->set("IS_TRANSLATED",$featureAv->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$featureAv->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/FeatureValue.php b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php index 42d50c57b..a91e25cd0 100755 --- a/core/lib/Thelia/Core/Template/Loop/FeatureValue.php +++ b/core/lib/Thelia/Core/Template/Loop/FeatureValue.php @@ -25,7 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -49,7 +49,7 @@ use Thelia\Type; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class FeatureValue extends BaseLoop +class FeatureValue extends BaseI18nLoop { /** * @return ArgumentCollection @@ -68,8 +68,7 @@ class FeatureValue extends BaseLoop new Type\EnumListType(array('alpha', 'alpha_reverse', 'manual', 'manual_reverse')) ), 'manual' - ), - Argument::createIntTypeArgument('lang') + ) ); } @@ -83,11 +82,12 @@ class FeatureValue extends BaseLoop $search = FeatureProductQuery::create(); /* manage featureAv translations */ - $this->configureI18nProcessing( + $locale = $this->configureI18nProcessing( $search, array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), FeatureAvTableMap::TABLE_NAME, - 'FEATURE_AV_ID' + 'FEATURE_AV_ID', + true ); $feature = $this->getFeature(); @@ -141,7 +141,9 @@ class FeatureValue extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $featureValue->getId()); - $loopResultRow->set("PERSONAL_VALUE", $featureValue->getByDefault()) + $loopResultRow + ->set("LOCALE",$locale) + ->set("PERSONAL_VALUE", $featureValue->getByDefault()) ->set("TITLE",$featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_TITLE')) ->set("CHAPO", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_CHAPO')) ->set("DESCRIPTION", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_DESCRIPTION')) diff --git a/core/lib/Thelia/Core/Template/Loop/Folder.php b/core/lib/Thelia/Core/Template/Loop/Folder.php index 327ce76d4..95aedaed6 100755 --- a/core/lib/Thelia/Core/Template/Loop/Folder.php +++ b/core/lib/Thelia/Core/Template/Loop/Folder.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -44,7 +44,7 @@ use Thelia\Type\BooleanOrBothType; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Folder extends BaseLoop +class Folder extends BaseI18nLoop { /** * @return ArgumentCollection @@ -57,7 +57,6 @@ class Folder extends BaseLoop Argument::createBooleanTypeArgument('current'), Argument::createBooleanTypeArgument('not_empty', 0), Argument::createBooleanOrBothTypeArgument('visible', 1), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -79,7 +78,7 @@ class Folder extends BaseLoop $search = FolderQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $id = $this->getId(); @@ -157,12 +156,13 @@ class Folder extends BaseLoop $loopResultRow ->set("ID", $folder->getId()) ->set("IS_TRANSLATED",$folder->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$folder->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $folder->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $folder->getVirtualColumn('i18n_POSTSCRIPTUM')) ->set("PARENT", $folder->getParent()) - ->set("URL", $folder->getUrl()) + ->set("URL", $folder->getUrl($locale)) ->set("CONTENT_COUNT", $folder->countChild()) ->set("VISIBLE", $folder->getVisible() ? "1" : "0") ->set("POSITION", $folder->getPosition()) diff --git a/core/lib/Thelia/Core/Template/Loop/Image.php b/core/lib/Thelia/Core/Template/Loop/Image.php index 638905dc2..fc34a40b6 100755 --- a/core/lib/Thelia/Core/Template/Loop/Image.php +++ b/core/lib/Thelia/Core/Template/Loop/Image.php @@ -22,7 +22,7 @@ /*************************************************************************************/ namespace Thelia\Core\Template\Loop; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Core\Event\ImageEvent; use Thelia\Model\CategoryImageQuery; @@ -43,7 +43,7 @@ use Thelia\Log\Tlog; * * @author Franck Allimant */ -class Image extends BaseLoop +class Image extends BaseI18nLoop { /** * @var array Possible image sources @@ -63,7 +63,6 @@ class Image extends BaseLoop $queryClass = sprintf("\Thelia\Model\%sImageQuery", $object); $filterMethod = sprintf("filterBy%sId", $object); - $mapClass = sprintf("\Thelia\Model\Map\%sI18nTableMap", $object); // xxxImageQuery::create() $method = new \ReflectionMethod($queryClass, 'create'); @@ -73,19 +72,16 @@ class Image extends BaseLoop $method = new \ReflectionMethod($queryClass, $filterMethod); $method->invoke($search, $object_id); - $map = new \ReflectionClass($mapClass); - $title_map = $map->getConstant('TITLE'); - $orders = $this->getOrder(); // Results ordering foreach ($orders as $order) { switch ($order) { case "alpha": - $search->addAscendingOrderByColumn($title_map); + $search->addAscendingOrderByColumn('i18n_TITLE'); break; case "alpha-reverse": - $search->addDescendingOrderByColumn($title_map); + $search->addDescendingOrderByColumn('i18n_TITLE'); break; case "manual-reverse": $search->orderByPosition(Criteria::DESC); @@ -122,7 +118,7 @@ class Image extends BaseLoop $source_id = $this->getSourceId(); - // echo "source = ".$this->getSource().", id=".$id."
"; + // echo "source = ".$this->getSource().", id=".$source_id." - ".$this->getArg('source_id')->getValue()."
"; if (is_null($source_id)) { throw new \InvalidArgumentException("'source_id' argument cannot be null if 'source' argument is specified."); @@ -167,6 +163,9 @@ class Image extends BaseLoop $search = $this->getSearchQuery($object_type, $object_id); + /* manage translations */ + $locale = $this->configureI18nProcessing($search); + $id = $this->getId(); if (! is_null($id)) { @@ -187,7 +186,7 @@ class Image extends BaseLoop $background_color = $this->getBackgroundColor(); $quality = $this->getQuality(); $effects = $this->getEffects(); - $effects = $this->getEffects(); + if (! is_null($effects)) { $effects = explode(',', $effects); } @@ -207,8 +206,7 @@ class Image extends BaseLoop } - /* manage translations */ - $this->configureI18nProcessing($search); + // echo "sql=".$search->toString(); $results = $this->search($search, $pagination); @@ -247,14 +245,15 @@ class Image extends BaseLoop $loopResultRow ->set("ID", $result->getId()) + ->set("LOCALE",$locale) ->set("IMAGE_URL", $event->getFileUrl()) ->set("ORIGINAL_IMAGE_URL", $event->getOriginalFileUrl()) ->set("IMAGE_PATH", $event->getCacheFilepath()) ->set("ORIGINAL_IMAGE_PATH", $source_filepath) - ->set("TITLE", $result->getTitle()) - ->set("CHAPO", $result->getChapo()) - ->set("DESCRIPTION", $result->getDescription()) - ->set("POSTSCRIPTUM", $result->getPostscriptum()) + ->set("TITLE",$folder->getVirtualColumn('i18n_TITLE')) + ->set("CHAPO", $folder->getVirtualColumn('i18n_CHAPO')) + ->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION')) + ->set("POSTSCRIPTUM", $folder->getVirtualColumn('i18n_POSTSCRIPTUM')) ->set("POSITION", $result->getPosition()) ->set("OBJECT_TYPE", $object_type) ->set("OBJECT_ID", $object_id) @@ -314,9 +313,7 @@ class Image extends BaseLoop new EnumType($this->possible_sources) ) ), - Argument::createIntTypeArgument('source_id'), - - Argument::createIntListTypeArgument('lang') + Argument::createIntTypeArgument('source_id') ); // Add possible image sources diff --git a/core/lib/Thelia/Core/Template/Loop/Product.php b/core/lib/Thelia/Core/Template/Loop/Product.php index 1570acca8..a35ff90b3 100755 --- a/core/lib/Thelia/Core/Template/Loop/Product.php +++ b/core/lib/Thelia/Core/Template/Loop/Product.php @@ -25,7 +25,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Join; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -56,7 +56,7 @@ use Thelia\Type\BooleanOrBothType; * * @todo : manage currency in price filter */ -class Product extends BaseLoop +class Product extends BaseI18nLoop { /** * @return ArgumentCollection @@ -83,7 +83,6 @@ class Product extends BaseLoop Argument::createBooleanTypeArgument('current_category'), Argument::createIntTypeArgument('depth', 1), Argument::createBooleanOrBothTypeArgument('visible', 1), - Argument::createIntTypeArgument('lang'), new Argument( 'order', new TypeCollection( @@ -137,7 +136,7 @@ class Product extends BaseLoop $search = ProductQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search); + $locale = $this->configureI18nProcessing($search); $attributeNonStrictMatch = $this->getAttribute_non_strict_match(); $isPSELeftJoinList = array(); @@ -510,11 +509,12 @@ class Product extends BaseLoop $loopResultRow->set("ID", $product->getId()) ->set("REF",$product->getRef()) ->set("IS_TRANSLATED",$product->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("TITLE",$product->getVirtualColumn('i18n_TITLE')) ->set("CHAPO", $product->getVirtualColumn('i18n_CHAPO')) ->set("DESCRIPTION", $product->getVirtualColumn('i18n_DESCRIPTION')) ->set("POSTSCRIPTUM", $product->getVirtualColumn('i18n_POSTSCRIPTUM')) - ->set("URL", $product->getUrl()) + ->set("URL", $product->getUrl($locale)) ->set("BEST_PRICE", $product->getVirtualColumn('real_lowest_price')) ->set("IS_PROMO", $product->getVirtualColumn('main_product_is_promo')) ->set("IS_NEW", $product->getVirtualColumn('main_product_is_new')) diff --git a/core/lib/Thelia/Core/Template/Loop/Title.php b/core/lib/Thelia/Core/Template/Loop/Title.php index c53be086a..cd7ec7d5d 100755 --- a/core/lib/Thelia/Core/Template/Loop/Title.php +++ b/core/lib/Thelia/Core/Template/Loop/Title.php @@ -24,7 +24,7 @@ namespace Thelia\Core\Template\Loop; use Propel\Runtime\ActiveQuery\Criteria; -use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResultRow; @@ -43,7 +43,7 @@ use Thelia\Model\ConfigQuery; * @package Thelia\Core\Template\Loop * @author Etienne Roudeix */ -class Title extends BaseLoop +class Title extends BaseI18nLoop { /** * @return ArgumentCollection @@ -51,8 +51,7 @@ class Title extends BaseLoop protected function getArgDefinitions() { return new ArgumentCollection( - Argument::createIntListTypeArgument('id'), - Argument::createIntTypeArgument('lang') + Argument::createIntListTypeArgument('id') ); } @@ -66,7 +65,7 @@ class Title extends BaseLoop $search = CustomerTitleQuery::create(); /* manage translations */ - $this->configureI18nProcessing($search, array('SHORT', 'LONG')); + $locale = $this->configureI18nProcessing($search, array('SHORT', 'LONG')); $id = $this->getId(); @@ -85,6 +84,7 @@ class Title extends BaseLoop $loopResultRow = new LoopResultRow(); $loopResultRow->set("ID", $title->getId()) ->set("IS_TRANSLATED",$title->getVirtualColumn('IS_TRANSLATED')) + ->set("LOCALE",$locale) ->set("DEFAULT", $title->getByDefault()) ->set("SHORT", $title->getVirtualColumn('i18n_SHORT')) ->set("LONG", $title->getVirtualColumn('i18n_LONG')); diff --git a/core/lib/Thelia/Core/Template/ParserContext.php b/core/lib/Thelia/Core/Template/ParserContext.php index 03c3cf45f..90079abf5 100755 --- a/core/lib/Thelia/Core/Template/ParserContext.php +++ b/core/lib/Thelia/Core/Template/ParserContext.php @@ -40,11 +40,7 @@ class ParserContext implements \IteratorAggregate public function __construct(Request $request) { // Setup basic variables - $this - ->set('BASE_URL' , ConfigQuery::read('base_url', '/')) - ->set('INDEX_PAGE' , URL::getIndexPage()) - ->set('RETURN_TO_URL' , URL::absoluteUrl($request->getSession()->getReturnToUrl())) - ->set('THELIA_VERSION' , ConfigQuery::read('thelia_version', 'undefined')) + $this->set('THELIA_VERSION' , ConfigQuery::read('thelia_version', 'undefined')) ; } @@ -53,24 +49,23 @@ class ParserContext implements \IteratorAggregate /** * @param BaseForm $form the errored form */ - public function setErrorForm(BaseForm $form) + public function addForm(BaseForm $form) { - $this->set('error_form', $form); + $this->set($form->getName(), $form); + + return $this; + } + + public function getForm($name) + { + return $this->get($name, null); } public function setGeneralError($error) { $this->set('general_error', $error); - } - public function getErrorForm() - { - return $this->get('error_form', null); - } - - public function clearErrorForm() - { - return $this->remove('error_form'); + return $this; } // -- Internal table manipulation ------------------------------------------ diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php index 5216dbfbe..554d3f9de 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Form.php @@ -82,6 +82,7 @@ class Form extends AbstractSmartyPlugin public function generateForm($params, $content, \Smarty_Internal_Template $template, &$repeat) { + if ($repeat) { $name = $this->getParam($params, 'name'); @@ -93,15 +94,11 @@ class Form extends AbstractSmartyPlugin $instance = $this->createInstance($name); // Check if parser context contains our form - $errorForm = $this->parserContext->getErrorForm(); + $form = $this->parserContext->getForm($instance->getName()); - if (null != $errorForm && $errorForm->getName() == $instance->getName()) { - - // Re-use the errored form - $instance = $errorForm; - - // Don't do that, as we may want to use this form firther in the template code - //$this->parserContext->clearErrorForm(); + if (null != $form) { + // Re-use the form + $instance = $form; } $instance->createView(); @@ -110,7 +107,8 @@ class Form extends AbstractSmartyPlugin $template->assign("form_error", $instance->hasError() ? true : false); $template->assign("form_error_message", $instance->getErrorMessage()); - } else { + } + else { return $content; } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index 0163d6a71..91036517a 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -311,13 +311,13 @@ class TheliaLoop extends AbstractSmartyPlugin $type = strtolower($smartyParams['type']); if (! isset($this->loopDefinition[$type])) { - throw new ElementNotFoundException(sprintf("%s loop does not exists", $type)); + throw new ElementNotFoundException(sprintf("'%s' loop type does not exists", $type)); } $class = new \ReflectionClass($this->loopDefinition[$type]); if ($class->isSubclassOf("Thelia\Core\Template\Element\BaseLoop") === false) { - throw new InvalidElementException(sprintf("%s Loop class have to extends Thelia\Core\Template\Element\BaseLoop", + throw new InvalidElementException(sprintf("'%s' Loop class should extends Thelia\Core\Template\Element\BaseLoop", $type)); } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php index b3814f088..33e699c43 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/UrlGenerator.php @@ -47,14 +47,15 @@ class UrlGenerator extends AbstractSmartyPlugin public function generateUrlFunction($params, &$smarty) { // the path to process - $path = $this->getParam($params, 'path'); + $path = $this->getParam($params, 'path'); - $target = $this->getParam($params, 'target', null); + $target = $this->getParam($params, 'target', null); - $url = URL::absoluteUrl($path, $this->getArgsFromParam($params, array('path', 'target'))); + $url = URL::absoluteUrl($path, $this->getArgsFromParam($params, array('path', 'target'))); - if ($target != null) $url .= '#'.$target; - return $url; + if ($target != null) $url .= '#'.$target; + + return $url; } /** @@ -81,6 +82,15 @@ class UrlGenerator extends AbstractSmartyPlugin return $this->generateViewUrlFunction($params, true); } + public function navigateToUrlFunction($params, &$smarty) + { + $to = $this->getParam($params, 'to', null); + + $toMethod = $this->getNavigateToMethod($to); + + return $this->$toMethod(); + } + protected function generateViewUrlFunction($params, $forAdmin) { // the view name (without .html) @@ -125,7 +135,50 @@ class UrlGenerator extends AbstractSmartyPlugin return array( new SmartyPluginDescriptor('function', 'url', $this, 'generateUrlFunction'), new SmartyPluginDescriptor('function', 'viewurl', $this, 'generateFrontViewUrlFunction'), - new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction') + new SmartyPluginDescriptor('function', 'admin_viewurl', $this, 'generateAdminViewUrlFunction'), + new SmartyPluginDescriptor('function', 'navigate', $this, 'navigateToUrlFunction'), ); } + + /** + * @return array sur le format "to_value" => "method_name" + */ + protected function getNavigateToValues() + { + return array( + "current" => "getCurrentUrl", + "return_to" => "getReturnToUrl", + "index" => "getIndexUrl", + ); + } + + protected function getNavigateToMethod($to) + { + if($to === null) { + throw new \InvalidArgumentException("Missing 'to' parameter in `navigate` substitution."); + } + + $navigateToValues = $this->getNavigateToValues(); + + if(!array_key_exists($to, $navigateToValues)) { + throw new \InvalidArgumentException("Incorrect value for parameter `to` in `navigate` substitution."); + } + + return $navigateToValues[$to]; + } + + protected function getCurrentUrl() + { + return URL::retrieveCurrent($this->request); + } + + protected function getReturnToUrl() + { + return URL::absoluteUrl($this->request->getSession()->getReturnToUrl()); + } + + protected function getIndexUrl() + { + return Url::getIndexPage(); + } } diff --git a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php index ed74fe3f0..12014e817 100755 --- a/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php +++ b/core/lib/Thelia/Core/Template/Smarty/SmartyParser.php @@ -212,14 +212,14 @@ class SmartyParser extends Smarty implements ParserInterface $templateDir = realpath(THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/"); if (strpos($pathFileName, $templateDir) !== 0) { - throw new ResourceNotFoundException(sprintf("%s view does not exists", $file)); + throw new ResourceNotFoundException(sprintf("'%s' view does not exists", $file)); } if (!file_exists($fileName)) { $fileName .= ".html"; if (!file_exists($fileName)) { - throw new ResourceNotFoundException(sprintf("%s file not found in %s template", $file, $this->template)); + throw new ResourceNotFoundException(sprintf("'%s' file not found in %s template", $file, $this->template)); } } diff --git a/core/lib/Thelia/Core/Thelia.php b/core/lib/Thelia/Core/Thelia.php index 54a3fd13c..b28b23156 100755 --- a/core/lib/Thelia/Core/Thelia.php +++ b/core/lib/Thelia/Core/Thelia.php @@ -26,7 +26,7 @@ namespace Thelia\Core; /** * Root class of Thelia * - * It extends Symfony\Component\HttpKernel\Kernel for changing some fonctionnality + * It extends Symfony\Component\HttpKernel\Kernel for changing some features * * * @author Manuel Raynaud diff --git a/core/lib/Thelia/Core/TheliaContainerBuilder.php b/core/lib/Thelia/Core/TheliaContainerBuilder.php index a97019b60..7e49a8141 100755 --- a/core/lib/Thelia/Core/TheliaContainerBuilder.php +++ b/core/lib/Thelia/Core/TheliaContainerBuilder.php @@ -25,6 +25,13 @@ namespace Thelia\Core; use Symfony\Component\DependencyInjection\ContainerBuilder; +/** + * extends Symfony\Component\DependencyInjection\ContainerBuilder for changing some behavior + * + * Class TheliaContainerBuilder + * @package Thelia\Core + * @author Manuel Raynaud + */ class TheliaContainerBuilder extends ContainerBuilder { diff --git a/core/lib/Thelia/Core/TheliaHttpKernel.php b/core/lib/Thelia/Core/TheliaHttpKernel.php index b34eb4bed..94ab09f1b 100755 --- a/core/lib/Thelia/Core/TheliaHttpKernel.php +++ b/core/lib/Thelia/Core/TheliaHttpKernel.php @@ -125,8 +125,10 @@ class TheliaHttpKernel extends HttpKernel $lang = $this->detectLang($request); if ($lang) { - $request->getSession()->set("lang", $lang->getCode()); - $request->getSession()->set("locale", $lang->getLocale()); + $request->getSession() + ->setLang($lang->getCode()) + ->setLocale($lang->getLocale()) + ; } } @@ -164,7 +166,7 @@ class TheliaHttpKernel extends HttpKernel } //check if lang is not defined. If not we have to search the good one. - if (null === $request->getSession()->get("lang")) { + if (null === $request->getSession()->getLang()) { if (Model\ConfigQuery::read("one_domain_foreach_lang", false) == 1) { //find lang with domain @@ -173,9 +175,7 @@ class TheliaHttpKernel extends HttpKernel //find default lang return Model\LangQuery::create()->findOneByByDefault(1); - } - } protected function initSession(Request $request) diff --git a/core/lib/Thelia/Form/BaseDescForm.php b/core/lib/Thelia/Form/BaseDescForm.php new file mode 100644 index 000000000..c4f4f90c3 --- /dev/null +++ b/core/lib/Thelia/Form/BaseDescForm.php @@ -0,0 +1,54 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * A base form for all objects with standard contents. + * + * @author Franck Allimant + */ +abstract class BaseDescForm extends BaseForm +{ + protected function buildForm() + { + $this->formBuilder + ->add("locale", "hidden", array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add("title", "text", array( + "constraints" => array( + new NotBlank() + ) + ) + ) + ->add("chapo", "text", array()) + ->add("description", "text", array()) + ->add("postscriptum", "text", array()) + ; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Form/BaseForm.php b/core/lib/Thelia/Form/BaseForm.php index ac336f994..edb51ad2a 100755 --- a/core/lib/Thelia/Form/BaseForm.php +++ b/core/lib/Thelia/Form/BaseForm.php @@ -32,6 +32,13 @@ use Symfony\Component\Validator\Validation; use Thelia\Model\ConfigQuery; use Thelia\Tools\URL; +/** + * Base form class for creating form objects + * + * Class BaseForm + * @package Thelia\Form + * @author Manuel Raynaud + */ abstract class BaseForm { /** diff --git a/core/lib/Thelia/Form/CartAdd.php b/core/lib/Thelia/Form/CartAdd.php index 25ca9ce57..fb6347cd9 100755 --- a/core/lib/Thelia/Form/CartAdd.php +++ b/core/lib/Thelia/Form/CartAdd.php @@ -30,6 +30,11 @@ use Thelia\Model\ProductSaleElementsQuery; use Thelia\Model\ConfigQuery; use Thelia\Model\ProductQuery; +/** + * Class CartAdd + * @package Thelia\Form + * @author Manuel Raynaud + */ class CartAdd extends BaseForm { diff --git a/core/lib/Thelia/Form/ConfigCreationForm.php b/core/lib/Thelia/Form/ConfigCreationForm.php new file mode 100644 index 000000000..5594830bc --- /dev/null +++ b/core/lib/Thelia/Form/ConfigCreationForm.php @@ -0,0 +1,75 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints; +use Thelia\Model\ConfigQuery; +use Symfony\Component\Validator\ExecutionContextInterface; + +class ConfigCreationForm extends BaseForm +{ + protected function buildForm($change_mode = false) + { + $name_constraints = array(new Constraints\NotBlank()); + + if (!$change_mode) { + $name_constraints[] = new Constraints\Callback(array( + "methods" => array(array($this, "checkDuplicateName")) + )); + } + + $this->formBuilder + ->add("name", "text", array( + "constraints" => $name_constraints + )) + ->add("title", "text", array( + "constraints" => array( + new Constraints\NotBlank() + ) + )) + ->add("locale", "hidden", array( + "constraints" => array( + new Constraints\NotBlank() + ) + )) + ->add("value", "text", array()) + ->add("hidden", "hidden", array()) + ->add("secured", "hidden", array()) + ; + } + + public function getName() + { + return "thelia_config_creation"; + } + + public function checkDuplicateName($value, ExecutionContextInterface $context) + { + $config = ConfigQuery::create()->findOneByName($value); + + if ($config) { + $context->addViolation(sprintf("A variable with name \"%s\" already exists.", $value)); + } + } + +} diff --git a/core/lib/Thelia/Form/ConfigModificationForm.php b/core/lib/Thelia/Form/ConfigModificationForm.php new file mode 100644 index 000000000..dd0a0e42f --- /dev/null +++ b/core/lib/Thelia/Form/ConfigModificationForm.php @@ -0,0 +1,59 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\NotBlank; +use Thelia\Model\LangQuery; +use Propel\Runtime\ActiveQuery\Criteria; +use Symfony\Component\Validator\Constraints\GreaterThan; + +class ConfigModificationForm extends BaseDescForm +{ + protected function buildForm() + { + parent::buildForm(true); + + $this->formBuilder + ->add("id", "hidden", array( + "constraints" => array( + new GreaterThan( + array('value' => 0) + ) + ) + )) + ->add("name", "text", array( + "constraints" => array( + new NotBlank() + ) + )) + ->add("value", "text", array()) + ->add("hidden", "hidden", array()) + ->add("secured", "hidden", array()) + ; + } + + public function getName() + { + return "thelia_config_modification"; + } +} diff --git a/core/lib/Thelia/Form/CustomerCreation.php b/core/lib/Thelia/Form/CustomerCreation.php index 0d7172510..1bc88407b 100755 --- a/core/lib/Thelia/Form/CustomerCreation.php +++ b/core/lib/Thelia/Form/CustomerCreation.php @@ -27,6 +27,11 @@ use Symfony\Component\Validator\ExecutionContextInterface; use Thelia\Model\ConfigQuery; use Thelia\Model\CustomerQuery; +/** + * Class CustomerCreation + * @package Thelia\Form + * @author Manuel Raynaud + */ class CustomerCreation extends BaseForm { diff --git a/core/lib/Thelia/Form/CustomerModification.php b/core/lib/Thelia/Form/CustomerModification.php index 8f5167d52..61f1e0834 100755 --- a/core/lib/Thelia/Form/CustomerModification.php +++ b/core/lib/Thelia/Form/CustomerModification.php @@ -25,6 +25,11 @@ namespace Thelia\Form; use Symfony\Component\Validator\Constraints; +/** + * Class CustomerModification + * @package Thelia\Form + * @author Manuel Raynaud + */ class CustomerModification extends BaseForm { /** diff --git a/core/lib/Thelia/Model/Base/Category.php b/core/lib/Thelia/Model/Base/Category.php index cd36ad47d..6c7ac3c3e 100755 --- a/core/lib/Thelia/Model/Base/Category.php +++ b/core/lib/Thelia/Model/Base/Category.php @@ -474,7 +474,6 @@ abstract class Category implements ActiveRecordInterface if (!$this->hasVirtualColumn($name)) { throw new PropelException(sprintf('Cannot get value of inexistent virtual column %s.', $name)); } - return $this->virtualColumns[$name]; } diff --git a/core/lib/Thelia/Model/Category.php b/core/lib/Thelia/Model/Category.php index 2ffd375dd..ac3b2fff6 100755 --- a/core/lib/Thelia/Model/Category.php +++ b/core/lib/Thelia/Model/Category.php @@ -4,9 +4,14 @@ namespace Thelia\Model; use Thelia\Model\Base\Category as BaseCategory; use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Tools\URL; +use Thelia\Core\Event\TheliaEvents; +use Propel\Runtime\Connection\ConnectionInterface; class Category extends BaseCategory { + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + /** * @return int number of child for the current category */ @@ -15,8 +20,9 @@ class Category extends BaseCategory return CategoryQuery::countChild($this->getId()); } - public function getUrl() + public function getUrl($locale) { + return URL::retrieve('category', $this->getId(), $locale); } /** @@ -72,6 +78,39 @@ class Category extends BaseCategory } return $countProduct; + } + public function preInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECATEGORY, new CategoryEvent($this)); + + return true; + } + + public function postInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CREATECATEGORY, new CategoryEvent($this)); + } + + public function preUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CHANGECATEGORY, new CategoryEvent($this)); + + return true; + } + + public function postUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CHANGECATEGORY, new CategoryEvent($this)); + } + + public function preDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECATEGORY, new CategoryEvent($this)); + } + + public function postDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_DELETECATEGORY, new CategoryEvent($this)); } } \ No newline at end of file diff --git a/core/lib/Thelia/Model/Config.php b/core/lib/Thelia/Model/Config.php index 04f760bd4..70880151c 100755 --- a/core/lib/Thelia/Model/Config.php +++ b/core/lib/Thelia/Model/Config.php @@ -1,9 +1,88 @@ . */ +/* */ +/*************************************************************************************/ namespace Thelia\Model; use Thelia\Model\Base\Config as BaseConfig; +use Propel\Runtime\Connection\ConnectionInterface; +use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\Event\ConfigEvent; class Config extends BaseConfig { -} + use \Thelia\Model\Tools\ModelEventDispatcherTrait; + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CREATECONFIG, new ConfigEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CHANGECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CHANGECONFIG, new ConfigEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECONFIG, new ConfigEvent($this)); + + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_DELETECONFIG, new ConfigEvent($this)); + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Model/ConfigQuery.php b/core/lib/Thelia/Model/ConfigQuery.php index b00ef7d8c..4165f4f7c 100755 --- a/core/lib/Thelia/Model/ConfigQuery.php +++ b/core/lib/Thelia/Model/ConfigQuery.php @@ -22,4 +22,14 @@ class ConfigQuery extends BaseConfigQuery { return $value ? $value->getValue() : $default; } + + public static function getDefaultLangWhenNoTranslationAvailable() + { + return ConfigQuery::read("default_lang_without_translation", 1); + } + + public static function isRewritingEnable() + { + return self::read("rewriting_enable") == 1; + } } // ConfigQuery diff --git a/core/lib/Thelia/Model/Content.php b/core/lib/Thelia/Model/Content.php index 3b5af9ede..1a797be89 100755 --- a/core/lib/Thelia/Model/Content.php +++ b/core/lib/Thelia/Model/Content.php @@ -3,11 +3,12 @@ namespace Thelia\Model; use Thelia\Model\Base\Content as BaseContent; +use Thelia\Tools\URL; class Content extends BaseContent { - public function getUrl() + public function getUrl($locale) { - + return URL::retrieve('content', $this->getId(), $locale); } } diff --git a/core/lib/Thelia/Model/Customer.php b/core/lib/Thelia/Model/Customer.php index d7418a4ea..8f3de28d1 100755 --- a/core/lib/Thelia/Model/Customer.php +++ b/core/lib/Thelia/Model/Customer.php @@ -31,10 +31,7 @@ use Thelia\Core\Event\CustomerEvent; */ class Customer extends BaseCustomer implements UserInterface { - /** - * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface - */ - protected $dispatcher; + use \Thelia\Model\Tools\ModelEventDispatcherTrait; /** * @param int $titleId customer title id (from customer_title table) @@ -105,45 +102,6 @@ class Customer extends BaseCustomer implements UserInterface } } - public function preInsert(ConnectionInterface $con = null) - { - $this->setRef($this->generateRef()); - $customerEvent = new CustomerEvent($this); - - $this->dispatchEvent(TheliaEvents::BEFORE_CREATECUSTOMER, $customerEvent); - - return true; - } - - public function postInsert(ConnectionInterface $con = null) - { - $customerEvent = new CustomerEvent($this); - - $this->dispatchEvent(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent); - - } - - public function preUpdate(ConnectionInterface $con = null) - { - $customerEvent = new CustomerEvent($this); - $this->dispatchEvent(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent); - - return true; - } - - public function postUpdate(ConnectionInterface $con = null) - { - $customerEvent = new CustomerEvent($this); - $this->dispatchEvent(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent); - } - - protected function dispatchEvent($eventName, CustomerEvent $customerEvent) - { - if (!is_null($this->dispatcher)) { - $this->dispatcher->dispatch($eventName, $customerEvent); - } - } - protected function generateRef() { return uniqid(substr($this->getLastname(), 0, (strlen($this->getLastname()) >= 3) ? 3 : strlen($this->getLastname())), true); @@ -184,11 +142,6 @@ class Customer extends BaseCustomer implements UserInterface return parent::setEmail($email); } - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - /** * {@inheritDoc} */ @@ -217,4 +170,57 @@ class Customer extends BaseCustomer implements UserInterface public function getRoles() { return array(new Role('CUSTOMER')); } + + /** + * {@inheritDoc} + */ + public function preInsert(ConnectionInterface $con = null) + { + $this->setRef($this->generateRef()); + + $this->dispatchEvent(TheliaEvents::BEFORE_CREATECUSTOMER, new CustomerEvent($this)); + return true; + } + + /** + * {@inheritDoc} + */ + public function postInsert(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CREATECUSTOMER, new CustomerEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_CHANGECUSTOMER, new CustomerEvent($this)); + return true; + } + + /** + * {@inheritDoc} + */ + public function postUpdate(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_CHANGECUSTOMER, new CustomerEvent($this)); + } + + /** + * {@inheritDoc} + */ + public function preDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::BEFORE_DELETECONFIG, new CustomerEvent($this)); + return true; + } + + /** + * {@inheritDoc} + */ + public function postDelete(ConnectionInterface $con = null) + { + $this->dispatchEvent(TheliaEvents::AFTER_DELETECONFIG, new CustomerEvent($this)); + } } diff --git a/core/lib/Thelia/Model/Folder.php b/core/lib/Thelia/Model/Folder.php index 1179f6e72..05838e939 100755 --- a/core/lib/Thelia/Model/Folder.php +++ b/core/lib/Thelia/Model/Folder.php @@ -3,6 +3,7 @@ namespace Thelia\Model; use Thelia\Model\Base\Folder as BaseFolder; +use Thelia\Tools\URL; class Folder extends BaseFolder { @@ -14,9 +15,9 @@ class Folder extends BaseFolder return FolderQuery::countChild($this->getId()); } - public function getUrl() + public function getUrl($locale) { - + return URL::retrieve('folder', $this->getId(), $locale); } /** diff --git a/core/lib/Thelia/Model/Lang.php b/core/lib/Thelia/Model/Lang.php index d63422680..3339dec64 100755 --- a/core/lib/Thelia/Model/Lang.php +++ b/core/lib/Thelia/Model/Lang.php @@ -6,4 +6,33 @@ use Thelia\Model\Base\Lang as BaseLang; class Lang extends BaseLang { + /** + * Return the default language object, using a local variable to cache it. + * + * @throws RuntimeException + */ + private static $default_lang = null; + + public static function getDefaultLanguage() { + + if (self::$default_lang == null) { + $default_lang = LangQuery::create()->findOneByByDefault(true); + + if ($default_lang == null) throw new RuntimeException("No default language is defined. Please define one."); + } + + return $default_lang; + } + + public function getDateFormat() { + return "d/m/Y"; + } + + public function getTimeFormat() { + return "H:i:s"; + } + + public function getDateTimeFormat() { + return "d/m/Y H:i:s"; + } } diff --git a/core/lib/Thelia/Model/Map/RewritingUrlTableMap.php b/core/lib/Thelia/Model/Map/RewritingUrlTableMap.php index c6d5e5473..1d6129ed8 100644 --- a/core/lib/Thelia/Model/Map/RewritingUrlTableMap.php +++ b/core/lib/Thelia/Model/Map/RewritingUrlTableMap.php @@ -162,9 +162,9 @@ class RewritingUrlTableMap extends TableMap // columns $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); $this->addColumn('URL', 'Url', 'VARCHAR', true, 255, null); - $this->addColumn('VIEW', 'View', 'VARCHAR', false, 255, null); + $this->addColumn('VIEW', 'View', 'VARCHAR', true, 255, null); $this->addColumn('VIEW_ID', 'ViewId', 'VARCHAR', false, 255, null); - $this->addColumn('VIEW_LOCALE', 'ViewLocale', 'VARCHAR', false, 255, null); + $this->addColumn('VIEW_LOCALE', 'ViewLocale', 'VARCHAR', true, 255, null); $this->addForeignKey('REDIRECTED', 'Redirected', 'INTEGER', 'rewriting_url', 'ID', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('UPDATED_AT', 'UpdatedAt', 'TIMESTAMP', false, null, null); diff --git a/core/lib/Thelia/Model/Product.php b/core/lib/Thelia/Model/Product.php index ae693e0aa..e7d0586cc 100755 --- a/core/lib/Thelia/Model/Product.php +++ b/core/lib/Thelia/Model/Product.php @@ -3,12 +3,12 @@ namespace Thelia\Model; use Thelia\Model\Base\Product as BaseProduct; -use Thelia\Model\ProductSaleElements; +use Thelia\Tools\URL; class Product extends BaseProduct { - public function getUrl() + public function getUrl($locale) { - + return URL::retrieve('product', $this->getId(), $locale); } } diff --git a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php index 3913b2890..5e22f08e9 100755 --- a/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php +++ b/core/lib/Thelia/Model/Tools/ModelCriteriaTools.php @@ -7,6 +7,7 @@ use Propel\Runtime\ActiveQuery\Join; use Propel\Runtime\ActiveQuery\ModelCriteria; use Thelia\Model\Base\LangQuery; use Thelia\Model\ConfigQuery; +use Thelia\Model\Lang; /** * Class ModelCriteriaTools @@ -23,7 +24,7 @@ class ModelCriteriaTools * @param null $foreignTable * @param string $foreignKey */ - public static function getFrontEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey) + public static function getFrontEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey, $forceReturn = false) { if($foreignTable === null) { $foreignTable = $search->getTableMap()->getName(); @@ -32,16 +33,16 @@ class ModelCriteriaTools $aliasPrefix = $foreignTable . '_'; } - $defaultLangWithoutTranslation = ConfigQuery::read("default_lang_without_translation", 1); + $defaultLangWithoutTranslation = ConfigQuery::getDefaultLangWhenNoTranslationAvailable(); - $requestedLocaleI18nAlias = 'requested_locale_i18n'; - $defaultLocaleI18nAlias = 'default_locale_i18n'; - - if (!$defaultLangWithoutTranslation == 0) { + $requestedLocaleI18nAlias = $aliasPrefix . 'requested_locale_i18n'; + $defaultLocaleI18nAlias = $aliasPrefix . 'default_locale_i18n'; + if($defaultLangWithoutTranslation == 0) { + $requestedLocaleJoin = new Join(); $requestedLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $requestedLocaleI18nAlias); - $requestedLocaleJoin->setJoinType(Criteria::INNER_JOIN); + $requestedLocaleJoin->setJoinType($forceReturn === false ? Criteria::INNER_JOIN : Criteria::LEFT_JOIN); $search->addJoinObject($requestedLocaleJoin, $requestedLocaleI18nAlias) ->addJoinCondition($requestedLocaleI18nAlias ,'`' . $requestedLocaleI18nAlias . '`.LOCALE = ?', $requestedLocale, null, \PDO::PARAM_STR); @@ -52,7 +53,7 @@ class ModelCriteriaTools $search->withColumn('`' . $requestedLocaleI18nAlias . '`.`' . $column . '`', $aliasPrefix . 'i18n_' . $column); } } else { - $defaultLocale = LangQuery::create()->findOneById($defaultLangWithoutTranslation)->getLocale(); + $defaultLocale = Lang::getDefaultLanguage()->getLocale(); $defaultLocaleJoin = new Join(); $defaultLocaleJoin->addExplicitCondition($search->getTableMap()->getName(), $foreignKey, null, $foreignTable . '_i18n', 'ID', $defaultLocaleI18nAlias); @@ -70,7 +71,9 @@ class ModelCriteriaTools $search->withColumn('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.`ID`)', $aliasPrefix . 'IS_TRANSLATED'); - $search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)'); + if($forceReturn === false) { + $search->where('NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID)')->_or()->where('NOT ISNULL(`' . $defaultLocaleI18nAlias . '`.ID)'); + } foreach($columns as $column) { $search->withColumn('CASE WHEN NOT ISNULL(`' . $requestedLocaleI18nAlias . '`.ID) THEN `' . $requestedLocaleI18nAlias . '`.`' . $column . '` ELSE `' . $defaultLocaleI18nAlias . '`.`' . $column . '` END', $aliasPrefix . 'i18n_' . $column); @@ -78,7 +81,7 @@ class ModelCriteriaTools } } - public static function getBackEndI18n(ModelCriteria &$search, $requestedLocale, $columns, $foreignTable, $foreignKey) + public static function getBackEndI18n(ModelCriteria &$search, $requestedLocale, $columns = array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'), $foreignTable = null, $foreignKey = 'ID') { if($foreignTable === null) { $foreignTable = $search->getTableMap()->getName(); @@ -103,7 +106,7 @@ class ModelCriteriaTools } } - public static function getI18n($backendContext, $requestedLangId, ModelCriteria &$search, $currentLocale, $columns, $foreignTable, $foreignKey) + public static function getI18n($backendContext, $requestedLangId, ModelCriteria &$search, $currentLocale, $columns, $foreignTable, $foreignKey, $forceReturn = false) { // If a lang has been requested, find the related Lang object, and get the locale if ($requestedLangId !== null) { @@ -124,7 +127,9 @@ class ModelCriteriaTools if ($backendContext) { self::getBackEndI18n($search, $locale, $columns, $foreignTable, $foreignKey); } else { - self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey); + self::getFrontEndI18n($search, $locale, $columns, $foreignTable, $foreignKey, $forceReturn); } + + return $locale; } } diff --git a/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php b/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php new file mode 100644 index 000000000..7e2e34d83 --- /dev/null +++ b/core/lib/Thelia/Model/Tools/ModelEventDispatcherTrait.php @@ -0,0 +1,53 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Model\Tools; + +use Thelia\Core\Event\ActionEvent; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * A trait to provide event dispatching mechanism to Model objects + */ +trait ModelEventDispatcherTrait { + + /** + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface + */ + protected $dispatcher = null; + + + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + + return $this; + } + + protected function dispatchEvent($eventName, ActionEvent $event) + { + if (!is_null($this->dispatcher)) { + $this->dispatcher->dispatch($eventName, $event); + } + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Rewriting/RewritingResolver.php b/core/lib/Thelia/Rewriting/RewritingResolver.php new file mode 100755 index 000000000..818dbec32 --- /dev/null +++ b/core/lib/Thelia/Rewriting/RewritingResolver.php @@ -0,0 +1,35 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Rewriting; + +/** + * Class RewritingResolver + * @package Thelia\Rewriting + * @author Etienne Roudeix + * + * This class provides methods to resolve rewritten URL as a query + */ +class RewritingResolver +{ + +} diff --git a/core/lib/Thelia/Rewriting/RewritingRetriever.php b/core/lib/Thelia/Rewriting/RewritingRetriever.php new file mode 100755 index 000000000..0deb7de45 --- /dev/null +++ b/core/lib/Thelia/Rewriting/RewritingRetriever.php @@ -0,0 +1,119 @@ +. */ +/* */ +/*************************************************************************************/ +namespace Thelia\Rewriting; + +use Propel\Runtime\ActiveQuery\Criteria; +use Thelia\Model\Base\RewritingUrlQuery; +use Thelia\Model\Map\RewritingUrlTableMap; + +/** + * Class RewritingRetriever + * @package Thelia\Rewriting + * @author Etienne Roudeix + * + * This class provides methods to retrieve a rewritten URL from a query + */ +class RewritingRetriever +{ + /** + * @param $view + * @param $viewLocale + * @param $viewId + * + * @return null|$url + */ + public function getViewUrl($view, $viewLocale, $viewId) + { + $url = $this->getViewUrlQuery($view, $viewId, $viewLocale); + + return $url === null ? null : $url->getUrl(); + } + + /** + * @param $view + * @param $viewId + * @param $viewLocale + * + * @return null|RewritingUrl + */ + protected function getViewUrlQuery($view, $viewId, $viewLocale) + { + return RewritingUrlQuery::create() + ->joinRewritingArgument('ra', Criteria::LEFT_JOIN) + ->where('ISNULL(`ra`.REWRITING_URL_ID)') + ->filterByView($view) + ->filterByViewLocale($viewLocale) + ->filterByViewId($viewId) + ->filterByRedirected(null) + ->orderByUpdatedAt(Criteria::DESC) + ->findOne(); + } + + /** + * @param $view + * @param $viewLocale + * @param null $viewId + * @param array $viewOtherParameters + * + * @return null|$url + */ + public function getSpecificUrl($view, $viewLocale, $viewId = null, $viewOtherParameters = array()) + { + $urlQuery = RewritingUrlQuery::create() + ->joinRewritingArgument('ra', Criteria::LEFT_JOIN) + ->withColumn('`ra`.REWRITING_URL_ID', 'ra_REWRITING_URL_ID') + ->filterByView($view) + ->filterByViewLocale($viewLocale) + ->filterByViewId($viewId) + ->filterByRedirected(null) + ->orderByUpdatedAt(Criteria::DESC); + + $otherParametersCount = count($viewOtherParameters); + if($otherParametersCount > 0) { + $parameterConditions = array(); + + foreach($viewOtherParameters as $parameter => $value) { + $conditionName = 'other_parameter_condition_' . count($parameterConditions); + $urlQuery->condition('parameter_condition', '`ra`.PARAMETER= ?', $parameter, \PDO::PARAM_STR) + ->condition('value_condition', '`ra`.VALUE = ?', $value, \PDO::PARAM_STR) + ->combine(array('parameter_condition', 'value_condition'), Criteria::LOGICAL_AND, $conditionName); + $parameterConditions[] = $conditionName; + } + + $urlQuery->where($parameterConditions, Criteria::LOGICAL_OR); + + $urlQuery->groupBy(RewritingUrlTableMap::ID); + + $urlQuery->condition('count_condition_1', 'COUNT(' . RewritingUrlTableMap::ID . ') = ?', $otherParametersCount, \PDO::PARAM_INT) // ensure we got all the asked parameters (provided by the query) + ->condition('count_condition_2', 'COUNT(' . RewritingUrlTableMap::ID . ') = (SELECT COUNT(*) FROM rewriting_argument WHERE rewriting_argument.REWRITING_URL_ID = ra_REWRITING_URL_ID)'); // ensure we don't miss any parameters (needed to match the rewritten url) + + $urlQuery->having(array('count_condition_1', 'count_condition_2'), Criteria::LOGICAL_AND); + } else { + $urlQuery->where('ISNULL(`ra`.REWRITING_URL_ID)'); + } + + $url = $urlQuery->findOne(); + + return $url === null ? null : $url->getUrl(); + } +} diff --git a/core/lib/Thelia/Tests/Cart/CartTraitTest.php b/core/lib/Thelia/Tests/Cart/CartTraitTest.php index 586de3d11..039e4448e 100755 --- a/core/lib/Thelia/Tests/Cart/CartTraitTest.php +++ b/core/lib/Thelia/Tests/Cart/CartTraitTest.php @@ -34,6 +34,7 @@ use Thelia\Model\Customer; * * Class CartTraitTest * @package Thelia\Tests\Cart\CartTraitTest + * @author Manuel Raynaud */ class CartTraitTest extends \PHPUnit_Framework_TestCase { diff --git a/core/lib/Thelia/Tests/Command/BaseCommandTest.php b/core/lib/Thelia/Tests/Command/BaseCommandTest.php index 09a84d54e..54b62e3f5 100755 --- a/core/lib/Thelia/Tests/Command/BaseCommandTest.php +++ b/core/lib/Thelia/Tests/Command/BaseCommandTest.php @@ -22,6 +22,13 @@ /*************************************************************************************/ namespace Thelia\Tests\Command; +/** + * base class for testing command line command + * + * Class BaseCommandTest + * @package Thelia\Tests\Command + * @author Manuel Raynaud + */ abstract class BaseCommandTest extends \PHPUnit_Framework_TestCase { public function getKernel() diff --git a/core/lib/Thelia/Tests/Command/CacheClearTest.php b/core/lib/Thelia/Tests/Command/CacheClearTest.php index 4e05e5611..ed2e512b6 100755 --- a/core/lib/Thelia/Tests/Command/CacheClearTest.php +++ b/core/lib/Thelia/Tests/Command/CacheClearTest.php @@ -28,6 +28,13 @@ use Thelia\Command\CacheClear; use Symfony\Component\Filesystem\Filesystem; +/** + * test the cache:clear command + * + * Class CacheClearTest + * @package Thelia\Tests\Command + * @author Manuel Raynaud + */ class CacheClearTest extends \PHPUnit_Framework_TestCase { diff --git a/core/lib/Thelia/Tests/Command/ModuleGenerateCommandTest.php b/core/lib/Thelia/Tests/Command/ModuleGenerateCommandTest.php index f1167fe09..78d84ea78 100755 --- a/core/lib/Thelia/Tests/Command/ModuleGenerateCommandTest.php +++ b/core/lib/Thelia/Tests/Command/ModuleGenerateCommandTest.php @@ -27,6 +27,13 @@ use Symfony\Component\Filesystem\Filesystem; use Thelia\Core\Application; use Thelia\Command\ModuleGenerateCommand; +/** + * test the module:generate command + * + * Class ModuleGenerateCommandTest + * @package Thelia\Tests\Command + * @author Manuel Raynaud + */ class ModuleGenerateCommandTest extends BaseCommandTest { protected $command; diff --git a/core/lib/Thelia/Tests/Controller/DefaultControllerTest.php b/core/lib/Thelia/Tests/Controller/DefaultControllerTest.php index e787403df..fda569435 100755 --- a/core/lib/Thelia/Tests/Controller/DefaultControllerTest.php +++ b/core/lib/Thelia/Tests/Controller/DefaultControllerTest.php @@ -26,6 +26,11 @@ namespace Thelia\Tests\Controller; use Symfony\Component\HttpFoundation\Request; use Thelia\Controller\Front\DefaultController; +/** + * Class DefaultControllerTest + * @package Thelia\Tests\Controller + * @author Manuel Raynaud + */ class DefaultControllerTest extends \PHPUnit_Framework_TestCase { diff --git a/core/lib/Thelia/Tests/Core/HttpFoundation/RequestTest.php b/core/lib/Thelia/Tests/Core/HttpFoundation/RequestTest.php index f94b5607f..d7437efb9 100755 --- a/core/lib/Thelia/Tests/Core/HttpFoundation/RequestTest.php +++ b/core/lib/Thelia/Tests/Core/HttpFoundation/RequestTest.php @@ -4,6 +4,13 @@ namespace Thelia\Tests\Core\HttpFoundation; use Thelia\Core\HttpFoundation\Request; +/** + * the the helpers addinf in Request class + * + * Class RequestTest + * @package Thelia\Tests\Core\HttpFoundation + * @author Manuel Raynaud + */ class RequestTest extends \PHPUnit_Framework_TestCase { diff --git a/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php b/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php index 7efebdedf..317b19dea 100755 --- a/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php +++ b/core/lib/Thelia/Tests/Core/HttpFoundation/Session/SessionTest.php @@ -28,6 +28,13 @@ use Thelia\Core\HttpFoundation\Session\Session; use Thelia\Model\Cart; use Thelia\Model\Customer; +/** + * Test the helpers adding in Session class + * + * Class SessionTest + * @package Thelia\Tests\Core\HttpFoundation\Session + * @author Manuel Raynaud + */ class SessionTest extends \PHPUnit_Framework_TestCase { diff --git a/core/lib/Thelia/Tests/Rewriting/RewritingRetrieverTest.php b/core/lib/Thelia/Tests/Rewriting/RewritingRetrieverTest.php new file mode 100755 index 000000000..741c22b4e --- /dev/null +++ b/core/lib/Thelia/Tests/Rewriting/RewritingRetrieverTest.php @@ -0,0 +1,44 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Rewriting; + +use Thelia\Rewriting\RewritingRetriever; + +/** + * + * @author Etienne Roudeix + * + */ +class RewritingRetrieverTest extends \PHPUnit_Framework_TestCase +{ + public function testGetViewUrl() + { + + } + + public function testGetSpecificUrl() + { + + } +} diff --git a/core/lib/Thelia/Tests/Tools/URLTest.php b/core/lib/Thelia/Tests/Tools/URLTest.php new file mode 100755 index 000000000..0c99651b4 --- /dev/null +++ b/core/lib/Thelia/Tests/Tools/URLTest.php @@ -0,0 +1,39 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Tests\Type; + +use Thelia\Tools\URL; + +/** + * + * @author Etienne Roudeix + * + */ +class URLTest extends \PHPUnit_Framework_TestCase +{ + public function testRetrieve() + { + + } +} diff --git a/core/lib/Thelia/Tools/URL.php b/core/lib/Thelia/Tools/URL.php index 5a88fa922..b84fdca73 100755 --- a/core/lib/Thelia/Tools/URL.php +++ b/core/lib/Thelia/Tools/URL.php @@ -23,7 +23,9 @@ namespace Thelia\Tools; +use Symfony\Component\HttpFoundation\Request; use Thelia\Model\ConfigQuery; +use Thelia\Rewriting\RewritingRetriever; class URL { @@ -51,13 +53,17 @@ class URL // Already absolute ? if (substr($path, 0, 4) != 'http') { + /** + * @etienne : can't be done here for it's already done in ::viewUrl / ::adminViewUrl + * @franck : should be done, as absoluteUrl() is sometimes called directly (see UrlGenerator::generateUrlFunction()) + */ $root = $path_only == self::PATH_TO_FILE ? ConfigQuery::read('base_url', '/') : self::getIndexPage(); + //$root = $path_only == self::PATH_TO_FILE ? ConfigQuery::read('base_url', '/') : ''; $base = rtrim($root, '/') . '/' . ltrim($path, '/'); } else $base = $path; - $queryString = ''; if (! is_null($parameters)) { @@ -101,4 +107,50 @@ class URL return self::absoluteUrl($path, $parameters); } + + /** + * @param $view + * @param $viewId + * @param $viewLocale + * + * @return null|string + */ + public static function retrieve($view, $viewId, $viewLocale) + { + $rewrittenUrl = null; + if(ConfigQuery::isRewritingEnable()) { + $retriever = new RewritingRetriever(); + $rewrittenUrl = $retriever->getViewUrl($view, $viewLocale, $viewId); + } + + return $rewrittenUrl === null ? self::viewUrl($view, array($view . '_id' => $viewId, 'locale' => $viewLocale)) : $rewrittenUrl; + } + + public static function retrieveCurrent(Request $request) + { + $rewrittenUrl = null; + if(ConfigQuery::isRewritingEnable()) { + $view = $request->query->get('view', null); + $viewLocale = $request->query->get('locale', null); + $viewId = $view === null ? null : $request->query->get($view . '_id', null); + + $allParameters = $request->query->all(); + $allParametersWithoutView = $allParameters; + if($view !== null) { + unset($allParametersWithoutView['view']); + } + $allOtherParameters = $allParametersWithoutView; + if($viewLocale !== null) { + unset($allOtherParameters['locale']); + } + if($viewId !== null) { + unset($allOtherParameters[$view . '_id']); + } + + $retriever = new RewritingRetriever(); + $rewrittenUrl = $retriever->getSpecificUrl($view, $viewLocale, $viewId, $allOtherParameters); + } + + return $rewrittenUrl === null ? self::viewUrl($view, $allParametersWithoutView) : $rewrittenUrl; + } } diff --git a/install/faker.php b/install/faker.php index 6e1aef8ba..8ba653bec 100755 --- a/install/faker.php +++ b/install/faker.php @@ -246,7 +246,7 @@ try { //categories and products $productIdList = array(); $categoryIdList = array(); - for($i=0; $i<4; $i++) { + for($i=1; $i<5; $i++) { $category = createCategory($faker, 0, $i, $categoryIdList, $contentIdList); for($j=1; $jsetProductId($productId); generate_image($image, 1, 'product', $productId); - + return $product; } @@ -423,7 +423,7 @@ function createCategory($faker, $parent, $position, &$categoryIdList, $contentId $image = new CategoryImage(); $image->setCategoryId($categoryId); generate_image($image, 1, 'category', $categoryId); - + return $category; } @@ -545,4 +545,4 @@ Sed facilisis pellentesque nisl, eu tincidunt erat scelerisque a. Nullam malesua $coupon1->setIsCumulative(1); $coupon1->setIsRemovingPostage(0); $coupon1->save(); -} \ No newline at end of file +} diff --git a/install/insert.sql b/install/insert.sql index cbb6725f3..4336eaa0c 100755 --- a/install/insert.sql +++ b/install/insert.sql @@ -7,6 +7,8 @@ INSERT INTO `lang`(`id`,`title`,`code`,`locale`,`url`,`by_default`,`created_at`, INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updated_at`) VALUES ('session_config.default', '1', 1, 1, NOW(), NOW()), ('verifyStock', '1', 1, 0, NOW(), NOW()), +('default_lang_without_translation', '1', 1, 0, NOW(), NOW()), +('rewriting_enable', '0', 1, 0, NOW(), NOW()), ('imagine_graphic_driver', 'gd', 1, 0, NOW(), NOW()), ('default_images_quality_percent', '75', 1, 0, NOW(), NOW()), ('original_image_delivery_mode', 'symlink', 1, 0, NOW(), NOW()), diff --git a/install/thelia.sql b/install/thelia.sql index 1993ee084..99b18513e 100755 --- a/install/thelia.sql +++ b/install/thelia.sql @@ -1443,9 +1443,9 @@ CREATE TABLE `rewriting_url` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `url` VARCHAR(255) NOT NULL, - `view` VARCHAR(255), + `view` VARCHAR(255) NOT NULL, `view_id` VARCHAR(255), - `view_locale` VARCHAR(255), + `view_locale` VARCHAR(255) NOT NULL, `redirected` INTEGER, `created_at` DATETIME, `updated_at` DATETIME, diff --git a/local/config/schema.xml b/local/config/schema.xml index 4495e87ed..159b21831 100755 --- a/local/config/schema.xml +++ b/local/config/schema.xml @@ -1096,9 +1096,9 @@ - + - + diff --git a/templates/admin/default/assets/css/admin.less b/templates/admin/default/assets/css/admin.less index 9d9f2c482..6c5c76a8d 100755 --- a/templates/admin/default/assets/css/admin.less +++ b/templates/admin/default/assets/css/admin.less @@ -216,6 +216,10 @@ hr { width: 23px; height: @top-bar-height; } + + a.profile { + color: #fff; + } } .view-shop { @@ -233,10 +237,6 @@ hr { .loginpage { - .brandbar { - width: 100%; - } - .hero-unit { background-color: transparent !important; @@ -316,6 +316,10 @@ hr { } } +.brandbar-wide { + width: 100%; +} + // -- Navigation bar ---------------------------------------------------------- .navbar { @@ -571,6 +575,11 @@ form .info .input-append .add-on { line-height: 30px; } + .title-without-tabs { + border-bottom: 2px solid #A5CED8; + margin-bottom: 0.5em; + } + // The action bar on the right .actions { text-align: right; @@ -590,6 +599,8 @@ form .info .input-append .add-on { line-height: 30px; margin-bottom: 1em; + border-bottom: 1px dotted #A5CED8; + padding-bottom: 0.5em; .inner-actions { text-align: right; @@ -629,7 +640,7 @@ label { } .input-append.input-block-level .add-on img { - max-height: 18px; + max-height: 16px; } // Information in field label @@ -699,9 +710,12 @@ label { line-height: 30px; - .btn-add-item { + .action-btn { display: block; float: right; + margin-left: 10px; + + text-transform: none; } } @@ -717,4 +731,59 @@ label { // Center the alert box (20px bottom margin) in the table cell padding: 20px 20px 0 20px; } + + th { + a { + color: inherit; + } + } + + td { + vertical-align: middle; + + img { + border: 2px solid white; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + } + + &.actions { + text-align: right; + } + } +} + +.menu-list-table .table-striped { + td, th { + text-align: left; + } + + td:nth-child(2) { + text-align: right; + } + + caption { + background-color: #FFFFFF; + border-bottom: 2px solid #A5CED8; + color: #5A6876; + font-weight: bold; + line-height: 30px; + text-align: left; + text-transform: uppercase; + } +} + +.table-left-aligned { + th, td { + text-align: left; + } + + select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input { + margin-bottom: 0; + } +} + +// Modal is no longer limited +.modal-body { + max-height: none; } \ No newline at end of file diff --git a/templates/admin/default/categories.html b/templates/admin/default/categories.html index e37018e02..ee20653f8 100755 --- a/templates/admin/default/categories.html +++ b/templates/admin/default/categories.html @@ -1,4 +1,4 @@ -{check_auth context="admin" roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"} +{check_auth roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"} {$page_title={intl l='Catalog'}} @@ -31,8 +31,8 @@ {module_include location='category_list_caption'} - {loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"} - + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.category.create"} + {/loop} @@ -41,25 +41,77 @@ {ifloop rel="category_list"} - + + {module_include location='category_list_header'} - - + + + + - {loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="manual"} + {loop name="category_list" type="category" visible="*" parent="{$current_category_id}" order="$category_order"} - + + + {module_include location='category_list_row'} @@ -101,7 +153,7 @@ - + @@ -156,7 +208,12 @@ {loop name="product_list" type="product" category="{$current_category_id}" order="manual"} - + diff --git a/templates/admin/default/configuration.html b/templates/admin/default/configuration.html new file mode 100644 index 000000000..129f8b004 --- /dev/null +++ b/templates/admin/default/configuration.html @@ -0,0 +1,174 @@ +{check_auth roles="ADMIN" permissions="admin.configuration.view" login_tpl="/admin/login"} + +{$page_title={intl l='Configuration'}} + +{include file='includes/header.inc.html'} + +
+ +
+ + {module_include location='configuration_top'} + +

{intl l="Thelia configuration"}

+ +
+ +
+
{intl l="Category title"}  + {if $category_order == 'alpha'} + + {$order_change = 'alpha_reverse'} + {elseif $category_order == 'alpha_reverse'} + + {$order_change = 'alpha'} + {else} + {$order_change = 'alpha'} + {/if} + + {intl l="Category title"} + + {intl l="Online"}{intl l="Position"} + {if $category_order == 'visible'} + + {$order_change = 'visible_reverse'} + {elseif $category_order == 'visible_reverse'} + + {$order_change = 'visible'} + {else} + {$order_change = 'visible'} + {/if} + + + {intl l="Online"} + + + {if $category_order == 'manual'} + + {$order_change = 'manual_reverse'} + {elseif $category_order == 'manual_reverse'} + + {$order_change = 'manual'} + {else} + {$order_change = 'manual'} + {/if} + + {intl l="Position"} + {intl l="Actions"}
{$TITLE} + {loop type="image" name="cat_image" source="category" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + #TITLE + {/loop} + + + {$TITLE} + + - {loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.category.edit"} {/loop} @@ -69,7 +121,7 @@ - {loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.category.edit"} {$POSITION} @@ -83,11 +135,11 @@ - {loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.category.edit"} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.category.edit"} {/loop} - {loop type="auth" name="can_delete" context="admin" roles="ADMIN" permissions="admin.category.delete"} + {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.category.delete"} {/loop}
- {loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"} + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.category.create"} {intl l="This category has no sub-categories. To create a new one, click the + button above."} {/loop} @@ -133,7 +185,7 @@ {module_include location='product_list_caption'} - + @@ -141,7 +193,7 @@ {ifloop rel="product_list"}
{intl l="Image"}  {intl l="Product title"}
Image ! + {loop type="image" name="cat_image" source="product" source_id="$ID" limit="1" width="50" height="50" resize_mode="crop" backend_context="1"} + + #TITLE + + {/loop} {$TITLE}
+ + + {module_include location='catalog_configuration_top'} + + {loop type="auth" name="pcc1" roles="ADMIN" permissions="admin.configuration.product_templates"} + + + + + {/loop} + + {loop type="auth" name="pcc2" roles="ADMIN" permissions="admin.configuration.product_attributes"} + + + + + {/loop} + + {loop type="auth" name="pcc3" roles="ADMIN" permissions="admin.configuration.product_features"} + + + + + {/loop} + + {loop type="auth" name="pcc4" roles="ADMIN" permissions="admin.configuration.mailing_template"} + + + + + {/loop} + + {loop type="auth" name="pcc5" roles="ADMIN" permissions="admin.configuration.currencies"} + + + + + {/loop} + + {module_include location='catalog_configuration_bottom'} + +
{intl l='Product catalog configuration'}
{intl l='Product templates'}
{intl l='Product attributes'}
{intl l='Product features'}
{intl l='Mailing templates'}
{intl l='Currencies'}
+ + + +
+ +
+ +
+ +
+ + {module_include location='configuration_bottom'} + + + + +{include file='includes/js.inc.html'} + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/edit_category.html b/templates/admin/default/edit_category.html index c1e19809f..d58c251fd 100755 --- a/templates/admin/default/edit_category.html +++ b/templates/admin/default/edit_category.html @@ -1,17 +1,17 @@ -{check_auth context="admin" roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"} +{check_auth roles="ADMIN" permissions="admin.catalog.view" login_tpl="/admin/login"} {$page_title={intl l='Edit category'}} {include file='includes/header.inc.html'} -
+
- + {loop name="category_edit" type="category" visible="*" id="{$current_category_id}" backend_context="1" lang="$edition_language"}
@@ -25,156 +25,187 @@
-
- -
+
-
- -
+
+
+
- {include file="includes/inner-form-toolbar.html"} + {include file="includes/inner-form-toolbar.html"} -
-
-
- +
+
+
+ -
- -
-
+
+ +
+
-
- +
+ -
- -
-
+
+ +
+
-
- +
+ -
- +
+ -
-
+
+
-
- +
+ -
- -
-
+
+ +
+
-
- +
+ -
-
- - {intl l='Use default'} +
+ +
{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}
+
+
+ +
+
+ +
+
+
+   +
+

{intl l='Category created on %date_create. Last modification: %date_change' date_create=$CREATE_DATE->format($datetime_format) date_change=$UPDATE_DATE->format($datetime_format)}

+
+
+
+
+ +
+
+
+ +
+
+
+ {include file="includes/inner-form-toolbar.html"} + +
+
+
+ + +
+
-
{intl l="The rewritten URL to the category page. Click \"Use Default\" button to use the default URL. Use only digits, letters, - and _ characters."}
-
-
+
+
+ -
-
+
+ - + +
+
+
+
- {loop name="cat-parent" type="category-tree" visible="*" category="0" exclude="{$current_category_id}"} - - {/loop} +
+
+
+ - -
-
+
+ +
+
+
-
-
- +
+
+
-
- -
-
-
-
-

aff Date creation ?

-

aff date modif ?

- - -
+
+

Images

+
-
-

Détails divers

-
+
+

Documents

+
-
-

Images

-
+
+

Modules

+
-
-

Documents

-
- -
-

Modules

-
- -
-
+
+ + + {/loop} @@ -189,6 +220,12 @@ $(function() { e.preventDefault(); $(this).tab('show'); }); + + $('.use_default_rewriten_url').click(function(ev) { + alert("Not functionnal"); + + ev.preventDefault(); + }); }) diff --git a/templates/admin/default/general_error.html b/templates/admin/default/general_error.html index c41fee7a4..b8f9e8661 100755 --- a/templates/admin/default/general_error.html +++ b/templates/admin/default/general_error.html @@ -1,4 +1,4 @@ -{$page_title={intl l='AN error occured'}} +{$page_title={intl l='An error occured'}} {include file='includes/header.inc.html'} diff --git a/templates/admin/default/home.html b/templates/admin/default/home.html index 6b429ae29..a48e30ec6 100755 --- a/templates/admin/default/home.html +++ b/templates/admin/default/home.html @@ -1,4 +1,4 @@ -{check_auth context="admin" roles="ADMIN" login_tpl="/admin/login"} +{check_auth roles="ADMIN" login_tpl="/admin/login"} {$page_title={intl l='Home'}} {include file='includes/header.inc.html'} diff --git a/templates/admin/default/includes/category_breadcrumb.html b/templates/admin/default/includes/category_breadcrumb.html index cf03c4082..f3eed7705 100755 --- a/templates/admin/default/includes/category_breadcrumb.html +++ b/templates/admin/default/includes/category_breadcrumb.html @@ -1,26 +1,13 @@ {* Breadcrumb for categories browsing and editing *}
  • Home /
  • -
  • Catalog +
  • Catalog {ifloop rel="category_path"} /
  • -{ifloop rel="category_path"} - / - - {loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"} - {if $ID == $current_category_id} -
  • - {if $action == 'edit'} - {intl l='Editing %cat' cat="{$TITLE}"} - {else} - {$TITLE} {intl l="(edit)"} - {/if} -
  • - {else} -
  • {$TITLE} /
  • - {/if} - {/loop} -{/ifloop} - -{elseloop rel="category_path"} - -{/elseloop} \ No newline at end of file +{loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"} {if $ID == $current_category_id} +
  • {if $action == 'edit'} {intl l='Editing %cat' cat="{$TITLE}"} {else} {$TITLE} {intl l="(edit)"} {/if} +
  • +{else} +
  • {$TITLE} /
  • +{/if} {/loop} {/ifloop} {elseloop rel="category_path"} + +{/elseloop} diff --git a/templates/admin/default/includes/header.inc.html b/templates/admin/default/includes/header.inc.html index 65500f05a..2ee435b4b 100755 --- a/templates/admin/default/includes/header.inc.html +++ b/templates/admin/default/includes/header.inc.html @@ -1,5 +1,5 @@ - + {intl l='Thelia Back Office'}{if ! empty($page_title)} - {$page_title}{/if} @@ -43,7 +43,7 @@ {* display top bar once admin is connected *} -{loop name="top-bar-auth" type="auth" context="admin" roles="ADMIN"} +{loop name="top-bar-auth" type="auth" roles="ADMIN"} {module_include location='before_topbar'} @@ -54,9 +54,11 @@ {module_include location='inside_topbar'} - + - {loop name="top-bar-search" type="auth" context="admin" roles="ADMIN" permissions="admin.search"} + {loop name="top-bar-search" type="auth" roles="ADMIN" permissions="admin.search"} @@ -87,13 +89,13 @@ {intl l="Home"} - {loop name="menu-auth-customer" type="auth" context="admin" roles="ADMIN" permissions="admin.customers.view"} + {loop name="menu-auth-customer" type="auth" roles="ADMIN" permissions="admin.customers.view"}
  • {intl l="Customers"}
  • {/loop} - {loop name="menu-auth-order" type="auth" context="admin" roles="ADMIN" permissions="admin.orders.view"} + {loop name="menu-auth-order" type="auth" roles="ADMIN" permissions="admin.orders.view"} {/loop} - {loop name="menu-auth-catalog" type="auth" context="admin" roles="ADMIN" permissions="admin.catalog.view"} + {loop name="menu-auth-catalog" type="auth" roles="ADMIN" permissions="admin.catalog.view"}
  • {intl l="Catalog"}
  • {/loop} - {loop name="menu-auth-content" type="auth" context="admin" roles="ADMIN" permissions="admin.content.view"} + {loop name="menu-auth-content" type="auth" roles="ADMIN" permissions="admin.content.view"}
  • {intl l="Content"}
  • {/loop} - {loop name="menu-auth-discount" type="auth" context="admin" roles="ADMIN" permissions="admin.discount.view"} + {loop name="menu-auth-discount" type="auth" roles="ADMIN" permissions="admin.discount.view"}
  • {intl l="Discount"}
  • {/loop} - {loop name="menu-auth-config" type="auth" context="admin" roles="ADMIN" permissions="admin.config.view"} + {loop name="menu-auth-config" type="auth" roles="ADMIN" permissions="admin.config.view"}
  • {intl l="Configuration"}
  • {/loop} - {loop name="menu-auth-modules" type="auth" context="admin" roles="ADMIN" permissions="admin.modules.view"} + {loop name="menu-auth-modules" type="auth" roles="ADMIN" permissions="admin.modules.view"}
  • {intl l="Modules"}
  • @@ -156,4 +158,10 @@ {module_include location='after_top_menu'} -{/loop} \ No newline at end of file +{/loop} + +{elseloop rel="top-bar-auth"} + +{/elseloop} diff --git a/templates/admin/default/includes/inner-form-toolbar.html b/templates/admin/default/includes/inner-form-toolbar.html index 4d5570f6c..082ad34e2 100755 --- a/templates/admin/default/includes/inner-form-toolbar.html +++ b/templates/admin/default/includes/inner-form-toolbar.html @@ -11,17 +11,17 @@
    - - + +
    diff --git a/templates/admin/default/includes/standard-description-form-fields.html b/templates/admin/default/includes/standard-description-form-fields.html new file mode 100644 index 000000000..e70092316 --- /dev/null +++ b/templates/admin/default/includes/standard-description-form-fields.html @@ -0,0 +1,60 @@ +{* The standard description fields, used by many Thelia objects *} + +{form_field form=$form field='title'} +
    + + +
    + + + +
    +
    +{/form_field} + +{form_field form=$form field='chapo'} +
    + + +
    + + + +
    +
    +{/form_field} + +{form_field form=$form field='description'} +
    + + +
    + + + +
    +
    +{/form_field} + +{form_field form=$form field='postscriptum'} +
    + + +
    + + + +
    +
    +{/form_field} \ No newline at end of file diff --git a/templates/admin/default/login.html b/templates/admin/default/login.html index 77195cf18..0fa6852a5 100755 --- a/templates/admin/default/login.html +++ b/templates/admin/default/login.html @@ -2,9 +2,6 @@ {include file='includes/header.inc.html'}
    -
    diff --git a/templates/admin/default/variable-edit.html b/templates/admin/default/variable-edit.html new file mode 100644 index 000000000..86d13060a --- /dev/null +++ b/templates/admin/default/variable-edit.html @@ -0,0 +1,136 @@ +{check_auth roles="ADMIN" permissions="admin.configuration.variables.edit" login_tpl="/admin/login"} + +{$page_title={intl l='Edit a system variable'}} + +{include file='includes/header.inc.html'} + +
    + +
    + + {loop name="config_edit" type="config" hidden="*" id="$variable_id" backend_context="1" lang="$edition_language"} + + + +
    +
    +
    + +
    + {intl l="Edit variable $NAME"} +
    + +
    +
    +
    + + {form name="thelia.admin.config.modification"} +
    + + {* Be sure to get the variable ID, even if the form could not be validated *} + + + {include file="includes/inner-form-toolbar.html"} + + {form_hidden_fields form=$form} + + {form_field form=$form field='success_url'} + + {/form_field} + + {* We do not allow creation of hidden variables *} + + {form_field form=$form field='id'} + + {/form_field} + + {form_field form=$form field='hidden'} + + {/form_field} + + {form_field form=$form field='locale'} + + {/form_field} + + {if #form_error}
    #form_error_message
    {/if} + +
    + + + +
    + {form_field form=$form field='name'} + + + + {/form_field} +
    +
    + +
    + + +
    + {form_field form=$form field='value'} + + + + {/form_field} +
    +
    + +
    + + +
    + {form_field form=$form field='secured'} + + + + {/form_field} +
    +
    + + {include file="includes/standard-description-form-fields.html"} + +
    + {/form} +
    +
    +
    +
    +
    + +
    + {/loop} + + {elseloop rel="config_edit"} +
    +
    +
    + {intl l="Sorry, variable ID=$variable_id was not found."} +
    +
    +
    + {/elseloop} + +
    +
    + +{include file='includes/js.inc.html'} + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/admin/default/variables.html b/templates/admin/default/variables.html new file mode 100644 index 000000000..f47ec53dd --- /dev/null +++ b/templates/admin/default/variables.html @@ -0,0 +1,284 @@ +{check_auth roles="ADMIN" permissions="admin.configuration.variables.view" login_tpl="/admin/login"} + +{$page_title={intl l='Thelia System Variables'}} + +{include file='includes/header.inc.html'} + +
    + +
    + + + + {module_include location='variables_top'} + +
    + +
    +
    +
    + + + + + + + + {module_include location='variables_table_header'} + + + + + {loop name="config" type="config" hidden="0" secured="*" backend_context="1" lang="$lang_id"} + + + + + + + + + {module_include location='variables_table_row'} + + + + {/loop} +
    + {intl l='Thelia system variables'} + {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.configuration.variables.create"} + + + + + {/loop} + +
    {intl l="Purpose"}{intl l="Name"}{intl l="Value"} 
    {$TITLE} + {if ! $SECURED} + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.variables.change"} + {$NAME} + {/loop} + {elseloop rel="can_change"} + {$NAME} + {/elseloop} + {else} + {$NAME} + {/if} + + {if $SECURED} + {$VALUE} + {else} + + {/if} + + {if ! $SECURED} +
    + + + {loop type="auth" name="can_change" roles="ADMIN" permissions="admin.configuration.variables.change"} + + {/loop} + + {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.configuration.variables.delete"} + + {/loop} +
    + {else} + + {/if} +
    +
    +
    +
    +
    + + {module_include location='variables_bottom'} + +
    +
    + + +{* Adding a new variable *} + + + + +{* Delete confirmation dialog *} + + + +{include file='includes/js.inc.html'} + + + +{include file='includes/footer.inc.html'} \ No newline at end of file diff --git a/templates/default/cart.html b/templates/default/cart.html index 03ec8e3ee..5597d28ad 100755 --- a/templates/default/cart.html +++ b/templates/default/cart.html @@ -8,7 +8,7 @@ {form name="thelia.cart.add" } -{* We use $INDEX_PAGE as form action to avoid mixing post and get data *} +{* We use {navigate to="index"} as form action to avoid mixing post and get data *}
    {* diff --git a/templates/default/category.html b/templates/default/category.html index af4cdcf14..dd5c6a20a 100755 --- a/templates/default/category.html +++ b/templates/default/category.html @@ -22,34 +22,10 @@ {loop name="product" type="product" category="#ID"}
    -

    PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)

    +

    PRODUCT #ID : #REF (#LOOP_COUNT / #LOOP_TOTAL)

    #TITLE

    #DESCRIPTION

    - {ifloop rel="acc"} -
    Accessories
    -
      - {loop name="acc" type="accessory" product="#ID" order="accessory"} -
    • #REF
    • - {/loop} -
    - {/ifloop} - {elseloop rel="acc"} -
    No accessory
    - {/elseloop} - - {ifloop rel="prod_ass_cont"} -
    Associated Content
    -
      - {loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"} -
    • #TITLE
    • - {/loop} -
    - {/ifloop} - {elseloop rel="prod_ass_cont"} -
    No associated content
    - {/elseloop} - {ifloop rel="ft"}
    Features
      @@ -67,29 +43,6 @@ {elseloop rel="ft"}
      No feature
      {/elseloop} - -
      Product sale elements
      - - {assign var=current_product value=#ID} - {loop name="pse" type="product_sale_elements" product="#ID"} -
      - {loop name="combi" type="attribute_combination" product_sale_elements="#ID"} - #ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE
      - {/loop} -
      #WEIGHT g -
      {if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if} -

      - Add - - to my cart -
    -
    - {/loop} -
    {/loop} {loop name="catgory1" type="category" parent="#ID"} @@ -110,75 +63,29 @@ {loop name="product" type="product" category="#ID"} -
    -

    PRODUCT : #REF (#LOOP_COUNT / #LOOP_TOTAL)

    -

    #TITLE

    -

    #DESCRIPTION

    +
    +

    PRODUCT #ID : #REF (#LOOP_COUNT / #LOOP_TOTAL)

    +

    #TITLE

    +

    #DESCRIPTION

    - {ifloop rel="acc"} -
    Accessories
    -
      - {loop name="acc" type="accessory" product="#ID" order="accessory"} -
    • #REF
    • - {/loop} -
    - {/ifloop} - {elseloop rel="acc"} -
    No accessory
    - {/elseloop} - - {ifloop rel="prod_ass_cont"} -
    Associated Content
    -
      - {loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"} -
    • #TITLE
    • - {/loop} -
    - {/ifloop} - {elseloop rel="prod_ass_cont"} -
    No associated content
    - {/elseloop} - - {ifloop rel="ft"} -
    Features
    -
      - {loop name="ft" type="feature" order="manual" product="#ID"} -
    • - #TITLE : - {loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"} - #TITLE / #PERSONAL_VALUE + {ifloop rel="ft"} +
      Features
      +
        + {assign var=current_product value=#ID} + {loop name="ft" type="feature" order="manual" product="#ID"} +
      • + #TITLE : + {loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"} + #TITLE / #PERSONAL_VALUE + {/loop} +
      • {/loop} - - {/loop} -
      - {/ifloop} - {elseloop rel="ft"} -
      No feature
      - {/elseloop} - -
      Product sale elements
      - - {assign var=current_product value=#ID} - {loop name="pse" type="product_sale_elements" product="#ID"} -
      - {loop name="combi" type="attribute_combination" product_sale_elements="#ID"} - #ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE
      - {/loop} -
      #WEIGHT g -
      {if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if} -

      - Add - - to my cart -
    -
    - {/loop} - -
    + + {/ifloop} + {elseloop rel="ft"} +
    No feature
    + {/elseloop} +
    {/loop} {/loop} diff --git a/templates/default/connexion.html b/templates/default/connexion.html index e3109e8b3..a6a2cc665 100755 --- a/templates/default/connexion.html +++ b/templates/default/connexion.html @@ -1,7 +1,7 @@ {include file="includes/header.html"} {form name="thelia.customer.creation"} -{* We use $INDEX_PAGE as form action to avoid mixing post and get data *} +{* We use {navigate to="index"} as form action to avoid mixing post and get data *} {* The two fields below are not par of the form, they are here to defines @@ -16,7 +16,7 @@ *} {form_field form=$form field='success_url'} - {* the url the user is redirected to on login success *} + {* the url the user is redirected to on login success *} {/form_field} {form_field form=$form field='auto_login'} diff --git a/templates/default/includes/header.html b/templates/default/includes/header.html index 0b93b6a1c..38e78478e 100755 --- a/templates/default/includes/header.html +++ b/templates/default/includes/header.html @@ -11,11 +11,11 @@
    {loop type="auth" name="customer_info_block" roles="CUSTOMER" context="front"} -

    Your are logged in ! Logout

    +

    Your are logged in as {customer attr="firstname"} {customer attr="lastname"} ! Logout

    {/loop} {loop type="auth" name="admin_info_block" roles="ADMIN" context="admin"} -

    You are logged as administrator

    +

    You are logged as administrator {admin attr="firstname"} {admin attr="lastname"}

    {/loop} {elseloop rel="customer_info_block"} diff --git a/templates/default/login.html b/templates/default/login.html index 0041fd80c..702f0a710 100755 --- a/templates/default/login.html +++ b/templates/default/login.html @@ -3,15 +3,12 @@

    {intl l='Please login'}

    {form name="thelia.customer.login" } -{* We use $INDEX_PAGE as form action to avoid mixing post and get data *} - + {* - The two fields below are not par of the Login form, they are here to defines - the action to process, and the view to render once the form is submited + The field below are not par of the Login form, it defines view to render if the form cannot be validated *} - {* the action triggered by this form *} - {* the view to return to if the form cannot be validated *} + {* the view to return to if the form cannot be validated *} {* This field is common to all BaseForm instances (thus, this one), and defines @@ -20,7 +17,7 @@ *} {form_field form=$form field='success_url'} - {* the url the user is redirected to on login success *} + {* the url the user is redirected to on login success *} {/form_field} {* @@ -34,11 +31,11 @@ {form_field form=$form field="email"} {if #error}{#message}{/if} -
    +
    {/form_field} {form_field form=$form field='password'} -
    +
    {/form_field} {form_field form=$form field='remember_me'} diff --git a/templates/default/product.html b/templates/default/product.html new file mode 100755 index 000000000..4f82b5fb8 --- /dev/null +++ b/templates/default/product.html @@ -0,0 +1,88 @@ +Here you are : {navigate to="current"}
    +From : {navigate to="return_to"}
    +Index : {navigate to="index"}
    + +

    Product page

    + +{ifloop rel="product"} + +{loop type="product" name="product" current="true"} + +
    +

    PRODUCT (#ID) : #REF

    +

    #TITLE

    +

    #DESCRIPTION

    + + {ifloop rel="acc"} +

    Accessories

    +
      + {loop name="acc" type="accessory" product="#ID" order="accessory"} +
    • #REF
    • + {/loop} +
    + {/ifloop} + {elseloop rel="acc"} +

    No accessory

    + {/elseloop} + + {ifloop rel="prod_ass_cont"} +

    Associated Content

    +
      + {loop name="prod_ass_cont" type="associated_content" product="#ID" order="associated_content"} +
    • #TITLE
    • + {/loop} +
    + {/ifloop} + {elseloop rel="prod_ass_cont"} +

    No associated content

    + {/elseloop} + + {ifloop rel="ft"} +

    Features

    +
      + {assign var=current_product value=#ID} + {loop name="ft" type="feature" order="manual" product="#ID"} +
    • + #TITLE : + {loop name="ft_v" type="feature_value" product="{$current_product}" feature="#ID"} + #TITLE / #PERSONAL_VALUE + {/loop} +
    • + {/loop} +
    + {/ifloop} + {elseloop rel="ft"} +

    No feature

    + {/elseloop} + +

    Product sale elements

    + + {assign var=current_product value=#ID} + {loop name="pse" type="product_sale_elements" product="#ID"} +
    + {loop name="combi" type="attribute_combination" product_sale_elements="#ID"} + #ATTRIBUTE_TITLE = #ATTRIBUTE_AVAILABILITY_TITLE
    + {/loop} +
    #WEIGHT g +
    {if #IS_PROMO == 1} #PROMO_PRICE € (instead of #PRICE) {else} #PRICE € {/if} +

    + Add + + to my cart + +
    + {/loop} + +
    + +{/loop} + +{/ifloop} + +{elseloop rel="product"} +

    Produit introuvable !

    +{/elseloop} \ No newline at end of file