Categories ordrering in the catalog
This commit is contained in:
@@ -28,14 +28,38 @@ use Thelia\Form\BaseForm;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Action\Exception\FormValidationException;
|
||||
use Thelia\Core\Event\ActionEvent;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Thelia\Core\Template\ParserContext;
|
||||
use Thelia\Log\Tlog;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Thelia\Core\Security\SecurityContext;
|
||||
use Thelia\Core\Security\Exception\AuthorizationException;
|
||||
|
||||
abstract class BaseAction
|
||||
class BaseAction
|
||||
{
|
||||
/**
|
||||
* @var The container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a BaseForm
|
||||
*
|
||||
* @param BaseForm $aBaseForm the form
|
||||
* @param string $expectedMethod the expected method, POST or GET, or null for any of them
|
||||
* @throws FormValidationException is the form contains error, or the method is not the right one
|
||||
* @return Symfony\Component\Form\Form Form the symfony form object
|
||||
*/
|
||||
protected function validateForm(BaseForm $aBaseForm, $expectedMethod = null)
|
||||
{
|
||||
$form = $aBaseForm->getForm();
|
||||
|
||||
if ($aBaseForm->getRequest()->isMethod($expectedMethod)) {
|
||||
if ($expectedMethod == null || $aBaseForm->getRequest()->isMethod($expectedMethod)) {
|
||||
|
||||
$form->bind($aBaseForm->getRequest());
|
||||
|
||||
@@ -53,10 +77,11 @@ abstract class BaseAction
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate a form error in the action event
|
||||
*
|
||||
* @param BaseForm $aBaseForm
|
||||
* @param string $error_message
|
||||
* @param ActionEvent $event
|
||||
* @param BaseForm $aBaseForm the form
|
||||
* @param string $error_message an error message that may be displayed to the customer
|
||||
* @param ActionEvent $event the action event
|
||||
*/
|
||||
protected function propagateFormError(BaseForm $aBaseForm, $error_message, ActionEvent $event) {
|
||||
|
||||
@@ -71,6 +96,62 @@ abstract class BaseAction
|
||||
$event->stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, $context = false) {
|
||||
|
||||
if (! $this->getSecurityContext($context)->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 event dispatcher,
|
||||
*
|
||||
* @return ParserContext
|
||||
*/
|
||||
protected function getDispatcher()
|
||||
{
|
||||
return $this->container->get('event_dispatcher');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parser context,
|
||||
*
|
||||
* @return ParserContext
|
||||
*/
|
||||
protected function getParserContext()
|
||||
{
|
||||
return $this->container->get('thelia.parser.context');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the security context, by default in admin mode.
|
||||
*
|
||||
* @param string the context, either SecurityContext::CONTEXT_BACK_OFFICE or SecurityContext::CONTEXT_FRONT_OFFICE
|
||||
*
|
||||
* @return Thelia\Core\Security\SecurityContext
|
||||
*/
|
||||
protected function getSecurityContext($context = false)
|
||||
{
|
||||
$securityContext = $this->container->get('thelia.securityContext');
|
||||
|
||||
$securityContext->setContext($context === false ? SecurityContext::CONTEXT_BACK_OFFICE : $context);
|
||||
|
||||
return $securityContext;
|
||||
}
|
||||
|
||||
protected function redirect($url, $status = 302)
|
||||
{
|
||||
$response = new RedirectResponse($url, $status);
|
||||
@@ -78,5 +159,4 @@ abstract class BaseAction
|
||||
$response->send();
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,18 +53,6 @@ use Thelia\Model\Customer;
|
||||
class Cart extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
use \Thelia\Cart\CartTrait;
|
||||
/**
|
||||
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -122,7 +110,7 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
||||
|
||||
protected function updateQuantity(CartItem $cartItem, $quantity)
|
||||
{
|
||||
$cartItem->setDisptacher($this->dispatcher);
|
||||
$cartItem->setDisptacher($this->getDispatcher());
|
||||
$cartItem->addQuantity($quantity)
|
||||
->save();
|
||||
}
|
||||
@@ -130,7 +118,7 @@ class Cart extends BaseAction implements EventSubscriberInterface
|
||||
protected function addItem(\Thelia\Model\Cart $cart, $productId, $productSaleElementsId, $quantity, ProductPrice $productPrice)
|
||||
{
|
||||
$cartItem = new CartItem();
|
||||
$cartItem->setDisptacher($this->dispatcher);
|
||||
$cartItem->setDisptacher($this->getDispatcher());
|
||||
$cartItem
|
||||
->setCart($cart)
|
||||
->setProductId($productId)
|
||||
|
||||
@@ -34,11 +34,16 @@ use Thelia\Model\CategoryQuery;
|
||||
use Thelia\Model\AdminLog;
|
||||
use Thelia\Form\CategoryDeletionForm;
|
||||
use Thelia\Action\Exception\FormValidationException;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\Propel;
|
||||
use Thelia\Model\Map\CategoryTableMap;
|
||||
|
||||
class Category extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
public function create(ActionEvent $event)
|
||||
{
|
||||
$this->checkAuth("ADMIN", "admin.category.create");
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
try {
|
||||
@@ -82,6 +87,8 @@ class Category extends BaseAction implements EventSubscriberInterface
|
||||
|
||||
public function modify(ActionEvent $event)
|
||||
{
|
||||
$this->checkAuth("ADMIN", "admin.category.delete");
|
||||
|
||||
/*
|
||||
$request = $event->getRequest();
|
||||
|
||||
@@ -154,6 +161,8 @@ class Category extends BaseAction implements EventSubscriberInterface
|
||||
*/
|
||||
public function delete(ActionEvent $event)
|
||||
{
|
||||
$this->checkAuth("ADMIN", "admin.category.delete");
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
try {
|
||||
@@ -204,9 +213,11 @@ class Category extends BaseAction implements EventSubscriberInterface
|
||||
*/
|
||||
public function toggleVisibility(ActionEvent $event)
|
||||
{
|
||||
$this->checkAuth("ADMIN", "admin.category.edit");
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
$category = CategoryQuery::create()->findPk($request->get('id', 0));
|
||||
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
|
||||
|
||||
if ($category !== null) {
|
||||
|
||||
@@ -220,6 +231,144 @@ class Category extends BaseAction implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move category up
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
*/
|
||||
public function changePositionUp(ActionEvent $event) {
|
||||
return $this->exchangePosition($event, 'up');
|
||||
}
|
||||
|
||||
/**
|
||||
* Move category down
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
*/
|
||||
public function changePositionDown(ActionEvent $event) {
|
||||
return $this->exchangePosition($event, 'down');
|
||||
}
|
||||
|
||||
/**
|
||||
* Move up or down a category
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
* @param string $direction up to move up, down to move down
|
||||
*/
|
||||
protected function exchangePosition(ActionEvent $event, $direction) {
|
||||
|
||||
$this->checkAuth("ADMIN", "admin.category.edit");
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
|
||||
|
||||
if ($category !== null) {
|
||||
|
||||
// The current position of the category
|
||||
$my_position = $category->getPosition();
|
||||
|
||||
// Find category to exchange position with
|
||||
$search = CategoryQuery::create()
|
||||
->filterByParent($category->getParent());
|
||||
|
||||
// Up or down ?
|
||||
if ($direction == 'up') {
|
||||
// Find the category immediately before me
|
||||
$search->filterByPosition(array('max' => $my_position-1))->orderByPosition(Criteria::DESC);
|
||||
}
|
||||
else if ($direction == 'down') {
|
||||
// Find the category immediately after me
|
||||
$search->filterByPosition(array('min' => $my_position+1))->orderByPosition(Criteria::ASC);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
$result = $search->findOne();
|
||||
|
||||
|
||||
// If we found the proper category, exchange their positions
|
||||
if ($result) {
|
||||
|
||||
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
|
||||
|
||||
$cnx->beginTransaction();
|
||||
|
||||
try {
|
||||
$category->setPosition($result->getPosition())->save();
|
||||
|
||||
$result->setPosition($my_position)->save();
|
||||
|
||||
$cnx->commit();
|
||||
}
|
||||
catch(Exception $e) {
|
||||
$cnx->rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes category position
|
||||
*
|
||||
* @param ActionEvent $event
|
||||
*/
|
||||
public function changePosition(ActionEvent $event) {
|
||||
|
||||
$this->checkAuth("ADMIN", "admin.category.edit");
|
||||
|
||||
$request = $event->getRequest();
|
||||
|
||||
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
|
||||
|
||||
if ($category !== null) {
|
||||
|
||||
// The required position
|
||||
$new_position = $request->get('position', null);
|
||||
|
||||
// The current position
|
||||
$current_position = $category->getPosition();
|
||||
|
||||
if ($new_position != null && $new_position > 0 && $new_position != $current_position) {
|
||||
|
||||
// Find categories to offset
|
||||
$search = CategoryQuery::create()->filterByParent($category->getParent());
|
||||
|
||||
if ($new_position > $current_position) {
|
||||
// The new position is after the current position -> we will offset + 1 all categories located between us and the new position
|
||||
$search->filterByPosition(array('min' => 1+$current_position, 'max' => $new_position));
|
||||
|
||||
$delta = -1;
|
||||
}
|
||||
else {
|
||||
// The new position is brefore the current position -> we will offset - 1 all categories located between us and the new position
|
||||
$search->filterByPosition(array('min' => $new_position, 'max' => $current_position - 1));
|
||||
|
||||
$delta = 1;
|
||||
}
|
||||
|
||||
$results = $search->find();
|
||||
|
||||
$cnx = Propel::getWriteConnection(CategoryTableMap::DATABASE_NAME);
|
||||
|
||||
$cnx->beginTransaction();
|
||||
|
||||
try {
|
||||
foreach($results as $result) {
|
||||
$result->setPosition($result->getPosition() + $delta)->save($cnx);
|
||||
}
|
||||
|
||||
$category->setPosition($new_position)->save($cnx);
|
||||
|
||||
$cnx->commit();
|
||||
}
|
||||
catch(Exception $e) {
|
||||
$cnx->rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of event names this subscriber listens to.
|
||||
*
|
||||
@@ -247,7 +396,10 @@ class Category extends BaseAction implements EventSubscriberInterface
|
||||
"action.modifyCategory" => array("modify", 128),
|
||||
"action.deleteCategory" => array("delete", 128),
|
||||
|
||||
"action.toggleCategoryVisibility" => array("toggleVisibility", 128),
|
||||
"action.toggleCategoryVisibility" => array("toggleVisibility", 128),
|
||||
"action.changeCategoryPositionUp" => array("changePositionUp", 128),
|
||||
"action.changeCategoryPositionDown" => array("changePositionDown", 128),
|
||||
"action.changeCategoryPosition" => array("changePosition", 128),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,18 +43,8 @@ use Thelia\Core\Security\Exception\UsernameNotFoundException;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Thelia\Action\Exception\FormValidationException;
|
||||
|
||||
|
||||
class Customer extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var Thelia\Core\Security\SecurityContext
|
||||
*/
|
||||
protected $securityContext;
|
||||
|
||||
public function __construct(SecurityContext $securityContext) {
|
||||
$this->securityContext = $securityContext;
|
||||
}
|
||||
|
||||
public function create(ActionEvent $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
@@ -88,8 +78,14 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
||||
$customerEvent = new CustomerEvent($customer);
|
||||
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent);
|
||||
|
||||
// Connect the newly created user,and redirect to the success URL
|
||||
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
|
||||
|
||||
if (isset($data['auto_login']) && $data['auto_login']) {
|
||||
// Connect the newly created user,and redirect to the success URL
|
||||
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
|
||||
}
|
||||
else {
|
||||
$this->redirect($form->getSuccessUrl());
|
||||
}
|
||||
}
|
||||
catch (PropelException $e) {
|
||||
Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage()));
|
||||
@@ -139,9 +135,14 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
||||
$customerEvent->customer = $customer;
|
||||
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
|
||||
|
||||
// Update the logged-in user, and redirect to the success URL (exits)
|
||||
// We don-t send the login event, as the customer si already logged.
|
||||
$this->processSuccessfulLogin($event, $customer, $customerModification);
|
||||
if (isset($data['update_logged_in_user']) && $data['update_logged_in_user']) {
|
||||
// Update the logged-in user, and redirect to the success URL (exits)
|
||||
// We don't send the login event, as the customer si already logged.
|
||||
$this->processSuccessfulLogin($event, $customer, $customerModification);
|
||||
}
|
||||
else {
|
||||
$this->redirect($form->getSuccessUrl());
|
||||
}
|
||||
}
|
||||
catch(PropelException $e) {
|
||||
|
||||
@@ -168,7 +169,7 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
||||
{
|
||||
$event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event);
|
||||
|
||||
$this->getSecurityContext()->clear();
|
||||
$this->getFrontSecurityContext()->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,7 +260,7 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
||||
protected function processSuccessfulLogin(ActionEvent $event, CustomerModel $user, BaseForm $form, $sendLoginEvent = false)
|
||||
{
|
||||
// Success -> store user in security context
|
||||
$this->getSecurityContext()->setUser($user);
|
||||
$this->getFrontSecurityContext()->setUser($user);
|
||||
|
||||
if ($sendLoginEvent) $event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGIN, $event);
|
||||
|
||||
@@ -272,9 +273,7 @@ class Customer extends BaseAction implements EventSubscriberInterface
|
||||
*
|
||||
* @return SecurityContext the security context
|
||||
*/
|
||||
protected function getSecurityContext() {
|
||||
$this->securityContext->setContext(SecurityContext::CONTEXT_FRONT_OFFICE);
|
||||
|
||||
return $this->securityContext;
|
||||
protected function getFrontSecurityContext() {
|
||||
return $this->getSecurityContext(SecurityContext::CONTEXT_FRONT_OFFICE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user