Merge branch 'master' of https://github.com/thelia/thelia into coupon

# By franck (9) and others
# Via franck (3) and Etienne Roudeix (1)
* 'master' of https://github.com/thelia/thelia:
  Added get/setLangId() method in session
  Refactored VariableXxxxx.php as ConfigXxxx.php
  Added name duplication check when creating a variable
  Completed the backoffice variable management
  update propel version and dependencies
  add some phpdoc
  Fixed getUrl()
  Typo :(
  Intriducec BaseI18nLoop, started variable config management
  Fixed URL::absoluteUrl()
  Fixed customer front controller, events, addec admion config.
  rewriting
  specific rewrittend url retrievement
  product page
  url global substitution
  sid : rewriting
  rewriting tables
  start rewriting

Conflicts:
	core/lib/Thelia/Config/Resources/routing/admin.xml
	core/lib/Thelia/Core/Event/TheliaEvents.php
This commit is contained in:
gmorel
2013-09-02 09:19:24 +02:00
129 changed files with 3787 additions and 814 deletions

View File

@@ -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",

46
composer.lock generated
View File

@@ -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,

View File

@@ -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');
}
}

View File

@@ -41,6 +41,7 @@ use Thelia\Model\ConfigQuery;
*
* Class Cart
* @package Thelia\Action
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
class Cart extends BaseAction implements EventSubscriberInterface
{

View File

@@ -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);
}
}

View File

@@ -0,0 +1,155 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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),
);
}
}

View File

@@ -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 <mraynaud@openstudio.fr>
*/
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),
);
}
}

View File

