Initial commit

This commit is contained in:
2021-01-19 18:19:37 +01:00
commit 6524a071df
14506 changed files with 1808535 additions and 0 deletions

View File

@@ -0,0 +1,676 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\ActionEvent;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\BaseForm;
use Thelia\Form\Exception\FormValidationException;
/**
* An abstract CRUD controller for Thelia ADMIN, to manage basic CRUD operations on a givent object.
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
abstract class AbstractCrudController extends BaseAdminController
{
protected $objectName;
// List ordering
protected $defaultListOrder;
protected $orderRequestParameterName;
// Permissions
protected $resourceCode;
protected $moduleCode;
// Events
protected $createEventIdentifier;
protected $updateEventIdentifier;
protected $deleteEventIdentifier;
protected $visibilityToggleEventIdentifier;
protected $changePositionEventIdentifier;
/**
* @param string $objectName the lower case object name. Example. "message"
*
* @param string $defaultListOrder the default object list order, or null if list is not sortable. Example: manual
* @param string $orderRequestParameterName Name of the request parameter that set the list order (null if list is not sortable)
*
* @param string $resourceCode the 'resource' code. Example: "admin.configuration.message"
*
* @param string $createEventIdentifier the dispatched create TheliaEvent identifier. Example: TheliaEvents::MESSAGE_CREATE
* @param string $updateEventIdentifier the dispatched update TheliaEvent identifier. Example: TheliaEvents::MESSAGE_UPDATE
* @param string $deleteEventIdentifier the dispatched delete TheliaEvent identifier. Example: TheliaEvents::MESSAGE_DELETE
*
* @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY
* @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION
* @param string $moduleCode The module code for ACL
*/
public function __construct(
$objectName,
$defaultListOrder,
$orderRequestParameterName,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier = null,
$changePositionEventIdentifier = null,
$moduleCode = null
) {
$this->objectName = $objectName;
$this->defaultListOrder = $defaultListOrder;
$this->orderRequestParameterName = $orderRequestParameterName;
$this->resourceCode = $resourceCode;
$this->createEventIdentifier = $createEventIdentifier;
$this->updateEventIdentifier = $updateEventIdentifier;
$this->deleteEventIdentifier = $deleteEventIdentifier;
$this->visibilityToggleEventIdentifier = $visibilityToggleEventIdentifier;
$this->changePositionEventIdentifier = $changePositionEventIdentifier;
$this->moduleCode = $moduleCode;
}
/**
* Return the creation form for this object
* @return BaseForm
*/
abstract protected function getCreationForm();
/**
* Return the update form for this object
* @return BaseForm
*/
abstract protected function getUpdateForm();
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param mixed $object
* @return BaseForm
*/
abstract protected function hydrateObjectForm($object);
/**
* Creates the creation event with the provided form data
*
* @param mixed $formData
* @return \Thelia\Core\Event\ActionEvent
*/
abstract protected function getCreationEvent($formData);
/**
* Creates the update event with the provided form data
*
* @param mixed $formData
* @return \Thelia\Core\Event\ActionEvent
*/
abstract protected function getUpdateEvent($formData);
/**
* Creates the delete event with the provided form data
* @return \Thelia\Core\Event\ActionEvent
*/
abstract protected function getDeleteEvent();
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param mixed $event
*/
abstract protected function eventContainsObject($event);
/**
* Get the created object from an event.
*
* @param mixed $event
*/
abstract protected function getObjectFromEvent($event);
/**
* Load an existing object from the database
*/
abstract protected function getExistingObject();
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param string|null $object
*/
abstract protected function getObjectLabel($object);
/**
* Returns the object ID from the object
*
* @param int|null $object
*/
abstract protected function getObjectId($object);
/**
* Render the main list template
*
* @param mixed $currentOrder, if any, null otherwise.
* @return \Thelia\Core\HttpFoundation\Response
*/
abstract protected function renderListTemplate($currentOrder);
/**
* Render the edition template
* @return \Thelia\Core\HttpFoundation\Response
*/
abstract protected function renderEditionTemplate();
/**
* Must return a RedirectResponse instance
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
abstract protected function redirectToEditionTemplate();
/**
* Must return a RedirectResponse instance
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
abstract protected function redirectToListTemplate();
/**
* @param $positionChangeMode
* @param $positionValue
* @return ActionEvent
*/
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
throw new \LogicException("Position Update is not supported for this object");
}
/**
* @return ActionEvent
*/
protected function createToggleVisibilityEvent()
{
throw new \LogicException("Toggle Visibility is not supported for this object");
}
/**
* Put in this method post object creation processing if required.
*
* @param ActionEvent $createEvent the create event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalCreateAction($createEvent)
{
return null;
}
/**
* Put in this method post object update processing if required.
*
* @param ActionEvent $updateEvent the update event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalUpdateAction($updateEvent)
{
return null;
}
/**
* Put in this method post object delete processing if required.
*
* @param ActionEvent $deleteEvent the delete event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
return null;
}
/**
* Put in this method post object position change processing if required.
*
* @param ActionEvent $positionChangeEvent the delete event
* @return Response|null a response, or null to continue normal processing
*/
protected function performAdditionalUpdatePositionAction($positionChangeEvent)
{
return null;
}
/**
* Return the current list order identifier, updating it in the same time.
*/
protected function getCurrentListOrder($update_session = true)
{
return $this->getListOrderFromSession(
$this->objectName,
$this->orderRequestParameterName,
$this->defaultListOrder
);
}
protected function getModuleCode()
{
if (null !== $this->moduleCode) {
return [$this->moduleCode];
} else {
return [];
}
}
/**
* Render the object list, ensuring the sort order is set.
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
protected function renderList()
{
return $this->renderListTemplate($this->getCurrentListOrder());
}
/**
* The default action is displaying the list.
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function defaultAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::VIEW)) {
return $response;
}
return $this->renderList();
}
/**
* Create a new object
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function createAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::CREATE)) {
return $response;
}
// Error (Default: false)
$error_msg = false;
// Create the Creation Form
$creationForm = $this->getCreationForm($this->getRequest());
try {
// Check the form against constraints violations
$form = $this->validateForm($creationForm, "POST");
// Get the form field values
$data = $form->getData();
// Create a new event object with the modified fields
$createEvent = $this->getCreationEvent($data);
$createEvent->bindForm($form);
// Dispatch Create Event
$this->dispatch($this->createEventIdentifier, $createEvent);
// Check if object exist
if (! $this->eventContainsObject($createEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was created.", ['%obj' => $this->objectName])
);
}
// Log object creation
if (null !== $createdObject = $this->getObjectFromEvent($createEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::CREATE,
sprintf(
"%s %s (ID %s) created",
ucfirst($this->objectName),
$this->getObjectLabel($createdObject),
$this->getObjectId($createdObject)
),
$this->getObjectId($createdObject)
);
}
// Execute additional Action
$response = $this->performAdditionalCreateAction($createEvent);
if ($response == null) {
// Substitute _ID_ in the URL with the ID of the created object
$successUrl = str_replace('_ID_', $this->getObjectId($createdObject), $creationForm->getSuccessUrl());
// Redirect to the success URL
return $this->generateRedirect($successUrl);
} else {
return $response;
}
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", ['%obj' => $this->objectName]),
$error_msg,
$creationForm,
$ex
);
// At this point, the form has error, and should be redisplayed.
return $this->renderList();
}
}
/**
* Load a object for modification, and display the edit template.
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function updateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
// Load object if exist
if (null !== $object = $this->getExistingObject()) {
// Hydrate the form abd pass it to the parser
$changeForm = $this->hydrateObjectForm($object);
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
}
// Render the edition template.
return $this->renderEditionTemplate();
}
/**
* Save changes on a modified object, and either go back to the object list, or stay on the edition page.
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function processUpdateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
// Error (Default: false)
$error_msg = false;
// Create the Form from the request
$changeForm = $this->getUpdateForm($this->getRequest());
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
// Get the form field values
$data = $form->getData();
// Create a new event object with the modified fields
$changeEvent = $this->getUpdateEvent($data);
$changeEvent->bindForm($form);
// Dispatch Update Event
$this->dispatch($this->updateEventIdentifier, $changeEvent);
// Check if object exist
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", ['%obj' => $this->objectName])
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
// Execute additional Action
$response = $this->performAdditionalUpdateAction($changeEvent);
if ($response == null) {
// If we have to stay on the same page, do not redirect to the successUrl,
// just redirect to the edit page again.
if ($this->getRequest()->get('save_mode') == 'stay') {
return $this->redirectToEditionTemplate($this->getRequest());
}
// Redirect to the success URL
return $this->generateSuccessRedirect($changeForm);
} else {
return $response;
}
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
// At this point, the form has errors, and should be redisplayed.
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", ['%obj' => $this->objectName]),
$error_msg,
$changeForm,
$ex
);
return $this->renderEditionTemplate();
}
}
/**
* Update object position (only for objects whichsupport that)
*
*/
public function updatePositionAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
try {
$mode = $this->getRequest()->get('mode', null);
if ($mode == 'up') {
$mode = UpdatePositionEvent::POSITION_UP;
} elseif ($mode == 'down') {
$mode = UpdatePositionEvent::POSITION_DOWN;
} else {
$mode = UpdatePositionEvent::POSITION_ABSOLUTE;
}
$position = $this->getRequest()->get('position', null);
$event = $this->createUpdatePositionEvent($mode, $position);
$this->dispatch($this->changePositionEventIdentifier, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
$response = $this->performAdditionalUpdatePositionAction($event);
if ($response == null) {
return $this->redirectToListTemplate();
} else {
return $response;
}
}
protected function genericUpdatePositionAction($object, $eventName, $doFinalRedirect = true)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
if ($object != null) {
try {
$mode = $this->getRequest()->get('mode', null);
if ($mode == 'up') {
$mode = UpdatePositionEvent::POSITION_UP;
} elseif ($mode == 'down') {
$mode = UpdatePositionEvent::POSITION_DOWN;
} else {
$mode = UpdatePositionEvent::POSITION_ABSOLUTE;
}
$position = $this->getRequest()->get('position', null);
$event = new UpdatePositionEvent($object->getId(), $mode, $position);
$this->dispatch($eventName, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
if ($doFinalRedirect) {
return $this->redirectToEditionTemplate();
}
}
/**
* Online status toggle (only for object which support it)
*/
public function setToggleVisibilityAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
$changeEvent = $this->createToggleVisibilityEvent($this->getRequest());
try {
$this->dispatch($this->visibilityToggleEventIdentifier, $changeEvent);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->nullResponse();
}
/**
* Delete an object
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function deleteAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::DELETE)) {
return $response;
}
try {
// Check token
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get("_token")
);
// Get the currency id, and dispatch the delete request
$deleteEvent = $this->getDeleteEvent();
$this->dispatch($this->deleteEventIdentifier, $deleteEvent);
if (null !== $deletedObject = $this->getObjectFromEvent($deleteEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::DELETE,
sprintf(
"%s %s (ID %s) deleted",
ucfirst($this->objectName),
$this->getObjectLabel($deletedObject),
$this->getObjectId($deletedObject)
),
$this->getObjectId($deletedObject)
);
}
$response = $this->performAdditionalDeleteAction($deleteEvent);
if ($response == null) {
return $this->redirectToListTemplate();
} else {
return $response;
}
} catch (\Exception $e) {
return $this->renderAfterDeleteError($e);
}
}
/**
* @param \Exception $e
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function renderAfterDeleteError(\Exception $e)
{
$errorMessage = sprintf(
"Unable to delete '%s'. Error message: %s",
$this->objectName,
$e->getMessage()
);
$this->getParserContext()
->setGeneralError($errorMessage)
;
return $this->defaultAction();
}
/**
* @return \Thelia\Core\HttpFoundation\Request
* @since 2.3
*/
protected function getRequest()
{
return $this->container->get('request_stack')->getCurrentRequest();
}
}

View File

@@ -0,0 +1,222 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\UpdateSeoEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\SeoForm;
/**
* Extend abstract CRUD controller to manage basic CRUD + SEO operations on a given object.
*
* @author Christophe Laffont <claffont@openstudio.fr>
*/
abstract class AbstractSeoCrudController extends AbstractCrudController
{
// Events
protected $updateSeoEventIdentifier;
/**
* @param string $objectName the lower case object name. Example. "message"
*
* @param string $defaultListOrder the default object list order, or null if list is not sortable. Example: manual
* @param string $orderRequestParameterName Name of the request parameter that set the list order (null if list is not sortable)
*
* @param string $resourceCode the 'resource' code. Example: "admin.configuration.message"
*
* @param string $createEventIdentifier the dispatched create TheliaEvent identifier. Example: TheliaEvents::MESSAGE_CREATE
* @param string $updateEventIdentifier the dispatched update TheliaEvent identifier. Example: TheliaEvents::MESSAGE_UPDATE
* @param string $deleteEventIdentifier the dispatched delete TheliaEvent identifier. Example: TheliaEvents::MESSAGE_DELETE
*
* @param string $visibilityToggleEventIdentifier the dispatched visibility toggle TheliaEvent identifier, or null if the object has no visible options. Example: TheliaEvents::MESSAGE_TOGGLE_VISIBILITY
* @param string $changePositionEventIdentifier the dispatched position change TheliaEvent identifier, or null if the object has no position. Example: TheliaEvents::MESSAGE_UPDATE_POSITION
* @param string $updateSeoEventIdentifier the dispatched update SEO change TheliaEvent identifier, or null if the object has no SEO. Example: TheliaEvents::MESSAGE_UPDATE_SEO
* @param string $moduleCode The module code for ACL
*/
public function __construct(
$objectName,
$defaultListOrder,
$orderRequestParameterName,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier = null,
$changePositionEventIdentifier = null,
$updateSeoEventIdentifier = null,
$moduleCode = null
) {
parent::__construct(
$objectName,
$defaultListOrder,
$orderRequestParameterName,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier,
$changePositionEventIdentifier,
$moduleCode
);
$this->updateSeoEventIdentifier = $updateSeoEventIdentifier;
}
/**
* Put in this method post object update SEO processing if required.
*
* @param UpdateSeoEvent $updateSeoEvent the update event
* @return null|Response a response, or null to continue normal processing
*/
protected function performAdditionalUpdateSeoAction($updateSeoEvent)
{
return null;
}
/**
* Return the update SEO form for this object
*/
protected function getUpdateSeoForm()
{
return $this->createForm(AdminForm::SEO);
}
/**
* Creates the update SEO event with the provided form data
*
* @param $formData
* @return UpdateSeoEvent
*/
protected function getUpdateSeoEvent($formData)
{
$updateSeoEvent = new UpdateSeoEvent($formData['id']);
$updateSeoEvent
->setLocale($formData['locale'])
->setMetaTitle($formData['meta_title'])
->setMetaDescription($formData['meta_description'])
->setMetaKeywords($formData['meta_keywords'])
->setUrl($formData['url'])
;
// Create and dispatch the change event
return $updateSeoEvent;
}
/**
* Hydrate the SEO form for this object, before passing it to the update template
*
* @param mixed $object
*/
protected function hydrateSeoForm($object)
{
// The "SEO" tab form
$locale = $object->getLocale();
$data = array(
'id' => $object->getId(),
'locale' => $locale,
'url' => $object->getRewrittenUrl($locale),
'meta_title' => $object->getMetaTitle(),
'meta_description' => $object->getMetaDescription(),
'meta_keywords' => $object->getMetaKeywords()
);
$seoForm = $this->createForm(AdminForm::SEO, "form", $data);
$this->getParserContext()->addForm($seoForm);
// URL based on the language
$this->getParserContext()->set('url_language', $this->getUrlLanguage($locale));
}
/**
* Update SEO modification, and either go back to the object list, or stay on the edition page.
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function processUpdateSeoAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
// Error (Default: false)
$error_msg = false;
// Create the Form from the request
$updateSeoForm = $this->getUpdateSeoForm($this->getRequest());
// Pass the object id to the request
$this->getRequest()->attributes->set($this->objectName . '_id', $this->getRequest()->get('current_id'));
try {
// Check the form against constraints violations
$form = $this->validateForm($updateSeoForm, "POST");
// Get the form field values
$data = $form->getData();
// Create a new event object with the modified fields
$updateSeoEvent = $this->getUpdateSeoEvent($data);
// Dispatch Update SEO Event
$this->dispatch($this->updateSeoEventIdentifier, $updateSeoEvent);
// Execute additional Action
$response = $this->performAdditionalUpdateSeoAction($updateSeoEvent);
if ($response == null) {
// If we have to stay on the same page, do not redirect to the successUrl,
// just redirect to the edit page again.
if ($this->getRequest()->get('save_mode') == 'stay') {
return $this->redirectToEditionTemplate($this->getRequest());
}
// Redirect to the success URL
return $this->generateSuccessRedirect($updateSeoForm);
} else {
return $response;
}
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
/*} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();*/
}
// Load object if exist
if (null !== $object = $this->getExistingObject()) {
// Hydrate the form abd pass it to the parser
$changeForm = $this->hydrateObjectForm($object);
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj SEO modification", array('%obj' => $this->objectName)),
$error_msg,
$updateSeoForm,
$ex
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
}
}

View File

@@ -0,0 +1,322 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Address\AddressCreateOrUpdateEvent;
use Thelia\Core\Event\Address\AddressEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\AddressQuery;
use Thelia\Model\CustomerQuery;
/**
* Class AddressController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class AddressController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'registration_date',
null,
null,
AdminResources::ADDRESS,
TheliaEvents::ADDRESS_CREATE,
TheliaEvents::ADDRESS_UPDATE,
TheliaEvents::ADDRESS_DELETE
);
}
public function useAddressAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$address_id = $this->getRequest()->request->get('address_id');
try {
$address = AddressQuery::create()->findPk($address_id);
if (null === $address) {
throw new \InvalidArgumentException(sprintf('%d address does not exists', $address_id));
}
$addressEvent = new AddressEvent($address);
$this->dispatch(TheliaEvents::ADDRESS_DEFAULT, $addressEvent);
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"address %d for customer %d set as default address",
$address_id,
$address->getCustomerId()
),
$address_id
);
} catch (\Exception $e) {
\Thelia\Log\Tlog::getInstance()->error(sprintf("error during address setting as default with message %s", $e->getMessage()));
}
return $this->redirectToEditionTemplate();
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::ADDRESS_CREATE);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::ADDRESS_UPDATE);
}
/**
* Fills in the form data array
*
* @param unknown $object
* @return array
*/
protected function createFormDataArray($object)
{
return array(
"label" => $object->getLabel(),
"title" => $object->getTitleId(),
"firstname" => $object->getFirstname(),
"lastname" => $object->getLastname(),
"address1" => $object->getAddress1(),
"address2" => $object->getAddress2(),
"address3" => $object->getAddress3(),
"zipcode" => $object->getZipcode(),
"city" => $object->getCity(),
"country" => $object->getCountryId(),
"state" => $object->getStateId(),
"cellphone" => $object->getCellphone(),
"phone" => $object->getPhone(),
"company" => $object->getCompany()
);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\Address $object
*/
protected function hydrateObjectForm($object)
{
return $this->createForm(AdminForm::ADDRESS_UPDATE, "form", $this->createFormDataArray($object));
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
*/
protected function getCreationEvent($formData)
{
$event = $this->getCreateOrUpdateEvent($formData);
$customer = CustomerQuery::create()->findPk($this->getRequest()->get("customer_id"));
$event->setCustomer($customer);
return $event;
}
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
*/
protected function getUpdateEvent($formData)
{
$event = $this->getCreateOrUpdateEvent($formData);
$event->setAddress($this->getExistingObject());
return $event;
}
protected function getCreateOrUpdateEvent($formData)
{
$event = new AddressCreateOrUpdateEvent(
$formData["label"],
$formData["title"],
$formData["firstname"],
$formData["lastname"],
$formData["address1"],
$formData["address2"],
$formData["address3"],
$formData["zipcode"],
$formData["city"],
$formData["country"],
$formData["cellphone"],
$formData["phone"],
$formData["company"],
$formData["is_default"],
$formData["state"]
);
return $event;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new AddressEvent($this->getExistingObject());
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param unknown $event
*/
protected function eventContainsObject($event)
{
return null !== $event->getAddress();
}
/**
* Get the created object from an event.
*
* @param unknown $createEvent
*/
protected function getObjectFromEvent($event)
{
return null;
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
return AddressQuery::create()->findPk($this->getRequest()->get('address_id'));
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param unknown $object
*/
protected function getObjectLabel($object)
{
return $object->getLabel();
}
/**
* Returns the object ID from the object
*
* @param unknown $object
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
*/
protected function renderListTemplate($currentOrder)
{
// We render here the customer edit template.
return $this->renderEditionTemplate();
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('customer-edit', array(
"address_id" => $this->getRequest()->get('address_id'),
"page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
));
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
// We display here the custromer edition template
return $this->generateRedirectFromRoute(
'admin.customer.update.view',
[
"page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
]
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
// TODO: Implement redirectToListTemplate() method.
}
/**
* Put in this method post object delete processing if required.
*
* @param \Thelia\Core\Event\AddressEvent $deleteEvent the delete event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
return $this->redirectToEditionTemplate();
}
/**
* Put in this method post object creation processing if required.
*
* @param AddressCreateOrUpdateEvent $createEvent the create event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalCreateAction($createEvent)
{
return $this->redirectToEditionTemplate();
}
protected function performAdditionalUpdateAction($event)
{
return $this->redirectToEditionTemplate();
}
protected function getCustomerId()
{
if (null !== $address = $this->getExistingObject()) {
return $address->getCustomerId();
} else {
return $this->getRequest()->get('customer_id', 0);
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Tools\URL;
class AdminController extends BaseAdminController
{
public function indexAction()
{
if (!$this->getSecurityContext()->hasAdminUser()) {
return new RedirectResponse(URL::getInstance()->absoluteUrl($this->getRoute("admin.login")));
}
return $this->render("home");
}
public function updateAction()
{
return $this->render("profile-edit");
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Model\AdminLog;
use Thelia\Model\AdminLogQuery;
class AdminLogsController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::ADMIN_LOG, array(), AccessManager::VIEW)) {
return $response;
}
// Render the edition template.
return $this->render('admin-logs');
}
public function loadLoggerAjaxAction()
{
$entries = array();
/** @var AdminLog $entry */
foreach (AdminLogQuery::getEntries(
$this->getRequest()->request->get('admins', array()),
$this->getRequest()->request->get('fromDate', null),
$this->getRequest()->request->get('toDate', null),
array_merge($this->getRequest()->request->get('resources', array()), $this->getRequest()->request->get('modules', array())),
null
) as $entry) {
$entries[] = array(
"head" => sprintf(
"%s|%s|%s:%s%s",
date('Y-m-d H:i:s', $entry->getCreatedAt()->getTimestamp()),
$entry->getAdminLogin(),
$entry->getResource(),
$entry->getAction(),
(null !== $entry->getResourceId()) ? ":" . $entry->getResourceId() : ""
),
"data" => $entry->getMessage(),
);
}
return $this->render(
'ajax/logger',
array(
'entries' => $entries,
)
);
}
}

View File

@@ -0,0 +1,201 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Administrator\AdministratorEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Admin;
use Thelia\Model\AdminQuery;
class AdministratorController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'administrator',
'manual',
'order',
AdminResources::ADMINISTRATOR,
TheliaEvents::ADMINISTRATOR_CREATE,
TheliaEvents::ADMINISTRATOR_UPDATE,
TheliaEvents::ADMINISTRATOR_DELETE
);
}
public function viewAction()
{
// Open the update dialog for the current administrator
return $this->render('administrators', [ 'show_update_dialog' => true ]);
}
public function setEmailAction()
{
// Open the update dialog for the current administrator, and display the "set email address" notice.
return $this->render(
'administrators',
[
'show_update_dialog' => true,
'show_email_change_notice' => true
]
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::ADMINISTRATOR_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$event = new AdministratorEvent();
$event->setLogin($formData['login']);
$event->setFirstname($formData['firstname']);
$event->setLastname($formData['lastname']);
$event->setPassword($formData['password']);
$event->setProfile($formData['profile'] ? : null);
$event->setLocale($formData['locale']);
$event->setEmail($formData['email']);
return $event;
}
protected function getUpdateEvent($formData)
{
$event = new AdministratorEvent();
$event->setId($formData['id']);
$event->setLogin($formData['login']);
$event->setFirstname($formData['firstname']);
$event->setLastname($formData['lastname']);
$event->setPassword($formData['password']);
$event->setProfile($formData['profile'] ? : null);
$event->setLocale($formData['locale']);
$event->setEmail($formData['email']);
return $event;
}
protected function getDeleteEvent()
{
$event = new AdministratorEvent();
$event->setId(
$this->getRequest()->get('administrator_id', 0)
);
return $event;
}
protected function eventContainsObject($event)
{
return $event->hasAdministrator();
}
/**
* @param Admin $object
*
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'firstname' => $object->getFirstname(),
'lastname' => $object->getLastname(),
'login' => $object->getLogin(),
'profile' => $object->getProfileId(),
'locale' => $object->getLocale(),
'email' => $object->getEmail()
);
// Setup the object form
return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasAdministrator() ? $event->getAdministrator() : null;
}
protected function getExistingObject()
{
return AdminQuery::create()
->findOneById($this->getRequest()->get('administrator_id'));
}
/**
* @param Admin $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getLogin();
}
/**
* @param Admin $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
// We always return to the feature edition form
return $this->render(
'administrators',
array()
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('administrators');
}
protected function redirectToEditionTemplate()
{
// We always return to the feature edition form
return $this->redirectToListTemplate();
}
protected function performAdditionalCreateAction($updateEvent)
{
// We always return to the feature edition form
return $this->redirectToListTemplate();
}
protected function performAdditionalUpdateAction($updateEvent)
{
// We always return to the feature edition form
return $this->redirectToListTemplate();
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.administrators.view"
);
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Cache\CacheEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
/**
* Class CacheController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class AdvancedConfigurationController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::VIEW)) {
return $result;
}
return $this->render('advanced-configuration');
}
public function flushCacheAction()
{
if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) {
return $result;
}
$form = $this->createForm(AdminForm::CACHE_FLUSH);
try {
$this->validateForm($form);
$event = new CacheEvent($this->container->getParameter("kernel.cache_dir"));
$this->dispatch(TheliaEvents::CACHE_CLEAR, $event);
} catch (\Exception $e) {
Tlog::getInstance()->addError(sprintf("Flush cache error: %s", $e->getMessage()));
}
return $this->generateRedirectFromRoute('admin.configuration.advanced');
}
public function flushAssetsAction()
{
if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) {
return $result;
}
$form = $this->createForm(AdminForm::ASSETS_FLUSH);
try {
$this->validateForm($form);
$event = new CacheEvent(THELIA_WEB_DIR . "assets");
$this->dispatch(TheliaEvents::CACHE_CLEAR, $event);
} catch (\Exception $e) {
Tlog::getInstance()->addError(sprintf("Flush assets error: %s", $e->getMessage()));
}
return $this->generateRedirectFromRoute('admin.configuration.advanced');
}
public function flushImagesAndDocumentsAction()
{
if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::UPDATE)) {
return $result;
}
$form = $this->createForm(AdminForm::IMAGES_AND_DOCUMENTS_CACHE_FLUSH);
try {
$this->validateForm($form);
$event = new CacheEvent(
THELIA_WEB_DIR . ConfigQuery::read(
'image_cache_dir_from_web_root',
'cache' . DS . 'images'
)
);
$this->dispatch(TheliaEvents::CACHE_CLEAR, $event);
$event = new CacheEvent(
THELIA_WEB_DIR . ConfigQuery::read(
'document_cache_dir_from_web_root',
'cache' . DS . 'documents'
)
);
$this->dispatch(TheliaEvents::CACHE_CLEAR, $event);
} catch (\Exception $e) {
Tlog::getInstance()->addError(sprintf("Flush images and document error: %s", $e->getMessage()));
}
return $this->generateRedirectFromRoute('admin.configuration.advanced');
}
}

View File

@@ -0,0 +1,210 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Core\Event\Api\ApiCreateEvent;
use Thelia\Core\Event\Api\ApiDeleteEvent;
use Thelia\Core\Event\Api\ApiUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Translation\Translator;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\Api;
use Thelia\Model\ApiQuery;
use Thelia\Tools\URL;
/**
* Class ApiController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ApiController extends BaseAdminController
{
protected $api;
public function downloadAction($api_id)
{
if (null === $response = $this->checkApiAccess($api_id, AccessManager::VIEW)) {
$response = $this->retrieveSecureKey($this->api);
}
return $response;
}
public function deleteAction()
{
$api_id = $this->getRequest()->request->get('api_id');
if (null === $response = $this->checkApiAccess($api_id, AccessManager::DELETE)) {
$response = $this->deleteApi($this->api);
}
return $response;
}
private function deleteApi(Api $api)
{
$event = new ApiDeleteEvent($api);
$this->dispatch(TheliaEvents::API_DELETE, $event);
return RedirectResponse::create(URL::getInstance()->absoluteUrl($this->getRoute('admin.configuration.api')));
}
/**
* @param Api $api
* @return \Symfony\Component\HttpFoundation\Response
*/
private function retrieveSecureKey(Api $api)
{
$response = Response::create($api->getSecureKey());
$response->headers->add([
'Content-Type' => 'application/octet-stream',
'Content-disposition' => sprintf('filename=%s.key', $api->getApiKey())
]);
return $response;
}
public function indexAction()
{
if (null !== $response = $this->checkAuth([AdminResources::API], [], AccessManager::VIEW)) {
return $response;
}
return $this->renderList();
}
public function createAction()
{
if (null !== $response = $this->checkAuth([AdminResources::API], [], AccessManager::CREATE)) {
return $response;
}
$form = $this->createForm(AdminForm::API_CREATE);
$error_msg = null;
try {
$createForm = $this->validateForm($form);
$event = new ApiCreateEvent(
$createForm->get('label')->getData(),
$createForm->get('profile')->getData() ?: null
);
$this->dispatch(TheliaEvents::API_CREATE, $event);
return RedirectResponse::create($form->getSuccessUrl());
} catch (FormValidationException $e) {
$error_msg = $this->createStandardFormValidationErrorMessage($e);
} catch (\Exception $e) {
$error_msg = $e->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Api')),
$error_msg,
$form,
$e
);
// At this point, the form has error, and should be redisplayed.
return $this->renderList();
}
}
public function updateAction($api_id)
{
if (null === $response = $this->checkApiAccess($api_id, AccessManager::UPDATE)) {
$form = $this->createForm(AdminForm::API_UPDATE, 'form', ['profile' => $this->api->getProfileId()]);
$this->getParserContext()->addForm($form);
$response = $this->renderList($api_id);
}
return $response;
}
public function processUpdateAction($api_id)
{
if (null === $response = $this->checkApiAccess($api_id, AccessManager::UPDATE)) {
$response = $this->doUpdate($this->api);
}
return $response;
}
private function doUpdate(Api $api)
{
$error_msg = null;
$form = $this->createForm(AdminForm::API_UPDATE);
try {
$updateForm = $this->validateForm($form);
$event = new ApiUpdateEvent($api, $updateForm->get('profile')->getData() ?: null);
$this->dispatch(TheliaEvents::API_UPDATE, $event);
$response = RedirectResponse::create(URL::getInstance()->absoluteUrl($this->getRoute('admin.configuration.api')));
} catch (FormValidationException $e) {
$error_msg = $this->createStandardFormValidationErrorMessage($e);
} catch (\Exception $e) {
$error_msg = $e->getMessage();
}
if (null !== $error_msg) {
$this->setupFormErrorContext(
"foo",
$error_msg,
$form,
$e
);
$response = $this->renderList($api->getId());
}
return $response;
}
private function checkApiAccess($api_id, $access)
{
$response = null;
if (null === $response = $this->checkAuth([AdminResources::API], [], AccessManager::UPDATE)) {
$this->api = ApiQuery::create()->findPk($api_id);
if (null === $this->api) {
$response = $this->errorPage(Translator::getInstance()->trans("api id %id does not exists", ['%id' => $api_id]));
}
}
return $response;
}
protected function renderList($api_id = null)
{
$apiAccessList = ApiQuery::create()->find()->toArray();
return $this->render(
'api',
[
'api_list' => $apiAccessList,
'api_id' => $api_id
]
);
}
}

View File

@@ -0,0 +1,440 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Area\AreaAddCountryEvent;
use Thelia\Core\Event\Area\AreaCreateEvent;
use Thelia\Core\Event\Area\AreaDeleteEvent;
use Thelia\Core\Event\Area\AreaRemoveCountryEvent;
use Thelia\Core\Event\Area\AreaUpdateEvent;
use Thelia\Core\Event\Area\AreaUpdatePostageEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\BaseForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\Area;
use Thelia\Model\AreaQuery;
/**
* Class AreaController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
* @author Franck Allimant <franck@cqfdev.fr>
*/
class AreaController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'area',
null,
null,
AdminResources::AREA,
TheliaEvents::AREA_CREATE,
TheliaEvents::AREA_UPDATE,
TheliaEvents::AREA_DELETE
);
}
protected function getAreaId()
{
return $this->getRequest()->get('area_id', 0);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::AREA_CREATE);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::AREA_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param Area $object
* @return BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
'area_id' => $object->getId(),
'name' => $object->getName()
);
return $this->createForm(AdminForm::AREA_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
*
* @return \Thelia\Core\Event\Area\AreaCreateEvent
*/
protected function getCreationEvent($formData)
{
$event = new AreaCreateEvent();
return $this->hydrateEvent($event, $formData);
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return \Thelia\Core\Event\Area\AreaUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$event = new AreaUpdateEvent();
$this->hydrateEvent($event, $formData);
$event->setAreaId($formData['area_id']);
return $event;
}
/**
* @param \Thelia\Core\Event\Area\AreaCreateEvent $event
* @param array $formData
* @return \Thelia\Core\Event\Area\AreaCreateEvent
*/
private function hydrateEvent($event, $formData)
{
$event->setAreaName($formData['name']);
return $event;
}
/**
* Creates the delete event with the provided form data
*
* @return AreaDeleteEvent
*/
protected function getDeleteEvent()
{
return new AreaDeleteEvent($this->getAreaId());
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param \Thelia\Core\Event\Area\AreaEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasArea();
}
/**
* Get the created object from an event.
*
* @param \Thelia\Core\Event\Area\AreaEvent $event
* @return Area
*/
protected function getObjectFromEvent($event)
{
return $event->getArea();
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
return AreaQuery::create()->findPk($this->getAreaId());
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\Area $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getName();
}
/**
* Returns the object ID from the object
*
* @param \Thelia\Model\Area $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param string|null $currentOrder, if any, null otherwise.
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function renderListTemplate($currentOrder)
{
return $this->render("shipping-configuration");
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render(
'shipping-configuration-edit',
array(
'area_id' => $this->getAreaId()
)
);
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.configuration.shipping-configuration.update.view',
[],
[
"area_id" => $this->getAreaId()
]
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.shipping-configuration.default');
}
/**
* add a country to a define area
*/
public function addCountry()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$areaCountryForm = $this->createForm(AdminForm::AREA_COUNTRY);
$error_msg = null;
try {
$form = $this->validateForm($areaCountryForm);
$event = new AreaAddCountryEvent($form->get('area_id')->getData(), $form->get('country_id')->getData());
$this->dispatch(TheliaEvents::AREA_ADD_COUNTRY, $event);
if (! $this->eventContainsObject($event)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName))
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($event)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified, new country added",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
// Redirect to the success URL
return $this->generateSuccessRedirect($areaCountryForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)),
$error_msg,
$areaCountryForm
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
/**
* delete several countries from a shipping zone
*/
public function removeCountries()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$areaDeleteCountriesForm = $this->createForm(AdminForm::AREA_DELETE_COUNTRY);
try {
$form = $this->validateForm($areaDeleteCountriesForm);
$data = $form->getData();
foreach ($data['country_id'] as $countryId) {
$country = explode('-', $countryId);
$this->removeOneCountryFromArea($data['area_id'], $country[0], $country[1]);
}
// Redirect to the success URL
return $this->generateSuccessRedirect($areaDeleteCountriesForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("Failed to delete selected countries"),
$error_msg,
$areaDeleteCountriesForm
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
protected function removeOneCountryFromArea($areaId, $countryId, $stateId)
{
if (\intval($stateId) === 0) {
$stateId = null;
}
$removeCountryEvent = new AreaRemoveCountryEvent($areaId, $countryId, $stateId);
$this->dispatch(TheliaEvents::AREA_REMOVE_COUNTRY, $removeCountryEvent);
if (null !== $changedObject = $this->getObjectFromEvent($removeCountryEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) removed country ID %s from shipping zone ID %s",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject),
$countryId,
$areaId
),
$this->getObjectId($changedObject)
);
}
}
public function removeCountry()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$this->removeOneCountryFromArea(
$this->getRequest()->get('area_id', 0),
$this->getRequest()->get('country_id', 0),
$this->getRequest()->get('state_id', null)
);
return $this->redirectToEditionTemplate();
}
public function updatePostageAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$areaUpdateForm = $this->createForm(AdminForm::AREA_POSTAGE);
$error_msg = null;
try {
$form = $this->validateForm($areaUpdateForm);
$event = new AreaUpdatePostageEvent($form->get('area_id')->getData());
$event->setPostage($form->get('postage')->getData());
$this->dispatch(TheliaEvents::AREA_POSTAGE_UPDATE, $event);
if (! $this->eventContainsObject($event)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName))
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($event)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified, country remove",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
// Redirect to the success URL
return $this->generateSuccessRedirect($areaUpdateForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)),
$error_msg,
$areaUpdateForm
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
}

View File

@@ -0,0 +1,183 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Attribute\AttributeAvCreateEvent;
use Thelia\Core\Event\Attribute\AttributeAvDeleteEvent;
use Thelia\Core\Event\Attribute\AttributeAvUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\AttributeAv;
use Thelia\Model\AttributeAvQuery;
/**
* Manages attributes-av
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class AttributeAvController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'attributeav',
'manual',
'order',
AdminResources::ATTRIBUTE,
TheliaEvents::ATTRIBUTE_AV_CREATE,
TheliaEvents::ATTRIBUTE_AV_UPDATE,
TheliaEvents::ATTRIBUTE_AV_DELETE,
null, // No visibility toggle
TheliaEvents::ATTRIBUTE_AV_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::ATTRIBUTE_AV_CREATION);
}
protected function getUpdateForm()
{
throw new \LogicException("Attribute Av. modification is not yet implemented");
}
protected function getCreationEvent($formData)
{
$createEvent = new AttributeAvCreateEvent();
$createEvent
->setAttributeId($formData['attribute_id'])
->setTitle($formData['title'])
->setLocale($formData["locale"])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new AttributeAvUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $changeEvent;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('attributeav_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new AttributeAvDeleteEvent($this->getRequest()->get('attributeav_id'));
}
protected function eventContainsObject($event)
{
return $event->hasAttributeAv();
}
protected function hydrateObjectForm($object)
{
throw new \LogicException("Attribute Av. modification is not yet implemented");
}
protected function getObjectFromEvent($event)
{
return $event->hasAttributeAv() ? $event->getAttributeAv() : null;
}
protected function getExistingObject()
{
$attributeAv = AttributeAvQuery::create()
->findOneById($this->getRequest()->get('attributeav_id', 0));
if (null !== $attributeAv) {
$attributeAv->setLocale($this->getCurrentEditionLocale());
}
return $attributeAv;
}
/**
* @param AttributeAv $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param AttributeAv $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments()
{
return array(
'attribute_id' => $this->getRequest()->get('attribute_id'),
'order' => $this->getCurrentListOrder()
);
}
protected function renderListTemplate($currentOrder)
{
// We always return to the attribute edition form
return $this->render(
'attribute-edit',
$this->getViewArguments()
);
}
protected function renderEditionTemplate()
{
// We always return to the attribute edition form
return $this->render('attribute-edit', $this->getViewArguments());
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
);
}
}

View File

@@ -0,0 +1,266 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Attribute\AttributeAvUpdateEvent;
use Thelia\Core\Event\Attribute\AttributeCreateEvent;
use Thelia\Core\Event\Attribute\AttributeDeleteEvent;
use Thelia\Core\Event\Attribute\AttributeEvent;
use Thelia\Core\Event\Attribute\AttributeUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Attribute;
use Thelia\Model\AttributeQuery;
/**
* Manages attributes
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class AttributeController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'attribute',
'manual',
'order',
AdminResources::ATTRIBUTE,
TheliaEvents::ATTRIBUTE_CREATE,
TheliaEvents::ATTRIBUTE_UPDATE,
TheliaEvents::ATTRIBUTE_DELETE,
null, // No visibility toggle
TheliaEvents::ATTRIBUTE_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::ATTRIBUTE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new AttributeCreateEvent();
$createEvent
->setTitle($formData['title'])
->setLocale($formData["locale"])
->setAddToAllTemplates($formData['add_to_all'])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new AttributeUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $changeEvent;
}
/**
* Process the attributes values (fix it in future version to integrate it in the attribute form as a collection)
*
* @see \Thelia\Controller\Admin\AbstractCrudController::performAdditionalUpdateAction()
*/
protected function performAdditionalUpdateAction($updateEvent)
{
$attr_values = $this->getRequest()->get('attribute_values', null);
if ($attr_values !== null) {
foreach ($attr_values as $id => $value) {
$event = new AttributeAvUpdateEvent($id);
$event->setTitle($value);
$event->setLocale($this->getCurrentEditionLocale());
$this->dispatch(TheliaEvents::ATTRIBUTE_AV_UPDATE, $event);
}
}
return null;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('attribute_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new AttributeDeleteEvent($this->getRequest()->get('attribute_id'));
}
protected function eventContainsObject($event)
{
return $event->hasAttribute();
}
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum()
);
// Setup the object form
return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasAttribute() ? $event->getAttribute() : null;
}
protected function getExistingObject()
{
$attribute = AttributeQuery::create()
->findOneById($this->getRequest()->get('attribute_id', 0));
if (null !== $attribute) {
$attribute->setLocale($this->getCurrentEditionLocale());
}
return $attribute;
}
/**
* @param Attribute $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Attribute $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('attributes', array('order' => $currentOrder));
}
protected function renderEditionTemplate()
{
return $this->render(
'attribute-edit',
array(
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
)
);
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
[
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
]
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.attributes.default');
}
/**
* Get the Attribute value list order.
*
* @return string the current list order
*/
protected function getAttributeAvListOrder()
{
return $this->getListOrderFromSession(
'attributeav',
'attributeav_order',
'manual'
);
}
/**
* Add or Remove from all product templates
*/
protected function addRemoveFromAllTemplates($eventType)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
try {
if (null !== $object = $this->getExistingObject()) {
$event = new AttributeEvent($object);
$this->dispatch($eventType, $event);
}
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
/**
* Remove from all product templates
*/
public function removeFromAllTemplates()
{
return $this->addRemoveFromAllTemplates(TheliaEvents::ATTRIBUTE_REMOVE_FROM_ALL_TEMPLATES);
}
/**
* Add to all product templates
*/
public function addToAllTemplates()
{
return $this->addRemoveFromAllTemplates(TheliaEvents::ATTRIBUTE_ADD_TO_ALL_TEMPLATES);
}
}

View File

@@ -0,0 +1,402 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Thelia\Controller\BaseController;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\Exception\AuthorizationException;
use Thelia\Core\Template\ParserInterface;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Form\BaseForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\AdminLog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\CurrencyQuery;
use Thelia\Model\LangQuery;
use Thelia\Tools\URL;
class BaseAdminController extends BaseController
{
const CONTROLLER_TYPE = 'admin';
const TEMPLATE_404 = "404";
/**
* The current router identifier. The default is router.admin. Modules may use
* setCurrentRouter() method to pass their own router, and use the route related
* methods of this class.
*/
protected $currentRouter = "router.admin";
/**
* Helper to append a message to the admin log.
*
* @param string $resource
* @param string $action
* @param string $message
*/
public function adminLogAppend($resource, $action, $message, $resourceId = null)
{
AdminLog::append(
$resource,
$action,
$message,
$this->getRequest(),
$this->getSecurityContext()->getAdminUser(),
true,
$resourceId
);
}
/**
* This method process the rendering of view called from an admin page
*
* @param string $template the template name
* @return Response the response 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')) {
return $this->render($view);
}
} catch (\Exception $ex) {
return $this->errorPage($ex->getMessage());
}
return $this->pageNotFound();
}
/**
* @return string
*/
public function getControllerType()
{
return self::CONTROLLER_TYPE;
}
/**
* Return a 404 error
*
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function pageNotFound()
{
return new Response($this->renderRaw(self::TEMPLATE_404), 404);
}
/**
* Return a general error page
*
* @param \Exception|string $message a message string, or an exception instance
* @param int $status the HTTP status (default is 500)
*
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function errorPage($message, $status = 500)
{
if ($message instanceof \Exception) {
$strMessage = $this->getTranslator()->trans(
"Sorry, an error occured: %msg",
[ '%msg' => $message->getMessage() ]
);
Tlog::getInstance()->addError($strMessage.": ".$message->getTraceAsString());
$message = $strMessage;
} else {
Tlog::getInstance()->addError($message);
}
return $this->render(
'general_error',
array(
"error_message" => $message
),
$status
);
}
/**
* Check current admin user authorisations. An ADMIN role is assumed.
*
* @param mixed $resources a single resource or an array of resources.
* @param mixed $modules a single module or an array of modules.
* @param mixed $accesses a single access or an array of accesses.
*
* @return mixed null if authorization is granted, or a Response object which contains the error page otherwise
*/
protected function checkAuth($resources, $modules, $accesses)
{
$resources = \is_array($resources) ? $resources : array($resources);
$modules = \is_array($modules) ? $modules : array($modules);
$accesses = \is_array($accesses) ? $accesses : array($accesses);
if ($this->getSecurityContext()->isGranted(array("ADMIN"), $resources, $modules, $accesses)) {
// Okay !
return null;
}
// Log the problem
$this->adminLogAppend(implode(",", $resources), implode(",", $accesses), "User is not granted for resources %s with accesses %s", implode(", ", $resources), implode(", ", $accesses));
return $this->errorPage($this->getTranslator()->trans("Sorry, you're not allowed to perform this action"), 403);
}
/*
* Create the standard message displayed to the user when the form cannot be validated.
*/
protected function createStandardFormValidationErrorMessage(FormValidationException $exception)
{
return $this->getTranslator()->trans(
"Please check your input: %error",
array(
'%error' => $exception->getMessage()
)
);
}
/**
* Setup the error context when an error occurs in a action method.
*
* @param string $action the action that caused the error (category modification, variable creation, currency update, etc.)
* @param BaseForm $form the form where the error occured, or null if no form was involved
* @param string $error_message the error message
* @param \Exception $exception the exception or null if no exception
*/
protected function setupFormErrorContext($action, $error_message, BaseForm $form = null, \Exception $exception = null)
{
if ($error_message !== false) {
// Log the error message
Tlog::getInstance()->error(
$this->getTranslator()->trans(
"Error during %action process : %error. Exception was %exc",
array(
'%action' => $action,
'%error' => $error_message,
'%exc' => $exception != null ? $exception->getMessage() : 'no exception'
)
)
);
if ($form != null) {
// Mark the form as errored
$form->setErrorMessage($error_message);
// Pass it to the parser context
$this->getParserContext()->addForm($form);
}
// Pass the error message to the parser.
$this->getParserContext()->setGeneralError($error_message);
}
}
/**
* @param TemplateDefinition $template the template to process
*
* @return ParserInterface instance parser
*/
protected function getParser($template = null)
{
$parser = $this->container->get("thelia.parser");
// Define the template that should be used
$parser->setTemplateDefinition(
$template ?: $this->getTemplateHelper()->getActiveAdminTemplate(),
$this->useFallbackTemplate
);
return $parser;
}
/**
* Forwards the request to another controller.
*
* @param string $controller The controller name (a string like BlogBundle:Post:index)
* @param array $path An array of path parameters
* @param array $query An array of query parameters
*
* @return Response A Response instance
*/
protected function forward($controller, array $path = array(), array $query = array())
{
$path['_controller'] = $controller;
$subRequest = $this->container->get('request_stack')->getCurrentRequest()->duplicate($query, null, $path);
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
/**
* Get the current edition currency ID, checking if a change was requested in the current request.
*/
protected function getCurrentEditionCurrency()
{
// Return the new language if a change is required.
if (null !== $edit_currency_id = $this->getRequest()->get('edit_currency_id', null)) {
if (null !== $edit_currency = CurrencyQuery::create()->findOneById($edit_currency_id)) {
return $edit_currency;
}
}
// Otherwise return the lang stored in session.
return $this->getSession()->getAdminEditionCurrency();
}
/**
* Get the current edition lang ID, checking if a change was requested in the current request.
*/
protected function getCurrentEditionLang()
{
// Return the new language if a change is required.
if (null !== $edit_language_id = $this->getRequest()->get('edit_language_id', null)) {
if (null !== $edit_language = LangQuery::create()->findOneById($edit_language_id)) {
return $edit_language;
}
}
// Otherwise return the lang stored in session.
return $this->getSession()->getAdminEditionLang();
}
/**
* A simple helper to get the current edition locale.
*/
protected function getCurrentEditionLocale()
{
return $this->getCurrentEditionLang()->getLocale();
}
/**
* A simple helper to get the URL based on the language.
*
* @param string $locale the locale, or null to get the current one
* @return null|string the URL for the current language, or null if the "One domain for each lang" feature is disabled.
*/
protected function getUrlLanguage($locale = null)
{
// Check if the functionality is activated
if (!ConfigQuery::isMultiDomainActivated()) {
return null;
}
// If we don't have a locale value, use the locale value in the session
if (!$locale) {
$locale = $this->getCurrentEditionLocale();
}
return LangQuery::create()->findOneByLocale($locale)->getUrl();
}
/**
* Return the current list order identifier for a given object name,
* updating in using the current request.
*
* @param string $objectName the object name (e.g. 'attribute', 'message')
* @param string $requestParameterName the name of the request parameter that defines the list order
* @param string $defaultListOrder the default order to use, if none is defined
* @param bool $updateSession if true, the session will be updated with the current order.
*
* @return String the current list order.
*/
protected function getListOrderFromSession($objectName, $requestParameterName, $defaultListOrder, $updateSession = true)
{
$orderSessionIdentifier = sprintf("admin.%s.currentListOrder", $objectName);
// Find the current order
$order = $this->getRequest()->get(
$requestParameterName,
$this->getSession()->get($orderSessionIdentifier, $defaultListOrder)
);
if ($updateSession) {
$this->getSession()->set($orderSessionIdentifier, $order);
}
return $order;
}
/**
* Render the given template, and returns the result as an Http Response.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param int $status http code status
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function render($templateName, $args = array(), $status = 200)
{
$response = $this->renderRaw($templateName, $args);
if (!$response instanceof \Symfony\Component\HttpFoundation\Response) {
$response = Response::create($response, $status);
}
return $response;
}
/**
* Render the given template, and returns the result as a string.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param null $templateDir
*
* @return string|\Symfony\Component\HttpFoundation\RedirectResponse
*/
protected function renderRaw($templateName, $args = array(), $templateDir = null)
{
// Add the template standard extension
$templateName .= '.html';
// Find the current edit language ID
$edition_language = $this->getCurrentEditionLang();
// Find the current edit currency ID
$edition_currency = $this->getCurrentEditionCurrency();
// Prepare common template variables
$args = array_merge($args, array(
'edit_language_id' => $edition_language->getId(),
'edit_language_locale' => $edition_language->getLocale(),
'edit_currency_id' => $edition_currency->getId(),
));
// Update the current edition language & currency in session
$this->getSession()
->setAdminEditionLang($edition_language)
->setAdminEditionCurrency($edition_currency)
;
// Render the template.
try {
$content = $this->getParser($templateDir)->render($templateName, $args);
} 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.
$content = RedirectResponse::create(URL::getInstance()->absoluteUrl($ex->getLoginTemplate()));
} catch (AuthorizationException $ex) {
// User is not allowed to perform the required action. Return the error page instead of the requested page.
$content = $this->errorPage($this->getTranslator()->trans("Sorry, you are not allowed to perform this action."), 403);
}
return $content;
}
}

View File

@@ -0,0 +1,282 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Brand\BrandCreateEvent;
use Thelia\Core\Event\Brand\BrandDeleteEvent;
use Thelia\Core\Event\Brand\BrandEvent;
use Thelia\Core\Event\Brand\BrandToggleVisibilityEvent;
use Thelia\Core\Event\Brand\BrandUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Brand\BrandModificationForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Brand;
use Thelia\Model\BrandQuery;
/**
* Class BrandController
* @package Thelia\Controller\Admin
* @author Franck Allimant <franck@cqfdev.fr>
*/
class BrandController extends AbstractSeoCrudController
{
public function __construct()
{
parent::__construct(
'brand',
'manual',
'order',
AdminResources::BRAND,
TheliaEvents::BRAND_CREATE,
TheliaEvents::BRAND_UPDATE,
TheliaEvents::BRAND_DELETE,
TheliaEvents::BRAND_TOGGLE_VISIBILITY,
TheliaEvents::BRAND_UPDATE_POSITION,
TheliaEvents::BRAND_UPDATE_SEO
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::BRAND_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::BRAND_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param Brand $object
* @return BrandModificationForm $object
*/
protected function hydrateObjectForm($object)
{
// Hydrate the "SEO" tab form
$this->hydrateSeoForm($object);
// Prepare the data that will hydrate the form
$data = [
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'visible' => $object->getVisible() ? true : false,
'logo_image_id' => $object->getLogoImageId()
];
// Setup the object form
return $this->createForm(AdminForm::BRAND_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return BrandCreateEvent
*/
protected function getCreationEvent($formData)
{
$brandCreateEvent = new BrandCreateEvent();
$brandCreateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setVisible($formData['visible'])
;
return $brandCreateEvent;
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return BrandUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$brandUpdateEvent = new BrandUpdateEvent($formData['id']);
$brandUpdateEvent
->setLogoImageId($formData['logo_image_id'])
->setVisible($formData['visible'])
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $brandUpdateEvent;
}
/**
* Creates the delete event with the provided form data
*
* @return BrandDeleteEvent
*/
protected function getDeleteEvent()
{
return new BrandDeleteEvent($this->getRequest()->get('brand_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param BrandEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasBrand();
}
/**
* Get the created object from an event.
*
* @param $event \Thelia\Core\Event\Brand\BrandEvent
*
* @return null|\Thelia\Model\Brand
*/
protected function getObjectFromEvent($event)
{
return $event->getBrand();
}
/**
* Load an existing object from the database
*
* @return \Thelia\Model\Brand
*/
protected function getExistingObject()
{
$brand = BrandQuery::create()
->findOneById($this->getRequest()->get('brand_id', 0));
if (null !== $brand) {
$brand->setLocale($this->getCurrentEditionLocale());
}
return $brand;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param Brand $object
*
* @return string brand title
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param Brand $object
*
* @return int brand id
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param string $currentOrder, if any, null otherwise.
*
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
$this->getListOrderFromSession('brand', 'order', 'manual');
return $this->render('brands', [
'order' => $currentOrder,
]);
}
protected function getEditionArguments()
{
return [
'brand_id' => $this->getRequest()->get('brand_id', 0),
'current_tab' => $this->getRequest()->get('current_tab', 'general')
];
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('brand-edit', $this->getEditionArguments());
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.brand.update',
[],
$this->getEditionArguments()
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.brand.default');
}
/**
* @return BrandToggleVisibilityEvent|void
*/
protected function createToggleVisibilityEvent()
{
return new BrandToggleVisibilityEvent($this->getExistingObject());
}
/**
* @inheritdoc
*/
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('brand_id', null),
$positionChangeMode,
$positionValue
);
}
}

View File

@@ -0,0 +1,405 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Propel\Runtime\ActiveQuery\Criteria;
use Thelia\Core\Event\Category\CategoryAddContentEvent;
use Thelia\Core\Event\Category\CategoryCreateEvent;
use Thelia\Core\Event\Category\CategoryDeleteContentEvent;
use Thelia\Core\Event\Category\CategoryDeleteEvent;
use Thelia\Core\Event\Category\CategoryToggleVisibilityEvent;
use Thelia\Core\Event\Category\CategoryUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Category;
use Thelia\Model\CategoryAssociatedContentQuery;
use Thelia\Model\CategoryQuery;
use Thelia\Model\ContentQuery;
use Thelia\Model\FolderQuery;
/**
* Manages categories
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class CategoryController extends AbstractSeoCrudController
{
public function __construct()
{
parent::__construct(
'category',
'manual',
'category_order',
AdminResources::CATEGORY,
TheliaEvents::CATEGORY_CREATE,
TheliaEvents::CATEGORY_UPDATE,
TheliaEvents::CATEGORY_DELETE,
TheliaEvents::CATEGORY_TOGGLE_VISIBILITY,
TheliaEvents::CATEGORY_UPDATE_POSITION,
TheliaEvents::CATEGORY_UPDATE_SEO
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::CATEGORY_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::CATEGORY_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new CategoryCreateEvent();
$createEvent
->setTitle($formData['title'])
->setLocale($formData["locale"])
->setParent($formData['parent'])
->setVisible($formData['visible'])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new CategoryUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
->setVisible($formData['visible'])
->setParent($formData['parent'])
->setDefaultTemplateId($formData['default_template_id'])
;
return $changeEvent;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('category_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new CategoryDeleteEvent($this->getRequest()->get('category_id', 0));
}
protected function eventContainsObject($event)
{
return $event->hasCategory();
}
/**
* @param \Thelia\Model\Category $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
// Hydrate the "SEO" tab form
$this->hydrateSeoForm($object);
// The "General" tab form
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'visible' => $object->getVisible(),
'parent' => $object->getParent(),
'default_template_id' => $object->getDefaultTemplateId()
);
// Setup the object form
return $this->createForm(AdminForm::CATEGORY_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasCategory() ? $event->getCategory() : null;
}
protected function getExistingObject()
{
$category = CategoryQuery::create()
->findOneById($this->getRequest()->get('category_id', 0));
if (null !== $category) {
$category->setLocale($this->getCurrentEditionLocale());
}
return $category;
}
/**
* @param Category $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Category $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getEditionArguments()
{
return array(
'category_id' => $this->getRequest()->get('category_id', 0),
'folder_id' => $this->getRequest()->get('folder_id', 0),
'current_tab' => $this->getRequest()->get('current_tab', 'general'),
'page' => $this->getRequest()->get('page', 1)
);
}
protected function renderListTemplate($currentOrder)
{
// Get product order
$product_order = $this->getListOrderFromSession('product', 'product_order', 'manual');
return $this->render(
'categories',
array(
'category_order' => $currentOrder,
'product_order' => $product_order,
'category_id' => $this->getRequest()->get('category_id', 0),
'page' => $this->getRequest()->get('page', 1)
)
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
'admin.categories.default',
[
'category_id' => $this->getRequest()->get('category_id', 0),
'page' => $this->getRequest()->get('page', 1)
]
);
}
protected function redirectToListTemplateWithId($category_id)
{
$response = null;
if ($category_id > 0) {
$response = $this->generateRedirectFromRoute(
'admin.categories.default',
['category_id' => $category_id]
);
} else {
$response = $this->generateRedirectFromRoute('admin.catalog');
}
return $response;
}
protected function renderEditionTemplate()
{
return $this->render('category-edit', $this->getEditionArguments());
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.categories.update",
$this->getEditionArguments()
);
}
/**
* Online status toggle category
*/
public function setToggleVisibilityAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new CategoryToggleVisibilityEvent($this->getExistingObject());
try {
$this->dispatch(TheliaEvents::CATEGORY_TOGGLE_VISIBILITY, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
// Ajax response -> no action
return $this->nullResponse();
}
/**
* @param CategoryDeleteEvent $deleteEvent
* @return null|\Symfony\Component\HttpFoundation\Response
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
// Redirect to parent category list
$category_id = $deleteEvent->getCategory()->getParent();
return $this->redirectToListTemplateWithId($category_id);
}
/**
* @param CategoryUpdateEvent $updateEvent
* @return null|\Symfony\Component\HttpFoundation\Response
*/
protected function performAdditionalUpdateAction($updateEvent)
{
$response = null;
if ($this->getRequest()->get('save_mode') != 'stay') {
// Redirect to parent category list
$category_id = $updateEvent->getCategory()->getParent();
$response = $this->redirectToListTemplateWithId($category_id);
}
return $response;
}
/**
* @param UpdatePositionEvent $event
* @return null|\Symfony\Component\HttpFoundation\Response
*/
protected function performAdditionalUpdatePositionAction($event)
{
$category = CategoryQuery::create()->findPk($event->getObjectId());
$response = null;
if ($category != null) {
// Redirect to parent category list
$category_id = $category->getParent();
$response = $this->redirectToListTemplateWithId($category_id);
}
return $response;
}
public function getAvailableRelatedContentAction($categoryId, $folderId)
{
$result = array();
$folders = FolderQuery::create()->filterById($folderId)->find();
if ($folders !== null) {
$list = ContentQuery::create()
->joinWithI18n($this->getCurrentEditionLocale())
->filterByFolder($folders, Criteria::IN)
->filterById(
CategoryAssociatedContentQuery::create()->select('content_id')->findByCategoryId($categoryId),
Criteria::NOT_IN
)
->find();
;
if ($list !== null) {
foreach ($list as $item) {
$result[] = array('id' => $item->getId(), 'title' => $item->getTitle());
}
}
}
return $this->jsonResponse(json_encode($result));
}
public function addRelatedContentAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$content_id = \intval($this->getRequest()->get('content_id'));
if ($content_id > 0) {
$event = new CategoryAddContentEvent(
$this->getExistingObject(),
$content_id
);
try {
$this->dispatch(TheliaEvents::CATEGORY_ADD_CONTENT, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
return $this->redirectToEditionTemplate();
}
/**
* Add category pictures
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function addRelatedPictureAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
return $this->redirectToEditionTemplate();
}
public function deleteRelatedContentAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$content_id = \intval($this->getRequest()->get('content_id'));
if ($content_id > 0) {
$event = new CategoryDeleteContentEvent(
$this->getExistingObject(),
$content_id
);
try {
$this->dispatch(TheliaEvents::CATEGORY_REMOVE_CONTENT, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
return $this->redirectToEditionTemplate();
}
}

View File

@@ -0,0 +1,205 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Config\ConfigCreateEvent;
use Thelia\Core\Event\Config\ConfigDeleteEvent;
use Thelia\Core\Event\Config\ConfigUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Config;
use Thelia\Model\ConfigQuery;
/**
* Manages variables
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class ConfigController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'variable',
'name',
'order',
AdminResources::CONFIG,
TheliaEvents::CONFIG_CREATE,
TheliaEvents::CONFIG_UPDATE,
TheliaEvents::CONFIG_DELETE,
null, // No visibility toggle
null // no position change
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::CONFIG_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::CONFIG_MODIFICATION);
}
protected function getCreationEvent($data)
{
$createEvent = new ConfigCreateEvent();
$createEvent
->setEventName($data['name'])
->setValue($data['value'])
->setLocale($data["locale"])
->setTitle($data['title'])
->setHidden($data['hidden'])
->setSecured($data['secured'])
;
return $createEvent;
}
protected function getUpdateEvent($data)
{
$changeEvent = new ConfigUpdateEvent($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'])
;
return $changeEvent;
}
protected function getDeleteEvent()
{
return new ConfigDeleteEvent($this->getRequest()->get('variable_id'));
}
protected function eventContainsObject($event)
{
return $event->hasConfig();
}
protected function hydrateObjectForm($object)
{
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'name' => $object->getName(),
'value' => $object->getValue(),
'hidden' => $object->getHidden(),
'secured' => $object->getSecured(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum()
);
// Setup the object form
return $this->createForm(AdminForm::CONFIG_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasConfig() ? $event->getConfig() : null;
}
protected function getExistingObject()
{
$config = ConfigQuery::create()
->findOneById($this->getRequest()->get('variable_id'));
if (null !== $config) {
$config->setLocale($this->getCurrentEditionLocale());
}
return $config;
}
/**
* @param Config $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getName();
}
/**
* @param Config $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('variables', array('order' => $currentOrder));
}
protected function renderEditionTemplate()
{
return $this->render('variable-edit', array('variable_id' => $this->getRequest()->get('variable_id')));
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.variables.update",
array('variable_id' => $this->getRequest()->get('variable_id'))
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.variables.default');
}
/**
* Change values modified directly from the variable list
*
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function changeValuesAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$variables = $this->getRequest()->get('variable', array());
// Process all changed variables
foreach ($variables as $id => $value) {
$event = new ConfigUpdateEvent($id);
$event->setValue($value);
$this->dispatch(TheliaEvents::CONFIG_SETVALUE, $event);
}
return $this->generateRedirectFromRoute('admin.configuration.variables.default');
}
}

View File

@@ -0,0 +1,137 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\ConfigQuery;
/**
* Class ConfigStoreController
* @package Thelia\Controller\Admin
* @author Christophe Laffont <claffont@openstudio.fr>
*/
class ConfigStoreController extends BaseAdminController
{
protected function renderTemplate()
{
return $this->render('config-store');
}
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::VIEW)) {
return $response;
}
// The form is self-hydrated
$configStoreForm = $this->createForm(AdminForm::CONFIG_STORE);
$this->getParserContext()->addForm($configStoreForm);
return $this->renderTemplate();
}
protected function getAndWriteStoreMediaFileInConfig($form, $inputName, $configKey, $storeMediaUploadDir)
{
$file = $form->get($inputName)->getData();
if ($file != null) {
// Delete the old file
$fs = new \Symfony\Component\Filesystem\Filesystem();
$oldFileName = ConfigQuery::read($configKey);
if ($oldFileName !== null) {
$oldFilePath = $storeMediaUploadDir . DS . $oldFileName;
if ($fs->exists($oldFilePath)) {
$fs->remove($oldFilePath);
}
}
// Write the new file
$newFileName = uniqid() . '-' . $file->getClientOriginalName();
$file->move($storeMediaUploadDir, $newFileName);
ConfigQuery::write($configKey, $newFileName, false);
}
}
public function saveAction()
{
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = $ex = false;
$response = null;
$configStoreForm = $this->createForm(AdminForm::CONFIG_STORE);
try {
$form = $this->validateForm($configStoreForm);
$storeMediaUploadDir = ConfigQuery::read('images_library_path');
if ($storeMediaUploadDir === null) {
$storeMediaUploadDir = THELIA_LOCAL_DIR . 'media' . DS . 'images';
} else {
$storeMediaUploadDir = THELIA_ROOT . $storeMediaUploadDir;
}
$storeMediaUploadDir .= DS . 'store';
// List of medias that can be uploaded through this form.
// [Name of the form input] => [Key in the config table]
$storeMediaList = [
'favicon_file' => 'favicon_file',
'logo_file' => 'logo_file',
'banner_file' => 'banner_file'
];
foreach ($storeMediaList as $input_name => $config_key) {
$this->getAndWriteStoreMediaFileInConfig($form, $input_name, $config_key, $storeMediaUploadDir);
}
$data = $form->getData();
// Update store
foreach ($data as $name => $value) {
if (!array_key_exists($name, $storeMediaList) && !$configStoreForm->isTemplateDefinedHiddenFieldName($name)) {
ConfigQuery::write($name, $value, false);
}
}
$this->adminLogAppend(AdminResources::STORE, AccessManager::UPDATE, "Store configuration changed");
if ($this->getRequest()->get('save_mode') == 'stay') {
$response = $this->generateRedirectFromRoute('admin.configuration.store.default');
} else {
$response = $this->generateSuccessRedirect($configStoreForm);
}
} catch (\Exception $ex) {
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("Store configuration failed."),
$error_msg,
$configStoreForm,
$ex
);
$response = $this->renderTemplate();
}
return $response;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
/**
* Class ConfigurationController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ConfigurationController extends BaseAdminController
{
public function indexAction()
{
if (null !== $response = $this->checkAuth([AdminResources::CONFIG], [], [AccessManager::VIEW])) {
return $response;
}
return $this->render('configuration');
}
}

View File

@@ -0,0 +1,413 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Content\ContentAddFolderEvent;
use Thelia\Core\Event\Content\ContentCreateEvent;
use Thelia\Core\Event\Content\ContentDeleteEvent;
use Thelia\Core\Event\Content\ContentRemoveFolderEvent;
use Thelia\Core\Event\Content\ContentToggleVisibilityEvent;
use Thelia\Core\Event\Content\ContentUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Content;
use Thelia\Model\ContentQuery;
/**
* Class ContentController
* @package Thelia\Controller\Admin
* @author manuel raynaud <manu@raynaud.io>
*/
class ContentController extends AbstractSeoCrudController
{
public function __construct()
{
parent::__construct(
'content',
'manual',
'content_order',
AdminResources::CONTENT,
TheliaEvents::CONTENT_CREATE,
TheliaEvents::CONTENT_UPDATE,
TheliaEvents::CONTENT_DELETE,
TheliaEvents::CONTENT_TOGGLE_VISIBILITY,
TheliaEvents::CONTENT_UPDATE_POSITION,
TheliaEvents::CONTENT_UPDATE_SEO
);
}
/**
* controller adding content to additional folder
*
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function addAdditionalFolderAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$folder_id = \intval($this->getRequest()->request->get('additional_folder_id'));
if ($folder_id > 0) {
$event = new ContentAddFolderEvent(
$this->getExistingObject(),
$folder_id
);
try {
$this->dispatch(TheliaEvents::CONTENT_ADD_FOLDER, $event);
} catch (\Exception $e) {
return $this->errorPage($e);
}
}
return $this->redirectToEditionTemplate();
}
/**
* controller removing additional folder to a content
*
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function removeAdditionalFolderAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$folder_id = \intval($this->getRequest()->request->get('additional_folder_id'));
if ($folder_id > 0) {
$event = new ContentRemoveFolderEvent(
$this->getExistingObject(),
$folder_id
);
try {
$this->dispatch(TheliaEvents::CONTENT_REMOVE_FOLDER, $event);
} catch (\Exception $e) {
return $this->errorPage($e);
}
}
return $this->redirectToEditionTemplate();
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::CONTENT_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::CONTENT_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param Content $object
* @return \Thelia\Form\ContentModificationForm
*/
protected function hydrateObjectForm($object)
{
// Hydrate the "SEO" tab form
$this->hydrateSeoForm($object);
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'visible' => $object->getVisible()
);
// Setup the object form
return $this->createForm(AdminForm::CONTENT_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return \Thelia\Core\Event\Content\ContentCreateEvent
*/
protected function getCreationEvent($formData)
{
$contentCreateEvent = new ContentCreateEvent();
$contentCreateEvent
->setLocale($formData['locale'])
->setDefaultFolder($formData['default_folder'])
->setTitle($formData['title'])
->setVisible($formData['visible'])
;
return $contentCreateEvent;
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return \Thelia\Core\Event\Content\ContentUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$contentUpdateEvent = new ContentUpdateEvent($formData['id']);
$contentUpdateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
->setVisible($formData['visible'])
->setDefaultFolder($formData['default_folder']);
return $contentUpdateEvent;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new ContentDeleteEvent($this->getRequest()->get('content_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param \Thelia\Core\Event\Content\ContentEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasContent();
}
/**
* Get the created object from an event.
*
* @param $event \Thelia\Core\Event\Content\ContentEvent
*
* @return null|\Thelia\Model\Content
*/
protected function getObjectFromEvent($event)
{
return $event->getContent();
}
/**
* Load an existing object from the database
*
* @return \Thelia\Model\Content
*/
protected function getExistingObject()
{
$content = ContentQuery::create()
->findOneById($this->getRequest()->get('content_id', 0));
if (null !== $content) {
$content->setLocale($this->getCurrentEditionLocale());
}
return $content;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param Content $object
*
* @return string content title
*
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param Content $object
*
* @return int content id
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getFolderId()
{
$folderId = $this->getRequest()->get('folder_id', null);
if (null === $folderId) {
$content = $this->getExistingObject();
if ($content) {
$folderId = $content->getDefaultFolderId();
}
}
return $folderId ?: 0;
}
/**
* Render the main list template
*
* @param int $currentOrder , if any, null otherwise.
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function renderListTemplate($currentOrder)
{
$this->getListOrderFromSession('content', 'content_order', 'manual');
return $this->render(
'folders',
array(
'content_order' => $currentOrder,
'parent' => $this->getFolderId()
)
);
}
protected function getEditionArguments()
{
return array(
'content_id' => $this->getRequest()->get('content_id', 0),
'current_tab' => $this->getRequest()->get('current_tab', 'general'),
'folder_id' => $this->getFolderId(),
);
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('content-edit', $this->getEditionArguments());
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.content.update',
[],
$this->getEditionArguments()
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
'admin.content.default',
['parent' => $this->getFolderId()]
);
}
/**
* @param \Thelia\Core\Event\Content\ContentUpdateEvent $updateEvent
* @return Response|void
*/
protected function performAdditionalUpdateAction($updateEvent)
{
if ($this->getRequest()->get('save_mode') != 'stay') {
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $this->getFolderId()]
);
} else {
return null;
}
}
/**
* Put in this method post object delete processing if required.
*
* @param \Thelia\Core\Event\Content\ContentDeleteEvent $deleteEvent the delete event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $deleteEvent->getDefaultFolderId()]
);
}
/**
* @param $event \Thelia\Core\Event\UpdatePositionEvent
* @return null|Response
*/
protected function performAdditionalUpdatePositionAction($event)
{
if (null !== $content = ContentQuery::create()->findPk($event->getObjectId())) {
// Redirect to parent category list
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $event->getReferrerId()]
);
} else {
return null;
}
}
/**
* @param $positionChangeMode
* @param $positionValue
* @return UpdatePositionEvent|void
*/
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('content_id', null),
$positionChangeMode,
$positionValue,
$this->getRequest()->get('folder_id', null)
);
}
/**
* @return ContentToggleVisibilityEvent|void
*/
protected function createToggleVisibilityEvent()
{
return new ContentToggleVisibilityEvent($this->getExistingObject());
}
}

View File

@@ -0,0 +1,344 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Country\CountryCreateEvent;
use Thelia\Core\Event\Country\CountryDeleteEvent;
use Thelia\Core\Event\Country\CountryToggleDefaultEvent;
use Thelia\Core\Event\Country\CountryToggleVisibilityEvent;
use Thelia\Core\Event\Country\CountryUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\BaseForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Log\Tlog;
use Thelia\Model\Country;
use Thelia\Model\CountryQuery;
use Thelia\Model\State;
use Thelia\Model\StateQuery;
/**
* Class CustomerController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class CountryController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'country',
'manual',
'country_order',
AdminResources::COUNTRY,
TheliaEvents::COUNTRY_CREATE,
TheliaEvents::COUNTRY_UPDATE,
TheliaEvents::COUNTRY_DELETE,
TheliaEvents::COUNTRY_TOGGLE_VISIBILITY
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::COUNTRY_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::COUNTRY_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\Country $object
* @return BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'visible' => $object->getVisible() ? true : false,
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'isocode' => $object->getIsocode(),
'isoalpha2' => $object->getIsoalpha2(),
'isoalpha3' => $object->getIsoalpha3(),
'has_states' => $object->getHasStates() ? true : false,
'need_zip_code' => $object->getNeedZipCode() ? true : false,
'zip_code_format' => $object->getZipCodeFormat(),
);
return $this->createForm(AdminForm::COUNTRY_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return CountryCreateEvent
*/
protected function getCreationEvent($formData)
{
$event = new CountryCreateEvent();
return $this->hydrateEvent($event, $formData);
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return CountryUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$event = new CountryUpdateEvent($formData['id']);
$event = $this->hydrateEvent($event, $formData);
$event
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
->setNeedZipCode($formData['need_zip_code'])
->setZipCodeFormat($formData['zip_code_format'])
;
return $event;
}
protected function hydrateEvent($event, $formData)
{
$event
->setLocale($formData['locale'])
->setVisible($formData['visible'])
->setTitle($formData['title'])
->setIsocode($formData['isocode'])
->setIsoAlpha2($formData['isoalpha2'])
->setIsoAlpha3($formData['isoalpha3'])
->setHasStates($formData['has_states'])
;
return $event;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new CountryDeleteEvent($this->getRequest()->get('country_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param unknown $event
*/
protected function eventContainsObject($event)
{
return $event->hasCountry();
}
/**
* Get the created object from an event.
*
* @param unknown $createEvent
* @return Country
*/
protected function getObjectFromEvent($event)
{
return $event->getCountry();
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
$country = CountryQuery::create()
->findPk($this->getRequest()->get('country_id', 0));
if (null !== $country) {
$country->setLocale($this->getCurrentEditionLocale());
}
return $country;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\Country $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param \Thelia\Model\Country $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
return $this->render("countries", array("display_country" => 20));
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('country-edit', $this->getEditionArgument());
}
protected function getEditionArgument()
{
return array(
'country_id' => $this->getRequest()->get('country_id', 0)
);
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.configuration.countries.update',
[],
[
"country_id" => $this->getRequest()->get('country_id', 0)
]
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.countries.default');
}
public function toggleDefaultAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
if (null !== $country_id = $this->getRequest()->get('country_id')) {
$toogleDefaultEvent = new CountryToggleDefaultEvent($country_id);
try {
$this->dispatch(TheliaEvents::COUNTRY_TOGGLE_DEFAULT, $toogleDefaultEvent);
if ($toogleDefaultEvent->hasCountry()) {
return $this->nullResponse();
}
} catch (\Exception $ex) {
Tlog::getInstance()->error($ex->getMessage());
}
}
return $this->nullResponse(500);
}
/**
* @return CountryToggleVisibilityEvent|void
*/
protected function createToggleVisibilityEvent()
{
return new CountryToggleVisibilityEvent($this->getExistingObject());
}
public function getDataAction($visible = true, $locale = null)
{
$response = $this->checkAuth($this->resourceCode, array(), AccessManager::VIEW);
if (null !== $response) {
return $response;
}
if (null === $locale) {
$locale = $this->getCurrentEditionLocale();
}
$responseData = [];
/** @var CountryQuery $search */
$countries = CountryQuery::create()
->_if($visible)
->filterByVisible(true)
->_endif()
->joinWithI18n($locale)
;
/** @var Country $country */
foreach ($countries as $country) {
$currentCountry = [
'id' => $country->getId(),
'title' => $country->getTitle(),
'hasStates' => $country->getHasStates(),
'states' => []
];
if ($country->getHasStates()) {
$states = StateQuery::create()
->filterByCountryId($country->getId())
->_if($visible)
->filterByVisible(true)
->_endif()
->joinWithI18n($locale)
;
/** @var State $state */
foreach ($states as $state) {
$currentCountry['states'][] = [
'id' => $state->getId(),
'title' => $state->getTitle(),
];
}
}
$responseData[] = $currentCountry;
}
return $this->jsonResponse(json_encode($responseData));
}
}

View File

@@ -0,0 +1,884 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Router;
use Thelia\Condition\ConditionCollection;
use Thelia\Condition\ConditionFactory;
use Thelia\Condition\Implementation\ConditionInterface;
use Thelia\Core\Event\Coupon\CouponCreateOrUpdateEvent;
use Thelia\Core\Event\Coupon\CouponDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Coupon\CouponFactory;
use Thelia\Coupon\CouponManager;
use Thelia\Coupon\Type\CouponInterface;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\Coupon;
use Thelia\Model\CouponCountry;
use Thelia\Model\CouponModule;
use Thelia\Model\CouponQuery;
use Thelia\Model\LangQuery;
use Thelia\Tools\Rest\ResponseRest;
use Thelia\Tools\URL;
/**
* Control View and Action (Model) via Events
*
* @package Coupon
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class CouponController extends BaseAdminController
{
/**
* Manage Coupons list display
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function browseAction()
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
return $this->render('coupon-list', [
'coupon_order' => $this->getListOrderFromSession('coupon', 'coupon_order', 'code')
]);
}
/**
* Manage Coupons creation display
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function createAction()
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::CREATE)) {
return $response;
}
// Parameters given to the template
$args = [];
$eventToDispatch = TheliaEvents::COUPON_CREATE;
if ($this->getRequest()->isMethod('POST')) {
if (null !== $response = $this->validateCreateOrUpdateForm(
$eventToDispatch,
'created',
'creation'
)) {
return $response;
}
} else {
// If no input for expirationDate, now + 2 months
$defaultDate = new \DateTime();
$args['nowDate'] = $defaultDate->format($this->getDefaultDateFormat());
$args['defaultDate'] = $defaultDate->modify('+2 month')->format($this->getDefaultDateFormat());
}
$args['dateFormat'] = $this->getDefaultDateFormat();
$args['availableCoupons'] = $this->getAvailableCoupons();
$args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute(
'admin.coupon.draw.inputs.ajax',
['couponServiceId' => 'couponServiceId'],
Router::ABSOLUTE_URL
);
$args['formAction'] = 'admin/coupon/create';
// Setup empty data if form is already in parser context
$this->getParserContext()->addForm($this->createForm(AdminForm::COUPON_CREATION));
return $this->render(
'coupon-create',
$args
);
}
/**
* Manage Coupons edition display
*
* @param int $couponId Coupon id
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function updateAction($couponId)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
/** @var Coupon $coupon */
$coupon = CouponQuery::create()->findPk($couponId);
if (null === $coupon) {
return $this->pageNotFound();
}
$coupon->setLocale($this->getCurrentEditionLocale());
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
// Parameters given to the template
$args = [];
$eventToDispatch = TheliaEvents::COUPON_UPDATE;
// Update
if ($this->getRequest()->isMethod('POST')) {
if (null !== $response = $this->validateCreateOrUpdateForm(
$eventToDispatch,
'updated',
'update',
$coupon
)) {
return $response;
}
} else {
// Display
// Prepare the data that will hydrate the form
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$conditions = $conditionFactory->unserializeConditionCollection(
$coupon->getSerializedConditions()
);
$freeShippingForCountries = $freeShippingForModules = [];
/** @var CouponCountry $item */
foreach ($coupon->getFreeShippingForCountries() as $item) {
$freeShippingForCountries[] = $item->getCountryId();
}
/** @var CouponModule $item */
foreach ($coupon->getFreeShippingForModules() as $item) {
$freeShippingForModules[] = $item->getModuleId();
}
if (empty($freeShippingForCountries)) {
$freeShippingForCountries[] = 0;
}
if (empty($freeShippingForModules)) {
$freeShippingForModules[] = 0;
}
$data = [
'code' => $coupon->getCode(),
'title' => $coupon->getTitle(),
'amount' => $coupon->getAmount(),
'type' => $coupon->getType(),
'shortDescription' => $coupon->getShortDescription(),
'description' => $coupon->getDescription(),
'isEnabled' => $coupon->getIsEnabled(),
'startDate' => $coupon->getStartDate($this->getDefaultDateFormat()),
'expirationDate' => $coupon->getExpirationDate($this->getDefaultDateFormat()),
'isAvailableOnSpecialOffers' => $coupon->getIsAvailableOnSpecialOffers(),
'isCumulative' => $coupon->getIsCumulative(),
'isRemovingPostage' => $coupon->getIsRemovingPostage(),
'maxUsage' => $coupon->getMaxUsage(),
'conditions' => $conditions,
'locale' => $this->getCurrentEditionLocale(),
'freeShippingForCountries' => $freeShippingForCountries,
'freeShippingForModules' => $freeShippingForModules,
'perCustomerUsageCount' => $coupon->getPerCustomerUsageCount(),
];
$args['conditions'] = $this->cleanConditionForTemplate($conditions);
// Setup the object form
$changeForm = $this->createForm(AdminForm::COUPON_CREATION, 'form', $data);
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
}
$args['couponCode'] = $coupon->getCode();
$args['couponType'] = $coupon->getType();
$args['availableCoupons'] = $this->getAvailableCoupons();
$args['couponInputsHtml'] = $couponManager->drawBackOfficeInputs();
$args['urlAjaxAdminCouponDrawInputs'] = $this->getRoute(
'admin.coupon.draw.inputs.ajax',
['couponServiceId' => 'couponServiceId'],
Router::ABSOLUTE_URL
);
$args['availableConditions'] = $this->getAvailableConditions();
$args['urlAjaxGetConditionInputFromServiceId'] = $this->getRoute(
'admin.coupon.draw.condition.read.inputs.ajax',
['conditionId' => 'conditionId'],
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionInputFromConditionInterface'] = $this->getRoute(
'admin.coupon.draw.condition.update.inputs.ajax',
[
'couponId' => $couponId,
'conditionIndex' => 8888888
],
Router::ABSOLUTE_URL
);
$args['urlAjaxSaveConditions'] = $this->getRoute(
'admin.coupon.condition.save',
['couponId' => $couponId],
Router::ABSOLUTE_URL
);
$args['urlAjaxDeleteConditions'] = $this->getRoute(
'admin.coupon.condition.delete',
[
'couponId' => $couponId,
'conditionIndex' => 8888888
],
Router::ABSOLUTE_URL
);
$args['urlAjaxGetConditionSummaries'] = $this->getRoute(
'admin.coupon.draw.condition.summaries.ajax',
['couponId' => $couponId],
Router::ABSOLUTE_URL
);
$args['formAction'] = 'admin/coupon/update/' . $couponId;
$args['dateFormat'] = $this->getDefaultDateFormat();
$args['couponId'] = $couponId;
return $this->render('coupon-update', $args);
}
/**
* Manage Coupons read display
*
* @param string $conditionId Condition service id
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function getConditionEmptyInputAjaxAction($conditionId)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
if (! empty($conditionId)) {
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromServiceId($conditionId);
if (!$this->container->has($conditionId)) {
return false;
}
if ($inputs === null) {
return $this->pageNotFound();
}
/** @var ConditionInterface $condition */
$condition = $this->container->get($conditionId);
$html = $condition->drawBackOfficeInputs();
$serviceId = $condition->getServiceId();
} else {
$html = '';
$serviceId = '';
}
return $this->render(
'coupon/condition-input-ajax',
[
'inputsDrawn' => $html,
'conditionServiceId' => $serviceId,
'conditionIndex' => ''
]
);
}
/**
* Manage Coupons read display
*
* @param int $couponId Coupon id being updated
* @param int $conditionIndex Coupon Condition position in the collection
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function getConditionToUpdateInputAjaxAction($couponId, $conditionIndex)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$conditions = $couponManager->getConditions();
if (!isset($conditions[$conditionIndex])) {
return $this->pageNotFound();
}
/** @var ConditionInterface $condition */
$condition = $conditions[$conditionIndex];
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromConditionInterface($condition);
if ($inputs === null) {
return $this->pageNotFound();
}
return $this->render(
'coupon/condition-input-ajax',
[
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => $conditionIndex,
]
);
}
/**
* Manage Coupons read display
*
* @param int $couponId Coupon id
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function saveConditionsAction($couponId)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
$conditionToSave = $this->buildConditionFromRequest();
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$conditions = $couponManager->getConditions();
$conditionIndex = $this->getRequest()->request->get('conditionIndex');
if ($conditionIndex >= 0) {
// Update mode
$conditions[$conditionIndex] = $conditionToSave;
} else {
// Insert mode
$conditions[] = $conditionToSave;
}
$couponManager->setConditions($conditions);
$this->manageConditionUpdate($coupon, $conditions);
return new Response();
}
/**
* Manage Coupons condition deleteion
*
* @param int $couponId Coupon id
* @param int $conditionIndex Coupon condition index in the collection
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function deleteConditionsAction($couponId, $conditionIndex)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
$search = CouponQuery::create();
/** @var Coupon $coupon */
$coupon = $search->findOneById($couponId);
if (!$coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$conditions = $couponManager->getConditions();
unset($conditions[$conditionIndex]);
$couponManager->setConditions($conditions);
$this->manageConditionUpdate($coupon, $conditions);
return new Response();
}
/**
* Log error message
*
* @param string $action Creation|Update|Delete
* @param string $message Message to log
* @param \Exception $e Exception to log
*
* @return $this
*/
protected function logError($action, $message, $e)
{
Tlog::getInstance()->error(
sprintf(
'Error during Coupon ' . $action . ' process : %s. Exception was %s',
$message,
$e->getMessage()
)
);
return $this;
}
/**
* Validate the CreateOrUpdate form
*
* @param string $eventToDispatch Event which will activate actions
* @param string $log created|edited
* @param string $action creation|edition
* @param Coupon $model Model if in update mode
*
* @return $this
*/
protected function validateCreateOrUpdateForm($eventToDispatch, $log, $action, Coupon $model = null)
{
// Create the form from the request
$couponForm = $this->getForm($action, $model);
$response = null;
$message = false;
try {
// Check the form against conditions violations
$form = $this->validateForm($couponForm, 'POST');
$couponEvent = $this->feedCouponCreateOrUpdateEvent($form, $model);
// Dispatch Event to the Action
$this->dispatch(
$eventToDispatch,
$couponEvent
);
$this->adminLogAppend(
AdminResources::COUPON,
AccessManager::UPDATE,
sprintf(
'Coupon %s (ID ) ' . $log,
$couponEvent->getTitle(),
$couponEvent->getCouponModel()->getId()
),
$couponEvent->getCouponModel()->getId()
);
if ($this->getRequest()->get('save_mode') == 'stay') {
$response = RedirectResponse::create(str_replace(
'{id}',
$couponEvent->getCouponModel()->getId(),
$couponForm->getSuccessUrl()
));
} else {
// Redirect to the success URL
$response = RedirectResponse::create(
URL::getInstance()->absoluteUrl($this->getRoute('admin.coupon.list'))
);
}
} catch (FormValidationException $ex) {
// Invalid data entered
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$message = $this->getTranslator()->trans('Sorry, an error occurred: %err', ['%err' => $ex->getMessage()]);
$this->logError($action, $message, $ex);
}
if ($message !== false) {
// Mark the form as with error
$couponForm->setErrorMessage($message);
// Send the form and the error to the parser
$this->getParserContext()
->addForm($couponForm)
->setGeneralError($message);
}
return $response;
}
/**
* Get all available conditions
*
* @return array
*/
protected function getAvailableConditions()
{
/** @var CouponManager $couponManager */
$couponManager = $this->container->get('thelia.coupon.manager');
$availableConditions = $couponManager->getAvailableConditions();
$cleanedConditions = [];
/** @var ConditionInterface $availableCondition */
foreach ($availableConditions as $availableCondition) {
$condition = [];
$condition['serviceId'] = $availableCondition->getServiceId();
$condition['name'] = $availableCondition->getName();
$condition['toolTip'] = $availableCondition->getToolTip();
$cleanedConditions[] = $condition;
}
return $cleanedConditions;
}
/**
* Get all available coupons
*
* @return array
*/
protected function getAvailableCoupons()
{
/** @var CouponManager $couponManager */
$couponManager = $this->container->get('thelia.coupon.manager');
$availableCoupons = $couponManager->getAvailableCoupons();
$cleanedCoupons = [];
/** @var CouponInterface $availableCoupon */
foreach ($availableCoupons as $availableCoupon) {
$condition = [];
$condition['serviceId'] = $availableCoupon->getServiceId();
$condition['name'] = $availableCoupon->getName();
$condition['toolTip'] = $availableCoupon->getToolTip();
$cleanedCoupons[] = $condition;
}
return $cleanedCoupons;
}
/**
* Clean condition for template
*
* @param ConditionCollection $conditions Condition collection
*
* @return array
*/
protected function cleanConditionForTemplate(ConditionCollection $conditions)
{
$cleanedConditions = [];
/** @var $condition ConditionInterface */
foreach ($conditions as $index => $condition) {
$temp = [
'serviceId' => $condition->getServiceId(),
'index' => $index,
'name' => $condition->getName(),
'toolTip' => $condition->getToolTip(),
'summary' => $condition->getSummary(),
'validators' => $condition->getValidators()
];
$cleanedConditions[] = $temp;
}
return $cleanedConditions;
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon effect
*
* @param string $couponServiceId Coupon service id
*
* @return ResponseRest
*/
public function getBackOfficeInputsAjaxAction($couponServiceId)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
if (! empty($couponServiceId)) {
$this->checkXmlHttpRequest();
/** @var CouponInterface $coupon */
$couponManager = $this->container->get($couponServiceId);
if (!$couponManager instanceof CouponInterface) {
$this->pageNotFound();
}
$response = new ResponseRest($couponManager->drawBackOfficeInputs(), 'text');
} else {
// Return an empty response if the service ID is not defined
// Typically, when the user chooses "Please select a coupon type"
$response = new ResponseRest('');
}
return $response;
}
/**
* Draw the input displayed in the BackOffice
* allowing Admin to set its Coupon effect
*
* @param int $couponId Coupon id
*
* @return ResponseRest
*/
public function getBackOfficeConditionSummariesAjaxAction($couponId)
{
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::VIEW)) {
return $response;
}
$this->checkXmlHttpRequest();
/** @var Coupon $coupon */
$coupon = CouponQuery::create()->findPk($couponId);
if (null === $coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
$couponFactory = $this->container->get('thelia.coupon.factory');
$couponManager = $couponFactory->buildCouponFromModel($coupon);
if (!$couponManager instanceof CouponInterface) {
return $this->pageNotFound();
}
$args = [];
$args['conditions'] = $this->cleanConditionForTemplate($couponManager->getConditions());
return $this->render('coupon/conditions', $args);
}
/**
* Feed the Coupon Create or Update event with the User inputs
*
* @param Form $form Form containing user data
* @param Coupon $model Model if in update mode
*
* @return CouponCreateOrUpdateEvent
*/
protected function feedCouponCreateOrUpdateEvent(Form $form, Coupon $model = null)
{
// Get the form field values
$data = $form->getData();
$serviceId = $data['type'];
/** @var CouponInterface $coupon */
$coupon = $this->container->get($serviceId);
$couponEvent = new CouponCreateOrUpdateEvent(
$data['code'],
$serviceId,
$data['title'],
$coupon->getEffects($data),
$data['shortDescription'],
$data['description'],
$data['isEnabled'],
\DateTime::createFromFormat($this->getDefaultDateFormat(), $data['expirationDate']),
$data['isAvailableOnSpecialOffers'],
$data['isCumulative'],
$data['isRemovingPostage'],
$data['maxUsage'],
$data['locale'],
$data['freeShippingForCountries'],
$data['freeShippingForModules'],
$data['perCustomerUsageCount'],
empty($data['startDate']) ? null : \DateTime::createFromFormat($this->getDefaultDateFormat(), $data['startDate'])
);
// If Update mode
if (isset($model)) {
$couponEvent->setCouponModel($model);
}
return $couponEvent;
}
/**
* Build ConditionInterface from request
*
* @return ConditionInterface
*/
protected function buildConditionFromRequest()
{
$request = $this->getRequest();
$post = $request->request->getIterator();
$serviceId = $request->request->get('categoryCondition');
$operators = [];
$values = [];
foreach ($post as $key => $input) {
if (isset($input['operator']) && isset($input['value'])) {
$operators[$key] = $input['operator'];
$values[$key] = $input['value'];
}
}
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$conditionToSave = $conditionFactory->build($serviceId, $operators, $values);
return $conditionToSave;
}
/**
* Manage how a Condition is updated
*
* @param Coupon $coupon Coupon Model
* @param ConditionCollection $conditions Condition collection
*/
protected function manageConditionUpdate(Coupon $coupon, ConditionCollection $conditions)
{
$couponEvent = new CouponCreateOrUpdateEvent(
$coupon->getCode(),
$coupon->getType(),
$coupon->getTitle(),
$coupon->getEffects(),
$coupon->getShortDescription(),
$coupon->getDescription(),
$coupon->getIsEnabled(),
$coupon->getExpirationDate(),
$coupon->getIsAvailableOnSpecialOffers(),
$coupon->getIsCumulative(),
$coupon->getIsRemovingPostage(),
$coupon->getMaxUsage(),
$coupon->getLocale(),
$coupon->getFreeShippingForCountries(),
$coupon->getFreeShippingForModules(),
$coupon->getPerCustomerUsageCount(),
$coupon->getStartDate()
);
$couponEvent->setCouponModel($coupon);
$couponEvent->setConditions($conditions);
$eventToDispatch = TheliaEvents::COUPON_CONDITION_UPDATE;
// Dispatch Event to the Action
$this->dispatch(
$eventToDispatch,
$couponEvent
);
$this->adminLogAppend(
AdminResources::COUPON,
AccessManager::UPDATE,
sprintf(
'Coupon %s (ID %s) conditions updated',
$couponEvent->getCouponModel()->getTitle(),
$couponEvent->getCouponModel()->getType()
),
$couponEvent->getCouponModel()->getId()
);
}
protected function getDefaultDateFormat()
{
return LangQuery::create()->findOneByByDefault(true)->getDatetimeFormat();
}
/**
* @param string $action
* @param Coupon|null $coupon
* @return \Thelia\Form\BaseForm
*/
protected function getForm($action, $coupon)
{
$data = array();
if (null !== $coupon) {
$data["code"] = $coupon->getCode();
}
return $this->createForm(AdminForm::COUPON_CREATION, "form", $data, [
'validation_groups' => ["Default", $action]
]);
}
public function deleteAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::COUPON, [], AccessManager::DELETE)) {
return $response;
}
try {
// Check token
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get("_token")
);
// Retrieve coupon
$coupon = CouponQuery::create()
->findPk($couponId = $this->getRequest()->request->get("coupon_id"))
;
$deleteEvent = new CouponDeleteEvent($couponId, $coupon);
$this->dispatch(TheliaEvents::COUPON_DELETE, $deleteEvent);
if (null !== $deletedObject = $deleteEvent->getCoupon()) {
$this->adminLogAppend(
AdminResources::COUPON,
AccessManager::DELETE,
sprintf(
"Coupon %s (ID %s) deleted",
$deletedObject->getCode(),
$deletedObject->getId()
),
$deletedObject->getId()
);
}
return $response = RedirectResponse::create(
URL::getInstance()->absoluteUrl($this->getRoute('admin.coupon.list'))
);
} catch (\Exception $e) {
$this->getParserContext()
->setGeneralError($e->getMessage())
;
return $this->browseAction();
}
}
}

View File

@@ -0,0 +1,265 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Currency\CurrencyCreateEvent;
use Thelia\Core\Event\Currency\CurrencyDeleteEvent;
use Thelia\Core\Event\Currency\CurrencyUpdateEvent;
use Thelia\Core\Event\Currency\CurrencyUpdateRateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Currency;
use Thelia\Model\CurrencyQuery;
/**
* Manages currencies
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class CurrencyController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'currency',
'manual',
'order',
AdminResources::CURRENCY,
TheliaEvents::CURRENCY_CREATE,
TheliaEvents::CURRENCY_UPDATE,
TheliaEvents::CURRENCY_DELETE,
null, // No visibility toggle
TheliaEvents::CURRENCY_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::CURRENCY_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::CURRENCY_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new CurrencyCreateEvent();
$createEvent
->setCurrencyName($formData['name'])
->setLocale($formData["locale"])
->setSymbol($formData['symbol'])
->setFormat($formData['format'])
->setCode($formData['code'])
->setRate($formData['rate'])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new CurrencyUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setCurrencyName($formData['name'])
->setLocale($formData["locale"])
->setSymbol($formData['symbol'])
->setFormat($formData['format'])
->setCode($formData['code'])
->setRate($formData['rate'])
;
return $changeEvent;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('currency_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new CurrencyDeleteEvent($this->getRequest()->get('currency_id'));
}
protected function eventContainsObject($event)
{
return $event->hasCurrency();
}
protected function hydrateObjectForm($object)
{
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'name' => $object->getName(),
'locale' => $object->getLocale(),
'code' => $object->getCode(),
'symbol' => $object->getSymbol(),
'format' => $object->getFormat(),
'rate' => $object->getRate()
);
// Setup the object form
return $this->createForm(AdminForm::CURRENCY_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasCurrency() ? $event->getCurrency() : null;
}
protected function getExistingObject()
{
$currency = CurrencyQuery::create()
->findOneById($this->getRequest()->get('currency_id'));
if (null !== $currency) {
$currency->setLocale($this->getCurrentEditionLocale());
}
return $currency;
}
/**
* @param Currency $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getName();
}
/**
* @param Currency $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('currencies', array('order' => $currentOrder));
}
protected function renderEditionTemplate()
{
return $this->render('currency-edit', array('currency_id' => $this->getRequest()->get('currency_id')));
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.currencies.update",
[
'currency_id' => $this->getRequest()->get('currency_id'),
]
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.currencies.default');
}
/**
* Update currencies rates
*/
public function updateRatesAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
try {
$event = new CurrencyUpdateRateEvent();
$this->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES, $event);
if ($event->hasUndefinedRates()) {
return $this->render('currencies', [
'undefined_rates' => $event->getUndefinedRates()
]);
}
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
/**
* Sets the default currency
*/
public function setDefaultAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$changeEvent = new CurrencyUpdateEvent((int) $this->getRequest()->get('currency_id', 0));
// Create and dispatch the change event
$changeEvent->setIsDefault(true)->setVisible(1);
try {
$this->dispatch(TheliaEvents::CURRENCY_SET_DEFAULT, $changeEvent);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
/**
* Sets if the currency is visible for Front
*/
public function setVisibleAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$changeEvent = new CurrencyUpdateEvent((int) $this->getRequest()->get('currency_id', 0));
// Create and dispatch the change event
$changeEvent->setVisible((int) $this->getRequest()->get('visible', 0));
try {
$this->dispatch(TheliaEvents::CURRENCY_SET_VISIBLE, $changeEvent);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
}

View File

@@ -0,0 +1,254 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
use Thelia\Core\Event\Customer\CustomerEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Exception\CustomerException;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Customer;
use Thelia\Model\CustomerQuery;
use Thelia\Tools\Password;
/**
* Class CustomerController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class CustomerController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'customer',
'lastname',
'customer_order',
AdminResources::CUSTOMER,
TheliaEvents::CUSTOMER_CREATEACCOUNT,
TheliaEvents::CUSTOMER_UPDATEACCOUNT,
TheliaEvents::CUSTOMER_DELETEACCOUNT
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::CUSTOMER_CREATE);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::CUSTOMER_UPDATE);
}
protected function getCreationEvent($formData)
{
$event = $this->createEventInstance($formData);
// Create a secure password
$event->setPassword(Password::generateRandom(8));
// We will notify the customer of account creation
$event->setNotifyCustomerOfAccountCreation(true);
return $event;
}
protected function getUpdateEvent($formData)
{
$event = $this->createEventInstance($formData);
$event->setCustomer($this->getExistingObject());
// We allow customer email modification
$event->setEmailUpdateAllowed(true);
return $event;
}
protected function getDeleteEvent()
{
return new CustomerEvent($this->getExistingObject());
}
protected function eventContainsObject($event)
{
return $event->hasCustomer();
}
/**
* @param Customer $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
// Get default adress of the customer
$address = $object->getDefaultAddress();
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'firstname' => $object->getFirstname(),
'lastname' => $object->getLastname(),
'email' => $object->getEmail(),
'lang_id' => $object->getLangId(),
'title' => $object->getTitleId(),
'discount' => $object->getDiscount(),
'reseller' => $object->getReseller() ? true : false,
);
if ($address !== null) {
$data['company'] = $address->getCompany();
$data['address1'] = $address->getAddress1();
$data['address2'] = $address->getAddress2();
$data['address3'] = $address->getAddress3();
$data['phone'] = $address->getPhone();
$data['cellphone'] = $address->getCellphone();
$data['zipcode'] = $address->getZipcode();
$data['city'] = $address->getCity();
$data['country'] = $address->getCountryId();
$data['state'] = $address->getStateId();
}
// A loop is used in the template
return $this->createForm(AdminForm::CUSTOMER_UPDATE, 'form', $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasCustomer() ? $event->getCustomer() : null;
}
/**
* @param $data
* @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent
*/
private function createEventInstance($data)
{
// Use current language if it is not defined in the form
if (empty($data["lang_id"])) {
$data["lang_id"] = $this->getSession()->getLang()->getId();
}
$customerCreateEvent = new CustomerCreateOrUpdateEvent(
$data["title"],
$data["firstname"],
$data["lastname"],
$data["address1"],
$data["address2"],
$data["address3"],
$data["phone"],
$data["cellphone"],
$data["zipcode"],
$data["city"],
$data["country"],
isset($data["email"])?$data["email"]:null,
isset($data["password"]) && ! empty($data["password"]) ? $data["password"]:null,
$data["lang_id"],
isset($data["reseller"])?$data["reseller"]:null,
isset($data["sponsor"])?$data["sponsor"]:null,
isset($data["discount"])?$data["discount"]:null,
isset($data["company"])?$data["company"]:null,
null,
$data["state"]
);
return $customerCreateEvent;
}
protected function getExistingObject()
{
return CustomerQuery::create()->findPk($this->getRequest()->get('customer_id', 0));
}
/**
* @param Customer $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getRef() . "(".$object->getLastname()." ".$object->getFirstname().")";
}
/**
* @param Customer $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getEditionArguments()
{
return array(
'customer_id' => $this->getRequest()->get('customer_id', 0),
'page' => $this->getRequest()->get('page', 1),
'page_order' => $this->getRequest()->get('page_order', 1)
);
}
protected function renderListTemplate($currentOrder, $customParams = array())
{
return $this->render(
'customers',
array_merge(array(
'customer_order' => $currentOrder,
'page' => $this->getRequest()->get('page', 1)
), $customParams)
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
'admin.customers',
[
'page' => $this->getRequest()->get('page', 1)
]
);
}
protected function renderEditionTemplate()
{
return $this->render('customer-edit', $this->getEditionArguments());
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.customer.update.view",
$this->getEditionArguments()
);
}
public function deleteAction()
{
$errorMsg = "No error.";
$removalError = false;
try {
parent::deleteAction();
} catch (CustomerException $e) {
$errorMsg = $e->getMessage();
$removalError = true;
}
return $this->renderListTemplate($this->getCurrentListOrder(), [
"removal_error" => $removalError,
"error_message" => $errorMsg
]);
}
}

View File

@@ -0,0 +1,249 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Thelia\Core\DependencyInjection\Compiler\RegisterArchiverPass;
use Thelia\Core\DependencyInjection\Compiler\RegisterSerializerPass;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\LangQuery;
/**
* Class ExportController
* @author Jérôme Billiras <jbilliras@openstudio.fr>
*/
class ExportController extends BaseAdminController
{
/**
* Handle default action, that is, list available exports
*
* @param string $_view View to render
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function indexAction($_view = 'export')
{
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::VIEW]);
if ($authResponse !== null) {
return $authResponse;
}
$this->getParserContext()
->set('category_order', $this->getRequest()->query->get('category_order', 'manual'))
->set('export_order', $this->getRequest()->query->get('export_order', 'manual'))
;
return $this->render($_view);
}
/**
* Handle export position change action
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeExportPositionAction()
{
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
$query = $this->getRequest()->query;
$this->dispatch(
TheliaEvents::EXPORT_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
return $this->generateRedirectFromRoute('export.list');
}
/**
* Handle export category position change action
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeCategoryPositionAction()
{
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
$query = $this->getRequest()->query;
$this->dispatch(
TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
return $this->generateRedirectFromRoute('export.list');
}
/**
* Match position mode string against position mode constant value
*
* @param null|string $mode Position mode string
*
* @return integer Position mode constant value
*/
protected function matchPositionMode($mode)
{
if ($mode === 'up') {
return UpdatePositionEvent::POSITION_UP;
}
if ($mode === 'down') {
return UpdatePositionEvent::POSITION_DOWN;
}
return UpdatePositionEvent::POSITION_ABSOLUTE;
}
/**
* Display export configuration view
*
* @param integer $id An export identifier
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function configureAction($id)
{
/** @var \Thelia\Handler\Exporthandler $exportHandler */
$exportHandler = $this->container->get('thelia.export.handler');
$export = $exportHandler->getExport($id);
if ($export === null) {
return $this->pageNotFound();
}
// Render standard view or ajax one
$templateName = 'export-page';
if ($this->getRequest()->isXmlHttpRequest()) {
$templateName = 'ajax/export-modal';
}
return $this->render(
$templateName,
[
'exportId' => $id,
'hasImages' => $export->hasImages(),
'hasDocuments' => $export->hasDocuments(),
'useRange' => $export->useRangeDate()
]
);
}
/**
* Handle export action
*
* @param integer $id An export identifier
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function exportAction($id)
{
/** @var \Thelia\Handler\Exporthandler $exportHandler */
$exportHandler = $this->container->get('thelia.export.handler');
$export = $exportHandler->getExport($id);
if ($export === null) {
return $this->pageNotFound();
}
$form = $this->createForm(AdminForm::EXPORT);
try {
$validatedForm = $this->validateForm($form);
set_time_limit(0);
$lang = (new LangQuery)->findPk($validatedForm->get('language')->getData());
/** @var \Thelia\Core\Serializer\SerializerManager $serializerManager */
$serializerManager = $this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID);
$serializer = $serializerManager->get($validatedForm->get('serializer')->getData());
$archiver = null;
if ($validatedForm->get('do_compress')->getData()) {
/** @var \Thelia\Core\Archiver\ArchiverManager $archiverManager */
$archiverManager = $this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID);
$archiver = $archiverManager->get($validatedForm->get('archiver')->getData());
}
$rangeDate = null;
if ($validatedForm->get('range_date_start')->getData()
&& $validatedForm->get('range_date_end')->getData()
) {
$rangeDate = [
'start' => $validatedForm->get('range_date_start')->getData(),
'end' =>$validatedForm->get('range_date_end')->getData()
];
}
$exportEvent = $exportHandler->export(
$export,
$serializer,
$archiver,
$lang,
$validatedForm->get('images')->getData(),
$validatedForm->get('documents')->getData(),
$rangeDate
);
$contentType = $exportEvent->getSerializer()->getMimeType();
$fileExt = $exportEvent->getSerializer()->getExtension();
if ($exportEvent->getArchiver() !== null) {
$contentType = $exportEvent->getArchiver()->getMimeType();
$fileExt = $exportEvent->getArchiver()->getExtension();
}
$header = [
'Content-Type' => $contentType,
'Content-Disposition' => sprintf(
'%s; filename="%s.%s"',
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$exportEvent->getExport()->getFileName(),
$fileExt
)
];
return new BinaryFileResponse($exportEvent->getFilePath(), 200, $header, false);
} catch (FormValidationException $e) {
$form->setErrorMessage($this->createStandardFormValidationErrorMessage($e));
} catch (\Exception $e) {
$this->getParserContext()->setGeneralError($e->getMessage());
}
$this->getParserContext()
->addForm($form)
;
return $this->configureAction($id);
}
}

View File

@@ -0,0 +1,185 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
use Thelia\Core\Event\Feature\FeatureAvUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\FeatureAvModificationForm;
use Thelia\Model\FeatureAv;
use Thelia\Model\FeatureAvQuery;
/**
* Manages features-av
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class FeatureAvController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'featureav',
'manual',
'order',
AdminResources::FEATURE,
TheliaEvents::FEATURE_AV_CREATE,
TheliaEvents::FEATURE_AV_UPDATE,
TheliaEvents::FEATURE_AV_DELETE,
null, // No visibility toggle
TheliaEvents::FEATURE_AV_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::FEATURE_AV_CREATION);
}
protected function getUpdateForm()
{
throw new \LogicException("Featiure Av. modification is not yet implemented");
}
protected function getCreationEvent($formData)
{
$createEvent = new FeatureAvCreateEvent();
$createEvent
->setFeatureId($formData['feature_id'])
->setTitle($formData['title'])
->setLocale($formData["locale"])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new FeatureAvUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $changeEvent;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('featureav_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new FeatureAvDeleteEvent($this->getRequest()->get('featureav_id'));
}
protected function eventContainsObject($event)
{
return $event->hasFeatureAv();
}
protected function hydrateObjectForm($object)
{
throw new \LogicException("Feature Av. modification is not yet implemented");
}
protected function getObjectFromEvent($event)
{
return $event->hasFeatureAv() ? $event->getFeatureAv() : null;
}
protected function getExistingObject()
{
$featureAv = FeatureAvQuery::create()
->findOneById($this->getRequest()->get('featureav_id', 0));
if (null !== $featureAv) {
$featureAv->setLocale($this->getCurrentEditionLocale());
}
return $featureAv;
}
/**
* @param FeatureAv $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param FeatureAv $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments()
{
return array(
'feature_id' => $this->getRequest()->get('feature_id'),
'order' => $this->getCurrentListOrder()
);
}
protected function renderListTemplate($currentOrder)
{
// We always return to the feature edition form
return $this->render(
'feature-edit',
$this->getViewArguments()
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('feature-edit', $this->getViewArguments());
}
protected function redirectToEditionTemplate()
{
// We always return to the feature edition form
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
$this->getViewArguments()
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
$this->getViewArguments()
);
}
}

View File

@@ -0,0 +1,266 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Feature\FeatureAvUpdateEvent;
use Thelia\Core\Event\Feature\FeatureCreateEvent;
use Thelia\Core\Event\Feature\FeatureDeleteEvent;
use Thelia\Core\Event\Feature\FeatureEvent;
use Thelia\Core\Event\Feature\FeatureUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Feature;
use Thelia\Model\FeatureQuery;
/**
* Manages features
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class FeatureController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'feature',
'manual',
'order',
AdminResources::FEATURE,
TheliaEvents::FEATURE_CREATE,
TheliaEvents::FEATURE_UPDATE,
TheliaEvents::FEATURE_DELETE,
null, // No visibility toggle
TheliaEvents::FEATURE_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::FEATURE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::FEATURE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new FeatureCreateEvent();
$createEvent
->setTitle($formData['title'])
->setLocale($formData["locale"])
->setAddToAllTemplates($formData['add_to_all'])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new FeatureUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $changeEvent;
}
/**
* Process the features values (fix it in future version to integrate it in the feature form as a collection)
*
* @see \Thelia\Controller\Admin\AbstractCrudController::performAdditionalUpdateAction()
*/
protected function performAdditionalUpdateAction($updateEvent)
{
$attr_values = $this->getRequest()->get('feature_values', null);
if ($attr_values !== null) {
foreach ($attr_values as $id => $value) {
$event = new FeatureAvUpdateEvent($id);
$event->setTitle($value);
$event->setLocale($this->getCurrentEditionLocale());
$this->dispatch(TheliaEvents::FEATURE_AV_UPDATE, $event);
}
}
return null;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('feature_id', null),
$positionChangeMode,
$positionValue
);
}
protected function getDeleteEvent()
{
return new FeatureDeleteEvent($this->getRequest()->get('feature_id'));
}
protected function eventContainsObject($event)
{
return $event->hasFeature();
}
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum()
);
// Setup the object form
return $this->createForm(AdminForm::FEATURE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasFeature() ? $event->getFeature() : null;
}
protected function getExistingObject()
{
$feature = FeatureQuery::create()
->findOneById($this->getRequest()->get('feature_id', 0));
if (null !== $feature) {
$feature->setLocale($this->getCurrentEditionLocale());
}
return $feature;
}
/**
* @param Feature $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Feature $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('features', array('order' => $currentOrder));
}
protected function renderEditionTemplate()
{
return $this->render(
'feature-edit',
array(
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
)
);
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
[
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
]
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.features.default');
}
/**
* Get the Feature value list order.
*
* @return string the current list order
*/
protected function getFeatureAvListOrder()
{
return $this->getListOrderFromSession(
'featureav',
'featureav_order',
'manual'
);
}
/**
* Add or Remove from all product templates
*/
protected function addRemoveFromAllTemplates($eventType)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
try {
if (null !== $object = $this->getExistingObject()) {
$event = new FeatureEvent($object);
$this->dispatch($eventType, $event);
}
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
/**
* Remove from all product templates
*/
public function removeFromAllTemplates()
{
return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_REMOVE_FROM_ALL_TEMPLATES);
}
/**
* Add to all product templates
*/
public function addToAllTemplates()
{
return $this->addRemoveFromAllTemplates(TheliaEvents::FEATURE_ADD_TO_ALL_TEMPLATES);
}
}

View File

@@ -0,0 +1,866 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Propel\Runtime\Exception\PropelException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Thelia\Core\Event\File\FileCreateOrUpdateEvent;
use Thelia\Core\Event\File\FileDeleteEvent;
use Thelia\Core\Event\File\FileToggleVisibilityEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdateFilePositionEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Files\Exception\ProcessFileException;
use Thelia\Files\FileConfiguration;
use Thelia\Files\FileManager;
use Thelia\Files\FileModelInterface;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\Lang;
use Thelia\Tools\Rest\ResponseRest;
use Thelia\Tools\URL;
/**
* Created by JetBrains PhpStorm.
* Date: 8/19/13
* Time: 3:24 PM
*
* Control View and Action (Model) via Events
* Control Files and Images
*
* @package File
* @author Guillaume MOREL <gmorel@openstudio.fr>
*
*/
class FileController extends BaseAdminController
{
const MODULE_RIGHT = "thelia";
/**
* Get the FileManager
*
* @return FileManager
*/
public function getFileManager()
{
return $this->container->get('thelia.file_manager');
}
/**
* Manage how a file collection has to be saved
*
* @param int $parentId Parent id owning files being saved
* @param string $parentType Parent Type owning files being saved (product, category, content, etc.)
* @param string $objectType Object type, e.g. image or document
* @param array $validMimeTypes an array of valid mime types. If empty, any mime type is allowed.
* @param array $extBlackList an array of blacklisted extensions.
* @return Response
*/
public function saveFileAjaxAction(
$parentId,
$parentType,
$objectType,
$validMimeTypes = array(),
$extBlackList = array()
) {
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
if ($this->getRequest()->isMethod('POST')) {
/** @var UploadedFile $fileBeingUploaded */
$fileBeingUploaded = $this->getRequest()->files->get('file');
try {
$this->processFile(
$fileBeingUploaded,
$parentId,
$parentType,
$objectType,
$validMimeTypes,
$extBlackList
);
} catch (ProcessFileException $e) {
return new ResponseRest($e->getMessage(), 'text', $e->getCode());
}
return new ResponseRest(array('status' => true, 'message' => ''));
}
return new Response('', 404);
}
/**
* Process file uploaded
*
* @param UploadedFile $fileBeingUploaded
* @param int $parentId
* @param string $parentType
* @param string $objectType
* @param array $validMimeTypes
* @param array $extBlackList
* @return ResponseRest
*
* @deprecated since version 2.3, to be removed in 2.6. Please use the process method File present in the same class.
*/
public function processImage(
$fileBeingUploaded,
$parentId,
$parentType,
$objectType,
$validMimeTypes = array(),
$extBlackList = array()
) {
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 2.6. Please use the process method File present in the same class.', E_USER_DEPRECATED);
return $this->processFile($fileBeingUploaded, $parentId, $parentType, $objectType, $validMimeTypes, $extBlackList);
}
/**
* Process file uploaded
*
* @param UploadedFile $fileBeingUploaded
* @param int $parentId Parent id owning files being saved
* @param string $parentType Parent Type owning files being saved (product, category, content, etc.)
* @param string $objectType Object type, e.g. image or document
* @param array $validMimeTypes an array of valid mime types. If empty, any mime type is allowed.
* @param array $extBlackList an array of blacklisted extensions.
* @return ResponseRest
*
* @since 2.3
*/
public function processFile(
$fileBeingUploaded,
$parentId,
$parentType,
$objectType,
$validMimeTypes = array(),
$extBlackList = array()
) {
$fileManager = $this->getFileManager();
// Validate if file is too big
if ($fileBeingUploaded->getError() == 1) {
$message = $this->getTranslator()
->trans(
'File is too large, please retry with a file having a size less than %size%.',
array('%size%' => ini_get('upload_max_filesize')),
'core'
);
throw new ProcessFileException($message, 403);
}
$message = null;
$realFileName = $fileBeingUploaded->getClientOriginalName();
if (! empty($validMimeTypes)) {
$mimeType = $fileBeingUploaded->getMimeType();
if (!isset($validMimeTypes[$mimeType])) {
$message = $this->getTranslator()
->trans(
'Only files having the following mime type are allowed: %types%',
[ '%types%' => implode(', ', array_keys($validMimeTypes))]
);
} else {
$regex = "#^(.+)\.(".implode("|", $validMimeTypes[$mimeType]).")$#i";
if (!preg_match($regex, $realFileName)) {
$message = $this->getTranslator()
->trans(
"There's a conflict between your file extension \"%ext\" and the mime type \"%mime\"",
[
'%mime' => $mimeType,
'%ext' => $fileBeingUploaded->getClientOriginalExtension()
]
);
}
}
}
if (!empty($extBlackList)) {
$regex = "#^(.+)\.(".implode("|", $extBlackList).")$#i";
if (preg_match($regex, $realFileName)) {
$message = $this->getTranslator()
->trans(
'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it',
[
'%extension' => $fileBeingUploaded->getClientOriginalExtension(),
]
);
}
}
if ($message !== null) {
throw new ProcessFileException($message, 415);
}
$fileModel = $fileManager->getModelInstance($objectType, $parentType);
$parentModel = $fileModel->getParentFileModel();
if ($parentModel === null || $fileModel === null || $fileBeingUploaded === null) {
throw new ProcessFileException('', 404);
}
$defaultTitle = $parentModel->getTitle();
if (empty($defaultTitle) && $objectType !== 'image') {
$defaultTitle = $fileBeingUploaded->getClientOriginalName();
}
$fileModel
->setParentId($parentId)
->setLocale(Lang::getDefaultLanguage()->getLocale())
->setTitle($defaultTitle)
;
$fileCreateOrUpdateEvent = new FileCreateOrUpdateEvent($parentId);
$fileCreateOrUpdateEvent->setModel($fileModel);
$fileCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded);
$fileCreateOrUpdateEvent->setParentName($parentModel->getTitle());
// Dispatch Event to the Action
$this->dispatch(
TheliaEvents::IMAGE_SAVE,
$fileCreateOrUpdateEvent
);
$this->adminLogAppend(
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
$this->getTranslator()->trans(
'Saving %obj% for %parentName% parent id %parentId%',
array(
'%parentName%' => $fileCreateOrUpdateEvent->getParentName(),
'%parentId%' => $fileCreateOrUpdateEvent->getParentId(),
'%obj%' => $objectType
)
)
);
//return new ResponseRest(array('status' => true, 'message' => ''));
return $fileCreateOrUpdateEvent;
}
/**
* Manage how a image collection has to be saved
*
* @param int $parentId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function saveImageAjaxAction($parentId, $parentType)
{
$config = FileConfiguration::getImageConfig();
return $this->saveFileAjaxAction(
$parentId,
$parentType,
$config['objectType'],
$config['validMimeTypes'],
$config['extBlackList']
);
}
/**
* Manage how a document collection has to be saved
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function saveDocumentAjaxAction($parentId, $parentType)
{
$config = FileConfiguration::getDocumentConfig();
return $this->saveFileAjaxAction(
$parentId,
$parentType,
$config['objectType'],
$config['validMimeTypes'],
$config['extBlackList']
);
}
/**
* Manage how a image list will be displayed in AJAX
*
* @param int $parentId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function getImageListAjaxAction($parentId, $parentType)
{
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$successUrl = $this->getRequest()->get('successUrl');
$args = [
'imageType' => $parentType,
'parentId' => $parentId,
'successUrl' => $successUrl
];
return $this->render('includes/image-upload-list-ajax', $args);
}
/**
* Manage how a document list will be displayed in AJAX
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function getDocumentListAjaxAction($parentId, $parentType)
{
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
return $this->render('includes/document-upload-list-ajax', $args);
}
/**
* Manage how an image list will be uploaded in AJAX
*
* @param int $parentId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function getImageFormAjaxAction($parentId, $parentType)
{
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$successUrl = $this->getRequest()->get('successUrl');
$args = [
'imageType' => $parentType,
'parentId' => $parentId,
'successUrl' => $successUrl
];
return $this->render('includes/image-upload-form', $args);
}
/**
* Manage how an document list will be uploaded in AJAX
*
* @param int $parentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function getDocumentFormAjaxAction($parentId, $parentType)
{
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
return $this->render('includes/document-upload-form', $args);
}
/**
* Manage how an image is viewed
*
* @param int $imageId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function viewImageAction($imageId, $parentType)
{
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$fileManager = $this->getFileManager();
$imageModel = $fileManager->getModelInstance('image', $parentType);
$image = $imageModel->getQueryInstance()->findPk($imageId);
$redirectUrl = $image->getRedirectionUrl();
return $this->render('image-edit', array(
'imageId' => $imageId,
'imageType' => $parentType,
'redirectUrl' => $redirectUrl,
'formId' => $imageModel->getUpdateFormId(),
'breadcrumb' => $image->getBreadcrumb(
$this->getRouter($this->getCurrentRouter()),
$this->container,
'images',
$this->getCurrentEditionLocale()
)
));
}
/**
* Manage how an document is viewed
*
* @param int $documentId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function viewDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$fileManager = $this->getFileManager();
$documentModel = $fileManager->getModelInstance('document', $parentType);
$document = $documentModel->getQueryInstance()->findPk($documentId);
$redirectUrl = $document->getRedirectionUrl();
return $this->render('document-edit', array(
'documentId' => $documentId,
'documentType' => $parentType,
'redirectUrl' => $redirectUrl,
'formId' => $documentModel->getUpdateFormId(),
'breadcrumb' => $document->getBreadcrumb(
$this->getRouter($this->getCurrentRouter()),
$this->container,
'documents',
$this->getCurrentEditionLocale()
)
));
}
/**
* Manage how a file is updated
*
* @param int $fileId File identifier
* @param string $parentType Parent Type owning file being saved
* @param string $objectType the type of the file, image or document
* @param string $eventName the event type.
*
* @return FileModelInterface
*/
protected function updateFileAction($fileId, $parentType, $objectType, $eventName)
{
$message = false;
$fileManager = $this->getFileManager();
$fileModelInstance = $fileManager->getModelInstance($objectType, $parentType);
$fileUpdateForm = $this->createForm($fileModelInstance->getUpdateFormId());
/** @var FileModelInterface $file */
$file = $fileModelInstance->getQueryInstance()->findPk($fileId);
try {
$oldFile = clone $file;
if (null === $file) {
throw new \InvalidArgumentException(sprintf('%d %s id does not exist', $fileId, $objectType));
}
$data = $this->validateForm($fileUpdateForm)->getData();
$event = new FileCreateOrUpdateEvent(null);
if (array_key_exists('visible', $data)) {
$file->setVisible($data['visible'] ? 1 : 0);
}
$file->setLocale($data['locale']);
if (array_key_exists('title', $data)) {
$file->setTitle($data['title']);
}
if (array_key_exists('chapo', $data)) {
$file->setChapo($data['chapo']);
}
if (array_key_exists('description', $data)) {
$file->setDescription($data['description']);
}
if (array_key_exists('postscriptum', $data)) {
$file->setPostscriptum($data['postscriptum']);
}
if (isset($data['file'])) {
$file->setFile($data['file']);
}
$event->setModel($file);
$event->setOldModel($oldFile);
$files = $this->getRequest()->files;
$fileForm = $files->get($fileUpdateForm->getName());
if (isset($fileForm['file'])) {
$event->setUploadedFile($fileForm['file']);
}
$this->dispatch($eventName, $event);
$fileUpdated = $event->getModel();
$this->adminLogAppend(
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
sprintf(
'%s with Ref %s (ID %d) modified',
ucfirst($objectType),
$fileUpdated->getTitle(),
$fileUpdated->getId()
),
$fileUpdated->getId()
);
if ($this->getRequest()->get('save_mode') == 'close') {
if ($objectType == 'document') {
$tab = 'documents';
} else {
$tab = 'images';
}
return $this->generateRedirect(
URL::getInstance()->absoluteUrl($file->getRedirectionUrl(), ['current_tab' => $tab])
);
} else {
return $this->generateSuccessRedirect($fileUpdateForm);
}
} catch (FormValidationException $e) {
$message = sprintf('Please check your input: %s', $e->getMessage());
} catch (PropelException $e) {
$message = $e->getMessage();
} catch (\Exception $e) {
$message = sprintf('Sorry, an error occurred: %s', $e->getMessage().' '.$e->getFile());
}
if ($message !== false) {
Tlog::getInstance()->error(sprintf('Error during %s editing : %s.', $objectType, $message));
$fileUpdateForm->setErrorMessage($message);
$this->getParserContext()
->addForm($fileUpdateForm)
->setGeneralError($message);
}
return $file;
}
/**
* Manage how an image is updated
*
* @param int $imageId Parent id owning images being saved
* @param string $parentType Parent Type owning images being saved
*
* @return Response
*/
public function updateImageAction($imageId, $parentType)
{
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$imageInstance = $this->updateFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_UPDATE);
if ($imageInstance instanceof \Symfony\Component\HttpFoundation\Response) {
return $imageInstance;
} else {
return $this->render('image-edit', array(
'imageId' => $imageId,
'imageType' => $parentType,
'redirectUrl' => $imageInstance->getRedirectionUrl(),
'formId' => $imageInstance->getUpdateFormId()
));
}
}
/**
* Manage how an document is updated
*
* @param int $documentId Parent id owning documents being saved
* @param string $parentType Parent Type owning documents being saved
*
* @return Response
*/
public function updateDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$documentInstance = $this->updateFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_UPDATE);
if ($documentInstance instanceof \Symfony\Component\HttpFoundation\Response) {
return $documentInstance;
} else {
return $this->render('document-edit', array(
'documentId' => $documentId,
'documentType' => $parentType,
'redirectUrl' => $documentInstance->getRedirectionUrl(),
'formId' => $documentInstance->getUpdateFormId()
));
}
}
/**
* Manage how a file has to be deleted
*
* @param int $fileId Parent id owning file being deleted
* @param string $parentType Parent Type owning file being deleted
* @param string $objectType the type of the file, image or document
* @param string $eventName the event type.
*
* @return Response
*/
public function deleteFileAction($fileId, $parentType, $objectType, $eventName)
{
$message = null;
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = $this->getFileManager();
$modelInstance = $fileManager->getModelInstance($objectType, $parentType);
$model = $modelInstance->getQueryInstance()->findPk($fileId);
if ($model == null) {
return $this->pageNotFound();
}
// Feed event
$fileDeleteEvent = new FileDeleteEvent($model);
// Dispatch Event to the Action
try {
$this->dispatch($eventName, $fileDeleteEvent);
$this->adminLogAppend(
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
$this->getTranslator()->trans(
'Deleting %obj% for %id% with parent id %parentId%',
array(
'%obj%' => $objectType,
'%id%' => $fileDeleteEvent->getFileToDelete()->getId(),
'%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(),
)
),
$fileDeleteEvent->getFileToDelete()->getId()
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Fail to delete %obj% for %id% with parent id %parentId% (Exception : %e%)',
array(
'%obj%' => $objectType,
'%id%' => $fileDeleteEvent->getFileToDelete()->getId(),
'%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(),
'%e%' => $e->getMessage()
)
);
$this->adminLogAppend(
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
$message,
$fileDeleteEvent->getFileToDelete()->getId()
);
}
if (null === $message) {
$message = $this->getTranslator()->trans(
'%obj%s deleted successfully',
['%obj%' => ucfirst($objectType)],
'image'
);
}
return new Response($message);
}
/**
* Manage how an image has to be deleted (AJAX)
*
* @param int $imageId Parent id owning image being deleted
* @param string $parentType Parent Type owning image being deleted
*
* @return Response
*/
public function deleteImageAction($imageId, $parentType)
{
return $this->deleteFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_DELETE);
}
/**
* Manage how a document has to be deleted (AJAX)
*
* @param int $documentId Parent id owning document being deleted
* @param string $parentType Parent Type owning document being deleted
*
* @return Response
*/
public function deleteDocumentAction($documentId, $parentType)
{
return $this->deleteFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_DELETE);
}
public function updateFilePositionAction($parentType, $parentId, $objectType, $eventName)
{
$message = null;
$position = $this->getRequest()->request->get('position');
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = $this->getFileManager();
$modelInstance = $fileManager->getModelInstance($objectType, $parentType);
$model = $modelInstance->getQueryInstance()->findPk($parentId);
if ($model === null || $position === null) {
return $this->pageNotFound();
}
// Feed event
$event = new UpdateFilePositionEvent(
$modelInstance->getQueryInstance($parentType),
$parentId,
UpdateFilePositionEvent::POSITION_ABSOLUTE,
$position
);
// Dispatch Event to the Action
try {
$this->dispatch($eventName, $event);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Fail to update %type% position: %err%',
[ '%type%' => $objectType, '%err%' => $e->getMessage() ]
);
}
if (null === $message) {
$message = $this->getTranslator()->trans(
'%type% position updated',
[ '%type%' => ucfirst($objectType) ]
);
}
return new Response($message);
}
public function updateImageTitleAction($imageId, $parentType)
{
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$fileManager = $this->getFileManager();
$fileModelInstance = $fileManager->getModelInstance('image', $parentType);
/** @var FileModelInterface $file */
$file = $fileModelInstance->getQueryInstance()->findPk($imageId);
$new_title = $this->getRequest()->request->get('title');
$locale = $this->getRequest()->request->get('locale');
if (!empty($new_title)) {
$file->setLocale($locale);
$file->setTitle($new_title);
$file->save();
}
return $this->generateRedirect(
URL::getInstance()->absoluteUrl($this->getRequest()->request->get('success_url'), ['current_tab' => 'images'])
);
}
public function updateImagePositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */ $parentId)
{
$imageId = $this->getRequest()->request->get('image_id');
return $this->updateFilePositionAction($parentType, $imageId, 'image', TheliaEvents::IMAGE_UPDATE_POSITION);
}
public function updateDocumentPositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */ $parentId)
{
$documentId = $this->getRequest()->request->get('document_id');
return $this->updateFilePositionAction($parentType, $documentId, 'document', TheliaEvents::DOCUMENT_UPDATE_POSITION);
}
public function toggleVisibilityFileAction($documentId, $parentType, $objectType, $eventName)
{
$message = null;
//$position = $this->getRequest()->request->get('position');
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = $this->getFileManager();
$modelInstance = $fileManager->getModelInstance($objectType, $parentType);
$model = $modelInstance->getQueryInstance()->findPk($documentId);
if ($model === null) {
return $this->pageNotFound();
}
// Feed event
$event = new FileToggleVisibilityEvent(
$modelInstance->getQueryInstance(),
$documentId
);
// Dispatch Event to the Action
try {
$this->dispatch($eventName, $event);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Fail to update %type% visibility: %err%',
[ '%type%' => $objectType, '%err%' => $e->getMessage() ]
);
}
if (null === $message) {
$message = $this->getTranslator()->trans(
'%type% visibility updated',
[ '%type%' => ucfirst($objectType) ]
);
}
return new Response($message);
}
public function toggleVisibilityDocumentAction($parentType, $documentId)
{
return $this->toggleVisibilityFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY);
}
public function toggleVisibilityImageAction($parentType, $documentId)
{
return $this->toggleVisibilityFileAction($documentId, $parentType, 'image', TheliaEvents::IMAGE_TOGGLE_VISIBILITY);
}
}

View File

@@ -0,0 +1,337 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Folder\FolderCreateEvent;
use Thelia\Core\Event\Folder\FolderDeleteEvent;
use Thelia\Core\Event\Folder\FolderToggleVisibilityEvent;
use Thelia\Core\Event\Folder\FolderUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\BaseForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Folder;
use Thelia\Model\FolderQuery;
/**
* Class FolderController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class FolderController extends AbstractSeoCrudController
{
public function __construct()
{
parent::__construct(
'folder',
'manual',
'folder_order',
AdminResources::FOLDER,
TheliaEvents::FOLDER_CREATE,
TheliaEvents::FOLDER_UPDATE,
TheliaEvents::FOLDER_DELETE,
TheliaEvents::FOLDER_TOGGLE_VISIBILITY,
TheliaEvents::FOLDER_UPDATE_POSITION,
TheliaEvents::FOLDER_UPDATE_SEO
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::FOLDER_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::FOLDER_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\Folder $object
* @return BaseForm
*/
protected function hydrateObjectForm($object)
{
// Hydrate the "SEO" tab form
$this->hydrateSeoForm($object);
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'visible' => $object->getVisible(),
'parent' => $object->getParent()
);
// Setup the object form
return $this->createForm(AdminForm::FOLDER_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return FolderCreateEvent
*/
protected function getCreationEvent($formData)
{
$creationEvent = new FolderCreateEvent();
$creationEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setVisible($formData['visible'])
->setParent($formData['parent']);
return $creationEvent;
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return FolderUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$updateEvent = new FolderUpdateEvent($formData['id']);
$updateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
->setVisible($formData['visible'])
->setParent($formData['parent'])
;
return $updateEvent;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new FolderDeleteEvent($this->getRequest()->get('folder_id'), 0);
}
/**
* @return \Thelia\Core\Event\Folder\FolderToggleVisibilityEvent|void
*/
protected function createToggleVisibilityEvent()
{
return new FolderToggleVisibilityEvent($this->getExistingObject());
}
/**
* @param $positionChangeMode
* @param $positionValue
* @return UpdatePositionEvent|void
*/
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('folder_id', null),
$positionChangeMode,
$positionValue
);
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param \Thelia\Core\Event\Folder\FolderEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasFolder();
}
/**
* Get the created object from an event.
*
* @param $event \Thelia\Core\Event\Folder\FolderEvent $event
*
* @return null|\Thelia\Model\Folder
*/
protected function getObjectFromEvent($event)
{
return $event->hasFolder() ? $event->getFolder() : null;
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
$folder = FolderQuery::create()
->findOneById($this->getRequest()->get('folder_id', 0));
if (null !== $folder) {
$folder->setLocale($this->getCurrentEditionLocale());
}
return $folder;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param Folder $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param Folder $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param int $currentOrder, if any, null otherwise.
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
// Get content order
$content_order = $this->getListOrderFromSession('content', 'content_order', 'manual');
return $this->render(
'folders',
array(
'folder_order' => $currentOrder,
'content_order' => $content_order,
'parent' => $this->getRequest()->get('parent', 0)
)
);
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('folder-edit', $this->getEditionArguments());
}
protected function getEditionArguments(Request $request = null)
{
if (null === $request) {
$request = $this->getRequest();
}
return array(
'folder_id' => $request->get('folder_id', 0),
'current_tab' => $request->get('current_tab', 'general')
);
}
/**
* @param \Thelia\Core\Event\Folder\FolderUpdateEvent $updateEvent
* @return Response|void
*/
protected function performAdditionalUpdateAction($updateEvent)
{
if ($this->getRequest()->get('save_mode') != 'stay') {
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $updateEvent->getFolder()->getParent()]
);
} else {
return null;
}
}
/**
* Put in this method post object delete processing if required.
*
* @param \Thelia\Core\Event\Folder\FolderDeleteEvent $deleteEvent the delete event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $deleteEvent->getFolder()->getParent()]
);
}
/**
* @param $event \Thelia\Core\Event\UpdatePositionEvent
* @return null|Response
*/
protected function performAdditionalUpdatePositionAction($event)
{
$folder = FolderQuery::create()->findPk($event->getObjectId());
if ($folder != null) {
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $folder->getParent()]
);
} else {
return null;
}
}
/**
* Redirect to the edition template
*
* @param Request|null $request
* @return Response
*/
protected function redirectToEditionTemplate(Request $request = null)
{
return $this->generateRedirectFromRoute('admin.folders.update', [], $this->getEditionArguments($request));
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute(
'admin.folders.default',
['parent' => $this->getRequest()->get('parent', 0)]
);
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
class HomeController extends BaseAdminController
{
const RESOURCE_CODE = "admin.home";
public function defaultAction()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) {
return $response;
}
// Render the edition template.
return $this->render('home');
}
}

View File

@@ -0,0 +1,474 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Propel\Runtime\ActiveQuery\Criteria;
use Symfony\Component\HttpFoundation\JsonResponse;
use Thelia\Core\Event\Hook\HookCreateAllEvent;
use Thelia\Core\Event\Hook\HookCreateEvent;
use Thelia\Core\Event\Hook\HookDeactivationEvent;
use Thelia\Core\Event\Hook\HookDeleteEvent;
use Thelia\Core\Event\Hook\HookToggleActivationEvent;
use Thelia\Core\Event\Hook\HookToggleNativeEvent;
use Thelia\Core\Event\Hook\HookUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Core\Translation\Translator;
use Thelia\Form\Definition\AdminForm;
use Thelia\Log\Tlog;
use Thelia\Model\Hook;
use Thelia\Model\HookQuery;
use Thelia\Model\Lang;
/**
* Class HookController
* @package Thelia\Controller\Admin
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
*/
class HookController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'hook',
'id',
'order',
AdminResources::HOOK,
TheliaEvents::HOOK_CREATE,
TheliaEvents::HOOK_UPDATE,
TheliaEvents::HOOK_DELETE
);
}
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::VIEW)) {
return $response;
}
return $this->renderList();
}
public function discoverAction()
{
if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::VIEW)) {
return $response;
}
$templateType = \intval($this->getRequest()->get("template_type", TemplateDefinition::FRONT_OFFICE));
$json_data = [];
try {
// parse the current template
$hookHelper = $this->container->get("thelia.hookHelper");
$hooks = $hookHelper->parseActiveTemplate($templateType);
// official hook
$allHooks = $this->getAllHooks($templateType);
// diff
$newHooks = [];
$existingHooks = [];
foreach ($hooks as $hook) {
if (array_key_exists($hook["code"], $allHooks)) {
$existingHooks[] = $hook["code"];
} else {
$newHooks[] = $hook;
}
}
foreach ($existingHooks as $code) {
unset($allHooks[$code]);
}
$json_data = [
"success" => true,
"new" => $newHooks,
"missing" => $allHooks
];
$response = JsonResponse::create($json_data);
} catch (\Exception $e) {
$response = JsonResponse::create(["error" => $e->getMessage()], 500);
}
return $response;
}
public function discoverSaveAction()
{
if (null !== $response = $this->checkAuth(AdminResources::HOOK, [], AccessManager::UPDATE)) {
return $response;
}
$errors = [];
$templateType = $this->getRequest()->request->get("templateType");
// new hooks in the template
if (null !== $newHooks = $this->getRequest()->request->get("new", null)) {
foreach ($newHooks as $hook) {
$event = $this->getDiscoverCreationEvent($hook, $templateType);
$this->dispatch(TheliaEvents::HOOK_CREATE_ALL, $event);
if (!$event->hasHook()) {
$errors[] = sprintf(
Translator::getInstance()->trans("Failed to create new hook %s"),
$hook["code"]
);
}
}
}
// missing official hooks
if (null !== $missingHooks = $this->getRequest()->request->get("missing")) {
foreach ($missingHooks as $hookId) {
$event = new HookDeactivationEvent($hookId);
$this->dispatch(TheliaEvents::HOOK_DEACTIVATION, $event);
if (!$event->hasHook()) {
$errors[] = sprintf(
Translator::getInstance()->trans("Failed to deactivate hook with id %s"),
$hookId
);
}
}
}
$json_data = [
"success" => true
];
if (\count($errors)) {
$response = JsonResponse::create(["error" => $errors], 500);
} else {
$response = JsonResponse::create($json_data);
}
return $response;
}
protected function getDiscoverCreationEvent($data, $type)
{
$event = new HookCreateAllEvent();
$event
->setLocale(Lang::getDefaultLanguage()->getLocale())
->setType($type)
->setCode($data['code'])
->setNative(false)
->setActive(true)
->setTitle(($data['title'] != "") ? $data['title'] : $data['code'])
->setByModule($data['module'])
->setBlock($data['block'])
->setChapo("")
->setDescription("");
return $event;
}
protected function getDeactivationEvent($code, $type)
{
$event = null;
$hook_id = HookQuery::create()
->filterByActivate(true, Criteria::EQUAL)
->filterByType($type, Criteria::EQUAL)
->filterByCode($code, Criteria::EQUAL)
->select("Id")
->findOne();
if (null !== $hook_id) {
$event = new HookDeactivationEvent($hook_id);
}
return $event;
}
protected function getAllHooks($templateType)
{
// get the all hooks
$hooks = HookQuery::create()
->filterByType($templateType, Criteria::EQUAL)
->find();
$ret = [];
/** @var Hook $hook */
foreach ($hooks as $hook) {
$ret[$hook->getCode()] = [
"id" => $hook->getId(),
"code" => $hook->getCode(),
"native" => $hook->getNative(),
"activate" => $hook->getActivate(),
"title" => $hook->getTitle()
];
}
return $ret;
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::HOOK_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::HOOK_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\Hook $object
*
* @return \Thelia\Form\HookModificationForm
*/
protected function hydrateObjectForm($object)
{
$data = [
'id' => $object->getId(),
'code' => $object->getCode(),
'type' => $object->getType(),
'native' => $object->getNative(),
'by_module' => $object->getByModule(),
'block' => $object->getBlock(),
'active' => $object->getActivate(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
];
return $this->createForm(AdminForm::HOOK_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
*/
protected function getCreationEvent($formData)
{
$event = new HookCreateEvent();
return $this->hydrateEvent($event, $formData);
}
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
*/
protected function getUpdateEvent($formData)
{
$event = new HookUpdateEvent($formData['id']);
return $this->hydrateEvent($event, $formData, true);
}
protected function hydrateEvent($event, $formData, $update = false)
{
$event
->setLocale($formData['locale'])
->setType($formData['type'])
->setCode($formData['code'])
->setNative($formData['native'])
->setActive($formData['active'])
->setTitle($formData['title']);
if ($update) {
$event
->setByModule($formData['by_module'])
->setBlock($formData['block'])
->setChapo($formData['chapo'])
->setDescription($formData['description']);
}
return $event;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new HookDeleteEvent($this->getRequest()->get('hook_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param unknown $event
*/
protected function eventContainsObject($event)
{
return $event->hasHook();
}
/**
* Get the created object from an event.
*
* @param unknown $event
*
* @return
* @internal param \Thelia\Controller\Admin\unknown $createEvent
*/
protected function getObjectFromEvent($event)
{
return $event->getHook();
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
$hook = HookQuery::create()
->findPk($this->getRequest()->get('hook_id', 0));
if (null !== $hook) {
$hook->setLocale($this->getCurrentEditionLocale());
}
return $hook;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\Hook $object
*
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param \Thelia\Model\Hook $object
*
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param unknown $currentOrder , if any, null otherwise.
*/
protected function renderListTemplate($currentOrder)
{
return $this->render("hooks", ['order' => $currentOrder]);
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('hook-edit', $this->getEditionArgument());
}
protected function getEditionArgument()
{
return [
'hook_id' => $this->getRequest()->get('hook_id', 0)
];
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.hook.update',
[],
[
"hook_id" => $this->getRequest()->get('hook_id', 0),
]
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.hook');
}
public function toggleNativeAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, [], AccessManager::UPDATE)) {
return $response;
}
$content = null;
if (null !== $hook_id = $this->getRequest()->get('hook_id')) {
$toggleDefaultEvent = new HookToggleNativeEvent($hook_id);
try {
$this->dispatch(TheliaEvents::HOOK_TOGGLE_NATIVE, $toggleDefaultEvent);
if ($toggleDefaultEvent->hasHook()) {
return $this->nullResponse();
}
} catch (\Exception $ex) {
$content = $ex->getMessage();
Tlog::getInstance()->debug(sprintf("%s", $content));
}
}
return $this->nullResponse(500);
}
public function toggleActivationAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, [], AccessManager::UPDATE)) {
return $response;
}
$content = null;
if (null !== $hook_id = $this->getRequest()->get('hook_id')) {
$toggleDefaultEvent = new HookToggleActivationEvent($hook_id);
try {
$this->dispatch(TheliaEvents::HOOK_TOGGLE_ACTIVATION, $toggleDefaultEvent);
if ($toggleDefaultEvent->hasHook()) {
return $this->nullResponse();
}
} catch (\Exception $ex) {
$content = $ex->getMessage();
Tlog::getInstance()->debug(sprintf("%s", $content));
}
}
return $this->nullResponse(500);
}
}

View File

@@ -0,0 +1,242 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\DependencyInjection\Compiler\RegisterArchiverPass;
use Thelia\Core\DependencyInjection\Compiler\RegisterSerializerPass;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\LangQuery;
/**
* Class ImportController
* @author Jérôme Billiras <jbilliras@openstudio.fr>
*/
class ImportController extends BaseAdminController
{
/**
* Handle default action, that is, list available imports
*
* @param string $_view View to render
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function indexAction($_view = 'import')
{
$authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::VIEW]);
if ($authResponse !== null) {
return $authResponse;
}
$this->getParserContext()
->set('category_order', $this->getRequest()->query->get('category_order', 'manual'))
->set('import_order', $this->getRequest()->query->get('import_order', 'manual'))
;
return $this->render($_view);
}
/**
* Handle import position change action
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeImportPositionAction()
{
$authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
$query = $this->getRequest()->query;
$this->dispatch(
TheliaEvents::IMPORT_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
return $this->generateRedirectFromRoute('import.list');
}
/**
* Handle import category position change action
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeCategoryPositionAction()
{
$authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
$query = $this->getRequest()->query;
$this->dispatch(
TheliaEvents::IMPORT_CATEGORY_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
return $this->generateRedirectFromRoute('import.list');
}
/**
* Match position mode string against position mode constant value
*
* @param null|string $mode Position mode string
*
* @return integer Position mode constant value
*/
protected function matchPositionMode($mode)
{
if ($mode === 'up') {
return UpdatePositionEvent::POSITION_UP;
}
if ($mode === 'down') {
return UpdatePositionEvent::POSITION_DOWN;
}
return UpdatePositionEvent::POSITION_ABSOLUTE;
}
/**
* Display import configuration view
*
* @param integer $id An import identifier
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function configureAction($id)
{
/** @var \Thelia\Handler\ImportHandler $importHandler */
$importHandler = $this->container->get('thelia.import.handler');
$import = $importHandler->getImport($id);
if ($import === null) {
return $this->pageNotFound();
}
$extensions = [];
$mimeTypes = [];
/** @var \Thelia\Core\Serializer\AbstractSerializer $serializer */
foreach ($this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID)->getSerializers() as $serializer) {
$extensions[] = $serializer->getExtension();
$mimeTypes[] = $serializer->getMimeType();
}
/** @var \Thelia\Core\Archiver\AbstractArchiver $archiver */
foreach ($this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID)->getArchivers(true) as $archiver) {
$extensions[] = $archiver->getExtension();
$mimeTypes[] = $archiver->getMimeType();
}
// Render standard view or ajax one
$templateName = 'import-page';
if ($this->getRequest()->isXmlHttpRequest()) {
$templateName = 'ajax/import-modal';
}
return $this->render(
$templateName,
[
'importId' => $id,
'ALLOWED_MIME_TYPES' => implode(', ', $mimeTypes),
'ALLOWED_EXTENSIONS' => implode(', ', $extensions),
]
);
}
/**
* Handle import action
*
* @param integer $id An import identifier
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\Response
*/
public function importAction($id)
{
/** @var \Thelia\Handler\Importhandler $importHandler */
$importHandler = $this->container->get('thelia.import.handler');
$import = $importHandler->getImport($id);
if ($import === null) {
return $this->pageNotFound();
}
$form = $this->createForm(AdminForm::IMPORT);
try {
$validatedForm = $this->validateForm($form);
/** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
$file = $validatedForm->get('file_upload')->getData();
$file = $file->move(
THELIA_CACHE_DIR . 'import' . DS . (new\DateTime)->format('Ymd'),
uniqid() . '-' . $file->getClientOriginalName()
);
$lang = (new LangQuery)->findPk($validatedForm->get('language')->getData());
$importEvent = $importHandler->import($import, $file, $lang);
if (\count($importEvent->getErrors()) > 0) {
$this->getSession()->getFlashBag()->add(
'thelia.import.error',
$this->getTranslator()->trans(
'Error(s) in import&nbsp;:<br />%errors',
[
'%errors' => implode('<br />', $importEvent->getErrors())
]
)
);
}
$this->getSession()->getFlashBag()->add(
'thelia.import.success',
$this->getTranslator()->trans(
'Import successfully done, %count row(s) have been changed',
[
'%count' => $importEvent->getImport()->getImportedRows()
]
)
);
return $this->generateRedirectFromRoute('import.view', [], ['id' => $id]);
} catch (FormValidationException $e) {
$form->setErrorMessage($this->createStandardFormValidationErrorMessage($e));
} catch (\Exception $e) {
$this->getParserContext()->setGeneralError($e->getMessage());
}
$this->getParserContext()
->addForm($form)
;
return $this->configureAction($id);
}
}

View File

@@ -0,0 +1,456 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Thelia\Core\Event\Lang\LangCreateEvent;
use Thelia\Core\Event\Lang\LangDefaultBehaviorEvent;
use Thelia\Core\Event\Lang\LangDeleteEvent;
use Thelia\Core\Event\Lang\LangEvent;
use Thelia\Core\Event\Lang\LangToggleActiveEvent;
use Thelia\Core\Event\Lang\LangToggleDefaultEvent;
use Thelia\Core\Event\Lang\LangToggleVisibleEvent;
use Thelia\Core\Event\Lang\LangUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\Lang\LangUrlEvent;
use Thelia\Form\Lang\LangUrlForm;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
/**
* Class LangController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class LangController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->renderDefault();
}
public function renderDefault(array $param = array(), $status = 200)
{
$data = array();
foreach (LangQuery::create()->find() as $lang) {
$data[LangUrlForm::LANG_PREFIX.$lang->getId()] = $lang->getUrl();
}
$langUrlForm = $this->createForm(AdminForm::LANG_URL, 'form', $data);
$this->getParserContext()->addForm($langUrlForm);
return $this->render('languages', array_merge($param, array(
'lang_without_translation' => ConfigQuery::getDefaultLangWhenNoTranslationAvailable(),
'one_domain_per_lang' => ConfigQuery::isMultiDomainActivated()
)), $status);
}
public function updateAction($lang_id)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
$lang = LangQuery::create()->findPk($lang_id);
$langForm = $this->createForm(AdminForm::LANG_UPDATE, 'form', array(
'id' => $lang->getId(),
'title' => $lang->getTitle(),
'code' => $lang->getCode(),
'locale' => $lang->getLocale(),
'date_time_format' => $lang->getDateTimeFormat(),
'date_format' => $lang->getDateFormat(),
'time_format' => $lang->getTimeFormat(),
'decimal_separator' => $lang->getDecimalSeparator(),
'thousands_separator' => $lang->getThousandsSeparator(),
'decimals' => $lang->getDecimals(),
));
$this->getParserContext()->addForm($langForm);
return $this->render('ajax/language-update-modal', array(
'lang_id' => $lang_id
));
}
public function processUpdateAction($lang_id)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$langForm = $this->createForm(AdminForm::LANG_UPDATE);
try {
$form = $this->validateForm($langForm);
$event = new LangUpdateEvent($form->get('id')->getData());
$event = $this->hydrateEvent($event, $form);
$this->dispatch(TheliaEvents::LANG_UPDATE, $event);
if (false === $event->hasLang()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang'))
);
}
/** @var Lang $changedObject */
$changedObject = $event->getLang();
$this->adminLogAppend(
AdminResources::LANGUAGE,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
'Lang',
$changedObject->getTitle(),
$changedObject->getId()
),
$changedObject->getId()
);
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (\Exception $ex) {
$error_msg = $this->getTranslator()->trans("Failed to update language definition: %ex", array("%ex" => $ex->getMessage()));
Tlog::getInstance()->addError("Failed to update language definition", $ex->getMessage());
}
if (false !== $error_msg) {
$response = $this->renderDefault(array('error_message' => $error_msg));
}
return $response;
}
/**
* @param LangCreateEvent $event
* @param Form $form
* @return LangCreateEvent
*/
protected function hydrateEvent($event, Form $form)
{
return $event
->setTitle($form->get('title')->getData())
->setCode($form->get('code')->getData())
->setLocale($form->get('locale')->getData())
->setDateTimeFormat($form->get('date_time_format')->getData())
->setDateFormat($form->get('date_format')->getData())
->setTimeFormat($form->get('time_format')->getData())
->setDecimalSeparator($form->get('decimal_separator')->getData())
->setThousandsSeparator($form->get('thousands_separator')->getData())
->setDecimals($form->get('decimals')->getData())
;
}
public function toggleDefaultAction($lang_id)
{
return $this->toggleLangDispatch(
TheliaEvents::LANG_TOGGLEDEFAULT,
new LangToggleDefaultEvent($lang_id)
);
}
public function toggleActiveAction($lang_id)
{
return $this->toggleLangDispatch(
TheliaEvents::LANG_TOGGLEACTIVE,
new LangToggleActiveEvent($lang_id)
);
}
public function toggleVisibleAction($lang_id)
{
return $this->toggleLangDispatch(
TheliaEvents::LANG_TOGGLEVISIBLE,
new LangToggleVisibleEvent($lang_id)
);
}
public function addAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::CREATE)) {
return $response;
}
$createForm = $this->createForm(AdminForm::LANG_CREATE);
$error_msg = false;
$ex = null;
try {
$form = $this->validateForm($createForm);
$createEvent = new LangCreateEvent();
$createEvent = $this->hydrateEvent($createEvent, $form);
$this->dispatch(TheliaEvents::LANG_CREATE, $createEvent);
if (false === $createEvent->hasLang()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang'))
);
}
/** @var Lang $createdObject */
$createdObject = $createEvent->getLang();
$this->adminLogAppend(
AdminResources::LANGUAGE,
AccessManager::CREATE,
sprintf(
"%s %s (ID %s) created",
'Lang',
$createdObject->getTitle(),
$createdObject->getId()
),
$createdObject->getId()
);
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')),
$error_msg,
$createForm,
$ex
);
// At this point, the form has error, and should be redisplayed.
$response = $this->renderDefault();
}
return $response;
}
public function deleteAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::DELETE)) {
return $response;
}
$error_msg = false;
try {
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get("_token")
);
$deleteEvent = new LangDeleteEvent($this->getRequest()->get('language_id', 0));
$this->dispatch(TheliaEvents::LANG_DELETE, $deleteEvent);
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (\Exception $ex) {
Tlog::getInstance()->error(sprintf("error during language removal with message : %s", $ex->getMessage()));
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$response = $this->renderDefault(array(
'error_message' => $error_msg
));
}
return $response;
}
public function defaultBehaviorAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$ex = null;
$behaviorForm = $this->createForm(AdminForm::LANG_DEFAULT_BEHAVIOR);
try {
$form = $this->validateForm($behaviorForm);
$event = new LangDefaultBehaviorEvent($form->get('behavior')->getData());
$this->dispatch(TheliaEvents::LANG_DEFAULTBEHAVIOR, $event);
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')),
$error_msg,
$behaviorForm,
$ex
);
// At this point, the form has error, and should be redisplayed.
$response = $this->renderDefault();
}
return $response;
}
public function domainAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$ex = null;
$langUrlForm = $this->createForm(AdminForm::LANG_URL);
try {
$form = $this->validateForm($langUrlForm);
$data = $form->getData();
$event = new LangUrlEvent();
foreach ($data as $key => $value) {
if (false !== strpos($key, LangUrlForm::LANG_PREFIX)) {
$event->addUrl(substr($key, \strlen(LangUrlForm::LANG_PREFIX)), $value);
}
}
$this->dispatch(TheliaEvents::LANG_URL, $event);
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')),
$error_msg,
$langUrlForm,
$ex
);
// At this point, the form has error, and should be redisplayed.
$response = $this->renderDefault();
}
return $response;
}
public function activateDomainAction()
{
return $this->domainActivation(1);
}
public function deactivateDomainAction()
{
return $this->domainActivation(0);
}
private function domainActivation($activate)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
ConfigQuery::create()
->filterByName('one_domain_foreach_lang')
->update(array('Value' => $activate));
return $this->generateRedirectFromRoute('admin.configuration.languages');
}
/**
* @param string $eventName
* @param LangEvent $event
* @return Response
*/
protected function toggleLangDispatch($eventName, $event)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$errorMessage = null;
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get('_token')
);
try {
$this->dispatch($eventName, $event);
if (false === $event->hasLang()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang'))
);
}
$changedObject = $event->getLang();
$this->adminLogAppend(
AdminResources::LANGUAGE,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
'Lang',
$changedObject->getTitle(),
$changedObject->getId()
),
$changedObject->getId()
);
} catch (\Exception $e) {
Tlog::getInstance()->error(sprintf("Error on changing languages with message : %s", $e->getMessage()));
$errorMessage = $e->getMessage();
}
if ($this->getRequest()->isXmlHttpRequest()) {
return new JsonResponse(
$errorMessage !== null ? ['message' => $errorMessage] : [],
$errorMessage !== null ? 500 : 200
);
}
if ($errorMessage !== null) {
return $this->renderDefault(['error_message' => $errorMessage], 500);
} else {
return $this->generateRedirectFromRoute('admin.configuration.languages');
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
/**
* Class LanguageController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class LanguageController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->render("languages");
}
}

View File

@@ -0,0 +1,156 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\MailingSystem\MailingSystemEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\ConfigQuery;
class MailingSystemController extends BaseAdminController
{
const RESOURCE_CODE = "admin.configuration.mailing-system";
public function defaultAction()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) {
return $response;
}
// Hydrate the form abd pass it to the parser
$data = array(
'enabled' => ConfigQuery::isSmtpEnable() ? true : false,
'host' => ConfigQuery::getSmtpHost(),
'port' => ConfigQuery::getSmtpPort(),
'encryption' => ConfigQuery::getSmtpEncryption(),
'username' => ConfigQuery::getSmtpUsername(),
'password' => ConfigQuery::getSmtpPassword(),
'authmode' => ConfigQuery::getSmtpAuthMode(),
'timeout' => ConfigQuery::getSmtpTimeout(),
'sourceip' => ConfigQuery::getSmtpSourceIp(),
);
// Setup the object form
$form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION, "form", $data);
// Pass it to the parser
$this->getParserContext()->addForm($form);
// Render the edition template.
return $this->render('mailing-system');
}
public function updateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
// Create the form from the request
$form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION);
try {
// Check the form against constraints violations
$formData = $this->validateForm($form, "POST");
// Get the form field values
$event = new MailingSystemEvent();
$event->setEnabled($formData->get('enabled')->getData());
$event->setHost($formData->get('host')->getData());
$event->setPort($formData->get('port')->getData());
$event->setEncryption($formData->get('encryption')->getData());
$event->setUsername($formData->get('username')->getData());
$event->setPassword($formData->get('password')->getData());
$event->setAuthMode($formData->get('authmode')->getData());
$event->setTimeout($formData->get('timeout')->getData());
$event->setSourceIp($formData->get('sourceip')->getData());
$this->dispatch(TheliaEvents::MAILING_SYSTEM_UPDATE, $event);
// Redirect to the success URL
$response = $this->generateRedirectFromRoute("admin.configuration.mailing-system.view");
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("mailing system modification", array()),
$error_msg,
$form,
$ex
);
// At this point, the form has errors, and should be redisplayed.
$response = $this->render('mailing-system');
}
return $response;
}
public function testAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) {
return $response;
}
$contactEmail = ConfigQuery::read('store_email');
$storeName = ConfigQuery::read('store_name', 'Thelia');
$json_data = array(
"success" => false,
"message" => "",
);
if ($contactEmail) {
$emailTest = $this->getRequest()->get("email", $contactEmail);
$message = $this->getTranslator()->trans("Email test from : %store%", array("%store%" => $storeName));
$htmlMessage = "<p>$message</p>";
$instance = $this->getMailer()->getMessageInstance()
->addTo($emailTest, $storeName)
->addFrom($contactEmail, $storeName)
->setSubject($message)
->setBody($message, 'text/plain')
->setBody($htmlMessage, 'text/html')
;
try {
$this->getMailer()->send($instance);
$json_data["success"] = true;
$json_data["message"] = $this->getTranslator()->trans("Your configuration seems to be ok. Checked out your mailbox : %email%", array("%email%" => $emailTest));
} catch (\Exception $ex) {
$json_data["message"] = $ex->getMessage();
}
} else {
$json_data["message"] = $this->getTranslator()->trans("You have to configure your store email first !");
}
$response = JsonResponse::create($json_data);
return $response;
}
}

View File

@@ -0,0 +1,330 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Thelia\Core\Event\Message\MessageCreateEvent;
use Thelia\Core\Event\Message\MessageDeleteEvent;
use Thelia\Core\Event\Message\MessageUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Message;
use Thelia\Model\MessageQuery;
use Thelia\Model\Module;
use Thelia\Model\ModuleQuery;
/**
* Manages messages sent by mail
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class MessageController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'message',
null, // no sort order change
null, // no sort order change
AdminResources::MESSAGE,
TheliaEvents::MESSAGE_CREATE,
TheliaEvents::MESSAGE_UPDATE,
TheliaEvents::MESSAGE_DELETE,
null, // No visibility toggle
null // No position update
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::MESSAGE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::MESSAGE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new MessageCreateEvent();
$createEvent
->setMessageName($formData['name'])
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setSecured($formData['secured'] ? true : false)
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new MessageUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setMessageName($formData['name'])
->setSecured($formData['secured'])
->setLocale($formData["locale"])
->setTitle($formData['title'])
->setSubject($formData['subject'])
->setHtmlLayoutFileName($formData['html_layout_file_name'])
->setHtmlTemplateFileName($formData['html_template_file_name'])
->setTextLayoutFileName($formData['text_layout_file_name'])
->setTextTemplateFileName($formData['text_template_file_name'])
->setHtmlMessage($formData['html_message'])
->setTextMessage($formData['text_message'])
;
return $changeEvent;
}
protected function getDeleteEvent()
{
return new MessageDeleteEvent($this->getRequest()->get('message_id'));
}
protected function eventContainsObject($event)
{
return $event->hasMessage();
}
protected function hydrateObjectForm($object)
{
// Prepare the data that will hydrate the form
$data = array(
'id' => $object->getId(),
'name' => $object->getName(),
'secured' => $object->getSecured() ? true : false,
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'subject' => $object->getSubject(),
'html_message' => $object->getHtmlMessage(),
'text_message' => $object->getTextMessage(),
'html_layout_file_name' => $object->getHtmlLayoutFileName(),
'html_template_file_name' => $object->getHtmlTemplateFileName(),
'text_layout_file_name' => $object->getTextLayoutFileName(),
'text_template_file_name' => $object->getTextTemplateFileName(),
);
// Setup the object form
return $this->createForm(AdminForm::MESSAGE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasMessage() ? $event->getMessage() : null;
}
protected function getExistingObject()
{
$message = MessageQuery::create()
->findOneById($this->getRequest()->get('message_id', 0));
if (null !== $message) {
$message->setLocale($this->getCurrentEditionLocale());
}
return $message;
}
/**
* @param Message $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getName();
}
/**
* @param Message $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('messages');
}
protected function listDirectoryContent($requiredExtension)
{
$list = array();
$mailTemplate = $this->getTemplateHelper()->getActiveMailTemplate();
$finder = Finder::create()->files()->in($mailTemplate->getAbsolutePath());
// Also add parent template files, if any.
/** @var TemplateDefinition $parentTemplate */
foreach ($mailTemplate->getParentList() as $parentTemplate) {
$finder->in($parentTemplate->getAbsolutePath());
}
$finder->ignoreDotFiles(true)->sortByName()->name("*.$requiredExtension");
/** @var SplFileInfo $file */
foreach ($finder as $file) {
$list[] = $file->getRelativePathname();
}
// Add modules templates
$modules = ModuleQuery::getActivated();
/** @var Module $module */
foreach ($modules as $module) {
$dir = $module->getAbsoluteTemplateBasePath() . DS . TemplateDefinition::EMAIL_SUBDIR . DS . 'default';
if (file_exists($dir)) {
$finder = Finder::create()
->files()
->in($dir)
->ignoreDotFiles(true)
->sortByName()
->name("*.$requiredExtension");
foreach ($finder as $file) {
$fileName = $file->getBasename();
if (!\in_array($fileName, $list)) {
$list[] = $fileName;
}
}
}
}
return $list;
}
protected function renderEditionTemplate()
{
return $this->render('message-edit', array(
'message_id' => $this->getRequest()->get('message_id'),
'layout_list' => $this->listDirectoryContent('tpl'),
'html_template_list' => $this->listDirectoryContent('html'),
'text_template_list' => $this->listDirectoryContent('txt'),
));
}
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
"admin.configuration.messages.update",
[
'message_id' => $this->getRequest()->get('message_id')
]
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.messages.default');
}
public function previewAction($messageId, $html = true)
{
if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) {
return $response;
}
if (null === $message = MessageQuery::create()->findPk($messageId)) {
$this->pageNotFound();
}
$parser = $this->getParser($this->getTemplateHelper()->getActiveMailTemplate());
foreach ($this->getRequest()->query->all() as $key => $value) {
$parser->assign($key, $value);
}
if ($html) {
$content = $message->setLocale($this->getCurrentEditionLocale())->getHtmlMessageBody($parser);
} else {
$content = $message->setLocale($this->getCurrentEditionLocale())->getTextMessageBody($parser);
}
return new Response($content);
}
public function previewAsHtmlAction($messageId)
{
return $this->previewAction($messageId);
}
public function previewAsTextAction($messageId)
{
$response = $this->previewAction($messageId, false);
$response->headers->add(["Content-Type" => "text/plain"]);
return $response;
}
public function sendSampleByEmailAction($messageId)
{
if (null !== $response = $this->checkAuth(AdminResources::MESSAGE, [], AccessManager::VIEW)) {
return $response;
}
if (null !== $message = MessageQuery::create()->findPk($messageId)) {
// Ajax submission: prevent CRSF control, as page is not refreshed
$baseForm = $this->createForm(AdminForm::MESSAGE_SEND_SAMPLE, 'form', [], ['csrf_protection' => false]);
try {
$form = $this->validateForm($baseForm, "POST");
$data = $form->getData();
$messageParameters = [];
foreach ($this->getRequest()->request->all() as $key => $value) {
$messageParameters[$key] = $value;
}
$this->getMailer()->sendEmailMessage(
$message->getName(),
[ConfigQuery::getStoreEmail() => ConfigQuery::getStoreName()],
[ $data['recipient_email'] => $data['recipient_email'] ],
$messageParameters,
$this->getCurrentEditionLocale()
);
return new Response(
$this->getTranslator()->trans(
"The message has been successfully sent to %recipient.",
[ '%recipient' => $data['recipient_email'] ]
)
);
} catch (\Exception $ex) {
return new Response(
$this->getTranslator()->trans(
"Something goes wrong, the message was not sent to recipient. Error is : %err",
[ '%err' => $ex->getMessage() ]
)
);
}
} else {
return $this->pageNotFound();
}
}
}

View File

@@ -0,0 +1,480 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Michelf\Markdown;
use Michelf\MarkdownExtra;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Finder\Finder;
use Thelia\Core\Event\Module\ModuleDeleteEvent;
use Thelia\Core\Event\Module\ModuleEvent;
use Thelia\Core\Event\Module\ModuleInstallEvent;
use Thelia\Core\Event\Module\ModuleToggleActivationEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Exception\InvalidModuleException;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\ModuleInstallForm;
use Thelia\Log\Tlog;
use Thelia\Model\Module;
use Thelia\Model\ModuleQuery;
use Thelia\Module\ModuleManagement;
/**
* Class ModuleController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ModuleController extends AbstractCrudController
{
protected $moduleErrors = [];
public function __construct()
{
parent::__construct(
'module',
'manual',
'module_order',
AdminResources::MODULE,
null,
TheliaEvents::MODULE_UPDATE,
null,
null,
TheliaEvents::MODULE_UPDATE_POSITION
);
}
protected function getCreationForm()
{
return null;
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::MODULE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
return null;
}
protected function getUpdateEvent($formData)
{
$event = new ModuleEvent();
$event->setLocale($formData['locale']);
$event->setId($formData['id']);
$event->setTitle($formData['title']);
$event->setChapo($formData['chapo']);
$event->setDescription($formData['description']);
$event->setPostscriptum($formData['postscriptum']);
return $event;
}
protected function getDeleteEvent()
{
return null;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('module_id', null),
$positionChangeMode,
$positionValue
);
}
protected function eventContainsObject($event)
{
return $event->hasModule();
}
protected function hydrateObjectForm($object)
{
$object->setLocale($this->getCurrentEditionLocale());
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
);
// Setup the object form
return $this->createForm(AdminForm::MODULE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasModule() ? $event->getModule() : null;
}
protected function getExistingObject()
{
$module = ModuleQuery::create()
->findOneById($this->getRequest()->get('module_id', 0));
if (null !== $module) {
$module->setLocale($this->getCurrentEditionLocale());
}
return $module;
}
/**
* @param Module $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Module $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments()
{
return array();
}
protected function getRouteArguments($module_id = null)
{
$request = $this->getRequest();
return array(
'module_id' => $module_id === null ? $request->get('module_id') : $module_id,
'current_tab' => $request->get('current_tab', 'general'),
);
}
protected function renderListTemplate($currentOrder)
{
// We always return to the feature edition form
return $this->render(
'modules',
array(
'module_order' => $currentOrder,
'module_errors' => $this->moduleErrors
)
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('module-edit', array_merge($this->getViewArguments(), $this->getRouteArguments()));
}
protected function redirectToEditionTemplate($request = null, $country = null)
{
return $this->generateRedirectFromRoute(
"admin.module.update",
$this->getViewArguments(),
$this->getRouteArguments()
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute("admin.module");
}
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) {
return $response;
}
try {
$moduleManagement = new ModuleManagement($this->getContainer());
$moduleManagement->updateModules($this->getContainer());
} catch (InvalidModuleException $ex) {
$this->moduleErrors = $ex->getErrors();
} catch (Exception $ex) {
Tlog::getInstance()->addError("Failed to get modules list:", $ex);
}
return $this->renderList();
}
public function configureAction($module_code)
{
$module = ModuleQuery::create()->findOneByCode($module_code);
if (null === $module) {
throw new \InvalidArgumentException(sprintf("Module `%s` does not exists", $module_code));
}
if (null !== $response = $this->checkAuth(array(), $module_code, AccessManager::VIEW)) {
return $response;
}
return $this->render(
"module-configure",
array(
"module_code" => $module_code,
)
);
}
public function toggleActivationAction($module_id)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
try {
$event = new ModuleToggleActivationEvent($module_id);
$this->dispatch(TheliaEvents::MODULE_TOGGLE_ACTIVATION, $event);
if (null === $event->getModule()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module'))
);
}
} catch (\Exception $e) {
$message = $e->getMessage();
Tlog::getInstance()->addError("Failed to activate/deactivate module:", $e);
}
if ($this->getRequest()->isXmlHttpRequest()) {
if ($message) {
$response = $this->jsonResponse(json_encode(array(
"error" => $message
)), 500);
} else {
$response = $this->nullResponse();
}
} else {
$response = $this->generateRedirectFromRoute('admin.module');
}
return $response;
}
public function deleteAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::DELETE)) {
return $response;
}
$message = false;
try {
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get("_token")
);
$module_id = $this->getRequest()->get('module_id');
$deleteEvent = new ModuleDeleteEvent($module_id);
$deleteEvent->setDeleteData('1' == $this->getRequest()->get('delete-module-data', '0'));
$this->dispatch(TheliaEvents::MODULE_DELETE, $deleteEvent);
if ($deleteEvent->hasModule() === false) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module'))
);
}
} catch (\Exception $e) {
$message = $e->getMessage();
Tlog::getInstance()->addError("Error during module removal", $e);
}
if (false !== $message) {
$response = $this->render("modules", array(
"error_message" => $message
));
} else {
$response = $this->generateRedirectFromRoute('admin.module');
}
return $response;
}
public function installAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::CREATE)) {
return $response;
}
$newModule = null;
$moduleDefinition = null;
/** @var ModuleInstallForm $moduleInstall */
$moduleInstall = $this->createForm(AdminForm::MODULE_INSTALL);
try {
$this->validateForm($moduleInstall, "post");
$moduleDefinition = $moduleInstall->getModuleDefinition();
$modulePath = $moduleInstall->getModulePath();
$moduleInstallEvent = new ModuleInstallEvent();
$moduleInstallEvent
->setModulePath($modulePath)
->setModuleDefinition($moduleDefinition);
$this->dispatch(TheliaEvents::MODULE_INSTALL, $moduleInstallEvent);
$newModule = $moduleInstallEvent->getModule();
if (null !== $newModule) {
$this->getSession()->getFlashBag()->add(
'module-installed',
$this->getTranslator()->trans(
'The module %module has been installed successfully.',
['%module' => $moduleDefinition->getCode()]
)
);
return $this->generateRedirectFromRoute('admin.module');
} else {
$message = $this->getTranslator()->trans(
"Sorry, an error occured."
);
}
} catch (FormValidationException $e) {
$message = $e->getMessage();
} catch (\Exception $e) {
$message = $this->getTranslator()->trans("Sorry, an error occured: %s", ['%s' => $e->getMessage()]);
}
Tlog::getInstance()->error(sprintf("Error during module installation process. Exception was %s", $message));
$moduleInstall->setErrorMessage($message);
$this->getParserContext()
->addForm($moduleInstall)
->setGeneralError($message);
return $this->render("modules");
}
public function informationAction($module_id)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) {
return $response;
}
$status = 200;
if (null !== $module = ModuleQuery::create()->findPk($module_id)) {
$title = $module->setLocale($this->getSession()->getLang()->getLocale())->getTitle();
// Get the module descriptor
$moduleDescriptor = $module->getAbsoluteConfigPath() . DS . 'module.xml';
if (false !== $xmlData = @simplexml_load_file($moduleDescriptor)) {
// Transform the pseudo-array into a real array
$arrayData = json_decode(json_encode((array)$xmlData), 1);
$content = $this->renderRaw("ajax/module-information", [
'moduleId' => $module_id,
'moduleData' => $arrayData
]);
} else {
$status = 500;
$content = $this->getTranslator()->trans(
'Failed to load descriptor (module.xml) for module ID "%id".',
[ '%id' => $module_id]
);
}
} else {
$status = 404;
$title = $this->getTranslator()->trans('Error occured.');
$content = $this->getTranslator()->trans('Module ID "%id" was not found.', [ '%id' => $module_id]);
}
return new JsonResponse([ 'title' => $title, 'body' => $content], $status);
}
public function documentationAction($module_id)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) {
return $response;
}
$status = 200;
$content = null;
if (null !== $module = ModuleQuery::create()->findPk($module_id)) {
$title = $module->setLocale($this->getSession()->getLang()->getLocale())->getTitle();
$finder = null;
// Check if the module has declared a documentation
$moduleDescriptor = $module->getAbsoluteConfigPath() . DS . 'module.xml';
if (false !== $xmlData = @simplexml_load_file($moduleDescriptor)) {
$documentationDirectory = (string) $xmlData->documentation;
if (! empty($documentationDirectory)) {
$finder = Finder::create()->files()->in($module->getAbsoluteBaseDir())->name('/.+\.md$/i');
}
}
// Fallback to readme.md (if any)
if ($finder == null || $finder->count() == 0) {
$finder = Finder::create()->files()->in($module->getAbsoluteBaseDir())->name('/readme\.md/i');
}
// Merge all MD files
if ($finder && $finder->count() > 0) {
$finder->sortByName();
/** @var \DirectoryIterator $file */
foreach ($finder as $file) {
if (false !== $mdDocumentation = @file_get_contents($file->getPathname())) {
if ($content == null) {
$content = '';
}
$content .= MarkdownExtra::defaultTransform($mdDocumentation);
}
}
}
} else {
$status = 404;
$title = $this->getTranslator()->trans('Error occured.');
$content = $this->getTranslator()->trans('Module ID "%id" was not found.', [ '%id' => $module_id]);
}
if ($content === null) {
$content = $this->getTranslator()->trans("This module has no Markdown documentation.");
}
return new JsonResponse([ 'title' => $title, 'body' => $content], $status);
}
}

View File

@@ -0,0 +1,399 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\JsonResponse;
use Thelia\Core\Event\Hook\ModuleHookCreateEvent;
use Thelia\Core\Event\Hook\ModuleHookDeleteEvent;
use Thelia\Core\Event\Hook\ModuleHookEvent;
use Thelia\Core\Event\Hook\ModuleHookToggleActivationEvent;
use Thelia\Core\Event\Hook\ModuleHookUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Hook\BaseHook;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\ModuleHookModificationForm;
use Thelia\Model\IgnoredModuleHook;
use Thelia\Model\IgnoredModuleHookQuery;
use Thelia\Model\ModuleHook;
use Thelia\Model\ModuleHookQuery;
/**
* Class HookController
* @package Thelia\Controller\Admin
* @author Julien Chanséaume <jchanseaume@openstudio.fr>
*/
class ModuleHookController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'hook',
'manual',
'hook_order',
AdminResources::MODULE_HOOK,
TheliaEvents::MODULE_HOOK_CREATE,
TheliaEvents::MODULE_HOOK_UPDATE,
TheliaEvents::MODULE_HOOK_DELETE,
null,
TheliaEvents::MODULE_HOOK_UPDATE_POSITION
);
}
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) {
return $response;
}
return $this->renderList();
}
public function toggleActivationAction($module_hook_id)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::UPDATE)) {
return $response;
}
$message = null;
$event = new ModuleHookToggleActivationEvent($this->getExistingObject());
try {
$this->dispatch(TheliaEvents::MODULE_HOOK_TOGGLE_ACTIVATION, $event);
} catch (\Exception $ex) {
$message = $ex->getMessage();
}
if ($this->getRequest()->isXmlHttpRequest()) {
if ($message) {
$response = $this->jsonResponse(json_encode([ "error" => $message]), 500);
} else {
$response = $this->nullResponse();
}
} else {
$response = $this->generateRedirectFromRoute('admin.module-hook');
}
return $response;
}
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('module_hook_id', null),
$positionChangeMode,
$positionValue
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::MODULE_HOOK_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::MODULE_HOOK_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param ModuleHook $object
* @return ModuleHookModificationForm
*/
protected function hydrateObjectForm($object)
{
$data = [
'id' => $object->getId(),
'hook_id' => $object->getHookId(),
'module_id' => $object->getModuleId(),
'classname' => $object->getClassname(),
'method' => $object->getMethod(),
'active' => $object->getActive(),
'templates' => $object->getTemplates(),
];
return $this->createForm(AdminForm::MODULE_HOOK_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return ModuleHookCreateEvent
*/
protected function getCreationEvent($formData)
{
$event = new ModuleHookCreateEvent();
return $this->hydrateEvent($event, $formData);
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return ModuleHookUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$event = new ModuleHookUpdateEvent();
return $this->hydrateEvent($event, $formData, true);
}
protected function hydrateEvent($event, $formData, $update = false)
{
if (!$update) {
$event
->setModuleId($formData['module_id'])
->setHookId($formData['hook_id']);
} else {
$event
->setModuleHookId($formData['id'])
->setModuleId($formData['module_id'])
->setHookId($formData['hook_id'])
->setClassname($formData['classname'])
->setMethod($formData['method'])
->setActive($formData['active'])
->setTemplates($formData['templates'])
;
}
return $event;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new ModuleHookDeleteEvent($this->getRequest()->get('module_hook_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param ModuleHookEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasModuleHook();
}
/**
* Get the created object from an event.
*
* @param ModuleHookEvent $event
* @return null|ModuleHook
*/
protected function getObjectFromEvent($event)
{
return $event->getModuleHook();
}
/**
* Load an existing object from the database
* @return null|ModuleHook
*/
protected function getExistingObject()
{
$moduleHook = ModuleHookQuery::create()
->findPK($this->getRequest()->get('module_hook_id', 0));
return $moduleHook;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param ModuleHook $object
* @return string
*/
protected function getObjectLabel($object)
{
try {
return sprintf(
"%s on %s",
$object->getModule()->getTitle(),
$object->getHook()->getTitle()
);
} catch (\Exception $ex) {
return "Undefined module hook";
}
}
/**
* Returns the object ID from the object
*
* @param ModuleHook $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param string $currentOrder , if any, null otherwise.
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
return $this->render(
'module-hooks',
['module_order' => $currentOrder]
);
}
/**
* Render the edition template
* @return Response
*/
protected function renderEditionTemplate()
{
return $this->render('module-hook-edit', $this->getEditionArgument());
}
/**
* @return array
*/
protected function getEditionArgument()
{
return [
'module_hook_id' => $this->getRequest()->get('module_hook_id', 0)
];
}
/**
* Redirect to the edition template
* @return Response
*/
protected function redirectToEditionTemplate($request = null, $country = null)
{
return $this->generateRedirectFromRoute(
"admin.module-hook.update",
$this->getViewArguments(),
$this->getRouteArguments()
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute("admin.module-hook");
}
protected function getViewArguments()
{
return [];
}
protected function getRouteArguments($module_hook_id = null)
{
return [
'module_hook_id' => $module_hook_id === null ? $this->getRequest()->get('module_hook_id') : $module_hook_id
];
}
public function getModuleHookClassnames($moduleId)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) {
return $response;
}
$result = [];
$moduleHooks = ModuleHookQuery::create()
->filterByModuleId($moduleId)
->groupByClassname()
->find();
/** @var ModuleHook $moduleHook */
foreach ($moduleHooks as $moduleHook) {
$result[] = $moduleHook->getClassname();
}
$ignoredModuleHooks = IgnoredModuleHookQuery::create()
->filterByModuleId($moduleId)
->groupByClassname()
->find();
/** @var IgnoredModuleHook $moduleHook */
foreach ($ignoredModuleHooks as $moduleHook) {
$className = $moduleHook->getClassname();
if (null !== $className && ! \in_array($className, $result)) {
$result[] = $className;
}
}
sort($result);
return new JsonResponse($result);
}
public function getModuleHookMethods($moduleId, $className)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE_HOOK, [], AccessManager::VIEW)) {
return $response;
}
$result = [BaseHook::INJECT_TEMPLATE_METHOD_NAME];
$moduleHooks = ModuleHookQuery::create()
->filterByModuleId($moduleId)
->filterByClassname($className)
->find();
/** @var ModuleHook $moduleHook */
foreach ($moduleHooks as $moduleHook) {
$method = $moduleHook->getMethod();
if (! \in_array($method, $result)) {
$result[] = $method;
}
}
$ignoredModuleHooks = IgnoredModuleHookQuery::create()
->filterByModuleId($moduleId)
->filterByClassname($className)
->find();
/** @var IgnoredModuleHook $moduleHook */
foreach ($ignoredModuleHooks as $moduleHook) {
$method = $moduleHook->getMethod();
if (! \in_array($method, $result)) {
$result[] = $method;
}
}
sort($result);
return new JsonResponse($result);
}
}

View File

@@ -0,0 +1,241 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Order\OrderAddressEvent;
use Thelia\Core\Event\Order\OrderEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\OrderUpdateAddress;
use Thelia\Model\ConfigQuery;
use Thelia\Model\OrderAddressQuery;
use Thelia\Model\OrderQuery;
use Thelia\Model\OrderStatusQuery;
/**
* Class OrderController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class OrderController extends BaseAdminController
{
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::VIEW)) {
return $response;
}
return $this->render("orders", array(
"display_order" => 20,
"orders_order" => $this->getListOrderFromSession("orders", "orders_order", "create-date-reverse")
));
}
public function viewAction($order_id)
{
return $this->render("order-edit", array(
"order_id" => $order_id
));
}
public function updateStatus($order_id = null)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
try {
if ($order_id === null) {
$order_id = $this->getRequest()->get("order_id");
}
$order = OrderQuery::create()->findPk($order_id);
$statusId = $this->getRequest()->get("status_id");
$status = OrderStatusQuery::create()->findPk($statusId);
if (null === $order) {
throw new \InvalidArgumentException("The order you want to update status does not exist");
}
if (null === $status) {
throw new \InvalidArgumentException("The status you want to set to the order does not exist");
}
$event = new OrderEvent($order);
$event->setStatus($statusId);
$this->dispatch(TheliaEvents::ORDER_UPDATE_STATUS, $event);
} catch (\Exception $e) {
$message = $e->getMessage();
}
$params = array();
if ($message) {
$params["update_status_error_message"] = $message;
}
$browsedPage = $this->getRequest()->get("order_page");
$currentStatus = $this->getRequest()->get("status");
if ($browsedPage) {
$params["order_page"] = $browsedPage;
if (null !== $currentStatus) {
$params["status"] = $currentStatus;
}
$response = $this->generateRedirectFromRoute("admin.order.list", $params);
} else {
$params["tab"] = $this->getRequest()->get("tab", 'cart');
$response = $this->generateRedirectFromRoute("admin.order.update.view", $params, [ 'order_id' => $order_id ]);
}
return $response;
}
public function updateDeliveryRef($order_id)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
try {
$order = OrderQuery::create()->findPk($order_id);
$deliveryRef = $this->getRequest()->get("delivery_ref");
if (null === $order) {
throw new \InvalidArgumentException("The order you want to update status does not exist");
}
$event = new OrderEvent($order);
$event->setDeliveryRef($deliveryRef);
$this->dispatch(TheliaEvents::ORDER_UPDATE_DELIVERY_REF, $event);
} catch (\Exception $e) {
$message = $e->getMessage();
}
$params = array();
if ($message) {
$params["update_status_error_message"] = $message;
}
$params["tab"] = $this->getRequest()->get("tab", 'bill');
return $this->generateRedirectFromRoute(
"admin.order.update.view",
$params,
[ 'order_id' => $order_id ]
);
}
public function updateAddress($order_id)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
$orderUpdateAddress = new OrderUpdateAddress($this->getRequest());
try {
$order = OrderQuery::create()->findPk($order_id);
if (null === $order) {
throw new \InvalidArgumentException("The order you want to update does not exist");
}
$form = $this->validateForm($orderUpdateAddress, "post");
$orderAddress = OrderAddressQuery::create()->findPk($form->get("id")->getData());
if ($orderAddress->getId() !== $order->getInvoiceOrderAddressId() && $orderAddress->getId() !== $order->getDeliveryOrderAddressId()) {
throw new \InvalidArgumentException("The order address you want to update does not belong to the current order not exist");
}
$event = new OrderAddressEvent(
$form->get("title")->getData(),
$form->get("firstname")->getData(),
$form->get("lastname")->getData(),
$form->get("address1")->getData(),
$form->get("address2")->getData(),
$form->get("address3")->getData(),
$form->get("zipcode")->getData(),
$form->get("city")->getData(),
$form->get("country")->getData(),
$form->get("phone")->getData(),
$form->get("company")->getData(),
$form->get("cellphone")->getData(),
$form->get("state")->getData()
);
$event->setOrderAddress($orderAddress);
$event->setOrder($order);
$this->dispatch(TheliaEvents::ORDER_UPDATE_ADDRESS, $event);
} catch (\Exception $e) {
$message = $e->getMessage();
}
$params = array();
if ($message) {
$params["update_status_error_message"] = $message;
}
$params["tab"] = $this->getRequest()->get("tab", 'bill');
return $this->generateRedirectFromRoute(
"admin.order.update.view",
$params,
[ 'order_id' => $order_id ]
);
}
public function generateInvoicePdf($order_id, $browser)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
return $this->generateBackOfficeOrderPdf($order_id, ConfigQuery::read('pdf_invoice_file', 'invoice'), $browser == 0);
}
public function generateDeliveryPdf($order_id, $browser)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
return $this->generateBackOfficeOrderPdf($order_id, ConfigQuery::read('pdf_delivery_file', 'delivery'), $browser == 0);
}
private function generateBackOfficeOrderPdf($order_id, $fileName, $browser)
{
if (null === $response = $this->generateOrderPdf($order_id, $fileName, true, true, $browser == 0)) {
return $this->generateRedirectFromRoute(
"admin.order.update.view",
[],
['order_id' => $order_id ]
);
}
return $response;
}
}

View File

@@ -0,0 +1,293 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\OrderStatus\OrderStatusCreateEvent;
use Thelia\Core\Event\OrderStatus\OrderStatusDeleteEvent;
use Thelia\Core\Event\OrderStatus\OrderStatusEvent;
use Thelia\Core\Event\OrderStatus\OrderStatusUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\OrderStatus\OrderStatusModificationForm;
use Thelia\Model\OrderStatusQuery;
use Thelia\Model\OrderStatus;
/**
* Class OrderStatusController
* @package Thelia\Controller\Admin
* @author Gilles Bourgeat <gbourgeat@openstudio.com>
* @since 2.4
*/
class OrderStatusController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'orderstatus',
'manual',
'order',
AdminResources::ORDER_STATUS,
TheliaEvents::ORDER_STATUS_CREATE,
TheliaEvents::ORDER_STATUS_UPDATE,
TheliaEvents::ORDER_STATUS_DELETE,
null,
TheliaEvents::ORDER_STATUS_UPDATE_POSITION
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::ORDER_STATUS_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::ORDER_STATUS_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param OrderStatus $object
* @return OrderStatusModificationForm $object
*/
protected function hydrateObjectForm($object)
{
// Prepare the data that will hydrate the form
$data = [
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'chapo' => $object->getChapo(),
'description' => $object->getDescription(),
'postscriptum' => $object->getPostscriptum(),
'color' => $object->getColor(),
'code' => $object->getCode()
];
$form = $this->createForm(AdminForm::ORDER_STATUS_MODIFICATION, "form", $data);
// Setup the object form
return $form;
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return OrderStatusCreateEvent
*/
protected function getCreationEvent($formData)
{
$orderStatusCreateEvent = new OrderStatusCreateEvent();
$orderStatusCreateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setCode($formData['code'])
->setColor($formData['color'])
;
return $orderStatusCreateEvent;
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return OrderStatusUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$orderStatusUpdateEvent = new OrderStatusUpdateEvent($formData['id']);
$orderStatusUpdateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
->setCode($formData['code'])
->setColor($formData['color'])
;
return $orderStatusUpdateEvent;
}
/**
* Creates the delete event with the provided form data
*
* @return OrderStatusDeleteEvent
* @throws \Exception
*/
protected function getDeleteEvent()
{
return new OrderStatusDeleteEvent((int) $this->getRequest()->get('order_status_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param OrderStatusEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasOrderStatus();
}
/**
* Get the created object from an event.
*
* @param $event \Thelia\Core\Event\OrderStatus\OrderStatusEvent
*
* @return null|OrderStatus
*/
protected function getObjectFromEvent($event)
{
return $event->getOrderStatus();
}
/**
* Load an existing object from the database
*
* @return \Thelia\Model\OrderStatus
*/
protected function getExistingObject()
{
$orderStatus = OrderStatusQuery::create()
->findOneById($this->getRequest()->get('order_status_id', 0));
if (null !== $orderStatus) {
$orderStatus->setLocale($this->getCurrentEditionLocale());
}
return $orderStatus;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param OrderStatus $object
*
* @return string order status title
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param OrderStatus $object
*
* @return int order status id
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param string $currentOrder , if any, null otherwise.
*
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
$this->getListOrderFromSession('orderstatus', 'order', 'manual');
return $this->render('order-status', [
'order' => $currentOrder,
]);
}
protected function getEditionArguments()
{
return [
'order_status_id' => $this->getRequest()->get('order_status_id', 0),
'current_tab' => $this->getRequest()->get('current_tab', 'general')
];
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('order-status-edit', $this->getEditionArguments());
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.order-status.update',
[],
$this->getEditionArguments()
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.order-status.default');
}
/**
* @param $positionChangeMode
* @param $positionValue
* @return UpdatePositionEvent|void
*/
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('order_status_id', null),
$positionChangeMode,
$positionValue
);
}
/**
* @param $event \Thelia\Core\Event\UpdatePositionEvent
* @return null|Response
*/
protected function performAdditionalUpdatePositionAction($event)
{
$folder = OrderStatusQuery::create()->findPk($event->getObjectId());
if ($folder != null) {
return $this->generateRedirectFromRoute(
'admin.order-status.default'
);
} else {
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,444 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Profile\ProfileEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\ProfileUpdateModuleAccessForm;
use Thelia\Form\ProfileUpdateResourceAccessForm;
use Thelia\Model\Profile;
use Thelia\Model\ProfileQuery;
class ProfileController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'profile',
'manual',
'order',
AdminResources::PROFILE,
TheliaEvents::PROFILE_CREATE,
TheliaEvents::PROFILE_UPDATE,
TheliaEvents::PROFILE_DELETE
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::PROFILE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::PROFILE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$event = new ProfileEvent();
$event->setLocale($formData['locale']);
$event->setCode($formData['code']);
$event->setTitle($formData['title']);
$event->setChapo($formData['chapo']);
$event->setDescription($formData['description']);
$event->setPostscriptum($formData['postscriptum']);
return $event;
}
protected function getUpdateEvent($formData)
{
$event = new ProfileEvent();
$event->setLocale($formData['locale']);
$event->setId($formData['id']);
$event->setTitle($formData['title']);
$event->setChapo($formData['chapo']);
$event->setDescription($formData['description']);
$event->setPostscriptum($formData['postscriptum']);
return $event;
}
protected function getDeleteEvent()
{
$event = new ProfileEvent();
$event->setId(
$this->getRequest()->get('profile_id', 0)
);
return $event;
}
/**
* @param ProfileEvent $event
* @return boolean
*/
protected function eventContainsObject($event)
{
return $event->hasProfile();
}
/**
* @param Profile $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'description' => $object->getDescription(),
'code' => $object->getCode(),
);
// Setup the object form
return $this->createForm(AdminForm::PROFILE_MODIFICATION, "form", $data);
}
/**
* @param Profile $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateResourceUpdateForm($object)
{
$data = array(
'id' => $object->getId(),
);
// Setup the object form
return $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS, "form", $data);
}
/**
* @param Profile $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateModuleUpdateForm($object)
{
$data = array(
'id' => $object->getId(),
);
// Setup the object form
return $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasProfile() ? $event->getProfile() : null;
}
protected function getExistingObject()
{
$profile = ProfileQuery::create()
->findOneById($this->getRequest()->get('profile_id', 0));
if (null !== $profile) {
$profile->setLocale($this->getCurrentEditionLocale());
}
return $profile;
}
/**
* @param Profile $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Profile $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments()
{
return (null !== $tab = $this->getRequest()->get('tab')) ? [ 'tab' => $tab ] : [];
}
protected function getRouteArguments($profile_id = null)
{
return array(
'profile_id' => $profile_id === null ? $this->getRequest()->get('profile_id') : $profile_id,
);
}
protected function renderListTemplate($currentOrder)
{
// We always return to the feature edition form
return $this->render(
'profiles',
array()
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('profile-edit', array_merge($this->getViewArguments(), $this->getRouteArguments()));
}
protected function redirectToEditionTemplate()
{
// We always return to the feature edition form
return $this->generateRedirectFromRoute(
"admin.configuration.profiles.update",
$this->getViewArguments(),
$this->getRouteArguments()
);
}
/**
* Put in this method post object creation processing if required.
*
* @param ProfileEvent $createEvent the create event
* @return \Symfony\Component\HttpFoundation\Response|Response
*/
protected function performAdditionalCreateAction($createEvent)
{
return $this->generateRedirectFromRoute(
"admin.configuration.profiles.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getProfile()->getId())
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute("admin.configuration.profiles.list");
}
public function updateAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$object = $this->getExistingObject();
if ($object != null) {
// Hydrate the form and pass it to the parser
$resourceAccessForm = $this->hydrateResourceUpdateForm($object);
$moduleAccessForm = $this->hydrateModuleUpdateForm($object);
// Pass it to the parser
$this->getParserContext()->addForm($resourceAccessForm);
$this->getParserContext()->addForm($moduleAccessForm);
}
return parent::updateAction();
}
protected function getUpdateResourceAccessEvent($formData)
{
$event = new ProfileEvent();
$event->setId($formData['id']);
$event->setResourceAccess($this->getResourceAccess($formData));
return $event;
}
protected function getUpdateModuleAccessEvent($formData)
{
$event = new ProfileEvent();
$event->setId($formData['id']);
$event->setModuleAccess($this->getModuleAccess($formData));
return $event;
}
protected function getResourceAccess($formData)
{
$requirements = array();
foreach ($formData as $data => $value) {
if (!strstr($data, ':')) {
continue;
}
$explosion = explode(':', $data);
$prefix = array_shift($explosion);
if ($prefix != ProfileUpdateResourceAccessForm::RESOURCE_ACCESS_FIELD_PREFIX) {
continue;
}
$requirements[implode('.', $explosion)] = $value;
}
return $requirements;
}
protected function getModuleAccess($formData)
{
$requirements = array();
foreach ($formData as $data => $value) {
if (!strstr($data, ':')) {
continue;
}
$explosion = explode(':', $data);
$prefix = array_shift($explosion);
if ($prefix != ProfileUpdateModuleAccessForm::MODULE_ACCESS_FIELD_PREFIX) {
continue;
}
$requirements[implode('.', $explosion)] = $value;
}
return $requirements;
}
public function processUpdateResourceAccess()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
// Create the form from the request
$changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS);
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
// Get the form field values
$data = $form->getData();
$changeEvent = $this->getUpdateResourceAccessEvent($data);
$this->dispatch(TheliaEvents::PROFILE_RESOURCE_ACCESS_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName))
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
if ($response == null) {
return $this->redirectToEditionTemplate();
} else {
return $response;
}
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
public function processUpdateModuleAccess()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
// Create the form from the request
$changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS);
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
// Get the form field values
$data = $form->getData();
$changeEvent = $this->getUpdateModuleAccessEvent($data);
$this->dispatch(TheliaEvents::PROFILE_MODULE_ACCESS_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName))
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
if ($response == null) {
return $this->redirectToEditionTemplate();
} else {
return $response;
}
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
}

View File

@@ -0,0 +1,405 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Sale\SaleActiveStatusCheckEvent;
use Thelia\Core\Event\Sale\SaleClearStatusEvent;
use Thelia\Core\Event\Sale\SaleCreateEvent;
use Thelia\Core\Event\Sale\SaleDeleteEvent;
use Thelia\Core\Event\Sale\SaleEvent;
use Thelia\Core\Event\Sale\SaleToggleActivityEvent;
use Thelia\Core\Event\Sale\SaleUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Sale\SaleModificationForm;
use Thelia\Model\Sale;
use Thelia\Model\SaleProduct;
use Thelia\Model\SaleQuery;
/**
* Class SaleController
* @package Thelia\Controller\Admin
* @author Franck Allimant <franck@cqfdev.fr>
*/
class SaleController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'sale',
'start-date',
'order',
AdminResources::SALES,
TheliaEvents::SALE_CREATE,
TheliaEvents::SALE_UPDATE,
TheliaEvents::SALE_DELETE
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::SALE_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::SALE_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param Sale $sale
* @return SaleModificationForm
*/
protected function hydrateObjectForm($sale)
{
// Find all categories of the selected products
$saleProducts = $sale->getSaleProductList();
$categories = $products = [ ];
/** @var SaleProduct $saleProduct */
foreach ($saleProducts as $saleProduct) {
$categories[] = $saleProduct->getProduct()->getDefaultCategoryId();
$products[$saleProduct->getProduct()->getId()] = $saleProduct->getProduct()->getId();
}
$dateFormat = SaleModificationForm::PHP_DATE_FORMAT;
// Transform the selected attributes list (product_id => array of attributes av id) into
// product_id => comma separated list of attributes av id, to math the collection type (text)
$saleProductsAttributesAvs = $sale->getSaleProductsAttributeList();
$product_attributes = [];
foreach ($saleProductsAttributesAvs as $productId => $saleProductsAttributesAv) {
$product_attributes[$productId] = implode(',', $saleProductsAttributesAv);
}
// Prepare the data that will hydrate the form
$data = [
'id' => $sale->getId(),
'locale' => $sale->getLocale(),
'title' => $sale->getTitle(),
'label' => $sale->getSaleLabel(),
'chapo' => $sale->getChapo(),
'description' => $sale->getDescription(),
'postscriptum' => $sale->getPostscriptum(),
'active' => $sale->getActive(),
'display_initial_price' => $sale->getDisplayInitialPrice(),
'start_date' => $sale->getStartDate($dateFormat),
'end_date' => $sale->getEndDate($dateFormat),
'price_offset_type' => $sale->getPriceOffsetType(),
'price_offset' => $sale->getPriceOffsets(),
'categories' => $categories,
'products' => $products,
'product_attributes' => $product_attributes
];
// Setup the object form
return $this->createForm(AdminForm::SALE_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param array $formData
* @return SaleCreateEvent
*/
protected function getCreationEvent($formData)
{
$saleCreateEvent = new SaleCreateEvent();
$saleCreateEvent
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setSaleLabel($formData['label'])
;
return $saleCreateEvent;
}
/**
* Creates the update event with the provided form data
*
* @param array $formData
* @return SaleUpdateEvent
*/
protected function getUpdateEvent($formData)
{
// Build the product attributes array
$productAttributes = [];
foreach ($formData['product_attributes'] as $productId => $attributeAvIdList) {
if (! empty($attributeAvIdList)) {
$productAttributes[$productId] = explode(',', $attributeAvIdList);
}
}
$saleUpdateEvent = new SaleUpdateEvent($formData['id']);
$saleUpdateEvent
->setStartDate($formData['start_date'])
->setEndDate($formData['end_date'])
->setActive($formData['active'])
->setDisplayInitialPrice($formData['display_initial_price'])
->setPriceOffsetType($formData['price_offset_type'])
->setPriceOffsets($formData['price_offset'])
->setProducts($formData['products'])
->setProductAttributes($productAttributes)
->setLocale($formData['locale'])
->setTitle($formData['title'])
->setSaleLabel($formData['label'])
->setChapo($formData['chapo'])
->setDescription($formData['description'])
->setPostscriptum($formData['postscriptum'])
;
return $saleUpdateEvent;
}
/**
* Creates the delete event with the provided form data
*
* @return SaleDeleteEvent
*/
protected function getDeleteEvent()
{
return new SaleDeleteEvent($this->getRequest()->get('sale_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param SaleEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
return $event->hasSale();
}
/**
* Get the created object from an event.
*
* @param $event \Thelia\Core\Event\Sale\SaleEvent
*
* @return null|\Thelia\Model\Sale
*/
protected function getObjectFromEvent($event)
{
return $event->getSale();
}
/**
* Load an existing object from the database
*
* @return \Thelia\Model\Sale
*/
protected function getExistingObject()
{
$sale = SaleQuery::create()
->findOneById($this->getRequest()->get('sale_id', 0));
if (null !== $sale) {
$sale->setLocale($this->getCurrentEditionLocale());
}
return $sale;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param Sale $object
*
* @return string sale title
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param Sale $object
*
* @return int sale id
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param string $currentOrder, if any, null otherwise.
*
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
$this->getListOrderFromSession('sale', 'order', 'start-date');
return $this->render('sales', [
'order' => $currentOrder,
]);
}
protected function getEditionArguments()
{
return [
'sale_id' => $this->getRequest()->get('sale_id', 0)
];
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('sale-edit', $this->getEditionArguments());
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute('admin.sale.update', [], $this->getEditionArguments());
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.sale.default');
}
/**
* Toggle activity status of the sale.
*
* @return Response
*/
public function toggleActivity()
{
if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) {
return $response;
}
try {
$this->dispatch(
TheliaEvents::SALE_TOGGLE_ACTIVITY,
new SaleToggleActivityEvent(
$this->getExistingObject()
)
);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->nullResponse();
}
public function updateProductList()
{
if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) {
return $response;
}
// Build the list of categories
$categories = '';
foreach ($this->getRequest()->get('categories', []) as $category_id) {
$categories .= $category_id . ',';
}
return $this->render(
'ajax/sale-edit-products',
[
'sale_id' => $this->getRequest()->get('sale_id'),
'category_list' => rtrim($categories, ','),
'product_list' => $this->getRequest()->get('products', [])
]
);
}
public function updateProductAttributes()
{
if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) {
return $response;
}
$selectedAttributesAvId = explode(',', $this->getRequest()->get('selected_attributes_av_id', []));
$productId = $this->getRequest()->get('product_id');
return $this->render(
'ajax/sale-edit-product-attributes',
[
'product_id' => $productId,
'selected_attributes_av_id' => $selectedAttributesAvId
]
);
}
public function resetSaleStatus()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::SALES, [], AccessManager::UPDATE)) {
return $response;
}
try {
$this->dispatch(
TheliaEvents::SALE_CLEAR_SALE_STATUS,
new SaleClearStatusEvent()
);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
public function checkSalesActivationStatus()
{
// We do not check auth, as the related route may be invoked from a cron
try {
$this->dispatch(
TheliaEvents::CHECK_SALE_ACTIVATION_EVENT,
new SaleActiveStatusCheckEvent()
);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToListTemplate();
}
}

View File

@@ -0,0 +1,317 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Action\Administrator;
use Thelia\Core\Event\Administrator\AdministratorEvent;
use Thelia\Core\Event\Administrator\AdministratorUpdatePasswordEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Authentication\AdminUsernamePasswordFormAuthenticator;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\User\UserInterface;
use Thelia\Exception\TheliaProcessException;
use Thelia\Form\AdminLogin;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\Admin;
use Thelia\Model\AdminLog;
use Thelia\Model\AdminQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
class SessionController extends BaseAdminController
{
use \Thelia\Tools\RememberMeTrait;
const ADMIN_TOKEN_SESSION_VAR_NAME = 'thelia_admin_password_renew_token';
protected function checkAdminLoggedIn()
{
// Check if user is already authenticate
if ($this->getSecurityContext()->hasAdminUser()) {
// Redirect to the homepage
return new RedirectResponse($this->retrieveUrlFromRouteId('admin.home.view'));
}
return null;
}
protected function checkPasswordRecoveryEnabled()
{
// Check if user is already authenticate
if (!\boolval(ConfigQuery::read('enable_lost_admin_password_recovery', false))) {
AdminLog::append(
"admin",
"ADMIN_CREATE_PASSWORD",
"Lost password recovery function invoked",
$this->getRequest()
);
// Redirect to the error page
return $this->errorPage($this->getTranslator()->trans("The lost admin password recovery feature is disabled."), 403);
}
}
public function showLoginAction()
{
if (null !== $response = $this->checkAdminLoggedIn()) {
return $response;
}
return $this->render("login");
}
public function showLostPasswordAction()
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
return $this->render("lost-password");
}
public function passwordCreateRequestAction()
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
$adminLostPasswordForm = $this->createForm(AdminForm::ADMIN_LOST_PASSWORD);
try {
$form = $this->validateForm($adminLostPasswordForm, "post");
$data = $form->getData();
// Check if user exists
if (null === $admin = AdminQuery::create()->findOneByEmail($data['username_or_email'])) {
$admin = AdminQuery::create()->findOneByLogin($data['username_or_email']);
}
if (null === $admin) {
throw new \Exception($this->getTranslator()->trans("Invalid username or email."));
}
$email = $admin->getEmail();
if (empty($email)) {
throw new \Exception($this->getTranslator()->trans("Sorry, no email defined for this administrator."));
}
$this->dispatch(TheliaEvents::ADMINISTRATOR_CREATEPASSWORD, new AdministratorEvent($admin));
// Redirect to the success URL
return $this->generateSuccessRedirect($adminLostPasswordForm);
} catch (FormValidationException $ex) {
// Validation problem
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Log failure
AdminLog::append("admin", "ADMIN_LOST_PASSWORD", $ex->getMessage(), $this->getRequest());
$message = $ex->getMessage();
}
$this->setupFormErrorContext("Admin password create request", $message, $adminLostPasswordForm, $ex);
return $this->render("lost-password");
}
public function passwordCreateRequestSuccessAction()
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
return $this->render("lost-password", [ 'create_request_success' => true ]);
}
public function displayCreateFormAction($token)
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
// Check the token
if (null == $admin = AdminQuery::create()->findOneByPasswordRenewToken($token)) {
return $this->render(
"lost-password",
[ 'token_error' => true ]
);
}
$this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, $token);
return $this->render("create-password");
}
public function passwordCreatedAction()
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
$adminCreatePasswordForm = $this->createForm(AdminForm::ADMIN_CREATE_PASSWORD);
try {
$form = $this->validateForm($adminCreatePasswordForm, "post");
$data = $form->getData();
$token = $this->getSession()->get(self::ADMIN_TOKEN_SESSION_VAR_NAME);
if (empty($token) || null === $admin = AdminQuery::create()->findOneByPasswordRenewToken($token)) {
throw new \Exception($this->getTranslator()->trans("An invalid token was provided, your password cannot be changed"));
}
$event = new AdministratorUpdatePasswordEvent($admin);
$event->setPassword($data['password']);
$this->dispatch(TheliaEvents::ADMINISTRATOR_UPDATEPASSWORD, $event);
$this->getSession()->set(self::ADMIN_TOKEN_SESSION_VAR_NAME, null);
return $this->generateSuccessRedirect($adminCreatePasswordForm);
} catch (FormValidationException $ex) {
// Validation problem
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Log authentication failure
AdminLog::append("admin", "ADMIN_CREATE_PASSWORD", $ex->getMessage(), $this->getRequest());
$message = $ex->getMessage();
}
$this->setupFormErrorContext("Login process", $message, $adminCreatePasswordForm, $ex);
return $this->render("create-password");
}
public function passwordCreatedSuccessAction()
{
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
return $this->render("create-password-success");
}
public function checkLogoutAction()
{
$this->dispatch(TheliaEvents::ADMIN_LOGOUT);
$this->getSecurityContext()->clearAdminUser();
// Clear the remember me cookie, if any
$this->clearRememberMeCookie($this->getRememberMeCookieName());
// Go back to login page.
return $this->generateRedirectFromRoute('admin.login');
}
public function checkLoginAction()
{
$request = $this->getRequest();
$adminLoginForm = new AdminLogin($request);
try {
$form = $this->validateForm($adminLoginForm, "post");
$authenticator = new AdminUsernamePasswordFormAuthenticator($request, $adminLoginForm);
/** @var Admin $user */
$user = $authenticator->getAuthentifiedUser();
// Success -> store user in security context
$this->getSecurityContext()->setAdminUser($user);
// Log authentication success
AdminLog::append("admin", "LOGIN", "Authentication successful", $request, $user, false);
$this->applyUserLocale($user);
if (\intval($form->get('remember_me')->getData()) > 0) {
// If a remember me field if present and set in the form, create
// the cookie thant store "remember me" information
$this->createRememberMeCookie(
$user,
$this->getRememberMeCookieName(),
$this->getRememberMeCookieExpiration()
);
}
$this->dispatch(TheliaEvents::ADMIN_LOGIN);
// Check if we have to ask the user to set its address email.
// This is the case if Thelia has been updated from a pre 2.3.0 version
if (false === strpos($user->getEmail(), '@')) {
return $this->generateRedirectFromRoute('admin.set-email-address');
}
// Redirect to the success URL, passing the cookie if one exists.
return $this->generateSuccessRedirect($adminLoginForm);
} catch (FormValidationException $ex) {
// Validation problem
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (AuthenticationException $ex) {
// Log authentication failure
AdminLog::append("admin", "LOGIN", sprintf("Authentication failure for username '%s'", $authenticator->getUsername()), $request);
$message = $this->getTranslator()->trans("Login failed. Please check your username and password.");
} catch (\Exception $ex) {
// Log authentication failure
AdminLog::append("admin", "LOGIN", sprintf("Undefined error: %s", $ex->getMessage()), $request);
$message = $this->getTranslator()->trans(
"Unable to process your request. Please try again (%err).",
array("%err" => $ex->getMessage())
);
}
$this->setupFormErrorContext("Login process", $message, $adminLoginForm, $ex);
// Display the login form again
return $this->render("login");
}
/**
* Save user locale preference in session.
*
* @param UserInterface $user
*/
protected function applyUserLocale(UserInterface $user)
{
// Set the current language according to locale preference
$locale = $user->getLocale();
if (null === $lang = LangQuery::create()->findOneByLocale($locale)) {
$lang = Lang::getDefaultLanguage();
}
$this->getSession()->setLang($lang);
}
protected function getRememberMeCookieName()
{
return ConfigQuery::read('admin_remember_me_cookie_name', 'armcn');
}
protected function getRememberMeCookieExpiration()
{
return ConfigQuery::read('admin_remember_me_cookie_expiration', 2592000 /* 1 month */);
}
}

View File

@@ -0,0 +1,149 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\ShippingZone\ShippingZoneAddAreaEvent;
use Thelia\Core\Event\ShippingZone\ShippingZoneRemoveAreaEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\ShippingZone\ShippingZoneAddArea;
use Thelia\Form\ShippingZone\ShippingZoneRemoveArea;
/**
* Class ShippingZoneController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ShippingZoneController extends BaseAdminController
{
public $objectName = 'areaDeliveryModule';
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->render("shipping-zones", array("display_shipping_zone" => 20));
}
public function updateAction($delivery_module_id)
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->render(
"shipping-zones-edit",
["delivery_module_id" => $delivery_module_id]
);
}
/**
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function addArea()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) {
return $response;
}
$shippingAreaForm = new ShippingZoneAddArea($this->getRequest());
$error_msg = null;
try {
$form = $this->validateForm($shippingAreaForm);
$event = new ShippingZoneAddAreaEvent(
$form->get('area_id')->getData(),
$form->get('shipping_zone_id')->getData()
);
$this->dispatch(TheliaEvents::SHIPPING_ZONE_ADD_AREA, $event);
// Redirect to the success URL
return $this->generateSuccessRedirect($shippingAreaForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)),
$error_msg,
$shippingAreaForm
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
public function removeArea()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) {
return $response;
}
$shippingAreaForm = new ShippingZoneRemoveArea($this->getRequest());
$error_msg = null;
try {
$form = $this->validateForm($shippingAreaForm);
$event = new ShippingZoneRemoveAreaEvent(
$form->get('area_id')->getData(),
$form->get('shipping_zone_id')->getData()
);
$this->dispatch(TheliaEvents::SHIPPING_ZONE_REMOVE_AREA, $event);
// Redirect to the success URL
return $this->generateSuccessRedirect($shippingAreaForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)),
$error_msg,
$shippingAreaForm
);
// At this point, the form has errors, and should be redisplayed.
return $this->renderEditionTemplate();
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render(
"shipping-zones-edit",
["delivery_module_id" => $this->getDeliveryModuleId()]
);
}
protected function getDeliveryModuleId()
{
return $this->getRequest()->get('delivery_module_id', 0);
}
}

View File

@@ -0,0 +1,244 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\State\StateCreateEvent;
use Thelia\Core\Event\State\StateDeleteEvent;
use Thelia\Core\Event\State\StateToggleVisibilityEvent;
use Thelia\Core\Event\State\StateUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\StateQuery;
/**
* Class StateController
* @package Thelia\Controller\Admin
* @author Julien Chanséaume <manu@raynaud.io>
*/
class StateController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'state',
'manual',
'state_order',
AdminResources::STATE,
TheliaEvents::STATE_CREATE,
TheliaEvents::STATE_UPDATE,
TheliaEvents::STATE_DELETE,
TheliaEvents::STATE_TOGGLE_VISIBILITY
);
}
/**
* Return the creation form for this object
*/
protected function getCreationForm()
{
return $this->createForm(AdminForm::STATE_CREATION);
}
/**
* Return the update form for this object
*/
protected function getUpdateForm()
{
return $this->createForm(AdminForm::STATE_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\State $object
*/
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'visible' => $object->getVisible() ? true : false,
'country_id' => $object->getCountryId(),
'title' => $object->getTitle(),
'isocode' => $object->getIsocode(),
);
return $this->createForm(AdminForm::STATE_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
*/
protected function getCreationEvent($formData)
{
$event = new StateCreateEvent();
return $this->hydrateEvent($event, $formData);
}
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
*/
protected function getUpdateEvent($formData)
{
$event = new StateUpdateEvent($formData['id']);
return $this->hydrateEvent($event, $formData);
}
protected function hydrateEvent($event, $formData)
{
$event
->setLocale($formData['locale'])
->setVisible($formData['visible'])
->setCountry($formData['country_id'])
->setTitle($formData['title'])
->setIsocode($formData['isocode'])
;
return $event;
}
/**
* Creates the delete event with the provided form data
*/
protected function getDeleteEvent()
{
return new StateDeleteEvent($this->getRequest()->get('state_id'));
}
/**
* Return true if the event contains the object, e.g. the action has updated the object in the event.
*
* @param unknown $event
*/
protected function eventContainsObject($event)
{
return $event->hasState();
}
/**
* Get the created object from an event.
*
* @param unknown $createEvent
*/
protected function getObjectFromEvent($event)
{
return $event->getState();
}
/**
* Load an existing object from the database
*/
protected function getExistingObject()
{
$state = StateQuery::create()
->findPk($this->getRequest()->get('state_id', 0))
;
if (null !== $state) {
$state->setLocale($this->getCurrentEditionLocale());
}
return $state;
}
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\State $object
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* Returns the object ID from the object
*
* @param \Thelia\Model\State $object
*/
protected function getObjectId($object)
{
return $object->getId();
}
/**
* Render the main list template
*
* @param unknown $currentOrder , if any, null otherwise.
*/
protected function renderListTemplate($currentOrder)
{
return $this->render(
"states",
array(
'page' => $this->getRequest()->get('page', 1),
"page_limit" => $this->getRequest()->get('page_limit', 50),
'page_order' => $this->getRequest()->get('page_order', 1)
)
);
}
/**
* Render the edition template
*/
protected function renderEditionTemplate()
{
return $this->render('state-edit', $this->getEditionArgument());
}
protected function getEditionArgument()
{
return array(
'state_id' => $this->getRequest()->get('state_id', 0),
'page' => $this->getRequest()->get('page', 1),
'page_order' => $this->getRequest()->get('page_order', 1)
);
}
/**
* Redirect to the edition template
*/
protected function redirectToEditionTemplate()
{
return $this->generateRedirectFromRoute(
'admin.configuration.states.update',
[],
[
"state_id" => $this->getRequest()->get('state_id', 0)
]
);
}
/**
* Redirect to the list template
*/
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.states.default');
}
/**
* @return StateToggleVisibilityEvent|void
*/
protected function createToggleVisibilityEvent()
{
return new StateToggleVisibilityEvent($this->getExistingObject());
}
}

View File

@@ -0,0 +1,165 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
/**
* Class LangController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class SystemLogController extends BaseAdminController
{
protected function renderTemplate()
{
$destinations = array();
$destination_directories = Tlog::getInstance()->getDestinationsDirectories();
foreach ($destination_directories as $dir) {
$this->loadDefinedDestinations($dir, $destinations);
}
$active_destinations = explode(";", ConfigQuery::read(Tlog::VAR_DESTINATIONS, Tlog::DEFAUT_DESTINATIONS));
return $this->render(
'system-logs',
array(
'ip_address' => $this->getRequest()->getClientIp(),
'destinations' => $destinations,
'active_destinations' => $active_destinations
)
);
}
protected function loadDefinedDestinations($directory, &$destinations)
{
try {
foreach (new \DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
$matches = array();
if (preg_match("/([^\.]+)\.php/", $fileInfo->getFilename(), $matches)) {
$classname = $matches[1];
if (! isset($destinations[$classname])) {
$full_class_name = "Thelia\\Log\\Destination\\".$classname;
$destinations[$classname] = new $full_class_name();
}
}
}
} catch (\UnexpectedValueException $ex) {
// Directory does no exists -> Nothing to do
}
}
/**
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::VIEW)) {
return $response;
}
// Hydrate the general configuration form
$systemLogForm = $this->createForm(AdminForm::SYSTEM_LOG_CONFIGURATION, 'form', array(
'level' => ConfigQuery::read(Tlog::VAR_LEVEL, Tlog::DEFAULT_LEVEL),
'format' => ConfigQuery::read(Tlog::VAR_PREFIXE, Tlog::DEFAUT_PREFIXE),
'show_redirections' => ConfigQuery::read(Tlog::VAR_SHOW_REDIRECT, Tlog::DEFAUT_SHOW_REDIRECT),
'files' => ConfigQuery::read(Tlog::VAR_FILES, Tlog::DEFAUT_FILES),
'ip_addresses' => ConfigQuery::read(Tlog::VAR_IP, Tlog::DEFAUT_IP),
));
$this->getParserContext()->addForm($systemLogForm);
return $this->renderTemplate();
}
public function saveAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$systemLogForm = $this->createForm(AdminForm::SYSTEM_LOG_CONFIGURATION);
try {
$form = $this->validateForm($systemLogForm);
$data = $form->getData();
ConfigQuery::write(Tlog::VAR_LEVEL, $data['level']);
ConfigQuery::write(Tlog::VAR_PREFIXE, $data['format']);
ConfigQuery::write(Tlog::VAR_SHOW_REDIRECT, $data['show_redirections']);
ConfigQuery::write(Tlog::VAR_FILES, $data['files']);
ConfigQuery::write(Tlog::VAR_IP, $data['ip_addresses']);
// Save destination configuration
$destinations = $this->getRequest()->get('destinations');
$configs = $this->getRequest()->get('config');
$active_destinations = array();
foreach ($destinations as $classname => $destination) {
if (isset($destination['active'])) {
$active_destinations[] = $destination['classname'];
}
if (isset($configs[$classname])) {
// Update destinations configuration
foreach ($configs[$classname] as $var => $value) {
ConfigQuery::write($var, $value, true, true);
}
}
}
// Update active destinations list
ConfigQuery::write(Tlog::VAR_DESTINATIONS, implode(';', $active_destinations));
$this->adminLogAppend(
AdminResources::SYSTEM_LOG,
AccessManager::UPDATE,
"System log configuration changed"
);
$response = $this->generateRedirectFromRoute('admin.configuration.system-logs.default');
} catch (\Exception $ex) {
$error_msg = $ex->getMessage();
}
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("System log configuration failed."),
$error_msg,
$systemLogForm,
$ex
);
$response = $this->renderTemplate();
}
return $response;
}
}

View File

@@ -0,0 +1,218 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Tax\TaxEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Tax;
use Thelia\Model\TaxQuery;
class TaxController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'tax',
'manual',
'order',
AdminResources::TAX,
TheliaEvents::TAX_CREATE,
TheliaEvents::TAX_UPDATE,
TheliaEvents::TAX_DELETE
);
}
protected function getCreationForm()
{
$form = $this->createForm(AdminForm::TAX_CREATION);
return $form;
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::TAX_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$event = new TaxEvent();
$event->setLocale($formData['locale']);
$event->setTitle($formData['title']);
$event->setDescription($formData['description']);
$event->setType(Tax::unescapeTypeName($formData['type']));
$event->setRequirements($this->getRequirements($formData['type'], $formData));
return $event;
}
protected function getUpdateEvent($formData)
{
$event = new TaxEvent();
$event->setLocale($formData['locale']);
$event->setId($formData['id']);
$event->setTitle($formData['title']);
$event->setDescription($formData['description']);
$event->setType(Tax::unescapeTypeName($formData['type']));
$event->setRequirements($this->getRequirements($formData['type'], $formData));
return $event;
}
protected function getDeleteEvent()
{
$event = new TaxEvent();
$event->setId(
$this->getRequest()->get('tax_id', 0)
);
return $event;
}
protected function eventContainsObject($event)
{
return $event->hasTax();
}
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'description' => $object->getDescription(),
'type' => Tax::escapeTypeName($object->getType()),
);
// Setup the object form
return $this->createForm(
AdminForm::TAX_MODIFICATION,
"form",
$data
);
}
protected function getObjectFromEvent($event)
{
return $event->hasTax() ? $event->getTax() : null;
}
protected function getExistingObject()
{
$tax = TaxQuery::create()
->findOneById($this->getRequest()->get('tax_id', 0));
if (null !== $tax) {
$tax->setLocale($this->getCurrentEditionLocale());
}
return $tax;
}
/**
* @param Tax $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param Tax $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments()
{
return array();
}
protected function getRouteArguments($tax_id = null)
{
return array(
'tax_id' => $tax_id === null ? $this->getRequest()->get('tax_id') : $tax_id,
);
}
protected function renderListTemplate($currentOrder)
{
return $this->render(
'taxes-rules',
array()
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('tax-edit', array_merge($this->getViewArguments(), $this->getRouteArguments()));
}
protected function redirectToEditionTemplate($request = null, $country = null)
{
return $this->generateRedirectFromRoute(
"admin.configuration.taxes.update",
$this->getViewArguments($country),
$this->getRouteArguments()
);
}
/**
* Put in this method post object creation processing if required.
*
* @param TaxEvent $createEvent the create event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalCreateAction($createEvent)
{
return $this->generateRedirectFromRoute(
"admin.configuration.taxes.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getTax()->getId())
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list");
}
protected function getRequirements($type, $formData)
{
$requirements = array();
foreach ($formData as $data => $value) {
if (!strstr($data, ':')) {
continue;
}
$couple = explode(':', $data);
if (\count($couple) == 2 && $couple[0] == $type) {
$requirements[$couple[1]] = $value;
}
}
return $requirements;
}
}

View File

@@ -0,0 +1,422 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Tax\TaxRuleEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\CountryQuery;
use Thelia\Model\ProductQuery;
use Thelia\Model\TaxRule;
use Thelia\Model\TaxRuleCountryQuery;
use Thelia\Model\TaxRuleQuery;
class TaxRuleController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'taxrule',
'manual',
'order',
AdminResources::TAX,
TheliaEvents::TAX_RULE_CREATE,
TheliaEvents::TAX_RULE_UPDATE,
TheliaEvents::TAX_RULE_DELETE
);
}
public function defaultAction()
{
// In the tax rule template we use the TaxCreationForm.
//
// The TaxCreationForm require the TaxEngine, but we cannot pass it from the Parser Form plugin,
// as the container is not passed to forms by this plugin.
//
// So we create an instance of TaxCreationForm here (we have the container), and put it in the ParserContext.
// This way, the Form plugin will use this instance, instead on creating it.
$taxCreationForm = $this->createForm(AdminForm::TAX_CREATION);
$this->getParserContext()->addForm($taxCreationForm);
return parent::defaultAction();
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::TAX_RULE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::TAX_RULE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$event = new TaxRuleEvent();
$event->setLocale($formData['locale']);
$event->setTitle($formData['title']);
$event->setDescription($formData['description']);
return $event;
}
protected function getUpdateEvent($formData)
{
$event = new TaxRuleEvent();
$event->setLocale($formData['locale']);
$event->setId($formData['id']);
$event->setTitle($formData['title']);
$event->setDescription($formData['description']);
return $event;
}
protected function getUpdateTaxListEvent($formData)
{
$event = new TaxRuleEvent();
$event->setId($formData['id']);
$event->setTaxList($formData['tax_list']);
$event->setCountryList($formData['country_list']);
$event->setCountryDeletedList($formData['country_deleted_list']);
return $event;
}
protected function getDeleteEvent()
{
$event = new TaxRuleEvent();
$event->setId(
$this->getRequest()->get('tax_rule_id', 0)
);
return $event;
}
protected function eventContainsObject($event)
{
return $event->hasTaxRule();
}
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'title' => $object->getTitle(),
'description' => $object->getDescription(),
);
// Setup the object form
return $this->createForm(AdminForm::TAX_RULE_MODIFICATION, "form", $data);
}
/**
* @param TaxRule $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateTaxUpdateForm($object)
{
$data = array(
'id' => $object->getId(),
);
// Setup the object form
return $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasTaxRule() ? $event->getTaxRule() : null;
}
protected function getExistingObject()
{
$taxRule = TaxRuleQuery::create()
->findOneById($this->getRequest()->get('tax_rule_id'));
if (null !== $taxRule) {
$taxRule->setLocale($this->getCurrentEditionLocale());
}
return $taxRule;
}
/**
* @param TaxRule $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getTitle();
}
/**
* @param TaxRule $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function getViewArguments($country = null, $tab = null, $state = null)
{
return array(
'tab' => $tab === null ? $this->getRequest()->get('tab', 'data') : $tab,
'country' => $country === null ? $this->getRequest()->get('country', CountryQuery::create()->findOneByByDefault(1)->getId()) : $country,
'state' => $state,
);
}
protected function getRouteArguments($tax_rule_id = null)
{
return array(
'tax_rule_id' => $tax_rule_id === null ? $this->getRequest()->get('tax_rule_id') : $tax_rule_id,
);
}
protected function renderListTemplate($currentOrder)
{
// We always return to the feature edition form
return $this->render(
'taxes-rules',
array()
);
}
protected function renderEditionTemplate()
{
// We always return to the feature edition form
return $this->render('tax-rule-edit', array_merge($this->getViewArguments(), $this->getRouteArguments()));
}
protected function redirectToEditionTemplate($request = null, $country = null, $state = null)
{
return $this->generateRedirectFromRoute(
"admin.configuration.taxes-rules.update",
$this->getViewArguments($country, null, $state),
$this->getRouteArguments()
);
}
/**
* Put in this method post object creation processing if required.
*
* @param TaxRuleEvent $createEvent the create event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalCreateAction($createEvent)
{
return $this->generateRedirectFromRoute(
"admin.configuration.taxes-rules.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getTaxRule()->getId())
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list");
}
public function updateAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$object = $this->getExistingObject();
if ($object != null) {
// Hydrate the form abd pass it to the parser
$changeTaxesForm = $this->hydrateTaxUpdateForm($object);
// Pass it to the parser
$this->getParserContext()->addForm($changeTaxesForm);
}
return parent::updateAction();
}
public function setDefaultAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$setDefaultEvent = new TaxRuleEvent();
$taxRuleId = $this->getRequest()->attributes->get('tax_rule_id');
$setDefaultEvent->setId(
$taxRuleId
);
$this->dispatch(TheliaEvents::TAX_RULE_SET_DEFAULT, $setDefaultEvent);
return $this->redirectToListTemplate();
}
public function processUpdateTaxesAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$responseData = [
"success" => false,
"message" => ''
];
$error_msg = false;
// Create the form from the request
$changeForm = $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE);
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
// Get the form field values
$data = $form->getData();
$changeEvent = $this->getUpdateTaxListEvent($data);
$this->dispatch(TheliaEvents::TAX_RULE_TAXES_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName))
);
}
// Log object modification
if (null !== $changedObject = $this->getObjectFromEvent($changeEvent)) {
$this->adminLogAppend(
$this->resourceCode,
AccessManager::UPDATE,
sprintf(
"%s %s (ID %s) modified",
ucfirst($this->objectName),
$this->getObjectLabel($changedObject),
$this->getObjectId($changedObject)
),
$this->getObjectId($changedObject)
);
}
$responseData['success'] = true;
$responseData['data'] = $this->getSpecification(
$changeEvent->getTaxRule()->getId()
);
return $this->jsonResponse(json_encode($responseData));
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext($this->getTranslator()->trans("%obj modification", array('%obj' => 'taxrule')), $error_msg, $changeForm, $ex);
// At this point, the form has errors, and should be redisplayed.
$responseData["message"] = $error_msg;
return $this->jsonResponse(json_encode($responseData));
}
/**
* @return Response
*/
public function specsAction($taxRuleId)
{
$data = $this->getSpecification($taxRuleId);
return $this->jsonResponse(json_encode($data));
}
protected function getSpecification($taxRuleId)
{
$taxRuleCountries = TaxRuleCountryQuery::create()
->filterByTaxRuleId($taxRuleId)
->orderByCountryId()
->orderByStateId()
->orderByPosition()
->orderByTaxId()
->find();
$specKey = [];
$specifications = [];
$taxRules = [];
if (!$taxRuleCountries->isEmpty()) {
$taxRuleCountry = $taxRuleCountries->getFirst();
$currentCountryId = $taxRuleCountry->getCountryId();
$currentStateId = \intval($taxRuleCountry->getStateId());
while (true) {
$hasChanged = $taxRuleCountry === null
|| $taxRuleCountry->getCountryId() != $currentCountryId
|| \intval($taxRuleCountry->getStateId()) != $currentStateId
;
if ($hasChanged) {
$specification = implode(',', $specKey);
$specifications[] = [
'country' => $currentCountryId,
'state' => $currentStateId,
'specification' => $specification
];
if (!\in_array($specification, $taxRules)) {
$taxRules[] = $specification;
}
if (null === $taxRuleCountry) {
break;
}
$currentCountryId = $taxRuleCountry->getCountryId();
$currentStateId = \intval($taxRuleCountry->getStateId());
$specKey = [];
}
$specKey[] = $taxRuleCountry->getTaxId() . '-' . $taxRuleCountry->getPosition();
$taxRuleCountry = $taxRuleCountries->getNext();
}
}
$data = [
'taxRules' => $taxRules,
'specifications' => $specifications,
];
return $data;
}
}

View File

@@ -0,0 +1,373 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Template\TemplateAddAttributeEvent;
use Thelia\Core\Event\Template\TemplateAddFeatureEvent;
use Thelia\Core\Event\Template\TemplateCreateEvent;
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
use Thelia\Core\Event\Template\TemplateDeleteEvent;
use Thelia\Core\Event\Template\TemplateDeleteFeatureEvent;
use Thelia\Core\Event\Template\TemplateDuplicateEvent;
use Thelia\Core\Event\Template\TemplateUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\AttributeTemplateQuery;
use Thelia\Model\FeatureTemplateQuery;
use Thelia\Model\Template;
use Thelia\Model\TemplateQuery;
/**
* Manages product templates
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class TemplateController extends AbstractCrudController
{
public function __construct()
{
parent::__construct(
'template',
null,
null,
AdminResources::TEMPLATE,
TheliaEvents::TEMPLATE_CREATE,
TheliaEvents::TEMPLATE_UPDATE,
TheliaEvents::TEMPLATE_DELETE,
null, // No visibility toggle
null // No position update
);
}
protected function getCreationForm()
{
return $this->createForm(AdminForm::TEMPLATE_CREATION);
}
protected function getUpdateForm()
{
return $this->createForm(AdminForm::TEMPLATE_MODIFICATION);
}
protected function getCreationEvent($formData)
{
$createEvent = new TemplateCreateEvent();
$createEvent
->setTemplateName($formData['name'])
->setLocale($formData["locale"])
;
return $createEvent;
}
protected function getUpdateEvent($formData)
{
$changeEvent = new TemplateUpdateEvent($formData['id']);
// Create and dispatch the change event
$changeEvent
->setLocale($formData["locale"])
->setTemplateName($formData['name'])
;
// Add feature and attributes list
return $changeEvent;
}
protected function getDeleteEvent()
{
return new TemplateDeleteEvent($this->getRequest()->get('template_id'));
}
protected function eventContainsObject($event)
{
return $event->hasTemplate();
}
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
'name' => $object->getName()
);
// Setup the object form
return $this->createForm(AdminForm::TEMPLATE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
{
return $event->hasTemplate() ? $event->getTemplate() : null;
}
protected function getExistingObject()
{
$template = TemplateQuery::create()
->findOneById($this->getRequest()->get('template_id', 0));
if (null !== $template) {
$template->setLocale($this->getCurrentEditionLocale());
}
return $template;
}
/**
* @param Template $object
* @return string
*/
protected function getObjectLabel($object)
{
return $object->getName();
}
/**
* @param Template $object
* @return int
*/
protected function getObjectId($object)
{
return $object->getId();
}
protected function renderListTemplate($currentOrder)
{
return $this->render('templates', array('order' => $currentOrder));
}
protected function renderEditionTemplate()
{
return $this->render(
'template-edit',
array(
'template_id' => $this->getRequest()->get('template_id'),
)
);
}
/**
* @param Request $request
* @param int $id
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function redirectToEditionTemplate($request = null, $id = null)
{
return $this->generateRedirectFromRoute(
"admin.configuration.templates.update",
[
'template_id' => $id ?: $this->getRequest()->get('template_id'),
]
);
}
protected function redirectToListTemplate()
{
return $this->generateRedirectFromRoute('admin.configuration.templates.default');
}
/**
* Process delete failure, which may occurs if template is in use.
*
* @param TemplateDeleteEvent $deleteEvent
* @return null|\Thelia\Core\HttpFoundation\Response
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
if ($deleteEvent->getProductCount() > 0) {
$this->getParserContext()->setGeneralError(
$this->getTranslator()->trans(
"This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again."
)
);
return $this->renderList();
}
// Normal delete processing
return null;
}
public function duplicateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::CREATE)) {
return $response;
}
$template_id = \intval($this->getRequest()->get('template_id'));
if ($template_id > 0) {
try {
$event = new TemplateDuplicateEvent($template_id, $this->getCurrentEditionLocale());
$this->dispatch(TheliaEvents::TEMPLATE_DUPLICATE, $event);
if ($event->hasTemplate()) {
$template_id = $event->getTemplate()->getId();
}
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
return $this->redirectToEditionTemplate(null, $template_id);
}
public function getAjaxFeaturesAction()
{
return $this->render(
'ajax/template-feature-list',
array('template_id' => $this->getRequest()->get('template_id'))
);
}
public function getAjaxAttributesAction()
{
return $this->render(
'ajax/template-attribute-list',
array('template_id' => $this->getRequest()->get('template_id'))
);
}
public function addAttributeAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$attribute_id = \intval($this->getRequest()->get('attribute_id'));
if ($attribute_id > 0) {
$event = new TemplateAddAttributeEvent(
$this->getExistingObject(),
$attribute_id
);
try {
$this->dispatch(TheliaEvents::TEMPLATE_ADD_ATTRIBUTE, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
return $this->redirectToEditionTemplate();
}
public function deleteAttributeAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new TemplateDeleteAttributeEvent(
$this->getExistingObject(),
\intval($this->getRequest()->get('attribute_id'))
);
try {
$this->dispatch(TheliaEvents::TEMPLATE_DELETE_ATTRIBUTE, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToEditionTemplate();
}
public function updateAttributePositionAction()
{
// Find attribute_template
$attributeTemplate = AttributeTemplateQuery::create()
->filterByTemplateId($this->getRequest()->get('template_id', null))
->filterByAttributeId($this->getRequest()->get('attribute_id', null))
->findOne()
;
return $this->genericUpdatePositionAction(
$attributeTemplate,
TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION
);
}
public function addFeatureAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$feature_id = \intval($this->getRequest()->get('feature_id'));
if ($feature_id > 0) {
$event = new TemplateAddFeatureEvent(
$this->getExistingObject(),
$feature_id
);
try {
$this->dispatch(TheliaEvents::TEMPLATE_ADD_FEATURE, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
}
return $this->redirectToEditionTemplate();
}
public function deleteFeatureAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new TemplateDeleteFeatureEvent(
$this->getExistingObject(),
\intval($this->getRequest()->get('feature_id'))
);
try {
$this->dispatch(TheliaEvents::TEMPLATE_DELETE_FEATURE, $event);
} catch (\Exception $ex) {
// Any error
return $this->errorPage($ex);
}
return $this->redirectToEditionTemplate();
}
public function updateFeaturePositionAction()
{
// Find feature_template
$featureTemplate = FeatureTemplateQuery::create()
->filterByTemplateId($this->getRequest()->get('template_id', null))
->filterByFeatureId($this->getRequest()->get('feature_id', null))
->findOne()
;
return $this->genericUpdatePositionAction(
$featureTemplate,
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
/**
* Class ToolsController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ToolsController extends BaseAdminController
{
public function indexAction()
{
if (null !== $response = $this->checkAuth([AdminResources::TOOLS], [], [AccessManager::VIEW])) {
return $response;
}
return $this->render('tools');
}
}

View File

@@ -0,0 +1,359 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Symfony\Component\Finder\Finder;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Translation\TranslationEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Core\Translation\Translator;
use Thelia\Model\Module;
use Thelia\Model\ModuleQuery;
use Thelia\Tools\URL;
/**
* Class TranslationsController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <manu@raynaud.io>
*/
class TranslationsController extends BaseAdminController
{
/**
* @param string $itemName the modume code
* @return Module the module object
* @throws \InvalidArgumentException if module was not found
*/
protected function getModule($itemName)
{
if (null !== $module = ModuleQuery::create()->findPk($itemName)) {
return $module;
}
throw new \InvalidArgumentException(
$this->getTranslator()->trans("No module found for code '%item'", ['%item' => $itemName])
);
}
protected function getModuleTemplateNames(Module $module, $templateType)
{
$templates =
$this->getTemplateHelper()->getList(
$templateType,
$module->getAbsoluteTemplateBasePath()
);
$names = [];
foreach ($templates as $template) {
$names[] = $template->getName();
}
return $names;
}
protected function renderTemplate()
{
// Get related strings, if all input data are here
$itemToTranslate = $this->getRequest()->get('item_to_translate');
$itemName = $this->getRequest()->get('item_name', '');
if ($itemToTranslate == 'mo' && ! empty($itemName)) {
$modulePart = $this->getRequest()->get('module_part', '');
} else {
$modulePart = false;
}
$template = $directory = $i18nDirectory = false;
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
$templateArguments = array(
'item_to_translate' => $itemToTranslate,
'item_name' => $itemName,
'module_part' => $modulePart,
'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only'),
'max_input_vars_warning' => false,
);
// Find the i18n directory, and the directory to examine.
if (! empty($itemName) || $itemToTranslate == 'co' || $itemToTranslate == 'in' || $itemToTranslate == 'wi') {
switch ($itemToTranslate) {
// Module core
case 'mo':
$module = $this->getModule($itemName);
if ($modulePart == 'core') {
$directory = $module->getAbsoluteBaseDir();
$domain = $module->getTranslationDomain();
$i18nDirectory = $module->getAbsoluteI18nPath();
$walkMode = TranslationEvent::WALK_MODE_PHP;
} elseif ($modulePart == 'admin-includes') {
$directory = $module->getAbsoluteAdminIncludesPath();
$domain = $module->getAdminIncludesTranslationDomain();
$i18nDirectory = $module->getAbsoluteAdminIncludesI18nPath();
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
} elseif (! empty($modulePart)) {
// Front, back, pdf or email office template,
// form of $module_part is [bo|fo|pdf|email].subdir-name
list($type, $subdir) = explode('.', $modulePart);
switch ($type) {
case 'bo':
$directory = $module->getAbsoluteBackOfficeTemplatePath($subdir);
$domain = $module->getBackOfficeTemplateTranslationDomain($subdir);
$i18nDirectory = $module->getAbsoluteBackOfficeI18nTemplatePath($subdir);
break;
case 'fo':
$directory = $module->getAbsoluteFrontOfficeTemplatePath($subdir);
$domain = $module->getFrontOfficeTemplateTranslationDomain($subdir);
$i18nDirectory = $module->getAbsoluteFrontOfficeI18nTemplatePath($subdir);
break;
case 'email':
$directory = $module->getAbsoluteEmailTemplatePath($subdir);
$domain = $module->getEmailTemplateTranslationDomain($subdir);
$i18nDirectory = $module->getAbsoluteEmailI18nTemplatePath($subdir);
break;
case 'pdf':
$directory = $module->getAbsolutePdfTemplatePath($subdir);
$domain = $module->getPdfTemplateTranslationDomain($subdir);
$i18nDirectory = $module->getAbsolutePdfI18nTemplatePath($subdir);
break;
default:
throw new \InvalidArgumentException("Undefined module template type: '$type'.");
}
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
}
// Modules translations files are in the cache, and are not always
// updated. Force a reload of the files to get last changes.
if (! empty($domain)) {
$this->loadTranslation($i18nDirectory, $domain);
}
// List front and back office templates defined by this module
$templateArguments['back_office_templates'] =
implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::BACK_OFFICE));
$templateArguments['front_office_templates'] =
implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::FRONT_OFFICE));
$templateArguments['email_templates'] =
implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::EMAIL));
$templateArguments['pdf_templates'] =
implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::PDF));
// Check if we have admin-include files
try {
$finder = Finder::create()
->files()
->depth(0)
->in($module->getAbsoluteAdminIncludesPath())
->name('/\.html$/i')
;
$hasAdminIncludes = $finder->count() > 0;
} catch (\InvalidArgumentException $ex) {
$hasAdminIncludes = false;
}
$templateArguments['has_admin_includes'] = $hasAdminIncludes;
break;
// Thelia Core
case 'co':
$directory = THELIA_LIB;
$domain = 'core';
$i18nDirectory = THELIA_LIB . 'Config' . DS . 'I18n';
$walkMode = TranslationEvent::WALK_MODE_PHP;
break;
// Thelia Install
case 'in':
$directory = THELIA_SETUP_DIRECTORY;
$domain = 'install';
$i18nDirectory = THELIA_SETUP_DIRECTORY . 'I18n';
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
// resources not loaded by default
$this->loadTranslation($i18nDirectory, $domain);
break;
// Thelia Install wizard
case 'wi':
$directory = THELIA_SETUP_WIZARD_DIRECTORY;
$domain = 'wizard';
$i18nDirectory = THELIA_SETUP_WIZARD_DIRECTORY . 'I18n';
$walkMode = TranslationEvent::WALK_MODE_PHP;
// resources not loaded by default
$this->loadTranslation($i18nDirectory, $domain);
break;
// Front-office template
case 'fo':
$template = new TemplateDefinition($itemName, TemplateDefinition::FRONT_OFFICE);
break;
// Back-office template
case 'bo':
$template = new TemplateDefinition($itemName, TemplateDefinition::BACK_OFFICE);
break;
// PDF templates
case 'pf':
$template = new TemplateDefinition($itemName, TemplateDefinition::PDF);
break;
// Email templates
case 'ma':
$template = new TemplateDefinition($itemName, TemplateDefinition::EMAIL);
break;
}
if ($template) {
$directory = $template->getAbsolutePath();
$i18nDirectory = $template->getAbsoluteI18nPath();
$domain = $template->getTranslationDomain();
// Load translations files if this template is not the current template
// as it is not loaded in Thelia.php
if (! $this->getTemplateHelper()->isActive($template)) {
$this->loadTranslation($i18nDirectory, $domain);
}
}
// Load strings to translate
if ($directory && ! empty($domain)) {
// Save the string set, if the form was submitted
if ($i18nDirectory) {
$save_mode = $this->getRequest()->get('save_mode', false);
if ($save_mode !== false) {
$texts = $this->getRequest()->get('text', array());
if (! empty($texts)) {
$event = TranslationEvent::createWriteFileEvent(
sprintf("%s".DS."%s.php", $i18nDirectory, $this->getCurrentEditionLocale()),
$texts,
$this->getRequest()->get('translation', []),
true
);
$event
->setDomain($domain)
->setLocale($this->getCurrentEditionLocale())
->setCustomFallbackStrings($this->getRequest()->get('translation_custom', []))
->setGlobalFallbackStrings($this->getRequest()->get('translation_global', []));
$this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_WRITE_FILE, $event);
if ($save_mode == 'stay') {
return $this->generateRedirectFromRoute(
"admin.configuration.translations",
$templateArguments
);
} else {
return $this->generateRedirect(URL::getInstance()->adminViewUrl('configuration'));
}
}
}
}
// Load strings
$event = TranslationEvent::createGetStringsEvent(
$directory,
$walkMode,
$this->getCurrentEditionLocale(),
$domain
);
$this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_GET_STRINGS, $event);
// Estimate number of fields, and compare to php ini max_input_vars
$stringsCount = $event->getTranslatableStringCount() * 4 + 6;
if ($stringsCount > ini_get('max_input_vars')) {
$templateArguments['max_input_vars_warning'] = true;
$templateArguments['required_max_input_vars'] = $stringsCount;
$templateArguments['current_max_input_vars'] = ini_get('max_input_vars');
} else {
$templateArguments['all_strings'] = $event->getTranslatableStrings();
}
$templateArguments['is_writable'] = $this->checkWritableI18nDirectory(THELIA_LOCAL_DIR . 'I18n');
}
}
return $this->render('translations', $templateArguments);
}
/**
* Check if a directory is writable or if the parent directory is writable
*
* @param string $dir the directory to test
* @return boolean return true if the directory is writable otr if the parent dir is writable.
*/
public function checkWritableI18nDirectory($dir)
{
if (file_exists($dir)) {
return is_writable($dir);
}
$parentDir = dirname($dir);
return file_exists($parentDir) && is_writable($parentDir);
}
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::TRANSLATIONS, array(), AccessManager::VIEW)) {
return $response;
}
return $this->renderTemplate();
}
public function updateAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
return $this->renderTemplate();
}
private function loadTranslation($directory, $domain)
{
try {
$finder = Finder::create()
->files()
->depth(0)
->in($directory);
/** @var \DirectoryIterator $file */
foreach ($finder as $file) {
list($locale, $format) = explode('.', $file->getBaseName(), 2);
Translator::getInstance()->addResource($format, $file->getPathname(), $locale, $domain);
}
} catch (\InvalidArgumentException $ex) {
// Ignore missing I18n directories
}
}
}

View File

@@ -0,0 +1,505 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Propel\Runtime\Propel;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\Security\AccessManager;
/**
* Class AbstractCrudApiController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
abstract class AbstractCrudApiController extends BaseApiController
{
/**
* @var string
*
* The entity name to display errors
*/
protected $objName;
/**
* @var mixed|array
*
* ACL resources used for rights checking
*/
protected $resources;
/**
* @var array
*
* Events to call on entity creation
*/
protected $createEvents;
/**
* @var array
*
* Events to call on entity update
*/
protected $updateEvents;
/**
* @var array
*
* Events to call on entity deletion
*/
protected $deleteEvents;
/**
* @var mixed|array
*
* ACL modules used for rights checking
*/
protected $modules;
/**
* @var integer
*
* limit for the list operation
*/
protected $defaultLoopArgs;
/**
* @var string
*
* The id parameter used to filter in the loop
*/
protected $idParameterName;
/**
* @param $objName
* @param $resources
* @param $createEvents
* @param $updateEvents
* @param $deleteEvents
* @param array $modules The module codes related to the ACL
* @param array $defaultLoopArgs The loop default arguments
* @param string $idParameterName The "id" parameter name in your loop. Generally "id"
*/
public function __construct(
$objName,
$resources,
$createEvents,
$updateEvents,
$deleteEvents,
$modules = [],
$defaultLoopArgs = null,
$idParameterName = "id"
) {
$this->objName = $objName;
$this->resources = $resources;
$this->initializeEvents([
"createEvents" => $createEvents,
"updateEvents" => $updateEvents,
"deleteEvents" => $deleteEvents,
]);
$this->modules = $modules;
$this->defaultLoopArgs = $defaultLoopArgs ?: ["limit" => 10, "offset" => 0, "visible" => "*"];
$this->idParameterName = $idParameterName;
}
/**
* @return JsonResponse
*
* The method provides the "list" feed for an entity.
*/
public function listAction()
{
$this->checkAuth($this->resources, $this->modules, AccessManager::VIEW);
$request = $this->getRequest();
if ($request->query->has('id')) {
$request->query->remove('id');
}
$params = array_merge(
$this->defaultLoopArgs,
$request->query->all()
);
try {
$results = $this->getLoopResults($params);
} catch (\Exception $e) {
throw new HttpException(500, json_encode(["error" => $e->getMessage()]));
}
return JsonResponse::create($results);
}
/**
* @param $entityId
* @return \Symfony\Component\HttpFoundation\Response
*
* This method provides the "GET" feed for an entity,
* you can define a route like this:
*
* <route id="api.my-entity.get" path="/api/my-entity/{entityId}" methods="get">
* <default key="_controller">Thelia:Api\MyEntity:get</default>
* <requirement key="entityId">\d+</requirement>
* </route>
*/
public function getAction($entityId)
{
$this->checkAuth($this->resources, $this->modules, AccessManager::VIEW);
$request = $this->getRequest();
$params = array_merge(
$request->query->all(),
[
$this->idParameterName => $entityId,
]
);
$result = $this->getLoopResults($params);
if ($result->isEmpty()) {
$this->entityNotFound($entityId);
}
return JsonResponse::create($result);
}
/**
* @return JsonResponse
*
* This feed creates your entity.
*/
public function createAction()
{
$this->checkAuth($this->resources, $this->modules, AccessManager::CREATE);
$baseForm = $this->getCreationForm();
$con = Propel::getConnection();
$con->beginTransaction();
try {
$form = $this->validateForm($baseForm);
$data = $form->getData();
$event = $this->getCreationEvent($data);
$dispatcher = $this->getDispatcher();
foreach ($this->createEvents as $eventName) {
$dispatcher->dispatch($eventName, $event);
}
$this->afterCreateEvents($event, $data);
$con->commit();
} catch (HttpException $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode());
} catch (\Exception $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], 500);
}
$obj = $this->extractObjectFromEvent($event);
$id = $this->extractIdFromObject($obj);
return new JsonResponse(
$this->getLoopResults(
array_merge(
$this->getRequest()->query->all(),
[$this->idParameterName => $id]
)
),
201
);
}
/**
* @return JsonResponse
*
* Generic action to update an entity
*/
public function updateAction()
{
$this->checkAuth($this->resources, $this->modules, AccessManager::UPDATE);
$baseForm = $this->getUpdateForm();
$baseForm->getFormBuilder()
->addEventListener(
FormEvents::PRE_SUBMIT,
[$this, "hydrateUpdateForm"]
)
;
$con = Propel::getConnection();
$con->beginTransaction();
try {
$form = $this->validateForm($baseForm);
$data = $form->getData();
$event = $this->getUpdateEvent($data);
$dispatcher = $this->getDispatcher();
foreach ($this->updateEvents as $eventName) {
$dispatcher->dispatch($eventName, $event);
}
$this->afterUpdateEvents($event, $data);
$con->commit();
} catch (HttpException $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode());
} catch (\Exception $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], 500);
}
$obj = $this->extractObjectFromEvent($event);
$id = $this->extractIdFromObject($obj);
return new JsonResponse(
$this->getLoopResults(
array_merge(
$this->getRequest()->query->all(),
[$this->idParameterName => $id]
)
),
201
);
}
/**
* @param $entityId
* @return JsonResponse|\Thelia\Core\HttpFoundation\Response
*
* generic feed for deleting an entity
*/
public function deleteAction($entityId)
{
$this->checkAuth($this->resources, $this->modules, AccessManager::DELETE);
$con = Propel::getConnection();
$con->beginTransaction();
try {
$event = $this->getDeleteEvent($entityId);
$obj = $this->extractObjectFromEvent($event);
if (null === $obj || false === $obj) {
$this->entityNotFound($entityId);
}
$dispatcher = $this->getDispatcher();
foreach ($this->deleteEvents as $eventName) {
$dispatcher->dispatch($eventName, $event);
}
$con->commit();
} catch (HttpException $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode());
} catch (\Exception $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], 500);
}
return $this->nullResponse(204);
}
/**
* @param $loopParams
* @return \Thelia\Core\Template\Element\LoopResult
*
* Returns the current class' loop results with the given parameters
*/
protected function getLoopResults($loopParams)
{
$loop = $this->getLoop();
$loop->initializeArgs(
array_merge($this->defaultLoopArgs, $loopParams)
);
return $loop->exec($pagination);
}
// Helpers
/**
* @param $entityId
*
* Throws a 404 exception building an error message with $this->objName and the entity id
*/
protected function entityNotFound($entityId)
{
throw new NotFoundHttpException(
json_encode([
"error" => sprintf("%s %s %d not found", $this->objName, $this->idParameterName, $entityId)
])
);
}
/**
* @param $eventsDefinition
*
* Register events into the class' variables
*/
protected function initializeEvents($eventsDefinition)
{
foreach ($eventsDefinition as $variableName => $eventValue) {
$value = array();
if (!empty($eventValue) && !\is_array($eventValue)) {
$value = [$eventValue];
} elseif (\is_array($eventValue)) {
$value = $eventValue;
}
$this->$variableName = $value;
}
}
/**
* @param $locale
* @param string $parameterName
*
* This helper defines the lang into the query ( you can use it to force a lang into a loop )
*/
protected function setLocaleIntoQuery($locale, $parameterName = 'lang')
{
$request = $this->getRequest();
if (!$request->query->has($parameterName)) {
$request->query->set($parameterName, $locale);
}
}
// Inner logic, override those methods to use your logic
/**
* @param mixed $obj
* @return mixed
*
* After having extracted the object, now extract the id.
*/
protected function extractIdFromObject($obj)
{
return $obj->getId();
}
/**
* @param FormEvent $event
*
* This method in called on your update form FormEvents::PRE_SUBMIT event.
*
* You can treat the given form, rewrite some data ...
*/
public function hydrateUpdateForm(FormEvent $event)
{
// This method is called on FormEvents::PRE_SUBMIT
}
/**
* @param Event $event
* @param array $data
*
* Hook after the entity creation
*/
protected function afterCreateEvents(Event $event, array &$data)
{
// This method is called after dispatches in createAction
}
/**
* @param Event $event
* @param array $data
*
* Hook after the entity update
*/
protected function afterUpdateEvents(Event $event, array &$data)
{
// This method is called after dispatches in updateAction
}
// Abstract methods
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
abstract protected function getLoop();
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
abstract protected function getCreationForm(array $data = array());
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
abstract protected function getUpdateForm(array $data = array());
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
abstract protected function extractObjectFromEvent(Event $event);
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
abstract protected function getCreationEvent(array &$data);
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
abstract protected function getUpdateEvent(array &$data);
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
abstract protected function getDeleteEvent($entityId);
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\AttributeAvailability;
/**
* Class AttributeAvController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class AttributeAvController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"attribute av",
AdminResources::ATTRIBUTE,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new AttributeAvailability($this->container);
}
/**
* @TODO: Implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,125 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Thelia\Controller\a;
use Thelia\Controller\BaseController;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Model\Api;
/**
* Class BaseApiController
* @package Thelia\Controller\Api
* @author Manuel Raynaud <manu@raynaud.io>
*/
class BaseApiController extends BaseController
{
const CONTROLLER_TYPE = 'api';
const EMPTY_FORM_NAME = "thelia.api.empty";
protected $apiUser;
protected $currentRouter = "router.api";
protected function checkAuth($resources, $modules, $accesses)
{
$resources = \is_array($resources) ? $resources : array($resources);
$modules = \is_array($modules) ? $modules : array($modules);
$accesses = \is_array($accesses) ? $accesses : array($accesses);
if (true !== $this->getSecurityContext()->isUserGranted(array("API"), $resources, $modules, $accesses, $this->getApiUser())) {
throw new AccessDeniedHttpException();
}
}
public function setApiUser(Api $apiUser)
{
$this->apiUser = $apiUser;
}
public function getApiUser()
{
return $this->apiUser;
}
/**
* @param null|mixed $template
* @return a ParserInterface instance parser
*/
protected function getParser($template = null)
{
throw new \RuntimeException("The parser is not available in an API controller");
}
/**
* Render the given template, and returns the result as an Http Response.
*
* @param mixed $content the response content
* @param array $args the template arguments
* @param int $status http code status
* @param array $headers The HTTP headers of the response
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function render($content, $args = array(), $status = 200, $headers = array())
{
return Response::create($this->renderRaw($content), $status, $headers);
}
/**
* Render the given template, and returns the result as a string.
*
* @param $content
* @param array $args the template arguments
* @param null $templateDir
*
* @return string
*/
protected function renderRaw($content, $args = array(), $templateDir = null)
{
if (\is_array($content)) {
$content = json_encode($content);
}
return $content;
}
/**
* @param $name
* @param string $type
* @param array $data
* @param array $options
* @return \Thelia\Form\BaseForm
*
* Deactivate csrf token by default on API
*/
public function createForm($name, $type = "form", array $data = array(), array $options = array())
{
$options = array_merge(
[
"csrf_protection" => false,
],
$options
);
return parent::createForm($name, $type, $data, $options);
}
/**
* @return string
*/
public function getControllerType()
{
return self::CONTROLLER_TYPE;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Brand;
/**
* Class BrandController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class BrandController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"brand",
AdminResources::BRAND,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Brand($this->container);
}
/**
* @TODO: Implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,152 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Form\FormEvent;
use Thelia\Core\Event\Category\CategoryCreateEvent;
use Thelia\Core\Event\Category\CategoryDeleteEvent;
use Thelia\Core\Event\Category\CategoryUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Category;
use Thelia\Model\CategoryQuery;
use Thelia\Form\Definition\ApiForm;
/**
* Class CategoryController
* @package Thelia\Controller\Api
* @author Manuel Raynaud <manu@raynaud.io>
*/
class CategoryController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"category",
AdminResources::CATEGORY,
TheliaEvents::CATEGORY_CREATE,
TheliaEvents::CATEGORY_UPDATE,
TheliaEvents::CATEGORY_DELETE
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Category($this->container);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getCreationForm(array $data = array())
{
return $this->createForm(ApiForm::CATEGORY_CREATION, "form", $data);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getUpdateForm(array $data = array())
{
return $this->createForm(ApiForm::CATEGORY_MODIFICATION, "form", $data, [
'method' => 'PUT',
]);
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
return $event->getCategory();
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getCreationEvent(array &$data)
{
$event = new CategoryCreateEvent();
$event
->setLocale($data['locale'])
->setTitle($data['title'])
->setVisible($data['visible'])
->setParent($data['parent'])
;
$this->setLocaleIntoQuery($data["locale"]);
return $event;
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getUpdateEvent(array &$data)
{
$event = new CategoryUpdateEvent($data["id"]);
$event
->setLocale($data['locale'])
->setParent($data['parent'])
->setTitle($data['title'])
->setVisible($data['visible'])
->setChapo($data['chapo'])
->setDescription($data['description'])
->setPostscriptum($data['postscriptum'])
->setDefaultTemplateId($data['default_template_id'])
;
$this->setLocaleIntoQuery($data["locale"]);
return $event;
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getDeleteEvent($entityId)
{
$event = new CategoryDeleteEvent($entityId);
$event->setCategory(CategoryQuery::create()->findPk($entityId));
return $event;
}
public function hydrateUpdateForm(FormEvent $event)
{
$id = $event->getData()["id"];
if (null === CategoryQuery::create()->findPk($id)) {
$this->entityNotFound($id);
}
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Country;
/**
* Class CountryController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class CountryController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"country",
AdminResources::COUNTRY,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Country($this->container);
}
/**
* @TODO: implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Currency;
/**
* Class CurrencyController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class CurrencyController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"currency",
AdminResources::CURRENCY,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Currency($this->container);
}
/**
* @TODO: Implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,216 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
use Thelia\Core\Event\Customer\CustomerEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator;
use Thelia\Core\Security\Exception\UsernameNotFoundException;
use Thelia\Core\Security\Exception\WrongPasswordException;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Security\User\UserInterface;
use Thelia\Core\Template\Loop\Customer;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\CustomerQuery;
use Thelia\Form\Definition\ApiForm;
/**
* Class CustomerController
* @package Thelia\Controller\Api
* @author Manuel Raynaud <manu@raynaud.io>
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class CustomerController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"customer",
AdminResources::CUSTOMER,
TheliaEvents::CUSTOMER_CREATEACCOUNT,
TheliaEvents::CUSTOMER_UPDATEACCOUNT,
TheliaEvents::CUSTOMER_DELETEACCOUNT,
[],
[
"limit" => 10,
"offset" => 0,
"current" => false,
]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Customer($this->container);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getCreationForm(array $data = array())
{
return $this->createForm(ApiForm::CUSTOMER_CREATE);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getUpdateForm(array $data = array())
{
return $this->createForm(
ApiForm::CUSTOMER_UPDATE,
"form",
[],
['method' => 'PUT']
);
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
return $event->getCustomer();
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getCreationEvent(array &$data)
{
return $this->hydrateEvent($data);
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getUpdateEvent(array &$data)
{
return $this->hydrateEvent($data);
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getDeleteEvent($entityId)
{
$customer = CustomerQuery::create()->findPk($entityId);
if (null === $customer) {
throw new HttpException(404, sprintf('{"error": "customer with id %d not found"}', $entityId));
}
return new CustomerEvent($customer);
}
protected function hydrateEvent(array $data)
{
$customerCreateEvent = new CustomerCreateOrUpdateEvent(
$data['title'],
$data['firstname'],
$data['lastname'],
$data['address1'],
$data['address2'],
$data['address3'],
$data['phone'],
$data['cellphone'],
$data['zipcode'],
$data['city'],
$data['country'],
$data['email'],
$data['password'],
$data['lang_id'],
isset($data["reseller"]) ? $data["reseller"] : null,
isset($data["sponsor"]) ? $data["sponsor"] : null,
isset($data["discount"]) ? $data["discount"] : null,
$data['company'],
null
);
if (isset($data["id"])) {
$customerCreateEvent->setCustomer(CustomerQuery::create()->findPk($data["id"]));
}
return $customerCreateEvent;
}
public function deleteAction($entityId)
{
$query = CustomerQuery::create()
->joinOrder()
->filterById($entityId)
->findOne()
;
if (null !== $query) {
throw new HttpException(403, json_encode([
"error" => sprintf("You can't delete the customer %d as he has orders", $entityId),
]));
}
return parent::deleteAction($entityId);
}
/**
* @return \Symfony\Component\HttpFoundation\Response|JsonResponse
*
* Get a customer given its email and password.
* @author Baptiste Cabarrou <bcabarrou@openstudio.fr>
*/
public function checkLoginAction()
{
$this->checkAuth($this->resources, $this->modules, AccessManager::VIEW);
$request = $this->getRequest();
$customerLoginForm = $this->createForm(ApiForm::CUSTOMER_LOGIN);
try {
$this->validateForm($customerLoginForm, "post");
$authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm);
/** @var UserInterface $customer */
$customer = $authenticator->getAuthentifiedUser();
return $this->getAction($customer->getId());
} catch (UsernameNotFoundException $e) {
return new JsonResponse(["error" => $e->getMessage()], 404);
} catch (WrongPasswordException $e) {
return new JsonResponse(["error" => $e->getMessage()], 404);
} catch (HttpException $e) {
return new JsonResponse(["error" => $e->getMessage()], $e->getStatusCode());
} catch (\Exception $e) {
return new JsonResponse(["error" => $e->getMessage()], 500);
}
}
}

View File

@@ -0,0 +1,374 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Propel\Runtime\Propel;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Thelia\Controller\Admin\FileController;
use Thelia\Core\Event\File\FileDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Image;
use Thelia\Files\FileConfiguration;
/**
* Class ImageController
* @package Thelia\Controller\Api
* @author manuel raynaud <manu@raynaud.io>
*/
class ImageController extends BaseApiController
{
/**
* @param integer $entityId source's primary key (product's pk, category's pk, etc)
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listAction($entityId)
{
$request = $this->getRequest();
$entity = $request->attributes->get('entity');
$this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::VIEW);
$this->checkEntityExists($entity, $entityId);
if ($request->query->has('id')) {
$request->query->remove('id');
}
$params = array_merge(
[
'limit' => 10,
'offset' => 0,
],
$request->query->all(),
[
'source' => strtolower($entity),
'source_id' => $entityId
]
);
$imageLoop = new Image($this->getContainer());
$imageLoop->initializeArgs($params);
return JsonResponse::create($imageLoop->exec($paginate));
}
public function getImageAction($entityId, $imageId)
{
$request = $this->getRequest();
$entity = $request->attributes->get('entity');
$this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::VIEW);
$this->checkEntityExists($entity, $entityId);
$params = array_merge(
$request->query->all(),
[
'source' => strtolower($entity),
'source_id' => $entityId,
'id' => $imageId
]
);
$imageLoop = new Image($this->getContainer());
$imageLoop->initializeArgs($params);
$results = $imageLoop->exec($paginate);
if ($results->isEmpty()) {
return JsonResponse::create(
array(
'error' => sprintf('image with id %d not found', $imageId)
),
404
);
}
return JsonResponse::create($results);
}
public function createImageAction($entityId)
{
$request = $this->getRequest();
$entity = $request->attributes->get('entity');
$this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE);
$fileController = new FileController();
$fileController->setContainer($this->getContainer());
$config = FileConfiguration::getImageConfig();
$files = $request->files->all();
$errors = null;
foreach ($files as $file) {
$errors = $this->processImage($fileController, $file, $entityId, $entity, $config);
}
if (!empty($errors)) {
$response = JsonResponse::create($errors, 500);
} else {
$response = $this->listAction($entityId);
$response->setStatusCode(201);
}
return $response;
}
public function updateImageAction($entityId, $imageId)
{
$request = $this->getRequest();
$entity = $request->attributes->get('entity');
$this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE);
$this->checkEntityExists($entity, $entityId);
$this->checkImage($entity, $imageId);
/**
* If there is a file, treat it
*/
$hasImage = $request->files->count() == 1;
if ($hasImage) {
$this->processImageUpdate($entityId, $entity);
}
/**
* Then treat i18n form
*/
$baseForm = $this->createForm(null, "image", [], array(
"csrf_protection" => false,
"method" => "PUT",
));
$baseForm->getFormBuilder()
->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($entity, $imageId) {
$this->onFormPreSubmit($event, $imageId, $entity);
}
)
;
$con = Propel::getConnection();
$con->beginTransaction();
try {
$form = $this->validateForm($baseForm);
$image = $this->checkImage($entity, $imageId);
foreach ($form->getData()["i18n"] as $locale => $i18nRow) {
$image->getTranslation($locale)
->setTitle($i18nRow["title"])
->setChapo($i18nRow["chapo"])
->setDescription($i18nRow["description"])
->setPostscriptum($i18nRow["postscriptum"])
;
}
$image->save();
$con->commit();
} catch (\Exception $e) {
$con->rollBack();
if (!$hasImage) {
throw new HttpException(500, $e->getMessage());
}
}
return $this->getImageAction($entityId, $imageId)->setStatusCode(201);
}
protected function onFormPreSubmit(FormEvent $event, $entityId, $entity)
{
$data = $event->getData();
$temporaryRegister = array();
foreach ($data["i18n"] as $key => &$value) {
$temporaryRegister["i18n"][$value["locale"]] = $value;
unset($data["i18n"][$key]);
}
$data = $temporaryRegister;
$i18ns = $this->getImageI18ns($entity, $entityId);
foreach ($i18ns as $i18n) {
$row = array(
"locale" => $i18n->getLocale(),
"title" => $i18n->getTitle(),
"chapo" => $i18n->getChapo(),
"description" => $i18n->getDescription(),
"postscriptum" => $i18n->getPostscriptum(),
);
if (!isset($data["i18n"][$i18n->getLocale()])) {
$data["i18n"][$i18n->getLocale()] = array();
}
$data["i18n"][$i18n->getLocale()] = array_merge(
$row,
$data["i18n"][$i18n->getLocale()]
);
}
$event->setData($data);
}
protected function processImageUpdate($entityId, $entity)
{
$file = $this->getRequest()->files->all();
reset($file);
$file = current($file);
$fileController = new FileController();
$fileController->setContainer($this->getContainer());
$config = FileConfiguration::getImageConfig();
$errors = $this->processImage($fileController, $file, $entityId, $entity, $config);
if (!empty($errors)) {
throw new HttpException(500, json_encode($errors), null, ["Content-Type" => "application/json"]);
}
}
protected function processImage(FileController $fileController, $file, $entityId, $entity, array $config)
{
try {
$fileController->processImage(
$file,
$entityId,
$entity,
$config['objectType'],
$config['validMimeTypes'],
$config['extBlackList']
);
} catch (\Exception $e) {
return [
'file' => $file->getClientOriginalName(),
'message' => $e->getMessage(),
];
}
return null;
}
public function deleteImageAction($entityId, $imageId)
{
$request = $this->getRequest();
$entity = $request->attributes->get('entity');
$this->checkAuth($this->getAdminResources()->getResource($entity), [], AccessManager::UPDATE);
$this->checkEntityExists($entity, $entityId);
$entityModel = $this->checkImage($entity, $imageId);
if (null === $entityModel) {
throw new HttpException(404, sprintf('{"error": "image with id %d not found"}', $imageId));
}
try {
$fileDeleteEvent = new FileDeleteEvent($entityModel);
$this->dispatch(TheliaEvents::IMAGE_DELETE, $fileDeleteEvent);
return Response::create('', 204);
} catch (\Exception $e) {
return JsonResponse::create(['error' => $e->getMessage()], 500);
}
}
/**
* @param string $entity image's source (eg : Product, Category, etc)
* @param int $entityId source's primary key
*/
protected function checkEntityExists($entity, $entityId)
{
$entity = ucfirst($entity);
$class = sprintf("Thelia\\Model\\%sQuery", $entity);
$method = new \ReflectionMethod($class, 'create');
$search = $method->invoke(null);
$entityModel = $search->findPk($entityId);
if (null === $entityModel) {
throw new HttpException(
404,
sprintf('{"error": "%s with id %d not found"}', $entity, $entityId),
null,
["Content-Type" => "application/json"]
);
}
return $entityModel;
}
/**
* @param $entity
* @param $imageId
* @return \Thelia\Files\FileModelInterface
*/
protected function checkImage($entity, $imageId)
{
$class = sprintf("Thelia\\Model\\%sImageQuery", ucfirst($entity));
$method = new \ReflectionMethod($class, 'create');
$search = $method->invoke(null);
$imageModel = $search->findPk($imageId);
if (null === $imageModel) {
throw new HttpException(
404,
sprintf('{"error": "image with id %d not found"}', $imageId),
null,
["Content-Type" => "application/json"]
);
}
return $imageModel;
}
/**
* @param $entity
* @param $imageId
* @return \Propel\Runtime\Collection\ObjectCollection
*/
protected function getImageI18ns($entity, $imageId)
{
$class = sprintf("Thelia\\Model\\%sImageI18nQuery", ucfirst($entity));
$method = new \ReflectionMethod($class, 'create');
$search = $method->invoke(null);
$search->orderByLocale();
return $search->findById($imageId);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\HttpFoundation\Response;
/**
*
* This controller allow to test if api server is up or down
*
* Class IndexController
* @package Thelia\Controller\Api
* @author Manuel Raynaud <manu@raynaud.io>
*/
class IndexController extends BaseApiController
{
public function indexAction()
{
return Response::create("OK");
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Lang;
/**
* Class LangController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class LangController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"lang",
AdminResources::LANGUAGE,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Lang($this->container);
}
/**
* @TODO: Implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,189 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Propel\Runtime\Propel;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Thelia\Core\Event\Product\ProductCreateEvent;
use Thelia\Core\Event\Product\ProductDeleteEvent;
use Thelia\Core\Event\Product\ProductUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Product;
use Thelia\Form\Api\Product\ProductCreationForm;
use Thelia\Form\Api\Product\ProductModificationForm;
use Thelia\Model\ProductQuery;
use Thelia\Form\Definition\ApiForm;
/**
* Class ProductController
* @package Thelia\Controller\Api
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ProductController extends BaseApiController
{
public function listAction()
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW);
$request = $this->getRequest();
if ($request->query->has('id')) {
$request->query->remove('id');
}
$params = array_merge(
$request->query->all(),
[
'limit' => $request->query->get('limit', 10),
'offset' => $request->query->get('offset', 0)
]
);
return JsonResponse::create($this->baseProductSearch($params));
}
public function getProductAction($productId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW);
$request = $this->getRequest();
$params = array_merge(
$request->query->all(),
['id' => $productId]
);
$results = $this->baseProductSearch($params);
if ($results->isEmpty()) {
return JsonResponse::create(
array(
'error' => sprintf('product with id %d not found', $productId)
),
404
);
}
return JsonResponse::create($results);
}
private function baseProductSearch($params)
{
$productLoop = new Product($this->getContainer());
$productLoop->initializeArgs($params);
return $productLoop->exec($paginate);
}
public function createAction()
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::CREATE);
$form = $this->createForm(ApiForm::PRODUCT_CREATION, 'form', [], ['csrf_protection' => false]);
try {
$creationForm = $this->validateForm($form);
$event = new ProductCreateEvent();
$event->bindForm($creationForm);
$this->dispatch(TheliaEvents::PRODUCT_CREATE, $event);
$product = $event->getProduct();
$updateEvent = new ProductUpdateEvent($product->getId());
$updateEvent->bindForm($creationForm);
$this->dispatch(TheliaEvents::PRODUCT_UPDATE, $updateEvent);
$this->getRequest()->query->set('lang', $creationForm->get('locale')->getData());
$response = $this->getProductAction($product->getId());
$response->setStatusCode(201);
return $response;
} catch (\Exception $e) {
return JsonResponse::create(['error' => $e->getMessage()], 500);
}
}
public function updateAction($productId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::UPDATE);
$this->checkProductExists($productId);
$form = $this->createForm(
ApiForm::PRODUCT_MODIFICATION,
'form',
['id' => $productId],
[
'csrf_protection' => false,
'method' => 'PUT'
]
);
$request = $this->getRequest();
$data = $request->request->all();
$data['id'] = $productId;
$request->request->add($data);
try {
$updateForm = $this->validateForm($form);
$event = new ProductUpdateEvent($productId);
$event->bindForm($updateForm);
$this->dispatch(TheliaEvents::PRODUCT_UPDATE, $event);
return JsonResponse::create(null, 204);
} catch (\Exception $e) {
return JsonResponse::create(['error' => $e->getMessage()], 500);
}
}
public function deleteAction($productId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::DELETE);
$this->checkProductExists($productId);
try {
$event = new ProductDeleteEvent($productId);
$this->dispatch(TheliaEvents::PRODUCT_DELETE, $event);
return Response::create('', 204);
} catch (\Exception $e) {
return JsonResponse::create(['error' => $e->getMessage()], 500);
}
}
/**
* @param $productId
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
protected function checkProductExists($productId)
{
$product = ProductQuery::create()
->findPk($productId);
if (null === $product) {
throw new HttpException(404, sprintf('{"error": "product with id %d not found"}', $productId), null, [
"Content-Type" => "application/json"
]);
}
}
}

View File

@@ -0,0 +1,467 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Propel\Runtime\Propel;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementCreateEvent;
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementDeleteEvent;
use Thelia\Core\Event\ProductSaleElement\ProductSaleElementUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\JsonResponse;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Country;
use Thelia\Model\Map\ProductSaleElementsTableMap;
use Thelia\Model\Product;
use Thelia\Model\ProductPriceQuery;
use Thelia\Model\ProductQuery;
use Thelia\Model\ProductSaleElements;
use Thelia\Core\Template\Loop\ProductSaleElements as ProductSaleElementsLoop;
use Thelia\Model\ProductSaleElementsQuery;
use Thelia\Model\TaxRuleQuery;
use Thelia\TaxEngine\Calculator;
use Thelia\Form\Definition\ApiForm;
/**
* Class ProductSaleElementsController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*
* API Controller for Product sale elements management
*/
class ProductSaleElementsController extends BaseApiController
{
protected $product;
/**
* Read actions
*/
/**
* @param $productId
* @return JsonResponse
*
* List a product pses
*/
public function listAction($productId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW);
if (null !== $response = $this->checkProduct($productId)) {
return $response;
}
$request = $this->getRequest();
if ($request->query->has('id')) {
$request->query->remove('id');
}
$params = array_merge(
array(
"limit" => 10,
"offset" => 0,
),
$request->query->all(),
array(
"product" => $productId,
)
);
return new JsonResponse($this->getProductSaleElements($params));
}
/**
* @param $pseId
* @return JsonResponse
*
* Get a pse details
*/
public function getPseAction($pseId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW);
$request = $this->getRequest();
$params = array_merge(
$request->query->all(),
[
'id' => $pseId,
]
);
$results = $this->getProductSaleElements($params);
if ($results->getCount() == 0) {
return new JsonResponse(
sprintf(
"The product sale elements id '%d' doesn't exist",
$pseId
),
404
);
}
return new JsonResponse($results);
}
/**
* Create action
*/
/**
* @return JsonResponse
*
* Create product sale elements
*/
public function createAction()
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::CREATE);
$baseForm = $this->createForm(ApiForm::PRODUCT_SALE_ELEMENTS, "form", [], [
"validation_groups" => ["create", "Default"],
'csrf_protection' => false,
"cascade_validation" => true,
]);
$con = Propel::getConnection(ProductSaleElementsTableMap::DATABASE_NAME);
$con->beginTransaction();
$createdIds = array();
try {
$form = $this->validateForm($baseForm);
$entries = $form->getData();
foreach ($entries["pse"] as $entry) {
$createEvent = new ProductSaleElementCreateEvent(
ProductQuery::create()->findPk($entry["product_id"]),
$entry["attribute_av"],
$entry["currency_id"]
);
$createEvent->bindForm($form);
$this->dispatch(TheliaEvents::PRODUCT_ADD_PRODUCT_SALE_ELEMENT, $createEvent);
$this->processUpdateAction(
$entry,
$pse = $createEvent->getProductSaleElement(),
$createEvent->getProduct()
);
$createdIds[] = $pse->getId();
}
$con->commit();
} catch (\Exception $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], 500);
}
return new JsonResponse(
$this->getProductSaleElements(
array_merge(
$this->getRequest()->query->all(),
["id" => implode(",", $createdIds)]
)
),
201
);
}
/**
* @return JsonResponse
*
* Create product sale elements
*/
public function updateAction()
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::UPDATE);
$baseForm = $this->createForm(ApiForm::PRODUCT_SALE_ELEMENTS, "form", [], [
"validation_groups" => ["update", "Default"],
'csrf_protection' => false,
"cascade_validation" => true,
"method" => "PUT",
]);
$baseForm->getFormBuilder()
->addEventListener(
FormEvents::PRE_SUBMIT,
[$this, "loadProductSaleElements"],
192
);
$updatedId = array();
$con = Propel::getConnection(ProductSaleElementsTableMap::DATABASE_NAME);
$con->beginTransaction();
try {
$form = $this->validateForm($baseForm);
$entries = $form->getData();
foreach ($entries["pse"] as $entry) {
$this->processUpdateAction(
$entry,
$pse = ProductSaleElementsQuery::create()->findPk($entry["id"]),
$pse->getProduct()
);
$updatedId[] = $pse->getId();
}
$con->commit();
} catch (\Exception $e) {
$con->rollBack();
return new JsonResponse(["error" => $e->getMessage()], 500);
}
return new JsonResponse(
$this->getProductSaleElements(
array_merge(
$this->getRequest()->query->all(),
[
"id" => implode(",", $updatedId),
"limit" => \count($updatedId),
]
)
),
201
);
}
/**
* Delete Action
*/
/**
* @param $pseId
* @return JsonResponse|\Thelia\Core\HttpFoundation\Response
*
* Delete a pse
*/
public function deleteAction($pseId)
{
$this->checkAuth(AdminResources::PRODUCT, [], AccessManager::VIEW);
$results = $this->getProductSaleElements([
'id' => $pseId
]);
if ($results->getCount() == 0) {
return new JsonResponse(
sprintf(
"The product sale elements id '%d' doesn't exist",
$pseId
),
404
);
}
$event = new ProductSaleElementDeleteEvent($pseId, null);
try {
$this->dispatch(TheliaEvents::PRODUCT_DELETE_PRODUCT_SALE_ELEMENT, $event);
} catch (\Exception $e) {
return new JsonResponse(array("error" => $e->getMessage()), 500);
}
return $this->nullResponse(204);
}
/**
* @param array $data
* @param ProductSaleElements $pse
* @param Product $product
*
* Process update on product sale elements values
*/
protected function processUpdateAction(
array $data,
ProductSaleElements $pse,
Product $product
) {
list($price, $salePrice) = $this->extractPrices($data);
$event = new ProductSaleElementUpdateEvent($product, $pse->getId());
$event
->setWeight($data["weight"])
->setTaxRuleId($data["tax_rule_id"])
->setEanCode($data["ean_code"])
->setOnsale($data["onsale"])
->setReference($data["reference"])
->setIsdefault($data["isdefault"])
->setIsnew($data["isnew"])
->setCurrencyId($data["currency_id"])
->setPrice($price)
->setSalePrice($salePrice)
->setQuantity($data["quantity"])
->setFromDefaultCurrency($data["use_exchange_rate"])
;
$this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event);
}
/**
* @param array $data
* @return array
*
* Return the untaxed prices to store
*/
protected function extractPrices(array $data)
{
$calculator = new Calculator();
$calculator->loadTaxRuleWithoutProduct(
TaxRuleQuery::create()->findPk($data["tax_rule_id"]),
Country::getShopLocation()
);
$price = null === $data["price_with_tax"] ?
$data["price"] :
$calculator->getUntaxedPrice($data["price_with_tax"])
;
$salePrice = null === $data["sale_price_with_tax"] ?
$data["sale_price"] :
$calculator->getUntaxedPrice($data["sale_price_with_tax"])
;
return [$price, $salePrice];
}
protected function retrievePrices(ProductSaleElements $pse)
{
$query = ProductPriceQuery::create()
->useCurrencyQuery()
->orderByByDefault()
->endUse()
;
$prices = $pse->getProductPrices($query);
if ($prices->count() === 0) {
return array(null, null, null, null);
}
/** @var \Thelia\Model\ProductPrice $currentPrices */
$currentPrices = $prices->get(0);
return [
$currentPrices->getPrice(),
$currentPrices->getPromoPrice(),
$currentPrices->getCurrencyId(),
$currentPrices->getFromDefaultCurrency()
];
}
/**
* @param FormEvent $event
*
* Loads initial pse data into a form.
* It is used in for a form event on pse update
*/
public function loadProductSaleElements(FormEvent $event)
{
$productSaleElementIds = array();
$data = array();
foreach ($event->getData()["pse"] as $entry) {
$productSaleElementIds[$entry["id"]] = $entry;
}
$productSaleElements = ProductSaleElementsQuery::create()
->findPks(array_keys($productSaleElementIds))
;
/** @var ProductSaleElements $productSaleElement */
foreach ($productSaleElements as $productSaleElement) {
$product = $productSaleElement->getProduct();
list($price, $salePrice, $currencyId, $fromDefaultCurrency) = $this->retrievePrices($productSaleElement);
$data["pse"][$productSaleElement->getId()] = array_merge(
[
"id" => $productSaleElement->getId(),
"reference" => $productSaleElement->getRef(),
"tax_rule_id" => $product->getTaxRuleId(),
"ean_code" => $productSaleElement->getEanCode(),
"onsale" => $productSaleElement->getPromo(),
"isdefault" => $productSaleElement->getIsDefault(),
"isnew" => $productSaleElement->getNewness(),
"quantity" => $productSaleElement->getQuantity(),
"weight" => $productSaleElement->getWeight(),
"price" => $price,
"sale_price" => $salePrice,
"currency_id" => $currencyId,
"use_exchange_rate" => $fromDefaultCurrency
],
$productSaleElementIds[$productSaleElement->getId()]
);
}
$event->setData($data);
}
/**
* @param $productId
* @return null|JsonResponse
*
* Checks if a productId exists
*/
protected function checkProduct($productId)
{
$this->product = ProductQuery::create()
->findPk($productId)
;
if (null === $this->product) {
return new JsonResponse(
[
"error" => sprintf(
"The product id '%d' doesn't exist",
$productId
)
],
404
);
}
return null;
}
/**
* @param $params
* @return \Thelia\Core\Template\Element\LoopResult
*
* Return loop results for a product sale element
*/
protected function getProductSaleElements($params)
{
$loop = new ProductSaleElementsLoop($this->container);
$loop->initializeArgs($params);
return $loop->exec($pagination);
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Tax;
/**
* Class TaxController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
*/
class TaxController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"tax",
AdminResources::TAX,
[],
[],
[]
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Tax($this->container);
}
/**
* @TODO: implement Create - Update - Delete
*/
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities creation.
*/
protected function getCreationForm(array $data = array())
{
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*
* Gives the form used for entities update
*/
protected function getUpdateForm(array $data = array())
{
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on creation.
*/
protected function getCreationEvent(array &$data)
{
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on update.
*/
protected function getUpdateEvent(array &$data)
{
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*
* Hydrates an event object to dispatch on entity deletion.
*/
protected function getDeleteEvent($entityId)
{
}
}

View File

@@ -0,0 +1,257 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Thelia\Core\Event\Tax\TaxRuleEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\TaxRule;
use Thelia\Model\Map\TaxRuleCountryTableMap;
use Thelia\Model\ProductQuery;
use Thelia\Model\TaxRuleCountryQuery;
use Thelia\Model\TaxRuleI18nQuery;
use Thelia\Model\TaxRuleQuery;
/**
* Class TaxRuleController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
* @author manuel raynaud <manu@raynaud.io>
*/
class TaxRuleController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"tax rule",
AdminResources::TAX,
[TheliaEvents::TAX_RULE_CREATE, TheliaEvents::TAX_RULE_TAXES_UPDATE],
[TheliaEvents::TAX_RULE_UPDATE, TheliaEvents::TAX_RULE_TAXES_UPDATE],
TheliaEvents::TAX_RULE_DELETE
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new TaxRule($this->container);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getCreationForm(array $data = array())
{
return $this->createForm(null, "tax_rule", $data);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getUpdateForm(array $data = array())
{
return $this->createForm(null, "tax_rule", $data, array(
"validation_groups" => ["Default", "update"],
"method" => "PUT",
));
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
return $event->getTaxRule();
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getCreationEvent(array &$data)
{
return $this->hydrateEvent($data);
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getUpdateEvent(array &$data)
{
return $this->hydrateEvent($data);
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getDeleteEvent($entityId)
{
$data = ["id" => $entityId];
return $this->hydrateEvent($data);
}
protected function afterCreateEvents(Event $event, array &$data)
{
$dispatcher = $this->getDispatcher();
if ($data["default"]) {
$dispatcher->dispatch(TheliaEvents::TAX_RULE_SET_DEFAULT, $event);
}
foreach ($data["i18n"] as $i18nRow) {
$this->hydrateI18nEvent($i18nRow, $event);
foreach ($this->updateEvents as $eventName) {
$dispatcher->dispatch($eventName, $event);
}
}
}
protected function afterUpdateEvents(Event $event, array &$data)
{
$this->afterCreateEvents($event, $data);
}
protected function hydrateEvent(array &$data)
{
$event = new TaxRuleEvent();
if (isset($data["country"])) {
$event->setCountryList($data["country"]);
}
if (isset($data["tax"])) {
$event->setTaxList($data["tax"]);
}
if (isset($data["id"])) {
$event->setId($data["id"]);
$event->setTaxRule(TaxRuleQuery::create()->findPk($data["id"]));
}
if (isset($data["i18n"]) && null !== $row = array_shift($data["i18n"])) {
$this->hydrateI18nEvent($row, $event);
}
return $event;
}
protected function hydrateI18nEvent(array $i18nRow, TaxRuleEvent $event)
{
$event
->setLocale($i18nRow["locale"])
->setTitle($i18nRow["title"])
->setDescription($i18nRow["description"])
;
}
public function hydrateUpdateForm(FormEvent $event)
{
$data = $event->getData();
$keys = array_keys($data["i18n"]);
foreach ($keys as $key) {
$value = $data["i18n"][$key];
$data["i18n"][$value["locale"]] = $value;
unset($data["i18n"][$key]);
}
$persistentI18n = $this->getI18nPersistentData($data["id"]);
foreach ($persistentI18n["i18n"] as $locale => $value) {
$data["i18n"][$locale] = array_merge($value, $data["i18n"][$locale]);
}
$data = array_merge($this->getPersistentData($data["id"]), $data);
$event->setData($data);
}
protected function getPersistentData($taxRuleId)
{
$taxRule = TaxRuleQuery::create()->findPk($taxRuleId);
if (null === $taxRule) {
throw new HttpException(404, json_encode([
"error" => sprintf("The tax rule %d doesn't exist", $taxRuleId)
]));
}
$countries = TaxRuleCountryQuery::create()
->filterByTaxRuleId($taxRuleId)
->distinct()
->select(TaxRuleCountryTableMap::COL_COUNTRY_ID)
->find()
->toArray()
;
$taxes = TaxRuleCountryQuery::create()
->filterByTaxRuleId($taxRuleId)
->distinct()
->select(TaxRuleCountryTableMap::COL_TAX_ID)
->find()
->toArray()
;
$data = [
"default" => (bool) $taxRule->getIsDefault(),
"tax" => $taxes,
"country" => $countries,
];
return $data;
}
/**
* @param int $taxRuleId
* @return array
*/
protected function getI18nPersistentData($taxRuleId)
{
$i18ns = TaxRuleI18NQuery::create()
->findById($taxRuleId)
;
$data = ['i18n' => []];
/** @var \Thelia\Model\TaxRuleI18n $i18n */
foreach ($i18ns as $i18n) {
$data["i18n"][$i18n->getLocale()] = array(
"locale" => $i18n->getLocale(),
"title" => $i18n->getTitle(),
"description" => $i18n->getDescription(),
);
}
return $data;
}
}

View File

@@ -0,0 +1,235 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Api;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Form\FormEvent;
use Thelia\Core\Event\CustomerTitle\CustomerTitleEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Loop\Title;
use Thelia\Model\CustomerTitleI18nQuery;
use Thelia\Model\CustomerTitleQuery;
/**
* Class TitleController
* @package Thelia\Controller\Api
* @author Benjamin Perche <bperche@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class TitleController extends AbstractCrudApiController
{
public function __construct()
{
parent::__construct(
"customer title",
AdminResources::TITLE,
[
TheliaEvents::CUSTOMER_TITLE_BEFORE_CREATE,
TheliaEvents::CUSTOMER_TITLE_CREATE,
TheliaEvents::CUSTOMER_TITLE_AFTER_CREATE,
],
[
TheliaEvents::CUSTOMER_TITLE_BEFORE_UPDATE,
TheliaEvents::CUSTOMER_TITLE_UPDATE,
TheliaEvents::CUSTOMER_TITLE_AFTER_UPDATE,
],
TheliaEvents::CUSTOMER_TITLE_DELETE
);
}
/**
* @return \Thelia\Core\Template\Element\BaseLoop
*
* Get the entity loop instance
*/
protected function getLoop()
{
return new Title($this->container);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getCreationForm(array $data = array())
{
return $this->createForm(null, "customer_title", $data);
}
/**
* @param array $data
* @return \Thelia\Form\BaseForm
*/
protected function getUpdateForm(array $data = array())
{
return $this->createForm(null, "customer_title", $data, array(
"validation_groups" => ["Default", "update"],
"method" => "PUT",
));
}
/**
* @param Event $event
* @return null|mixed
*
* Get the object from the event
*
* if return null or false, the action will throw a 404
*/
protected function extractObjectFromEvent(Event $event)
{
return $event->getCustomerTitle();
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getCreationEvent(array &$data)
{
return $this->createEvent($data);
}
/**
* @param array $data
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getUpdateEvent(array &$data)
{
return $this->createEvent($data);
}
/**
* @param mixed $entityId
* @return \Symfony\Component\EventDispatcher\Event
*/
protected function getDeleteEvent($entityId)
{
$data = ["title_id" => $entityId];
return $this->createEvent($data);
}
/**
* @param array $data
* @return CustomerTitleEvent
*
* Handler to create the customer title event
*/
protected function createEvent(array &$data)
{
$event = new CustomerTitleEvent();
if (isset($data["default"])) {
$event->setDefault($data["default"]);
}
if (isset($data["title_id"])) {
$event->setCustomerTitle(CustomerTitleQuery::create()->findPk($data["title_id"]));
}
if (isset($data["i18n"]) && !empty($data["i18n"])) {
$row = array_shift($data["i18n"]);
$this->hydrateEvent($row, $event);
}
return $event;
}
/**
* @param array $i18nRow
* @param CustomerTitleEvent $event
*
* Handler to hydrate the event with i18n data
*/
protected function hydrateEvent(array $i18nRow, CustomerTitleEvent $event)
{
$event
->setShort($i18nRow["short"])
->setLong($i18nRow["long"])
->setLocale($i18nRow["locale"])
;
}
protected function afterCreateEvents(Event $event, array &$data)
{
$dispatcher = $this->getDispatcher();
while (null !== $i18nRow = array_shift($data["i18n"])) {
$this->hydrateEvent($i18nRow, $event);
foreach ($this->updateEvents as $eventName) {
$dispatcher->dispatch($eventName, $event);
}
}
}
protected function afterUpdateEvents(Event $event, array &$data)
{
$this->afterCreateEvents($event, $data);
}
/**
* @param FormEvent $event
*
* This methods loads current title data into the update form.
* It uses an event to load only needed ids.
*/
public function hydrateUpdateForm(FormEvent $event)
{
$data = $event->getData();
$title = CustomerTitleQuery::create()->findPk($data["title_id"]);
if (null === $title) {
$this->entityNotFound($data["title_id"]);
}
$data["default"] |= (bool) $title->getByDefault();
$titleI18ns = CustomerTitleI18nQuery::create()
->filterById($data["title_id"])
->find()
->toKeyIndex('Locale')
;
$i18n = &$data["i18n"];
foreach ($data["i18n"] as $key => $value) {
$i18n[$value["locale"]] = $value;
unset($i18n[$key]);
}
/** @var \Thelia\Model\CustomerTitleI18n $titleI18n */
foreach ($titleI18ns as $titleI18n) {
$row = array();
$row["locale"] = $locale = $titleI18n->getLocale();
$row["short"] = $titleI18n->getShort();
$row["long"] = $titleI18n->getLong();
if (!isset($i18n[$locale])) {
$i18n[$locale] = array();
}
$i18n[$locale] = array_merge($row, $i18n[$locale]);
}
$event->setData($data);
}
}

View File

@@ -0,0 +1,631 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Router;
use Thelia\Core\Event\ActionEvent;
use Thelia\Core\Event\DefaultActionEvent;
use Thelia\Core\Event\PdfEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Template\ParserContext;
use Thelia\Core\Translation\Translator;
use Thelia\Exception\TheliaProcessException;
use Thelia\Form\BaseForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Mailer\MailerFactory;
use Thelia\Model\OrderQuery;
use Thelia\Tools\URL;
/**
*
* The defaut administration controller. Basically, display the login form if
* user is not yet logged in, or back-office home page if the user is logged in.
*
* @author Franck Allimant <franck@cqfdev.fr>
* @author Manuel Raynaud <manu@raynaud.io>
* @author Benjamin Perche <bperche@openstudio.fr>
*/
abstract class BaseController
{
use ContainerAwareTrait;
const EMPTY_FORM_NAME = "thelia.empty";
protected $tokenProvider;
protected $currentRouter;
protected $translator;
protected $templateHelper;
protected $adminResources;
/** @var bool Fallback on default template when setting the templateDefinition */
protected $useFallbackTemplate = true;
/**
* Return an empty response (after an ajax request, for example)
* @param int $status
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function nullResponse($status = 200)
{
return new Response(null, $status);
}
/**
* @param $jsonData
* @param int $status
* @return Response Return a JSON response
*/
protected function jsonResponse($jsonData, $status = 200)
{
return new Response($jsonData, $status, array('content-type' => 'application/json'));
}
/**
* @param $pdf
* @param $fileName
* @param int $status
* @param bool $browser
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function pdfResponse($pdf, $fileName, $status = 200, $browser = false)
{
return Response::create(
$pdf,
$status,
array(
'Content-type' => "application/pdf",
'Content-Disposition' =>sprintf(
'%s; filename=%s.pdf',
\boolval($browser) === false ? 'attachment' : 'inline',
$fileName
)
)
);
}
/**
* Dispatch a Thelia event
*
* @param string $eventName a TheliaEvent name, as defined in TheliaEvents class
* @param ActionEvent $event the action event, or null (a DefaultActionEvent will be dispatched)
*/
protected function dispatch($eventName, ActionEvent $event = null)
{
if ($event == null) {
$event = new DefaultActionEvent();
}
$this->getDispatcher()->dispatch($eventName, $event);
}
/**
* Return the event dispatcher,
*
* @return \Symfony\Component\EventDispatcher\EventDispatcher
*/
public function getDispatcher()
{
return $this->container->get('event_dispatcher');
}
/**
* return the Translator
*
* @return Translator
*/
public function getTranslator()
{
if (null === $this->translator) {
$this->translator = $this->container->get('thelia.translator');
}
return $this->translator;
}
/**
* 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.
*
* @return \Thelia\Core\Security\SecurityContext
*/
protected function getSecurityContext()
{
return $this->container->get('thelia.securityContext');
}
/**
* @return \Thelia\Core\HttpFoundation\Request
*/
protected function getRequest()
{
return $this->container->get('request_stack')->getCurrentRequest();
}
/**
* Returns the session from the current request
*
* @return \Thelia\Core\HttpFoundation\Session\Session
*/
protected function getSession()
{
return $this->container->get('request_stack')->getCurrentRequest()->getSession();
}
/**
* @return \Thelia\Tools\TokenProvider
*/
protected function getTokenProvider()
{
if (null === $this->tokenProvider) {
$this->tokenProvider = $this->container->get("thelia.token_provider");
}
return $this->tokenProvider;
}
/**
* @return \Thelia\Core\Template\TemplateHelperInterface
*/
protected function getTemplateHelper()
{
if (null === $this->templateHelper) {
$this->templateHelper = $this->container->get("thelia.template_helper");
}
return $this->templateHelper;
}
/**
* @since 2.3
* @return \Thelia\Core\Security\Resource\AdminResources
*/
protected function getAdminResources()
{
if (null === $this->adminResources) {
$this->adminResources = $this->container->get("thelia.admin.resources");
}
return $this->adminResources;
}
/**
* Get all errors that occurred in a form
*
* @param \Symfony\Component\Form\Form $form
* @return string the error string
*/
protected function getErrorMessages(Form $form)
{
return $this->getTheliaFormValidator()->getErrorMessages($form);
}
/**
* 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 = $this->getTheliaFormValidator()->validateForm($aBaseForm, $expectedMethod);
// At this point, the form is valid (no exception was thrown). Remove it from the error context.
$this->getParserContext()->clearForm($aBaseForm);
return $form;
}
/**
* @return \Thelia\Core\Form\TheliaFormValidatorInterface
*/
protected function getTheliaFormValidator()
{
return $this->container->get("thelia.form_validator");
}
/**
* @param int $order_id
* @param string $fileName
* @param bool $checkOrderStatus
* @param bool $checkAdminUser
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function generateOrderPdf($order_id, $fileName, $checkOrderStatus = true, $checkAdminUser = true, $browser = false)
{
$order = OrderQuery::create()->findPk($order_id);
// check if the order has the paid status
if ($checkAdminUser && !$this->getSecurityContext()->hasAdminUser()) {
if ($checkOrderStatus && !$order->isPaid(false)) {
throw new NotFoundHttpException();
}
}
$html = $this->renderRaw(
$fileName,
array(
'order_id' => $order_id
),
$this->getTemplateHelper()->getActivePdfTemplate()
);
try {
$pdfEvent = new PdfEvent($html);
$this->dispatch(TheliaEvents::GENERATE_PDF, $pdfEvent);
if ($pdfEvent->hasPdf()) {
return $this->pdfResponse($pdfEvent->getPdf(), $order->getRef(), 200, $browser);
}
} catch (\Exception $e) {
Tlog::getInstance()->error(
sprintf(
'error during generating invoice pdf for order id : %d with message "%s"',
$order_id,
$e->getMessage()
)
);
}
throw new TheliaProcessException(
$this->getTranslator()->trans(
"We're sorry, this PDF invoice is not available at the moment."
)
);
}
/**
* Search success url in a form if present, in the query string otherwise
*
* @param BaseForm $form
* @return mixed|null|string
*/
protected function retrieveSuccessUrl(BaseForm $form = null)
{
return $this->retrieveFormBasedUrl('success_url', $form);
}
/**
* Search error url in a form if present, in the query string otherwise
*
* @param BaseForm $form
* @return mixed|null|string
*/
protected function retrieveErrorUrl(BaseForm $form = null)
{
return $this->retrieveFormBasedUrl('error_url', $form);
}
/**
* Search url in a form parameter, or in a request parameter.
*
* @param string $parameterName the form parameter name, or request parameter name.
* @param BaseForm $form the form
* @return mixed|null|string
*/
protected function retrieveFormBasedUrl($parameterName, BaseForm $form = null)
{
$url = null;
if ($form != null) {
$url = $form->getFormDefinedUrl($parameterName);
} else {
$url = $this->container->get('request_stack')->getCurrentRequest()->get($parameterName);
}
return $url;
}
/**
* @param $routeId
* @param array $urlParameters
* @param array $routeParameters
* @param int $referenceType
* @return string
*/
protected function retrieveUrlFromRouteId(
$routeId,
array $urlParameters = [],
array $routeParameters = [],
$referenceType = Router::ABSOLUTE_PATH
) {
return URL::getInstance()->absoluteUrl(
$this->getRoute(
$routeId,
$routeParameters,
$referenceType
),
$urlParameters
);
}
/**
*
* create an instance of RedirectResponse
*
* @param $url
* @param int $status
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function generateRedirect($url, $status = 302)
{
return RedirectResponse::create($url, $status);
}
/**
* create an instance of RedirectReponse if a success url is present, return null otherwise
*
* @param BaseForm $form
* @return null|\Symfony\Component\HttpFoundation\Response
*/
protected function generateSuccessRedirect(BaseForm $form = null)
{
if (null !== $url = $this->retrieveSuccessUrl($form)) {
return $this->generateRedirect($url);
}
return null;
}
/**
* create an instance of RedirectReponse if a success url is present, return null otherwise
*
* @param BaseForm $form
* @return null|\Symfony\Component\HttpFoundation\Response
*/
protected function generateErrorRedirect(BaseForm $form = null)
{
if (null !== $url = $this->retrieveErrorUrl($form)) {
return $this->generateRedirect($url);
}
return null;
}
/**
*
* create an instance of RedriectResponse for a given route id.
*
* @param $routeId
* @param array $urlParameters
* @param array $routeParameters
* @param int $referenceType
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function generateRedirectFromRoute(
$routeId,
array $urlParameters = [],
array $routeParameters = [],
$referenceType = Router::ABSOLUTE_PATH
) {
return $this->generateRedirect(
$this->retrieveUrlFromRouteId($routeId, $urlParameters, $routeParameters, $referenceType)
);
}
/**
* Return the route path defined for the givent route ID
*
* @param string $routeId a route ID, as defines in Config/Resources/routing/admin.xml
* @param mixed $parameters An array of parameters
* @param int $referenceType The type of reference to be generated (one of the constants)
*
* @throws RouteNotFoundException If the named route doesn't exist
* @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
* @throws InvalidParameterException When a parameter value for a placeholder is not correct because
* it does not match the requirement
* @throws \InvalidArgumentException When the router doesn't exist
* @return string The generated URL
*
* @see \Thelia\Controller\BaseController::getRouteFromRouter()
*/
protected function getRoute($routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_URL)
{
return $this->getRouteFromRouter(
$this->getCurrentRouter(),
$routeId,
$parameters,
$referenceType
);
}
/**
* Get a route path from the route id.
*
* @param string $routerName Router name
* @param string $routeId The name of the route
* @param mixed $parameters An array of parameters
* @param int $referenceType The type of reference to be generated (one of the constants)
*
* @throws RouteNotFoundException If the named route doesn't exist
* @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
* @throws InvalidParameterException When a parameter value for a placeholder is not correct because
* it does not match the requirement
* @throws \InvalidArgumentException When the router doesn't exist
* @return string The generated URL
*/
protected function getRouteFromRouter(
$routerName,
$routeId,
$parameters = array(),
$referenceType = Router::ABSOLUTE_URL
) {
/** @var Router $router */
$router = $this->getRouter($routerName);
if ($router == null) {
throw new \InvalidArgumentException(sprintf("Router '%s' does not exists.", $routerName));
}
return $router->generate($routeId, $parameters, $referenceType);
}
/**
* @param $routerName
* @return Router
*/
protected function getRouter($routerName)
{
return $this->container->get($routerName);
}
/**
* Return a 404 error
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/
protected function pageNotFound()
{
throw new NotFoundHttpException();
}
/**
* Check if environment is in debug mode
*
* @return bool
*/
protected function isDebug()
{
return $this->container->getParameter('kernel.debug');
}
protected function accessDenied()
{
throw new AccessDeniedHttpException();
}
/**
* check if the current http request is a XmlHttpRequest.
*
* If not, send a
*/
protected function checkXmlHttpRequest()
{
if (false === $this->container->get('request_stack')->getCurrentRequest()->isXmlHttpRequest() && false === $this->isDebug()) {
$this->accessDenied();
}
}
/**
*
* return an instance of \Swift_Mailer with good Transporter configured.
*
* @return MailerFactory
*/
public function getMailer()
{
return $this->container->get('mailer');
}
protected function getCurrentRouter()
{
return $this->currentRouter;
}
protected function setCurrentRouter($routerId)
{
$this->currentRouter = $routerId;
}
/**
* @param $name
* @param $type
* @param array $data
* @param array $options
* @return BaseForm
*
* This method builds a thelia form with its name
*/
public function createForm($name, $type = "form", array $data = array(), array $options = array())
{
if (empty($name)) {
$name = static::EMPTY_FORM_NAME;
}
return $this->getTheliaFormFactory()->createForm($name, $type, $data, $options);
}
/**
* @return \Thelia\Core\Form\TheliaFormFactoryInterface
*/
protected function getTheliaFormFactory()
{
return $this->container->get("thelia.form_factory");
}
/**
* @return \Symfony\Component\DependencyInjection\ContainerInterface
*/
public function getContainer()
{
return $this->container;
}
/**
* Return controller type
*
* @return string
*/
abstract public function getControllerType();
/**
* @param null|mixed $template
* @return \Thelia\Core\Template\ParserInterface instance parser
*/
abstract protected function getParser($template = null);
/**
* Render the given template, and returns the result as an Http Response.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param int $status http code status
* @return \Thelia\Core\HttpFoundation\Response
*/
abstract protected function render($templateName, $args = array(), $status = 200);
/**
* Render the given template, and returns the result as a string.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param null $templateDir
*
* @return string
*/
abstract protected function renderRaw($templateName, $args = array(), $templateDir = null);
}

View File

@@ -0,0 +1,134 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Front;
use Thelia\Controller\BaseController;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\HttpKernel\Exception\RedirectException;
use Thelia\Core\Template\ParserInterface;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Model\AddressQuery;
use Thelia\Model\ModuleQuery;
class BaseFrontController extends BaseController
{
const CONTROLLER_TYPE = 'front';
protected $currentRouter = "router.front";
public function checkAuth()
{
if ($this->getSecurityContext()->hasCustomerUser() === false) {
throw new RedirectException($this->retrieveUrlFromRouteId('customer.login.process'));
}
}
/**
* @return string
*/
public function getControllerType()
{
return self::CONTROLLER_TYPE;
}
protected function checkCartNotEmpty()
{
$cart = $this->getSession()->getSessionCart($this->getDispatcher());
if ($cart===null || $cart->countCartItems() == 0) {
throw new RedirectException($this->retrieveUrlFromRouteId('cart.view'));
}
}
protected function checkValidDelivery()
{
$order = $this->getSession()->getOrder();
if (null === $order
||
null === $order->getChoosenDeliveryAddress()
||
null === $order->getDeliveryModuleId()
||
null === AddressQuery::create()->findPk($order->getChoosenDeliveryAddress())
||
null === ModuleQuery::create()->findPk($order->getDeliveryModuleId())) {
throw new RedirectException($this->retrieveUrlFromRouteId('order.delivery'));
}
}
protected function checkValidInvoice()
{
$order = $this->getSession()->getOrder();
if (null === $order
||
null === $order->getChoosenInvoiceAddress()
||
null === $order->getPaymentModuleId()
||
null === AddressQuery::create()->findPk($order->getChoosenInvoiceAddress())
||
null === ModuleQuery::create()->findPk($order->getPaymentModuleId())) {
throw new RedirectException($this->retrieveUrlFromRouteId('order.invoice'));
}
}
/**
* @param TemplateDefinition $template the template to process, or null for using the front template
*
* @return ParserInterface the Thelia parser²
*/
protected function getParser($template = null)
{
$parser = $this->container->get("thelia.parser");
// Define the template that should be used
$parser->setTemplateDefinition(
$template ?: $this->getTemplateHelper()->getActiveFrontTemplate(),
$this->useFallbackTemplate
);
return $parser;
}
/**
* Render the given template, and returns the result as an Http Response.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param int $status http code status
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function render($templateName, $args = array(), $status = 200)
{
return Response::create($this->renderRaw($templateName, $args), $status);
}
/**
* Render the given template, and returns the result as a string.
*
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param string$templateDir
*
* @return string
*/
protected function renderRaw($templateName, $args = array(), $templateDir = null)
{
// Add the template standard extension
$templateName .= '.html';
// Render the template.
$data = $this->getParser($templateDir)->render($templateName, $args);
return $data;
}
}

View File

@@ -0,0 +1,76 @@
<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Thelia\Controller\Front;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\HttpKernel\Exception\RedirectException;
use Thelia\Model\ConfigQuery;
use Thelia\Tools\URL;
/**
* This is the defualt Thelia controller, which is called when no controller was found to process the request.
*
* @author Manuel Raynaud <mraynadu@openstudio.fr>
*/
class DefaultController extends BaseFrontController
{
/**
* This is the default Thelia behaviour if no action is defined.
*
* If the request contains a 'view' parameter, this view will be displayed.
* If the request contains a '_view' attribute (set in the route definition, for example), this view will be displayed.
* Otherwise, we will use the "index" view.
*
* Additionaly, if the URL rewriting is enabled, the method will check if a redirect to the pâge rewritten URL should
* be done.
*
* @param \Thelia\Core\HttpFoundation\Request $request
* @throw RedirectException if a redirection to the rewritted URL shoud be done.
*/
public function noAction(Request $request)
{
$view = null;
if (! $view = $request->query->get('view')) {
if ($request->request->has('view')) {
$view = $request->request->get('view');
}
}
if (null !== $view) {
$request->attributes->set('_view', $view);
}
if (null === $view && null === $request->attributes->get("_view")) {
$request->attributes->set("_view", "index");
}
if (ConfigQuery::isRewritingEnable()) {
if ($request->attributes->get('_rewritten', false) === false) {
/* Does the query GET parameters match a rewritten URL ? */
$rewrittenUrl = URL::getInstance()->retrieveCurrent($request);
if ($rewrittenUrl->rewrittenUrl !== null) {
/* 301 redirection to rewritten URL */
throw new RedirectException($rewrittenUrl->rewrittenUrl, 301);
}
}
}
}
public function emptyRoute()
{
return new Response(null, 204);
}
}