@@ -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 <mraynaud@openstudio.fr>
*/
trait CartTrait
{
/**

View File

@@ -22,6 +22,13 @@
/*************************************************************************************/
namespace Thelia\Command;
/**
* base class for module commands
*
* Class BaseModuleGenerate
* @package Thelia\Command
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
abstract class BaseModuleGenerate extends ContainerAwareCommand
{
protected $module;

View File

@@ -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 <mraynaud@openstudio.fr>
*
*/
class CacheClear extends ContainerAwareCommand
{
protected function configure()

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class Install extends ContainerAwareCommand
{
/**

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class ModuleGenerateCommand extends BaseModuleGenerate
{
protected function configure()

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class ModuleGenerateModelCommand extends BaseModuleGenerate
{
protected function configure()

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class ModuleGenerateSqlCommand extends BaseModuleGenerate
{
public function configure()

View File

@@ -22,12 +22,17 @@
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.category" class="Thelia\Action\Image">
<service id="thelia.action.image" class="Thelia\Action\Image">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.customer" class="Thelia\Action\Category">
<service id="thelia.action.category" class="Thelia\Action\Category">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>
<service id="thelia.action.category" class="Thelia\Action\Config">
<argument type="service" id="service_container"/>
<tag name="kernel.event_subscriber"/>
</service>

View File

@@ -32,6 +32,7 @@
<loop class="Thelia\Core\Template\Loop\CategoryTree" name="category-tree"/>
<loop class="Thelia\Core\Template\Loop\Cart" name="cart"/>
<loop class="Thelia\Core\Template\Loop\Image" name="image"/>
<loop class="Thelia\Core\Template\Loop\Config" name="config"/>
</loops>
<forms>
@@ -45,6 +46,9 @@
<form name="thelia.admin.category.deletion" class="Thelia\Form\CategoryDeletionForm"/>
<form name="thelia.cart.add" class="Thelia\Form\CartAdd"/>
<form name="thelia.admin.config.creation" class="Thelia\Form\ConfigCreationForm"/>
<form name="thelia.admin.config.modification" class="Thelia\Form\ConfigModificationForm"/>
</forms>

View File

@@ -53,10 +53,38 @@
<default key="action">read</default>
</route>
<!-- Routes to the Config (system variables) controller -->
<route id="admin.configuration.variables.default" path="/admin/configuration/variables">
<default key="_controller">Thelia\Controller\Admin\ConfigController::defaultAction</default>
</route>
<route id="admin.configuration.variables.change-values" path="/admin/configuration/variables/change-values">
<default key="_controller">Thelia\Controller\Admin\ConfigController::changeValuesAction</default>
</route>
<route id="admin.configuration.variables.create" path="/admin/configuration/variables/create">
<default key="_controller">Thelia\Controller\Admin\ConfigController::createAction</default>
</route>
<route id="admin.configuration.variables.change" path="/admin/configuration/variables/change">
<default key="_controller">Thelia\Controller\Admin\ConfigController::changeAction</default>
</route>
<route id="admin.configuration.variables.save-change" path="/admin/configuration/variables/save-change">
<default key="_controller">Thelia\Controller\Admin\ConfigController::saveChangeAction</default>
</route>
<route id="admin.configuration.variables.delete" path="/admin/configuration/variables/delete">
<default key="_controller">Thelia\Controller\Admin\ConfigController::deleteAction</default>
</route>
<!-- The default route, to display a template -->
<route id="admin.processTemplate" path="/admin/{template}">
<default key="_controller">Thelia\Controller\Admin\AdminController::processTemplateAction</default>
<requirement key="template">.*</requirement>
</route>
</routes>

View File

@@ -18,10 +18,14 @@
<default key="_controller">Thelia\Controller\Front\CustomerController::updateAction</default>
</route>
<route id="customler.login.process" path="/customer/login" methods="post">
<route id="customer.login.process" path="/customer/login" methods="post">
<default key="_controller">Thelia\Controller\Front\CustomerController::loginAction</default>
</route>
<route id="customer.logout.process" path="/customer/logout">
<default key="_controller">Thelia\Controller\Front\CustomerController::logoutAction</default>
</route>
<route id="cart.add.process" path="/cart/add">
<default key="_controller">Thelia\Controller\Front\CartController::addItem</default>
<default key="_view">cart</default>

View File

@@ -29,10 +29,4 @@ class AdminController extends BaseAdminController
{
return $this->render("home");
}
public function processAction()
{
echo "not yet coded !";
exit();
}
}

View File

@@ -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.");
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,299 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <franck@cqfdev.fr>
*/
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'));
}
}

View File

@@ -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");

View File

@@ -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);
}
}

View File

@@ -63,7 +63,7 @@ class CartController extends BaseFrontController
if ($message) {
$cartAdd->setErrorMessage($message);
$this->getParserContext()->setErrorForm($cartAdd);
$this->getParserContext()->addForm($cartAdd);
}
}

View File

@@ -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;
}
}

View File

@@ -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
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class RegisterListenersPass implements CompilerPassInterface
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class RegisterParserPluginPass implements CompilerPassInterface
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class RegisterRouterPass implements CompilerPassInterface
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class XmlFileLoader extends FileLoader
{
/**

View File

@@ -0,0 +1,44 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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;
}
}

View File

@@ -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;
}
public function getCategoryId()
{
return $this->category_id;
}
public function setCategoryId($category_id)
{
$this->category_id = $category_id;
}
}

View File

@@ -77,6 +77,5 @@ class CategoryCreateEvent extends ActionEvent
public function setCreatedCategory(Category $created_category)
{
$this->created_category = $created_category;
var_dump($this->created_category);
}
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -0,0 +1,88 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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;
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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;
}
}

View File

@@ -26,7 +26,7 @@ namespace Thelia\Core\Event;
use Thelia\Model\Customer;
class CustomerLoginEvent {
class CustomerLoginEvent extends ActionEvent {
protected $customer;

View File

@@ -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";
}

View File

@@ -36,6 +36,7 @@ use Thelia\Core\Template\ParserContext;
*
* Class ControllerListener
* @package Thelia\Core\EventListener
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
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()

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class ActionEventFactory
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class Request extends BaseRequest
{

View File

@@ -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;
}
}

View File

@@ -55,8 +55,6 @@ class UsernamePasswordFormAuthenticator implements AuthenticatorInterface
);
$this->options = array_merge($defaults, $options);
$this->loginForm->bind($this->request);
}
/**

View File

@@ -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
*

View File

@@ -0,0 +1,79 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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
);
}
}

View File

@@ -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
);
}

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <mraynaud@openstudio.fr>
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*/
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())

View File

@@ -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 <franck@cqfdev.fr>
*/
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;

View File

@@ -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 <franck@cqfdev.fr>
*/
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();

View File

@@ -0,0 +1,128 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <franck@cqfdev.fr>
*/
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;
}
}

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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);

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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())

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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())

View File

@@ -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 <franck@cqfdev.fr>
*/
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."<br />";
// echo "source = ".$this->getSource().", id=".$source_id." - ".$this->getArg('source_id')->getValue()."<br />";
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

View File

@@ -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'))

View File

@@ -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 <eroudeix@openstudio.fr>
*/
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'));

View File

@@ -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 ------------------------------------------

View File

@@ -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;
}
}

View File

@@ -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));
}

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -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 <mraynaud@openstudio.fr>

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class TheliaContainerBuilder extends ContainerBuilder
{

View File

@@ -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)

View File

@@ -0,0 +1,54 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Form;
use Symfony\Component\Validator\Constraints\NotBlank;
/**
* A base form for all objects with standard contents.
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
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())
;
}
}

View File

@@ -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 <mraynaud@openstudio.fr>
*/
abstract class BaseForm
{
/**

View File

@@ -30,6 +30,11 @@ use Thelia\Model\ProductSaleElementsQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Model\ProductQuery;
/**
* Class CartAdd
* @package Thelia\Form
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
class CartAdd extends BaseForm
{

View File

@@ -0,0 +1,75 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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));
}
}
}

View File

@@ -0,0 +1,59 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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";
}
}

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class CustomerCreation extends BaseForm
{

View File

@@ -25,6 +25,11 @@ namespace Thelia\Form;
use Symfony\Component\Validator\Constraints;
/**
* Class CustomerModification
* @package Thelia\Form
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
class CustomerModification extends BaseForm
{
/**

View File

@@ -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];
}

View File

@@ -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));
}
}

View File

@@ -1,9 +1,88 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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));
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
/**

View File

@@ -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";
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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';
$requestedLocaleI18nAlias = $aliasPrefix . 'requested_locale_i18n';
$defaultLocaleI18nAlias = $aliasPrefix . 'default_locale_i18n';
if (!$defaultLangWithoutTranslation == 0) {
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;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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);
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Rewriting;
/**
* Class RewritingResolver
* @package Thelia\Rewriting
* @author Etienne Roudeix <eroudeix@openstudio.fr>
*
* This class provides methods to resolve rewritten URL as a query
*/
class RewritingResolver
{
}

View File

@@ -0,0 +1,119 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
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 <eroudeix@openstudio.fr>
*
* 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();
}
}

View File

@@ -34,6 +34,7 @@ use Thelia\Model\Customer;
*
* Class CartTraitTest
* @package Thelia\Tests\Cart\CartTraitTest
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
class CartTraitTest extends \PHPUnit_Framework_TestCase
{

View File

@@ -22,6 +22,13 @@
/*************************************************************************************/
namespace Thelia\Tests\Command;
/**
* base class for testing command line command
*
* Class BaseCommandTest
* @package Thelia\Tests\Command
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
abstract class BaseCommandTest extends \PHPUnit_Framework_TestCase
{
public function getKernel()

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class CacheClearTest extends \PHPUnit_Framework_TestCase
{

View File

@@ -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 <mraynaud@openstudio.fr>
*/
class ModuleGenerateCommandTest extends BaseCommandTest
{
protected $command;

Some files were not shown because too many files have changed in this diff Show More