Inital commit

This commit is contained in:
2020-11-19 15:36:28 +01:00
parent 71f32f83d3
commit 66ce4ee218
18077 changed files with 2166122 additions and 35184 deletions

View File

@@ -12,9 +12,13 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\Exception\FormValidationException;
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.
@@ -31,6 +35,7 @@ abstract class AbstractCrudController extends BaseAdminController
// Permissions
protected $resourceCode;
protected $moduleCode;
// Events
protected $createEventIdentifier;
@@ -53,82 +58,89 @@ abstract class AbstractCrudController extends BaseAdminController
*
* @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 = null,
$orderRequestParameterName = null,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier = null,
$changePositionEventIdentifier = null
$objectName,
$defaultListOrder,
$orderRequestParameterName,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier = null,
$changePositionEventIdentifier = null,
$moduleCode = null
) {
$this->objectName = $objectName;
$this->objectName = $objectName;
$this->defaultListOrder = $defaultListOrder;
$this->orderRequestParameterName = $orderRequestParameterName;
$this->defaultListOrder = $defaultListOrder;
$this->orderRequestParameterName = $orderRequestParameterName;
$this->resourceCode = $resourceCode;
$this->resourceCode = $resourceCode;
$this->createEventIdentifier = $createEventIdentifier;
$this->updateEventIdentifier = $updateEventIdentifier;
$this->deleteEventIdentifier = $deleteEventIdentifier;
$this->visibilityToggleEventIdentifier = $visibilityToggleEventIdentifier;
$this->changePositionEventIdentifier = $changePositionEventIdentifier;
$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 unknown $object
* @param mixed $object
* @return BaseForm
*/
abstract protected function hydrateObjectForm($object);
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
* @param mixed $formData
* @return \Thelia\Core\Event\ActionEvent
*/
abstract protected function getCreationEvent($formData);
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
* @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 unknown $event
* @param mixed $event
*/
abstract protected function eventContainsObject($event);
/**
* Get the created object from an event.
*
* @param unknown $event
* @param mixed $event
*/
abstract protected function getObjectFromEvent($event);
@@ -140,53 +152,65 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param unknown $object
* @param string|null $object
*/
abstract protected function getObjectLabel($object);
/**
* Returns the object ID from the object
*
* @param unknown $object
* @param int|null $object
*/
abstract protected function getObjectId($object);
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @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();
/**
* Redirect to the edition template
* Must return a RedirectResponse instance
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
abstract protected function redirectToEditionTemplate();
/**
* Redirect to the list template
* 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");
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");
throw new \LogicException("Toggle Visibility is not supported for this object");
}
/**
* Put in this method post object creation processing if required.
*
* @param unknown $createEvent the create event
* @param ActionEvent $createEvent the create event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalCreateAction($createEvent)
@@ -197,7 +221,7 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Put in this method post object update processing if required.
*
* @param unknown $updateEvent the update event
* @param ActionEvent $updateEvent the update event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalUpdateAction($updateEvent)
@@ -208,7 +232,7 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Put in this method post object delete processing if required.
*
* @param unknown $deleteEvent the delete event
* @param ActionEvent $deleteEvent the delete event
* @return Response a response, or null to continue normal processing
*/
protected function performAdditionalDeleteAction($deleteEvent)
@@ -219,8 +243,8 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Put in this method post object position change processing if required.
*
* @param unknown $positionChangeEvent the delete event
* @return Response a response, or null to continue normal processing
* @param ActionEvent $positionChangeEvent the delete event
* @return Response|null a response, or null to continue normal processing
*/
protected function performAdditionalUpdatePositionAction($positionChangeEvent)
{
@@ -233,16 +257,25 @@ abstract class AbstractCrudController extends BaseAdminController
protected function getCurrentListOrder($update_session = true)
{
return $this->getListOrderFromSession(
$this->objectName,
$this->orderRequestParameterName,
$this->defaultListOrder
$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
* @return \Thelia\Core\HttpFoundation\Response the response
*/
protected function renderList()
{
@@ -252,13 +285,14 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* The default action is displaying the list.
*
* @return Thelia\Core\HttpFoundation\Response the response
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function defaultAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::VIEW))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::VIEW)) {
return $response;
}
return $this->renderList();
}
@@ -266,13 +300,14 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Create a new object
*
* @return Thelia\Core\HttpFoundation\Response the response
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function createAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::CREATE))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::CREATE)) {
return $response;
}
// Error (Default: false)
$error_msg = false;
@@ -281,7 +316,6 @@ abstract class AbstractCrudController extends BaseAdminController
$creationForm = $this->getCreationForm($this->getRequest());
try {
// Check the form against constraints violations
$form = $this->validateForm($creationForm, "POST");
@@ -290,18 +324,31 @@ abstract class AbstractCrudController extends BaseAdminController
// 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))
if (! $this->eventContainsObject($createEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was created.", array('%obj', $this->objectName)));
$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->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
@@ -312,7 +359,7 @@ abstract class AbstractCrudController extends BaseAdminController
$successUrl = str_replace('_ID_', $this->getObjectId($createdObject), $creationForm->getSuccessUrl());
// Redirect to the success URL
$this->redirect($successUrl);
return $this->generateRedirect($successUrl);
} else {
return $response;
}
@@ -326,7 +373,7 @@ abstract class AbstractCrudController extends BaseAdminController
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => $this->objectName)),
$this->getTranslator()->trans("%obj creation", ['%obj' => $this->objectName]),
$error_msg,
$creationForm,
$ex
@@ -340,17 +387,17 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Load a object for modification, and display the edit template.
*
* @return Thelia\Core\HttpFoundation\Response the response
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function updateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE))
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);
@@ -365,13 +412,14 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* 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
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function processUpdateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
// Error (Default: false)
$error_msg = false;
@@ -380,7 +428,6 @@ abstract class AbstractCrudController extends BaseAdminController
$changeForm = $this->getUpdateForm($this->getRequest());
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
@@ -389,18 +436,31 @@ abstract class AbstractCrudController extends BaseAdminController
// 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))
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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
@@ -410,11 +470,11 @@ abstract class AbstractCrudController extends BaseAdminController
// 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') {
$this->redirectToEditionTemplate($this->getRequest());
return $this->redirectToEditionTemplate($this->getRequest());
}
// Redirect to the success URL
$this->redirect($changeForm->getSuccessUrl());
return $this->generateSuccessRedirect($changeForm);
} else {
return $response;
}
@@ -429,7 +489,7 @@ abstract class AbstractCrudController extends BaseAdminController
if (false !== $error_msg) {
// At this point, the form has errors, and should be redisplayed.
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)),
$this->getTranslator()->trans("%obj modification", ['%obj' => $this->objectName]),
$error_msg,
$changeForm,
$ex
@@ -446,25 +506,26 @@ abstract class AbstractCrudController extends BaseAdminController
public function updatePositionAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
try {
$mode = $this->getRequest()->get('mode', null);
if ($mode == 'up')
if ($mode == 'up') {
$mode = UpdatePositionEvent::POSITION_UP;
else if ($mode == 'down')
} elseif ($mode == 'down') {
$mode = UpdatePositionEvent::POSITION_DOWN;
else
} 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);
@@ -473,7 +534,7 @@ abstract class AbstractCrudController extends BaseAdminController
$response = $this->performAdditionalUpdatePositionAction($event);
if ($response == null) {
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
} else {
return $response;
}
@@ -482,20 +543,21 @@ abstract class AbstractCrudController extends BaseAdminController
protected function genericUpdatePositionAction($object, $eventName, $doFinalRedirect = true)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE))
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')
if ($mode == 'up') {
$mode = UpdatePositionEvent::POSITION_UP;
else if ($mode == 'down')
} elseif ($mode == 'down') {
$mode = UpdatePositionEvent::POSITION_DOWN;
else
} else {
$mode = UpdatePositionEvent::POSITION_ABSOLUTE;
}
$position = $this->getRequest()->get('position', null);
@@ -508,7 +570,9 @@ abstract class AbstractCrudController extends BaseAdminController
}
}
if ($doFinalRedirect) $this->redirectToEditionTemplate();
if ($doFinalRedirect) {
return $this->redirectToEditionTemplate();
}
}
/**
@@ -517,8 +581,9 @@ abstract class AbstractCrudController extends BaseAdminController
public function setToggleVisibilityAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
$changeEvent = $this->createToggleVisibilityEvent($this->getRequest());
@@ -535,30 +600,77 @@ abstract class AbstractCrudController extends BaseAdminController
/**
* Delete an object
*
* @return Thelia\Core\HttpFoundation\Response the response
* @return \Thelia\Core\HttpFoundation\Response the response
*/
public function deleteAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::DELETE))
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::DELETE)) {
return $response;
// Get the currency id, and dispatch the delet 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)));
}
$response = $this->performAdditionalDeleteAction($deleteEvent);
try {
// Check token
$this->getTokenProvider()->checkToken(
$this->getRequest()->query->get("_token")
);
if ($response == null)
$this->redirectToListTemplate();
else
return $response;
// 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

@@ -13,8 +13,9 @@
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;
@@ -43,23 +44,21 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
* @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 = null,
$orderRequestParameterName = null,
$defaultListOrder,
$orderRequestParameterName,
$resourceCode,
$createEventIdentifier,
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier = null,
$changePositionEventIdentifier = null,
$updateSeoEventIdentifier = null
)
{
$updateSeoEventIdentifier = null,
$moduleCode = null
) {
parent::__construct(
$objectName,
$defaultListOrder,
@@ -69,18 +68,18 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
$updateEventIdentifier,
$deleteEventIdentifier,
$visibilityToggleEventIdentifier,
$changePositionEventIdentifier
$changePositionEventIdentifier,
$moduleCode
);
$this->updateSeoEventIdentifier = $updateSeoEventIdentifier;
}
/**
* Put in this method post object update SEO processing if required.
*
* @param unknown $updateSeoEvent the update event
* @return Response a response, or null to continue normal processing
* @param UpdateSeoEvent $updateSeoEvent the update event
* @return null|Response a response, or null to continue normal processing
*/
protected function performAdditionalUpdateSeoAction($updateSeoEvent)
{
@@ -92,7 +91,7 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
*/
protected function getUpdateSeoForm()
{
return new SeoForm($this->getRequest());
return $this->createForm(AdminForm::SEO);
}
/**
@@ -103,7 +102,6 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
*/
protected function getUpdateSeoEvent($formData)
{
$updateSeoEvent = new UpdateSeoEvent($formData['id']);
$updateSeoEvent
@@ -121,7 +119,7 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
/**
* Hydrate the SEO form for this object, before passing it to the update template
*
* @param unknown $object
* @param mixed $object
*/
protected function hydrateSeoForm($object)
{
@@ -136,7 +134,7 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
'meta_keywords' => $object->getMetaKeywords()
);
$seoForm = new SeoForm($this->getRequest(), "form", $data);
$seoForm = $this->createForm(AdminForm::SEO, "form", $data);
$this->getParserContext()->addForm($seoForm);
// URL based on the language
@@ -151,7 +149,7 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
public function processUpdateSeoAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
if (null !== $response = $this->checkAuth($this->resourceCode, $this->getModuleCode(), AccessManager::UPDATE)) {
return $response;
}
@@ -165,7 +163,6 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
$this->getRequest()->attributes->set($this->objectName . '_id', $this->getRequest()->get('current_id'));
try {
// Check the form against constraints violations
$form = $this->validateForm($updateSeoForm, "POST");
@@ -185,11 +182,11 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
// 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') {
$this->redirectToEditionTemplate($this->getRequest());
return $this->redirectToEditionTemplate($this->getRequest());
}
// Redirect to the success URL
$this->redirect($updateSeoForm->getSuccessUrl());
return $this->generateSuccessRedirect($updateSeoForm);
} else {
return $response;
}
@@ -203,7 +200,6 @@ abstract class AbstractSeoCrudController extends AbstractCrudController
// Load object if exist
if (null !== $object = $this->getExistingObject()) {
// Hydrate the form abd pass it to the parser
$changeForm = $this->hydrateObjectForm($object);

View File

@@ -11,20 +11,20 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Address\AddressCreateOrUpdateEvent;
use Thelia\Core\Event\Address\AddressEvent;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\AddressCreateForm;
use Thelia\Form\AddressUpdateForm;
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 <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class AddressController extends AbstractCrudController
{
@@ -34,9 +34,7 @@ class AddressController extends AbstractCrudController
'registration_date',
null,
null,
AdminResources::ADDRESS,
TheliaEvents::ADDRESS_CREATE,
TheliaEvents::ADDRESS_UPDATE,
TheliaEvents::ADDRESS_DELETE
@@ -45,7 +43,9 @@ class AddressController extends AbstractCrudController
public function useAddressAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$address_id = $this->getRequest()->request->get('address_id');
@@ -60,12 +60,21 @@ class AddressController extends AbstractCrudController
$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()));
$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()));
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
/**
@@ -73,7 +82,7 @@ class AddressController extends AbstractCrudController
*/
protected function getCreationForm()
{
return new AddressCreateForm($this->getRequest());
return $this->createForm(AdminForm::ADDRESS_CREATE);
}
/**
@@ -81,14 +90,14 @@ class AddressController extends AbstractCrudController
*/
protected function getUpdateForm()
{
return new AddressUpdateForm($this->getRequest());
return $this->createForm(AdminForm::ADDRESS_UPDATE);
}
/**
* Fills in the form data array
*
* @param unknown $object
* @return multitype:NULL
* @return array
*/
protected function createFormDataArray($object)
{
@@ -103,6 +112,7 @@ class AddressController extends AbstractCrudController
"zipcode" => $object->getZipcode(),
"city" => $object->getCity(),
"country" => $object->getCountryId(),
"state" => $object->getStateId(),
"cellphone" => $object->getCellphone(),
"phone" => $object->getPhone(),
"company" => $object->getCompany()
@@ -116,7 +126,7 @@ class AddressController extends AbstractCrudController
*/
protected function hydrateObjectForm($object)
{
return new AddressUpdateForm($this->getRequest(), "form", $this->createFormDataArray($object));
return $this->createForm(AdminForm::ADDRESS_UPDATE, "form", $this->createFormDataArray($object));
}
/**
@@ -165,11 +175,11 @@ class AddressController extends AbstractCrudController
$formData["cellphone"],
$formData["phone"],
$formData["company"],
$formData["is_default"]
$formData["is_default"],
$formData["state"]
);
return $event;
}
/**
@@ -257,10 +267,13 @@ class AddressController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
// We display here the custromer edition template
$this->redirectToRoute('admin.customer.update.view', array(
"page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
));
return $this->generateRedirectFromRoute(
'admin.customer.update.view',
[
"page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
]
);
}
/**
@@ -279,7 +292,7 @@ class AddressController extends AbstractCrudController
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
/**
@@ -290,19 +303,20 @@ class AddressController extends AbstractCrudController
*/
protected function performAdditionalCreateAction($createEvent)
{
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
protected function performAdditionalUpdateAction($event)
{
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
protected function getCustomerId()
{
if (null !== $address = $this->getExistingObject())
if (null !== $address = $this->getExistingObject()) {
return $address->getCustomerId();
else
} else {
return $this->getRequest()->get('customer_id', 0);
}
}
}

View File

@@ -12,10 +12,17 @@
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");
}

View File

@@ -14,13 +14,16 @@ 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;
if (null !== $response = $this->checkAuth(AdminResources::ADMIN_LOG, array(), AccessManager::VIEW)) {
return $response;
}
// Render the edition template.
return $this->render('admin-logs');
@@ -30,21 +33,22 @@ class AdminLogsController extends BaseAdminController
{
$entries = array();
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) {
/** @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|%s|%s:%s%s",
date('Y-m-d H:i:s', $entry->getCreatedAt()->getTimestamp()),
$entry->getAdminLogin(),
$entry->getResource(),
$entry->getAction()
$entry->getAction(),
(null !== $entry->getResourceId()) ? ":" . $entry->getResourceId() : ""
),
"data" => $entry->getMessage(),
);

View File

@@ -12,11 +12,11 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Administrator\AdministratorEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Form\AdministratorCreationForm;
use Thelia\Form\AdministratorModificationForm;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Admin;
use Thelia\Model\AdminQuery;
class AdministratorController extends AbstractCrudController
@@ -27,23 +27,39 @@ class AdministratorController extends AbstractCrudController
'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 new AdministratorCreationForm($this->getRequest());
return $this->createForm(AdminForm::ADMINISTRATOR_CREATION);
}
protected function getUpdateForm()
{
return new AdministratorModificationForm($this->getRequest());
return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -56,6 +72,7 @@ class AdministratorController extends AbstractCrudController
$event->setPassword($formData['password']);
$event->setProfile($formData['profile'] ? : null);
$event->setLocale($formData['locale']);
$event->setEmail($formData['email']);
return $event;
}
@@ -71,6 +88,7 @@ class AdministratorController extends AbstractCrudController
$event->setPassword($formData['password']);
$event->setProfile($formData['profile'] ? : null);
$event->setLocale($formData['locale']);
$event->setEmail($formData['email']);
return $event;
}
@@ -91,6 +109,11 @@ class AdministratorController extends AbstractCrudController
return $event->hasAdministrator();
}
/**
* @param Admin $object
*
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
@@ -99,11 +122,12 @@ class AdministratorController extends AbstractCrudController
'lastname' => $object->getLastname(),
'login' => $object->getLogin(),
'profile' => $object->getProfileId(),
'locale' => $object->getLocale()
'locale' => $object->getLocale(),
'email' => $object->getEmail()
);
// Setup the object form
return new AdministratorModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::ADMINISTRATOR_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -117,11 +141,19 @@ class AdministratorController extends AbstractCrudController
->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();
@@ -145,24 +177,24 @@ class AdministratorController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
// We always return to the feature edition form
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
protected function performAdditionalCreateAction($updateEvent)
{
// We always return to the feature edition form
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
protected function performAdditionalUpdateAction($updateEvent)
{
// We always return to the feature edition form
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
protected function redirectToListTemplate()
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.administrators.view"
);
}

View File

@@ -16,20 +16,17 @@ 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\Cache\AssetsFlushForm;
use Thelia\Form\Cache\CacheFlushForm;
use Thelia\Form\Cache\ImagesAndDocumentsCacheFlushForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
/**
* Class CacheController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class AdvancedConfigurationController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $result = $this->checkAuth(AdminResources::ADVANCED_CONFIGURATION, [], AccessManager::VIEW)) {
@@ -45,18 +42,17 @@ class AdvancedConfigurationController extends BaseAdminController
return $result;
}
$form = new CacheFlushForm($this->getRequest());
$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()));
}
$this->redirectToRoute('admin.configuration.advanced');
return $this->generateRedirectFromRoute('admin.configuration.advanced');
}
public function flushAssetsAction()
@@ -65,18 +61,17 @@ class AdvancedConfigurationController extends BaseAdminController
return $result;
}
$form = new AssetsFlushForm($this->getRequest());
$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()));
}
$this->redirectToRoute('admin.configuration.advanced');
return $this->generateRedirectFromRoute('admin.configuration.advanced');
}
public function flushImagesAndDocumentsAction()
@@ -85,20 +80,29 @@ class AdvancedConfigurationController extends BaseAdminController
return $result;
}
$form = new ImagesAndDocumentsCacheFlushForm($this->getRequest());
$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'));
$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'));
$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()));
}
$this->redirectToRoute('admin.configuration.advanced');
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

@@ -12,7 +12,6 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Area\AreaAddCountryEvent;
use Thelia\Core\Event\Area\AreaCreateEvent;
use Thelia\Core\Event\Area\AreaDeleteEvent;
@@ -21,30 +20,28 @@ use Thelia\Core\Event\Area\AreaUpdateEvent;
use Thelia\Core\Event\Area\AreaUpdatePostageEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\Area\AreaCountryForm;
use Thelia\Form\Area\AreaCreateForm;
use Thelia\Form\Area\AreaModificationForm;
use Thelia\Form\Area\AreaPostageForm;
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 <mraynaud@openstudio.fr>
* @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
@@ -61,7 +58,7 @@ class AreaController extends AbstractCrudController
*/
protected function getCreationForm()
{
return new AreaCreateForm($this->getRequest());
return $this->createForm(AdminForm::AREA_CREATE);
}
/**
@@ -69,27 +66,29 @@ class AreaController extends AbstractCrudController
*/
protected function getUpdateForm()
{
return new AreaModificationForm($this->getRequest());
return $this->createForm(AdminForm::AREA_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param unknown $object
* @param Area $object
* @return BaseForm
*/
protected function hydrateObjectForm($object)
{
$data = array(
'area_id' => $object->getId(),
'name' => $object->getName()
);
return new AreaModificationForm($this->getRequest(), 'form', $data);
return $this->createForm(AdminForm::AREA_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
* @param array $formData
*
* @return \Thelia\Core\Event\Area\AreaCreateEvent
*/
@@ -103,15 +102,25 @@ class AreaController extends AbstractCrudController
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return \Thelia\Core\Event\Area\AreaUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$event = new AreaUpdateEvent();
return $this->hydrateEvent($event, $formData);
$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']);
@@ -121,6 +130,8 @@ class AreaController extends AbstractCrudController
/**
* Creates the delete event with the provided form data
*
* @return AreaDeleteEvent
*/
protected function getDeleteEvent()
{
@@ -131,6 +142,7 @@ class AreaController extends AbstractCrudController
* 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)
{
@@ -141,6 +153,7 @@ class AreaController extends AbstractCrudController
* Get the created object from an event.
*
* @param \Thelia\Core\Event\Area\AreaEvent $event
* @return Area
*/
protected function getObjectFromEvent($event)
{
@@ -159,6 +172,7 @@ class AreaController extends AbstractCrudController
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\Area $object
* @return string
*/
protected function getObjectLabel($object)
{
@@ -169,6 +183,7 @@ class AreaController extends AbstractCrudController
* Returns the object ID from the object
*
* @param \Thelia\Model\Area $object
* @return int
*/
protected function getObjectId($object)
{
@@ -178,7 +193,8 @@ class AreaController extends AbstractCrudController
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @param string|null $currentOrder, if any, null otherwise.
* @return \Thelia\Core\HttpFoundation\Response
*/
protected function renderListTemplate($currentOrder)
{
@@ -190,9 +206,12 @@ class AreaController extends AbstractCrudController
*/
protected function renderEditionTemplate()
{
return $this->render('shipping-configuration-edit',array(
return $this->render(
'shipping-configuration-edit',
array(
'area_id' => $this->getAreaId()
));
)
);
}
/**
@@ -200,9 +219,12 @@ class AreaController extends AbstractCrudController
*/
protected function redirectToEditionTemplate()
{
$this->redirectToRoute('admin.configuration.shipping-configuration.update.view', array(), array(
return $this->generateRedirectFromRoute(
'admin.configuration.shipping-configuration.update.view',
[],
[
"area_id" => $this->getAreaId()
)
]
);
}
@@ -211,7 +233,7 @@ class AreaController extends AbstractCrudController
*/
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.shipping-configuration.default');
return $this->generateRedirectFromRoute('admin.configuration.shipping-configuration.default');
}
/**
@@ -220,30 +242,42 @@ class AreaController extends AbstractCrudController
public function addCountry()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$areaCountryForm = new AreaCountryForm($this->getRequest());
$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))
if (! $this->eventContainsObject($event)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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
$this->redirect($areaCountryForm->getSuccessUrl());
return $this->generateSuccessRedirect($areaCountryForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -253,29 +287,106 @@ class AreaController extends AbstractCrudController
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), $error_msg, $areaCountryForm);
$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();
}
public function removeCountry()
/**
* 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;
$request = $this->getRequest();
$removeCountryEvent = new AreaRemoveCountryEvent($request->request->get('area_id', 0), $request->request->get('country_id', 0));
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);
$this->redirectToEditionTemplate();
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;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$areaUpdateForm = new AreaPostageForm($this->getRequest());
$areaUpdateForm = $this->createForm(AdminForm::AREA_POSTAGE);
$error_msg = null;
try {
@@ -286,17 +397,29 @@ class AreaController extends AbstractCrudController
$this->dispatch(TheliaEvents::AREA_POSTAGE_UPDATE, $event);
if (! $this->eventContainsObject($event))
if (! $this->eventContainsObject($event)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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
$this->redirect($areaUpdateForm->getSuccessUrl());
return $this->generateSuccessRedirect($areaUpdateForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -306,7 +429,10 @@ class AreaController extends AbstractCrudController
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), $error_msg, $areaUpdateForm);
$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

@@ -12,15 +12,15 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Attribute\AttributeAvDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Attribute\AttributeAvUpdateEvent;
use Thelia\Core\Event\Attribute\AttributeAvCreateEvent;
use Thelia\Model\AttributeAvQuery;
use Thelia\Form\AttributeAvModificationForm;
use Thelia\Form\AttributeAvCreationForm;
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
@@ -35,9 +35,7 @@ class AttributeAvController extends AbstractCrudController
'attributeav',
'manual',
'order',
AdminResources::ATTRIBUTE,
TheliaEvents::ATTRIBUTE_AV_CREATE,
TheliaEvents::ATTRIBUTE_AV_UPDATE,
TheliaEvents::ATTRIBUTE_AV_DELETE,
@@ -48,12 +46,12 @@ class AttributeAvController extends AbstractCrudController
protected function getCreationForm()
{
return new AttributeAvCreationForm($this->getRequest());
return $this->createForm(AdminForm::ATTRIBUTE_AV_CREATION);
}
protected function getUpdateForm()
{
return new AttributeAvModificationForm($this->getRequest());
throw new \LogicException("Attribute Av. modification is not yet implemented");
}
protected function getCreationEvent($formData)
@@ -88,9 +86,9 @@ class AttributeAvController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('attributeav_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('attributeav_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -106,17 +104,7 @@ class AttributeAvController extends AbstractCrudController
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 new AttributeAvModificationForm($this->getRequest(), "form", $data);
throw new \LogicException("Attribute Av. modification is not yet implemented");
}
protected function getObjectFromEvent($event)
@@ -136,11 +124,19 @@ class AttributeAvController extends AbstractCrudController
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();
@@ -158,8 +154,8 @@ class AttributeAvController extends AbstractCrudController
{
// We always return to the attribute edition form
return $this->render(
'attribute-edit',
$this->getViewArguments()
'attribute-edit',
$this->getViewArguments()
);
}
@@ -171,18 +167,17 @@ class AttributeAvController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
// We always return to the attribute edition form
$this->redirectToRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
$this->getViewArguments()
);
}
}
}

View File

@@ -12,19 +12,18 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Attribute\AttributeDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Attribute\AttributeUpdateEvent;
use Thelia\Core\Event\Attribute\AttributeCreateEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Model\AttributeQuery;
use Thelia\Form\AttributeModificationForm;
use Thelia\Form\AttributeCreationForm;
use Thelia\Core\Event\UpdatePositionEvent;
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
@@ -39,9 +38,7 @@ class AttributeController extends AbstractCrudController
'attribute',
'manual',
'order',
AdminResources::ATTRIBUTE,
TheliaEvents::ATTRIBUTE_CREATE,
TheliaEvents::ATTRIBUTE_UPDATE,
TheliaEvents::ATTRIBUTE_DELETE,
@@ -52,12 +49,12 @@ class AttributeController extends AbstractCrudController
protected function getCreationForm()
{
return new AttributeCreationForm($this->getRequest());
return $this->createForm(AdminForm::ATTRIBUTE_CREATION);
}
protected function getUpdateForm()
{
return new AttributeModificationForm($this->getRequest());
return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -99,9 +96,7 @@ class AttributeController extends AbstractCrudController
$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);
@@ -117,9 +112,9 @@ class AttributeController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('attribute_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('attribute_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -135,7 +130,6 @@ class AttributeController extends AbstractCrudController
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
@@ -146,7 +140,7 @@ class AttributeController extends AbstractCrudController
);
// Setup the object form
return new AttributeModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::ATTRIBUTE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -166,11 +160,19 @@ class AttributeController extends AbstractCrudController
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();
@@ -184,28 +186,28 @@ class AttributeController extends AbstractCrudController
protected function renderEditionTemplate()
{
return $this->render(
'attribute-edit',
array(
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
)
'attribute-edit',
array(
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
)
);
}
protected function redirectToEditionTemplate()
{
$this->redirectToRoute(
"admin.configuration.attributes.update",
array(
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
)
return $this->generateRedirectFromRoute(
"admin.configuration.attributes.update",
[
'attribute_id' => $this->getRequest()->get('attribute_id'),
'attributeav_order' => $this->getAttributeAvListOrder()
]
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.attributes.default');
return $this->generateRedirectFromRoute('admin.configuration.attributes.default');
}
/**
@@ -216,9 +218,9 @@ class AttributeController extends AbstractCrudController
protected function getAttributeAvListOrder()
{
return $this->getListOrderFromSession(
'attributeav',
'attributeav_order',
'manual'
'attributeav',
'attributeav_order',
'manual'
);
}
@@ -228,11 +230,12 @@ class AttributeController extends AbstractCrudController
protected function addRemoveFromAllTemplates($eventType)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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);
@@ -242,7 +245,7 @@ class AttributeController extends AbstractCrudController
return $this->errorPage($ex);
}
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
/**

View File

@@ -13,30 +13,26 @@
namespace Thelia\Controller\Admin;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Thelia\Controller\BaseController;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Exception\AuthorizationException;
use Thelia\Model\ConfigQuery;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Tools\URL;
use Thelia\Model\AdminLog;
use Thelia\Model\LangQuery;
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 Symfony\Component\Routing\Router;
use Thelia\Model\Admin;
use Thelia\Core\Security\Token\CookieTokenProvider;
use Thelia\Model\AdminLog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\CurrencyQuery;
use Thelia\Core\Template\TemplateHelper;
use Thelia\Model\LangQuery;
use Thelia\Tools\URL;
class BaseAdminController extends BaseController
{
const CONTROLLER_TYPE = 'admin';
const TEMPLATE_404 = "404";
/**
@@ -44,17 +40,7 @@ class BaseAdminController extends BaseController
* setCurrentRouter() method to pass their own router, and use the route related
* methods of this class.
*/
private $currentRouter = "router.admin";
protected function getCurrentRouter()
{
return $this->currentRouter;
}
protected function setCurrentRouter($routerId)
{
$this->currentRouter = $routerId;
}
protected $currentRouter = "router.admin";
/**
* Helper to append a message to the admin log.
@@ -63,15 +49,23 @@ class BaseAdminController extends BaseController
* @param string $action
* @param string $message
*/
public function adminLogAppend($resource, $action, $message)
public function adminLogAppend($resource, $action, $message, $resourceId = null)
{
AdminLog::append($resource, $action, $message, $this->getRequest(), $this->getSecurityContext()->getAdminUser());
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 unknown $template
* @param string $template the template name
* @return Response the response which contains the rendered view
*/
public function processTemplateAction($template)
@@ -90,6 +84,14 @@ class BaseAdminController extends BaseController
return $this->pageNotFound();
}
/**
* @return string
*/
public function getControllerType()
{
return self::CONTROLLER_TYPE;
}
/**
* Return a 404 error
*
@@ -103,17 +105,28 @@ class BaseAdminController extends BaseController
/**
* Return a general error page
*
* @param mixed $message a message string, or an exception instance
* @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) {
$message = $this->getTranslator()->trans("Sorry, an error occured: %msg", array('%msg' => $message->getMessage()));
$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',
return $this->render(
'general_error',
array(
"error_message" => $message
),
@@ -136,15 +149,15 @@ class BaseAdminController extends BaseController
$modules = is_array($modules) ? $modules : array($modules);
$accesses = is_array($accesses) ? $accesses : array($accesses);
if ($this->getSecurityContext()->isGranted(array("ADMIN"), $resources, $modules, $accesses)) {
// Okay !
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);
return $this->errorPage($this->getTranslator()->trans("Sorry, you're not allowed to perform this action"), 403);
}
/*
@@ -158,20 +171,19 @@ class BaseAdminController extends BaseController
'%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
* @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)
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(
@@ -198,14 +210,19 @@ class BaseAdminController extends BaseController
}
/**
* @return a ParserInterface instance parser
* @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 ?: TemplateHelper::getInstance()->getActiveAdminTemplate());
$parser->setTemplateDefinition(
$template ?: $this->getTemplateHelper()->getActiveAdminTemplate(),
$this->useFallbackTemplate
);
return $parser;
}
@@ -222,49 +239,11 @@ class BaseAdminController extends BaseController
protected function forward($controller, array $path = array(), array $query = array())
{
$path['_controller'] = $controller;
$subRequest = $this->container->get('request')->duplicate($query, null, $path);
$subRequest = $this->container->get('request_stack')->getCurrentRequest()->duplicate($query, null, $path);
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
/**
* 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 Boolean|string $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->currentRouter,
$routeId,
$parameters,
$referenceType
);
}
/**
* Redirect to à route ID related URL
*
* @param string $routeId the route ID, as found in Config/Resources/routing/admin.xml
* @param array $urlParameters the URL parameters, as a var/value pair array
* @param array $routeParameters
*/
public function redirectToRoute($routeId, array $urlParameters = array(), array $routeParameters = array())
{
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId, $routeParameters), $urlParameters));
}
/**
* Get the current edition currency ID, checking if a change was requested in the current request.
*/
@@ -272,7 +251,6 @@ class BaseAdminController extends BaseController
{
// 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;
}
@@ -289,7 +267,6 @@ class BaseAdminController extends BaseController
{
// 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;
}
@@ -309,17 +286,21 @@ class BaseAdminController extends BaseController
/**
* 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::read("one_domain_foreach_lang", false))
return;
if (!ConfigQuery::isMultiDomainActivated()) {
return null;
}
// If we don't have a locale value, use the locale value in the session
if(!$locale)
if (!$locale) {
$locale = $this->getCurrentEditionLocale();
}
return LangQuery::create()->findOneByLocale($locale)->getUrl();
}
@@ -338,60 +319,20 @@ class BaseAdminController extends BaseController
*/
protected function getListOrderFromSession($objectName, $requestParameterName, $defaultListOrder, $updateSession = true)
{
$order = $defaultListOrder;
$orderSessionIdentifier = sprintf("admin.%s.currentListOrder", $objectName);
// Find the current order
$order = $this->getRequest()->get(
$requestParameterName,
$this->getSession()->get($orderSessionIdentifier, $defaultListOrder)
$requestParameterName,
$this->getSession()->get($orderSessionIdentifier, $defaultListOrder)
);
if ($updateSession) $this->getSession()->set($orderSessionIdentifier, $order);
if ($updateSession) {
$this->getSession()->set($orderSessionIdentifier, $order);
}
return $order;
}
/**
* Create the remember me cookie for the given user.
*/
protected function createAdminRememberMeCookie(Admin $user)
{
$ctp = new CookieTokenProvider();
$cookieName = ConfigQuery::read('admin_remember_me_cookie_name', 'armcn');
$cookieExpiration = ConfigQuery::read('admin_remember_me_cookie_expiration', 2592000 /* 1 month */);
$ctp->createCookie($user, $cookieName, $cookieExpiration);
}
/**
* Get the rememberme key from the cookie.
*
* @return string hte key found, or null if no key was found.
*/
protected function getRememberMeKeyFromCookie()
{
// Check if we can authenticate the user with a cookie-based token
$cookieName = ConfigQuery::read('admin_remember_me_cookie_name', 'armcn');
$ctp = new CookieTokenProvider();
return $ctp->getKeyFromCookie($this->getRequest(), $cookieName);
}
/** Clear the remember me cookie.
*
*/
protected function clearRememberMeCookie()
{
$ctp = new CookieTokenProvider();
$cookieName = ConfigQuery::read('admin_remember_me_cookie_name', 'armcn');
$ctp->clearCookie($cookieName);
}
/**
* Render the given template, and returns the result as an Http Response.
*
@@ -414,20 +355,17 @@ class BaseAdminController extends BaseController
/**
* Render the given template, and returns the result as a string.
*
* @param $templateName the complete template name, with extension
* @param array $args the template arguments
* @param null $templateDir
* @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';
$session = $this->getSession();
// Find the current edit language ID
$edition_language = $this->getCurrentEditionLang();
@@ -436,16 +374,9 @@ class BaseAdminController extends BaseController
// Prepare common template variables
$args = array_merge($args, array(
'locale' => $session->getLang()->getLocale(),
'lang_code' => $session->getLang()->getCode(),
'lang_id' => $session->getLang()->getId(),
'edit_language_id' => $edition_language->getId(),
'edit_language_locale' => $edition_language->getLocale(),
'edit_currency_id' => $edition_currency->getId(),
'current_url' => $this->getRequest()->getUri()
));
// Update the current edition language & currency in session
@@ -457,7 +388,6 @@ class BaseAdminController extends BaseController
// 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.

View File

@@ -11,6 +11,7 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Brand\BrandCreateEvent;
use Thelia\Core\Event\Brand\BrandDeleteEvent;
use Thelia\Core\Event\Brand\BrandEvent;
@@ -20,8 +21,8 @@ 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\BrandCreationForm;
use Thelia\Form\Brand\BrandModificationForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\Brand;
use Thelia\Model\BrandQuery;
@@ -32,16 +33,13 @@ use Thelia\Model\BrandQuery;
*/
class BrandController extends AbstractSeoCrudController
{
public function __construct()
{
parent::__construct(
'brand',
'manual',
'order',
AdminResources::BRAND,
TheliaEvents::BRAND_CREATE,
TheliaEvents::BRAND_UPDATE,
TheliaEvents::BRAND_DELETE,
@@ -56,7 +54,7 @@ class BrandController extends AbstractSeoCrudController
*/
protected function getCreationForm()
{
return new BrandCreationForm($this->getRequest());
return $this->createForm(AdminForm::BRAND_CREATION);
}
/**
@@ -64,7 +62,7 @@ class BrandController extends AbstractSeoCrudController
*/
protected function getUpdateForm()
{
return new BrandModificationForm($this->getRequest());
return $this->createForm(AdminForm::BRAND_MODIFICATION);
}
/**
@@ -91,7 +89,7 @@ class BrandController extends AbstractSeoCrudController
];
// Setup the object form
return new BrandModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::BRAND_MODIFICATION, "form", $data);
}
/**
@@ -189,7 +187,7 @@ class BrandController extends AbstractSeoCrudController
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param $object \Thelia\Model\Brand
* @param Brand $object
*
* @return string brand title
*/
@@ -201,7 +199,7 @@ class BrandController extends AbstractSeoCrudController
/**
* Returns the object ID from the object
*
* @param $object \Thelia\Model\Brand
* @param Brand $object
*
* @return int brand id
*/
@@ -247,7 +245,11 @@ class BrandController extends AbstractSeoCrudController
*/
protected function redirectToEditionTemplate()
{
$this->redirect($this->getRoute('admin.brand.update', $this->getEditionArguments()));
return $this->generateRedirectFromRoute(
'admin.brand.update',
[],
$this->getEditionArguments()
);
}
/**
@@ -255,7 +257,7 @@ class BrandController extends AbstractSeoCrudController
*/
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.brand.default');
return $this->generateRedirectFromRoute('admin.brand.default');
}
/**
@@ -277,5 +279,4 @@ class BrandController extends AbstractSeoCrudController
$positionValue
);
}
}

View File

@@ -12,23 +12,23 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Category\CategoryDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Category\CategoryUpdateEvent;
use Thelia\Core\Event\Category\CategoryCreateEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Model\CategoryQuery;
use Thelia\Form\CategoryModificationForm;
use Thelia\Form\CategoryCreationForm;
use Thelia\Core\Event\UpdatePositionEvent;
use Thelia\Core\Event\Category\CategoryToggleVisibilityEvent;
use Thelia\Core\Event\Category\CategoryDeleteContentEvent;
use Thelia\Core\Event\Category\CategoryAddContentEvent;
use Thelia\Model\FolderQuery;
use Thelia\Model\ContentQuery;
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
@@ -43,9 +43,7 @@ class CategoryController extends AbstractSeoCrudController
'category',
'manual',
'category_order',
AdminResources::CATEGORY,
TheliaEvents::CATEGORY_CREATE,
TheliaEvents::CATEGORY_UPDATE,
TheliaEvents::CATEGORY_DELETE,
@@ -57,12 +55,12 @@ class CategoryController extends AbstractSeoCrudController
protected function getCreationForm()
{
return new CategoryCreationForm($this->getRequest());
return $this->createForm(AdminForm::CATEGORY_CREATION);
}
protected function getUpdateForm()
{
return new CategoryModificationForm($this->getRequest());
return $this->createForm(AdminForm::CATEGORY_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -92,6 +90,7 @@ class CategoryController extends AbstractSeoCrudController
->setPostscriptum($formData['postscriptum'])
->setVisible($formData['visible'])
->setParent($formData['parent'])
->setDefaultTemplateId($formData['default_template_id'])
;
return $changeEvent;
@@ -100,9 +99,9 @@ class CategoryController extends AbstractSeoCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('category_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('category_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -116,6 +115,10 @@ class CategoryController extends AbstractSeoCrudController
return $event->hasCategory();
}
/**
* @param \Thelia\Model\Category $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
// Hydrate the "SEO" tab form
@@ -123,18 +126,19 @@ class CategoryController extends AbstractSeoCrudController
// 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()
'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 new CategoryModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::CATEGORY_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -154,11 +158,19 @@ class CategoryController extends AbstractSeoCrudController
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();
@@ -179,35 +191,41 @@ class CategoryController extends AbstractSeoCrudController
// 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)
));
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()
{
$this->redirectToRoute('admin.categories', array(
return $this->generateRedirectFromRoute(
'admin.categories.default',
[
'category_id' => $this->getRequest()->get('category_id', 0),
'page' => $this->getRequest()->get('page', 1))
'page' => $this->getRequest()->get('page', 1)
]
);
}
protected function redirectToListTemplateWithId($category_id)
{
$response = null;
if ($category_id > 0) {
$this->redirectToRoute(
$response = $this->generateRedirectFromRoute(
'admin.categories.default',
array('category_id' => $category_id)
['category_id' => $category_id]
);
} else {
$this->redirectToRoute(
'admin.catalog'
);
$response = $this->generateRedirectFromRoute('admin.catalog');
}
return $response;
}
protected function renderEditionTemplate()
@@ -217,7 +235,10 @@ class CategoryController extends AbstractSeoCrudController
protected function redirectToEditionTemplate()
{
$this->redirectToRoute("admin.categories.update", $this->getEditionArguments());
return $this->generateRedirectFromRoute(
"admin.categories.update",
$this->getEditionArguments()
);
}
/**
@@ -226,7 +247,9 @@ class CategoryController extends AbstractSeoCrudController
public function setToggleVisibilityAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new CategoryToggleVisibilityEvent($this->getExistingObject());
@@ -241,34 +264,49 @@ class CategoryController extends AbstractSeoCrudController
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();
$this->redirectToListTemplateWithId($category_id);
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();
$this->redirectToListTemplateWithId($category_id);
$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();
$this->redirectToListTemplateWithId($category_id);
$response = $this->redirectToListTemplateWithId($category_id);
}
return null;
return $response;
}
public function getAvailableRelatedContentAction($categoryId, $folderId)
@@ -278,13 +316,15 @@ class CategoryController extends AbstractSeoCrudController
$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)
->filterById(
CategoryAssociatedContentQuery::create()->select('content_id')->findByCategoryId($categoryId),
Criteria::NOT_IN
)
->find();
;
;
if ($list !== null) {
foreach ($list as $item) {
@@ -299,15 +339,16 @@ class CategoryController extends AbstractSeoCrudController
public function addRelatedContentAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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
$this->getExistingObject(),
$content_id
);
try {
@@ -318,7 +359,7 @@ class CategoryController extends AbstractSeoCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
/**
@@ -333,21 +374,22 @@ class CategoryController extends AbstractSeoCrudController
return $response;
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
public function deleteRelatedContentAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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
$this->getExistingObject(),
$content_id
);
try {
@@ -358,7 +400,6 @@ class CategoryController extends AbstractSeoCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
}

View File

@@ -12,15 +12,15 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Config\ConfigDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Config\ConfigUpdateEvent;
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;
use Thelia\Form\ConfigModificationForm;
use Thelia\Form\ConfigCreationForm;
/**
* Manages variables
@@ -35,9 +35,7 @@ class ConfigController extends AbstractCrudController
'variable',
'name',
'order',
AdminResources::CONFIG,
TheliaEvents::CONFIG_CREATE,
TheliaEvents::CONFIG_UPDATE,
TheliaEvents::CONFIG_DELETE,
@@ -48,12 +46,12 @@ class ConfigController extends AbstractCrudController
protected function getCreationForm()
{
return new ConfigCreationForm($this->getRequest());
return $this->createForm(AdminForm::CONFIG_CREATION);
}
protected function getUpdateForm()
{
return new ConfigModificationForm($this->getRequest());
return $this->createForm(AdminForm::CONFIG_MODIFICATION);
}
protected function getCreationEvent($data)
@@ -119,7 +117,7 @@ class ConfigController extends AbstractCrudController
);
// Setup the object form
return new ConfigModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::CONFIG_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -139,11 +137,19 @@ class ConfigController extends AbstractCrudController
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();
@@ -161,26 +167,28 @@ class ConfigController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
$this->redirectToRoute(
"admin.configuration.variables.update",
array('variable_id' => $this->getRequest()->get('variable_id'))
return $this->generateRedirectFromRoute(
"admin.configuration.variables.update",
array('variable_id' => $this->getRequest()->get('variable_id'))
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.variables.default');
return $this->generateRedirectFromRoute('admin.configuration.variables.default');
}
/**
* Change values modified directly from the variable list
*
* @return Thelia\Core\HttpFoundation\Response the response
* @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;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$variables = $this->getRequest()->get('variable', array());
@@ -192,6 +200,6 @@ class ConfigController extends AbstractCrudController
$this->dispatch(TheliaEvents::CONFIG_SETVALUE, $event);
}
$this->redirectToRoute('admin.configuration.variables.default');
return $this->generateRedirectFromRoute('admin.configuration.variables.default');
}
}

View File

@@ -12,10 +12,11 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\ConfigStoreForm;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Definition\AdminForm;
use Thelia\Model\ConfigQuery;
/**
* Class ConfigStoreController
* @package Thelia\Controller\Admin
@@ -23,7 +24,6 @@ use Thelia\Model\ConfigQuery;
*/
class ConfigStoreController extends BaseAdminController
{
protected function renderTemplate()
{
return $this->render('config-store');
@@ -31,68 +31,107 @@ class ConfigStoreController extends BaseAdminController
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::VIEW)) {
return $response;
}
// Hydrate the store configuration form
$configStoreForm = new ConfigStoreForm($this->getRequest(), 'form', array(
'store_name' => ConfigQuery::read("store_name"),
'store_description' => ConfigQuery::read("store_description"),
'store_email' => ConfigQuery::read("store_email"),
'store_business_id' => ConfigQuery::read("store_business_id"),
'store_phone' => ConfigQuery::read("store_phone"),
'store_fax' => ConfigQuery::read("store_fax"),
'store_address1' => ConfigQuery::read("store_address1"),
'store_address2' => ConfigQuery::read("store_address2"),
'store_address3' => ConfigQuery::read("store_address3"),
'store_zipcode' => ConfigQuery::read("store_zipcode"),
'store_city' => ConfigQuery::read("store_city"),
'store_country' => ConfigQuery::read("store_country")
));
// 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;
if (null !== $response = $this->checkAuth(AdminResources::STORE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$configStoreForm = new ConfigStoreForm($this->getRequest());
$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(! in_array($name , array('success_url', 'error_message')))
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') {
$this->redirectToRoute('admin.configuration.store.default');
$response = $this->generateRedirectFromRoute('admin.configuration.store.default');
} else {
$response = $this->generateSuccessRedirect($configStoreForm);
}
// Redirect to the success URL
$this->redirect($configStoreForm->getSuccessUrl());
} catch (\Exception $ex) {
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("Store configuration failed."),
$error_msg,
$configStoreForm,
$ex
);
);
return $this->renderTemplate();
$response = $this->renderTemplate();
}
return $response;
}
}

View File

@@ -18,7 +18,7 @@ use Thelia\Core\Security\Resource\AdminResources;
/**
* Class ConfigurationController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ConfigurationController extends BaseAdminController
{

View File

@@ -11,7 +11,7 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Content\ContentAddFolderEvent;
use Thelia\Core\Event\Content\ContentCreateEvent;
use Thelia\Core\Event\Content\ContentDeleteEvent;
@@ -20,28 +20,27 @@ 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\Form\ContentCreationForm;
use Thelia\Form\ContentModificationForm;
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 <mraynaud@openstudio.fr>
* @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,
@@ -59,7 +58,9 @@ class ContentController extends AbstractSeoCrudController
public function addAdditionalFolderAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$folder_id = intval($this->getRequest()->request->get('additional_folder_id'));
@@ -76,7 +77,7 @@ class ContentController extends AbstractSeoCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
/**
@@ -87,7 +88,9 @@ class ContentController extends AbstractSeoCrudController
public function removeAdditionalFolderAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$folder_id = intval($this->getRequest()->request->get('additional_folder_id'));
@@ -104,7 +107,7 @@ class ContentController extends AbstractSeoCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
/**
@@ -112,7 +115,7 @@ class ContentController extends AbstractSeoCrudController
*/
protected function getCreationForm()
{
return new ContentCreationForm($this->getRequest());
return $this->createForm(AdminForm::CONTENT_CREATION);
}
/**
@@ -120,13 +123,14 @@ class ContentController extends AbstractSeoCrudController
*/
protected function getUpdateForm()
{
return new ContentModificationForm($this->getRequest());
return $this->createForm(AdminForm::CONTENT_MODIFICATION);
}
/**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Form\ContentModificationForm $object
* @param Content $object
* @return \Thelia\Form\ContentModificationForm
*/
protected function hydrateObjectForm($object)
{
@@ -145,13 +149,14 @@ class ContentController extends AbstractSeoCrudController
);
// Setup the object form
return new ContentModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::CONTENT_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return \Thelia\Core\Event\Content\ContentCreateEvent
*/
protected function getCreationEvent($formData)
{
@@ -170,7 +175,8 @@ class ContentController extends AbstractSeoCrudController
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return \Thelia\Core\Event\Content\ContentUpdateEvent
*/
protected function getUpdateEvent($formData)
{
@@ -199,7 +205,8 @@ class ContentController extends AbstractSeoCrudController
/**
* 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
* @param \Thelia\Core\Event\Content\ContentEvent $event
* @return bool
*/
protected function eventContainsObject($event)
{
@@ -238,7 +245,7 @@ class ContentController extends AbstractSeoCrudController
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param $object \Thelia\Model\Content
* @param Content $object
*
* @return string content title
*
@@ -251,7 +258,7 @@ class ContentController extends AbstractSeoCrudController
/**
* Returns the object ID from the object
*
* @param $object \Thelia\Model\Content
* @param Content $object
*
* @return int content id
*/
@@ -278,17 +285,20 @@ class ContentController extends AbstractSeoCrudController
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @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',
return $this->render(
'folders',
array(
'content_order' => $currentOrder,
'parent' => $this->getFolderId()
));
)
);
}
protected function getEditionArguments()
@@ -313,7 +323,11 @@ class ContentController extends AbstractSeoCrudController
*/
protected function redirectToEditionTemplate()
{
$this->redirect($this->getRoute('admin.content.update', $this->getEditionArguments()));
return $this->generateRedirectFromRoute(
'admin.content.update',
[],
$this->getEditionArguments()
);
}
/**
@@ -321,9 +335,9 @@ class ContentController extends AbstractSeoCrudController
*/
protected function redirectToListTemplate()
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.content.default',
array('parent' => $this->getFolderId())
['parent' => $this->getFolderId()]
);
}
@@ -334,12 +348,12 @@ class ContentController extends AbstractSeoCrudController
protected function performAdditionalUpdateAction($updateEvent)
{
if ($this->getRequest()->get('save_mode') != 'stay') {
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $this->getFolderId())
['parent' => $this->getFolderId()]
);
} else {
return null;
}
}
@@ -351,10 +365,9 @@ class ContentController extends AbstractSeoCrudController
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $deleteEvent->getDefaultFolderId())
['parent' => $deleteEvent->getDefaultFolderId()]
);
}
@@ -364,16 +377,15 @@ class ContentController extends AbstractSeoCrudController
*/
protected function performAdditionalUpdatePositionAction($event)
{
if (null !== $content = ContentQuery::create()->findPk($event->getObjectId())) {
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $content->getDefaultFolderId())
['parent' => $event->getReferrerId()]
);
} else {
return null;
}
return null;
}
/**
@@ -386,7 +398,8 @@ class ContentController extends AbstractSeoCrudController
return new UpdatePositionEvent(
$this->getRequest()->get('content_id', null),
$positionChangeMode,
$positionValue
$positionValue,
$this->getRequest()->get('folder_id', null)
);
}

View File

@@ -11,38 +11,42 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
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\Form\CountryCreationForm;
use Thelia\Form\CountryModificationForm;
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 <mraynaud@openstudio.fr>
* @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_DELETE,
TheliaEvents::COUNTRY_TOGGLE_VISIBILITY
);
}
@@ -51,7 +55,7 @@ class CountryController extends AbstractCrudController
*/
protected function getCreationForm()
{
return new CountryCreationForm($this->getRequest());
return $this->createForm(AdminForm::COUNTRY_CREATION);
}
/**
@@ -59,32 +63,41 @@ class CountryController extends AbstractCrudController
*/
protected function getUpdateForm()
{
return new CountryModificationForm($this->getRequest());
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 new CountryModificationForm($this->getRequest(), 'form', $data);
return $this->createForm(AdminForm::COUNTRY_MODIFICATION, 'form', $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return CountryCreateEvent
*/
protected function getCreationEvent($formData)
{
@@ -96,24 +109,36 @@ class CountryController extends AbstractCrudController
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return CountryUpdateEvent
*/
protected function getUpdateEvent($formData)
{
$event = new CountryUpdateEvent($formData['id']);
return $this->hydrateEvent($event, $formData);
$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'])
->setArea($formData['area'])
->setHasStates($formData['has_states'])
;
return $event;
@@ -141,6 +166,7 @@ class CountryController extends AbstractCrudController
* Get the created object from an event.
*
* @param unknown $createEvent
* @return Country
*/
protected function getObjectFromEvent($event)
{
@@ -166,6 +192,7 @@ class CountryController extends AbstractCrudController
* Returns the object label form the object event (name, title, etc.)
*
* @param \Thelia\Model\Country $object
* @return string
*/
protected function getObjectLabel($object)
{
@@ -176,6 +203,7 @@ class CountryController extends AbstractCrudController
* Returns the object ID from the object
*
* @param \Thelia\Model\Country $object
* @return int
*/
protected function getObjectId($object)
{
@@ -186,6 +214,7 @@ class CountryController extends AbstractCrudController
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @return Response
*/
protected function renderListTemplate($currentOrder)
{
@@ -212,9 +241,12 @@ class CountryController extends AbstractCrudController
*/
protected function redirectToEditionTemplate()
{
$this->redirectToRoute('admin.configuration.countries.update', array(), array(
return $this->generateRedirectFromRoute(
'admin.configuration.countries.update',
[],
[
"country_id" => $this->getRequest()->get('country_id', 0)
)
]
);
}
@@ -223,12 +255,14 @@ class CountryController extends AbstractCrudController
*/
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.countries.default');
return $this->generateRedirectFromRoute('admin.configuration.countries.default');
}
public function toggleDefaultAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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);
@@ -241,9 +275,70 @@ class CountryController extends AbstractCrudController
} 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

@@ -16,17 +16,18 @@ 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\Security\Resource\AdminResources;
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\Condition\ConditionCollection;
use Thelia\Coupon\Type\CouponInterface;
use Thelia\Form\CouponCreationForm;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\Coupon;
@@ -57,9 +58,9 @@ class CouponController extends BaseAdminController
return $response;
}
$args['coupon_order'] = $this->getListOrderFromSession('coupon', 'coupon_order', 'code');
return $this->render('coupon-list', $args);
return $this->render('coupon-list', [
'coupon_order' => $this->getListOrderFromSession('coupon', 'coupon_order', 'code')
]);
}
/**
@@ -79,16 +80,17 @@ class CouponController extends BaseAdminController
$eventToDispatch = TheliaEvents::COUPON_CREATE;
if ($this->getRequest()->isMethod('POST')) {
if(null !== $response = $this->validateCreateOrUpdateForm(
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());
}
@@ -101,6 +103,9 @@ class CouponController extends BaseAdminController
);
$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
@@ -124,7 +129,6 @@ class CouponController extends BaseAdminController
$coupon = CouponQuery::create()->findPk($couponId);
if (null === $coupon) {
return $this->pageNotFound();
}
$coupon->setLocale($this->getCurrentEditionLocale());
@@ -169,8 +173,12 @@ class CouponController extends BaseAdminController
$freeShippingForModules[] = $item->getModuleId();
}
if (empty($freeShippingForCountries)) $freeShippingForCountries[] = 0;
if (empty($freeShippingForModules)) $freeShippingForModules[] = 0;
if (empty($freeShippingForCountries)) {
$freeShippingForCountries[] = 0;
}
if (empty($freeShippingForModules)) {
$freeShippingForModules[] = 0;
}
$data = [
'code' => $coupon->getCode(),
@@ -180,6 +188,7 @@ class CouponController extends BaseAdminController
'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(),
@@ -195,7 +204,7 @@ class CouponController extends BaseAdminController
$args['conditions'] = $this->cleanConditionForTemplate($conditions);
// Setup the object form
$changeForm = new CouponCreationForm($this->getRequest(), 'form', $data);
$changeForm = $this->createForm(AdminForm::COUPON_CREATION, 'form', $data);
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
@@ -248,6 +257,8 @@ class CouponController extends BaseAdminController
$args['dateFormat'] = $this->getDefaultDateFormat();
$args['couponId'] = $couponId;
return $this->render('coupon-update', $args);
}
@@ -267,7 +278,6 @@ class CouponController extends BaseAdminController
$this->checkXmlHttpRequest();
if (! empty($conditionId)) {
/** @var ConditionFactory $conditionFactory */
$conditionFactory = $this->container->get('thelia.condition.factory');
$inputs = $conditionFactory->getInputsFromServiceId($conditionId);
@@ -347,7 +357,8 @@ class CouponController extends BaseAdminController
}
return $this->render(
'coupon/condition-input-ajax', [
'coupon/condition-input-ajax',
[
'inputsDrawn' => $condition->drawBackOfficeInputs(),
'conditionServiceId' => $condition->getServiceId(),
'conditionIndex' => $conditionIndex,
@@ -478,7 +489,7 @@ class CouponController extends BaseAdminController
protected function validateCreateOrUpdateForm($eventToDispatch, $log, $action, Coupon $model = null)
{
// Create the form from the request
$couponForm = new CouponCreationForm($this->getRequest());
$couponForm = $this->getForm($action, $model);
$response = null;
$message = false;
try {
@@ -494,12 +505,14 @@ class CouponController extends BaseAdminController
);
$this->adminLogAppend(
AdminResources::COUPON, AccessManager::UPDATE,
AdminResources::COUPON,
AccessManager::UPDATE,
sprintf(
'Coupon %s (ID ) ' . $log,
$couponEvent->getTitle(),
$couponEvent->getCouponModel()->getId()
)
),
$couponEvent->getCouponModel()->getId()
);
if ($this->getRequest()->get('save_mode') == 'stay') {
@@ -508,18 +521,15 @@ class CouponController extends BaseAdminController
$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()]);
@@ -637,7 +647,7 @@ class CouponController extends BaseAdminController
$this->pageNotFound();
}
$response = new ResponseRest($couponManager->drawBackOfficeInputs());
$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"
@@ -667,7 +677,6 @@ class CouponController extends BaseAdminController
$coupon = CouponQuery::create()->findPk($couponId);
if (null === $coupon) {
return $this->pageNotFound();
}
/** @var CouponFactory $couponFactory */
@@ -682,7 +691,6 @@ class CouponController extends BaseAdminController
$args['conditions'] = $this->cleanConditionForTemplate($couponManager->getConditions());
return $this->render('coupon/conditions', $args);
}
/**
@@ -718,7 +726,8 @@ class CouponController extends BaseAdminController
$data['locale'],
$data['freeShippingForCountries'],
$data['freeShippingForModules'],
$data['perCustomerUsageCount']
$data['perCustomerUsageCount'],
empty($data['startDate']) ? null : \DateTime::createFromFormat($this->getDefaultDateFormat(), $data['startDate'])
);
// If Update mode
@@ -779,7 +788,8 @@ class CouponController extends BaseAdminController
$coupon->getLocale(),
$coupon->getFreeShippingForCountries(),
$coupon->getFreeShippingForModules(),
$coupon->getPerCustomerUsageCount()
$coupon->getPerCustomerUsageCount(),
$coupon->getStartDate()
);
$couponEvent->setCouponModel($coupon);
$couponEvent->setConditions($conditions);
@@ -792,17 +802,83 @@ class CouponController extends BaseAdminController
);
$this->adminLogAppend(
AdminResources::COUPON, AccessManager::UPDATE,
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)->getDateFormat();
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

@@ -12,16 +12,17 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Currency\CurrencyDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Currency\CurrencyUpdateEvent;
use Thelia\Core\Event\Currency\CurrencyCreateEvent;
use Thelia\Model\CurrencyQuery;
use Thelia\Form\CurrencyModificationForm;
use Thelia\Form\CurrencyCreationForm;
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
@@ -36,9 +37,7 @@ class CurrencyController extends AbstractCrudController
'currency',
'manual',
'order',
AdminResources::CURRENCY,
TheliaEvents::CURRENCY_CREATE,
TheliaEvents::CURRENCY_UPDATE,
TheliaEvents::CURRENCY_DELETE,
@@ -49,12 +48,12 @@ class CurrencyController extends AbstractCrudController
protected function getCreationForm()
{
return new CurrencyCreationForm($this->getRequest());
return $this->createForm(AdminForm::CURRENCY_CREATION);
}
protected function getUpdateForm()
{
return new CurrencyModificationForm($this->getRequest());
return $this->createForm(AdminForm::CURRENCY_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -65,6 +64,7 @@ class CurrencyController extends AbstractCrudController
->setCurrencyName($formData['name'])
->setLocale($formData["locale"])
->setSymbol($formData['symbol'])
->setFormat($formData['format'])
->setCode($formData['code'])
->setRate($formData['rate'])
;
@@ -81,6 +81,7 @@ class CurrencyController extends AbstractCrudController
->setCurrencyName($formData['name'])
->setLocale($formData["locale"])
->setSymbol($formData['symbol'])
->setFormat($formData['format'])
->setCode($formData['code'])
->setRate($formData['rate'])
;
@@ -91,9 +92,9 @@ class CurrencyController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('currency_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('currency_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -116,11 +117,12 @@ class CurrencyController extends AbstractCrudController
'locale' => $object->getLocale(),
'code' => $object->getCode(),
'symbol' => $object->getSymbol(),
'format' => $object->getFormat(),
'rate' => $object->getRate()
);
// Setup the object form
return new CurrencyModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::CURRENCY_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -140,11 +142,19 @@ class CurrencyController extends AbstractCrudController
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();
@@ -162,15 +172,17 @@ class CurrencyController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
$this->redirectToRoute(
"admin.configuration.currencies.update",
array('currency_id' => $this->getRequest()->get('currency_id'))
return $this->generateRedirectFromRoute(
"admin.configuration.currencies.update",
[
'currency_id' => $this->getRequest()->get('currency_id'),
]
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.currencies.default');
return $this->generateRedirectFromRoute('admin.configuration.currencies.default');
}
/**
@@ -179,16 +191,26 @@ class CurrencyController extends AbstractCrudController
public function updateRatesAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
try {
$this->dispatch(TheliaEvents::CURRENCY_UPDATE_RATES);
$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);
}
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
/**
@@ -197,12 +219,14 @@ class CurrencyController extends AbstractCrudController
public function setDefaultAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$changeEvent = new CurrencyUpdateEvent($this->getRequest()->get('currency_id', 0));
$changeEvent = new CurrencyUpdateEvent((int) $this->getRequest()->get('currency_id', 0));
// Create and dispatch the change event
$changeEvent->setIsDefault(true);
$changeEvent->setIsDefault(true)->setVisible(1);
try {
$this->dispatch(TheliaEvents::CURRENCY_SET_DEFAULT, $changeEvent);
@@ -211,7 +235,31 @@ class CurrencyController extends AbstractCrudController
return $this->errorPage($ex);
}
$this->redirectToListTemplate();
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

@@ -12,51 +12,57 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
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\CustomerCreateForm;
use Thelia\Form\CustomerUpdateForm;
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 <mraynaud@openstudio.fr>
* @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
'customer',
'lastname',
'customer_order',
AdminResources::CUSTOMER,
TheliaEvents::CUSTOMER_CREATEACCOUNT,
TheliaEvents::CUSTOMER_UPDATEACCOUNT,
TheliaEvents::CUSTOMER_DELETEACCOUNT
);
}
protected function getCreationForm()
{
return new CustomerCreateForm($this->getRequest());
return $this->createForm(AdminForm::CUSTOMER_CREATE);
}
protected function getUpdateForm()
{
return new CustomerUpdateForm($this->getRequest());
return $this->createForm(AdminForm::CUSTOMER_UPDATE);
}
protected function getCreationEvent($formData)
{
return $this->createEventInstance($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)
@@ -65,6 +71,9 @@ class CustomerController extends AbstractCrudController
$event->setCustomer($this->getExistingObject());
// We allow customer email modification
$event->setEmailUpdateAllowed(true);
return $event;
}
@@ -78,6 +87,10 @@ class CustomerController extends AbstractCrudController
return $event->hasCustomer();
}
/**
* @param Customer $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateObjectForm($object)
{
// Get default adress of the customer
@@ -95,19 +108,20 @@ class CustomerController extends AbstractCrudController
);
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['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 new CustomerUpdateForm($this->getRequest(), 'form', $data);
return $this->createForm(AdminForm::CUSTOMER_UPDATE, 'form', $data);
}
protected function getObjectFromEvent($event)
@@ -122,25 +136,26 @@ class CustomerController extends AbstractCrudController
private function createEventInstance($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"],
isset($data["email"])?$data["email"]:null,
isset($data["password"]) && ! empty($data["password"]) ? $data["password"]:null,
$this->getRequest()->getSession()->getLang()->getId(),
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["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,
$this->getRequest()->getSession()->getLang()->getId(),
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;
@@ -151,11 +166,19 @@ class CustomerController extends AbstractCrudController
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();
@@ -165,13 +188,16 @@ class CustomerController extends AbstractCrudController
{
return array(
'customer_id' => $this->getRequest()->get('customer_id', 0),
'page' => $this->getRequest()->get('page', 1)
'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(
return $this->render(
'customers',
array_merge(array(
'customer_order' => $currentOrder,
'page' => $this->getRequest()->get('page', 1)
), $customParams)
@@ -180,8 +206,11 @@ class CustomerController extends AbstractCrudController
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.customers', array(
'page' => $this->getRequest()->get('page', 1))
return $this->generateRedirectFromRoute(
'admin.customers',
[
'page' => $this->getRequest()->get('page', 1)
]
);
}
@@ -192,20 +221,28 @@ class CustomerController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
$this->redirectToRoute("admin.customer.update.view", $this->getEditionArguments());
return $this->generateRedirectFromRoute(
"admin.customer.update.view",
$this->getEditionArguments()
);
}
public function deleteAction()
{
$errorMsg = "No error.";
$removalError = false;
try {
parent::deleteAction();
} catch (CustomerException $e) {
$error_msg = $e->getMessage();
$errorMsg = $e->getMessage();
$removalError = true;
}
return $this->renderListTemplate($this->getCurrentListOrder(), array(
"removal_error" => true,
"error_message" => $error_msg
));
return $this->renderListTemplate($this->getCurrentListOrder(), [
"removal_error" => $removalError,
"error_message" => $errorMsg
]);
}
}

View File

@@ -12,432 +12,238 @@
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\FileFormat\Archive\ArchiveBuilderManagerTrait;
use Thelia\Core\FileFormat\Formatting\FormatterManagerTrait;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Loop\Export as ExportLoop;
use Thelia\Core\Event\ImportExport as ImportExportEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder;
use Thelia\Core\FileFormat\Formatting\AbstractFormatter;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\ExportForm;
use Thelia\ImportExport\Export\DocumentsExportInterface;
use Thelia\ImportExport\Export\ExportHandler;
use Thelia\ImportExport\Export\ImagesExportInterface;
use Thelia\Model\ExportCategoryQuery;
use Thelia\Model\ExportQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
/**
* Class ExportController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Jérôme Billiras <jbilliras@openstudio.fr>
*/
class ExportController extends BaseAdminController
{
use ArchiveBuilderManagerTrait;
use FormatterManagerTrait;
public function indexAction()
/**
* Handle default action, that is, list available exports
*
* @param string $_view View to render
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function indexAction($_view = 'export')
{
if (null !== $response = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::VIEW])) {
return $response;
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::VIEW]);
if ($authResponse !== null) {
return $authResponse;
}
$this->setOrders();
$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('export');
return $this->render($_view);
}
/**
* @param integer $id
* @return Response
* Handle export position change action
*
* This method is called when the route /admin/export/{id}
* is called with a POST request.
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function export($id)
public function changeExportPositionAction()
{
if (null === $export = $this->getExport($id)) {
return $this->pageNotFound();
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
/**
* Get needed services
*/
$archiveBuilderManager = $this->getArchiveBuilderManager($this->container);
$formatterManager = $this->getFormatterManager($this->container);
$query = $this->getRequest()->query;
/**
* Get the archive builders
*/
$archiveBuilders = [];
foreach ($archiveBuilderManager->getNames() as $archiveBuilder) {
$archiveBuilders[$archiveBuilder] = $archiveBuilder;
}
/**
* Define and validate the form
*/
$form = new ExportForm($this->getRequest());
$errorMessage = null;
try {
$boundForm = $this->validateForm($form);
$lang = LangQuery::create()->findPk(
$boundForm->get("language")->getData()
);
$archiveBuilder = null;
/**
* Get the formatter and the archive builder if we have to compress the file(s)
*/
/** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter $formatter */
$formatter = $formatterManager->get(
$boundForm->get("formatter")->getData()
);
if ($boundForm->get("do_compress")->getData()) {
/** @var \Thelia\Core\FileFormat\Archive\ArchiveBuilderInterface $archiveBuilder */
$archiveBuilder = $archiveBuilderManager->get(
$boundForm->get("archive_builder")->getData()
);
}
/**
* Return the generated Response
*/
return $this->processExport(
$formatter,
$export->getHandleClassInstance($this->container),
$archiveBuilder,
$lang,
$boundForm->get("images")->getData(),
$boundForm->get("documents")->getData()
);
} catch (FormValidationException $e) {
$errorMessage = $this->createStandardFormValidationErrorMessage($e);
} catch (\Exception $e) {
$errorMessage = $e->getMessage();
}
/**
* If has an error, display it
*/
if (null !== $errorMessage) {
$form->setErrorMessage($errorMessage);
$this->getParserContext()
->addForm($form)
->setGeneralError($errorMessage)
;
}
return $this->exportView($id);
}
/**
* @param AbstractFormatter $formatter
* @param ExportHandler $handler
* @param AbstractArchiveBuilder $archiveBuilder
* @param bool $includeImages
* @param bool $includeDocuments
* @return Response
*
* Processes an export by returning a response with the export's content.
*/
protected function processExport(
AbstractFormatter $formatter,
ExportHandler $handler,
AbstractArchiveBuilder $archiveBuilder = null,
Lang $lang,
$includeImages = false,
$includeDocuments = false
) {
/**
* Build an event containing the formatter and the handler.
* Used for specific configuration (e.g: XML node names)
*/
$event = new ImportExportEvent($formatter, $handler);
$filename = $formatter::FILENAME . "." . $formatter->getExtension();
if ($archiveBuilder === null) {
$data = $handler->buildData($lang);
$event->setData($data);
$this->dispatch(TheliaEvents::EXPORT_BEFORE_ENCODE, $event);
$formattedContent = $formatter
->setOrder($handler->getOrder())
->encode($data)
;
$this->dispatch(TheliaEvents::EXPORT_AFTER_ENCODE, $event->setContent($formattedContent));
return new Response(
$event->getContent(),
200,
[
"Content-Type" => $formatter->getMimeType(),
"Content-Disposition" =>
"attachment; filename=\"" . $filename . "\"",
]
);
} else {
$event->setArchiveBuilder($archiveBuilder);
if ($includeImages && $handler instanceof ImagesExportInterface) {
$this->processExportImages($handler, $archiveBuilder);
$handler->setImageExport(true);
}
if ($includeDocuments && $handler instanceof DocumentsExportInterface) {
$this->processExportDocuments($handler, $archiveBuilder);
$handler->setDocumentExport(true);
}
$data = $handler
->buildData($lang)
->setLang($lang)
;
$this->dispatch(TheliaEvents::EXPORT_BEFORE_ENCODE, $event);
$formattedContent = $formatter
->setOrder($handler->getOrder())
->encode($data)
;
$this->dispatch(TheliaEvents::EXPORT_AFTER_ENCODE, $event->setContent($formattedContent));
$archiveBuilder->addFileFromString(
$event->getContent(), $filename
);
return $archiveBuilder->buildArchiveResponse($formatter::FILENAME);
}
}
/**
* @param ImagesExportInterface $handler
* @param AbstractArchiveBuilder $archiveBuilder
*
* Procedure that add images in the export's archive
*/
protected function processExportImages(ImagesExportInterface $handler, AbstractArchiveBuilder $archiveBuilder)
{
foreach ($handler->getImagesPaths() as $name => $documentPath) {
$archiveBuilder->addFile(
$documentPath,
$handler::IMAGES_DIRECTORY,
is_integer($name) ? null : $name
);
}
}
/**
* @param DocumentsExportInterface $handler
* @param AbstractArchiveBuilder $archiveBuilder
*
* Procedure that add documents in the export's archive
*/
protected function processExportDocuments(DocumentsExportInterface $handler, AbstractArchiveBuilder $archiveBuilder)
{
foreach ($handler->getDocumentsPaths() as $name => $documentPath) {
$archiveBuilder->addFile(
$documentPath,
$handler::DOCUMENTS_DIRECTORY,
is_integer($name) ? null : $name
);
}
}
/**
* @param integer $id
* @return Response
*
* This method is called when the route /admin/export/{id}
* is called with a GET request.
*
* It returns a modal view if the request is an AJAX one,
* otherwise it generates a "normal" back-office page
*/
public function exportView($id)
{
if (null === $export = $this->getExport($id)) {
return $this->pageNotFound();
}
/**
* Use the loop to inject the same vars in Smarty
*/
$loop = new ExportLoop($this->container);
$loop->initializeArgs([
"id" => $export->getId()
]);
$query = $loop->buildModelCriteria();
$result= $query->find();
$results = $loop->parseResults(
new LoopResult($result)
$this->dispatch(
TheliaEvents::EXPORT_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
$parserContext = $this->getParserContext();
/** @var \Thelia\Core\Template\Element\LoopResultRow $row */
foreach ($results as $row) {
foreach ($row->getVarVal() as $name=>$value) {
$parserContext->set($name, $value);
}
}
/**
* Inject conditions in smarty,
* It is used to display or not the checkboxes "Include images"
* and "Include documents"
*/
$this->getParserContext()
->set("HAS_IMAGES", $export->hasImages($this->container))
->set("HAS_DOCUMENTS", $export->hasDocuments($this->container))
->set("CURRENT_LANG_ID", $this->getSession()->getLang()->getId())
;
/** Then render the form */
if ($this->getRequest()->isXmlHttpRequest()) {
return $this->render("ajax/export-modal");
} else {
return $this->render("export-page");
}
return $this->generateRedirectFromRoute('export.list');
}
public function changePosition()
/**
* Handle export category position change action
*
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function changeCategoryPositionAction()
{
if (null !== $response = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE])) {
return $response;
$authResponse = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE]);
if ($authResponse !== null) {
return $authResponse;
}
$query = $this->getRequest()->query;
$mode = $query->get("mode");
$id = $query->get("id");
$value = $query->get("value");
$this->dispatch(
TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION,
new UpdatePositionEvent(
$query->get('id'),
$this->matchPositionMode($query->get('mode')),
$query->get('value')
)
);
$this->getExport($id);
$event = new UpdatePositionEvent($id, $this->getMode($mode), $value);
$this->dispatch(TheliaEvents::EXPORT_CHANGE_POSITION, $event);
$this->setOrders(null, "manual");
return $this->render('export');
return $this->generateRedirectFromRoute('export.list');
}
public function changeCategoryPosition()
/**
* 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 (null !== $response = $this->checkAuth([AdminResources::EXPORT], [], [AccessManager::UPDATE])) {
return $response;
if ($mode === 'up') {
return UpdatePositionEvent::POSITION_UP;
}
$query = $this->getRequest()->query;
if ($mode === 'down') {
return UpdatePositionEvent::POSITION_DOWN;
}
$mode = $query->get("mode");
$id = $query->get("id");
$value = $query->get("value");
$this->getCategory($id);
$event = new UpdatePositionEvent($id, $this->getMode($mode), $value);
$this->dispatch(TheliaEvents::EXPORT_CATEGORY_CHANGE_POSITION, $event);
$this->setOrders("manual");
return $this->render('export');
return UpdatePositionEvent::POSITION_ABSOLUTE;
}
public function getMode($action)
/**
* Display export configuration view
*
* @param integer $id An export identifier
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function configureAction($id)
{
if ($action === "up") {
$mode = UpdatePositionEvent::POSITION_UP;
} elseif ($action === "down") {
$mode = UpdatePositionEvent::POSITION_DOWN;
} else {
$mode = UpdatePositionEvent::POSITION_ABSOLUTE;
}
return $mode;
}
protected function setOrders($category = null, $export = null)
{
if ($category === null) {
$category = $this->getRequest()->query->get("category_order", "manual");
}
/** @var \Thelia\Handler\Exporthandler $exportHandler */
$exportHandler = $this->container->get('thelia.export.handler');
$export = $exportHandler->getExport($id);
if ($export === null) {
$export = $this->getRequest()->query->get("export_order", "manual");
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()
->set("category_order", $category)
->addForm($form)
;
$this->getParserContext()
->set("export_order", $export)
;
}
protected function getExport($id)
{
$export = ExportQuery::create()->findPk($id);
if (null === $export) {
throw new \ErrorException(
$this->getTranslator()->trans(
"There is no id \"%id\" in the exports",
[
"%id" => $id
]
)
);
}
return $export;
}
protected function getCategory($id)
{
$category = ExportCategoryQuery::create()->findPk($id);
if (null === $category) {
throw new \ErrorException(
$this->getTranslator()->trans(
"There is no id \"%id\" in the export categories",
[
"%id" => $id
]
)
);
}
return $category;
return $this->configureAction($id);
}
}

View File

@@ -12,15 +12,16 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Feature\FeatureAvDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Feature\FeatureAvUpdateEvent;
use Thelia\Core\Event\Feature\FeatureAvCreateEvent;
use Thelia\Model\FeatureAvQuery;
use Thelia\Form\FeatureAvModificationForm;
use Thelia\Form\FeatureAvCreationForm;
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
@@ -35,9 +36,7 @@ class FeatureAvController extends AbstractCrudController
'featureav',
'manual',
'order',
AdminResources::FEATURE,
TheliaEvents::FEATURE_AV_CREATE,
TheliaEvents::FEATURE_AV_UPDATE,
TheliaEvents::FEATURE_AV_DELETE,
@@ -48,12 +47,12 @@ class FeatureAvController extends AbstractCrudController
protected function getCreationForm()
{
return new FeatureAvCreationForm($this->getRequest());
return $this->createForm(AdminForm::FEATURE_AV_CREATION);
}
protected function getUpdateForm()
{
return new FeatureAvModificationForm($this->getRequest());
throw new \LogicException("Featiure Av. modification is not yet implemented");
}
protected function getCreationEvent($formData)
@@ -88,9 +87,9 @@ class FeatureAvController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('featureav_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('featureav_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -106,17 +105,7 @@ class FeatureAvController extends AbstractCrudController
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 new FeatureAvModificationForm($this->getRequest(), "form", $data);
throw new \LogicException("Feature Av. modification is not yet implemented");
}
protected function getObjectFromEvent($event)
@@ -136,11 +125,19 @@ class FeatureAvController extends AbstractCrudController
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();
@@ -158,8 +155,8 @@ class FeatureAvController extends AbstractCrudController
{
// We always return to the feature edition form
return $this->render(
'feature-edit',
$this->getViewArguments()
'feature-edit',
$this->getViewArguments()
);
}
@@ -172,17 +169,17 @@ class FeatureAvController extends AbstractCrudController
protected function redirectToEditionTemplate()
{
// We always return to the feature edition form
$this->redirectToRoute(
"admin.configuration.features.update",
$this->getViewArguments()
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
$this->getViewArguments()
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.configuration.features.update",
$this->getViewArguments()
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
$this->getViewArguments()
);
}
}
}

View File

@@ -12,19 +12,18 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Feature\FeatureDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Feature\FeatureUpdateEvent;
use Thelia\Core\Event\Feature\FeatureCreateEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Model\FeatureQuery;
use Thelia\Form\FeatureModificationForm;
use Thelia\Form\FeatureCreationForm;
use Thelia\Core\Event\UpdatePositionEvent;
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
@@ -39,9 +38,7 @@ class FeatureController extends AbstractCrudController
'feature',
'manual',
'order',
AdminResources::FEATURE,
TheliaEvents::FEATURE_CREATE,
TheliaEvents::FEATURE_UPDATE,
TheliaEvents::FEATURE_DELETE,
@@ -52,12 +49,12 @@ class FeatureController extends AbstractCrudController
protected function getCreationForm()
{
return new FeatureCreationForm($this->getRequest());
return $this->createForm(AdminForm::FEATURE_CREATION);
}
protected function getUpdateForm()
{
return new FeatureModificationForm($this->getRequest());
return $this->createForm(AdminForm::FEATURE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -99,9 +96,7 @@ class FeatureController extends AbstractCrudController
$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);
@@ -117,9 +112,9 @@ class FeatureController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('feature_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('feature_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -135,7 +130,6 @@ class FeatureController extends AbstractCrudController
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
@@ -146,7 +140,7 @@ class FeatureController extends AbstractCrudController
);
// Setup the object form
return new FeatureModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::FEATURE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -166,11 +160,19 @@ class FeatureController extends AbstractCrudController
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();
@@ -184,28 +186,28 @@ class FeatureController extends AbstractCrudController
protected function renderEditionTemplate()
{
return $this->render(
'feature-edit',
array(
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
)
'feature-edit',
array(
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
)
);
}
protected function redirectToEditionTemplate()
{
$this->redirectToRoute(
"admin.configuration.features.update",
array(
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
)
return $this->generateRedirectFromRoute(
"admin.configuration.features.update",
[
'feature_id' => $this->getRequest()->get('feature_id'),
'featureav_order' => $this->getFeatureAvListOrder()
]
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.features.default');
return $this->generateRedirectFromRoute('admin.configuration.features.default');
}
/**
@@ -216,9 +218,9 @@ class FeatureController extends AbstractCrudController
protected function getFeatureAvListOrder()
{
return $this->getListOrderFromSession(
'featureav',
'featureav_order',
'manual'
'featureav',
'featureav_order',
'manual'
);
}
@@ -228,11 +230,12 @@ class FeatureController extends AbstractCrudController
protected function addRemoveFromAllTemplates($eventType)
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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);
@@ -242,7 +245,7 @@ class FeatureController extends AbstractCrudController
return $this->errorPage($ex);
}
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
/**

View File

@@ -16,11 +16,13 @@ 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\Core\Security\Resource\AdminResources;
use Thelia\Files\Exception\ProcessFileException;
use Thelia\Files\FileConfiguration;
use Thelia\Files\FileManager;
use Thelia\Files\FileModelInterface;
use Thelia\Form\Exception\FormValidationException;
@@ -43,6 +45,8 @@ use Thelia\Tools\URL;
*/
class FileController extends BaseAdminController
{
const MODULE_RIGHT = "thelia";
/**
* Get the FileManager
*
@@ -70,45 +74,109 @@ class FileController extends BaseAdminController
$validMimeTypes = array(),
$extBlackList = array()
) {
if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
if ($this->getRequest()->isMethod('POST')) {
if ($this->getRequest()->isMethod('POST')) {
/** @var UploadedFile $fileBeingUploaded */
$fileBeingUploaded = $this->getRequest()->files->get('file');
$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'
);
return new ResponseRest($message, 'text', 403);
try {
$this->processFile(
$fileBeingUploaded,
$parentId,
$parentType,
$objectType,
$validMimeTypes,
$extBlackList
);
} catch (ProcessFileException $e) {
return new ResponseRest($e->getMessage(), 'text', $e->getCode());
}
$message = null;
$realFileName = $fileBeingUploaded->getClientOriginalName();
return new ResponseRest(array('status' => true, 'message' => ''));
}
if (! empty($validMimeTypes)) {
$mimeType = $fileBeingUploaded->getMimeType();
return new Response('', 404);
}
if (!isset($validMimeTypes[$mimeType])) {
$message = $this->getTranslator()
->trans(
'Only files having the following mime type are allowed: %types%',
[ '%types%' => implode(', ', $validMimeTypes)]
);
}
/**
* 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)) {
@@ -122,73 +190,72 @@ class FileController extends BaseAdminController
);
}
}
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) {
return new ResponseRest($message, 'text', 415);
}
$fileModel = $fileManager->getModelInstance($objectType, $parentType);
$parentModel = $fileModel->getParentFileModel();
if ($parentModel === null || $fileModel === null || $fileBeingUploaded === null) {
return new Response('', 404);
}
$defaultTitle = $parentModel->getTitle();
if (empty($defaultTitle)) {
$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(
AdminResources::retrieve($parentType),
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 new Response('', 404);
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;
}
/**
@@ -201,15 +268,13 @@ class FileController extends BaseAdminController
*/
public function saveImageAjaxAction($parentId, $parentType)
{
$config = FileConfiguration::getImageConfig();
return $this->saveFileAjaxAction(
$parentId,
$parentType,
'image',
[
'image/jpeg' => ["jpg", "jpeg"],
'image/png' => ["png"],
'image/gif' => ["gif"],
]
$config['objectType'],
$config['validMimeTypes'],
$config['extBlackList']
);
}
@@ -223,20 +288,13 @@ class FileController extends BaseAdminController
*/
public function saveDocumentAjaxAction($parentId, $parentType)
{
$config = FileConfiguration::getDocumentConfig();
return $this->saveFileAjaxAction(
$parentId,
$parentType,
'document',
[],
[
"php",
"php3",
"php4",
"php5",
"php6",
"asp",
"aspx",
]
$config['objectType'],
$config['validMimeTypes'],
$config['extBlackList']
);
}
@@ -250,7 +308,7 @@ class FileController extends BaseAdminController
*/
public function getImageListAjaxAction($parentId, $parentType)
{
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('imageType' => $parentType, 'parentId' => $parentId);
@@ -267,7 +325,7 @@ class FileController extends BaseAdminController
*/
public function getDocumentListAjaxAction($parentId, $parentType)
{
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
@@ -284,7 +342,7 @@ class FileController extends BaseAdminController
*/
public function getImageFormAjaxAction($parentId, $parentType)
{
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('imageType' => $parentType, 'parentId' => $parentId);
@@ -301,7 +359,7 @@ class FileController extends BaseAdminController
*/
public function getDocumentFormAjaxAction($parentId, $parentType)
{
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$args = array('documentType' => $parentType, 'parentId' => $parentId);
@@ -318,7 +376,7 @@ class FileController extends BaseAdminController
*/
public function viewImageAction($imageId, $parentType)
{
if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
$fileManager = $this->getFileManager();
@@ -334,10 +392,10 @@ class FileController extends BaseAdminController
'redirectUrl' => $redirectUrl,
'formId' => $imageModel->getUpdateFormId(),
'breadcrumb' => $image->getBreadcrumb(
$this->getRouter($this->getCurrentRouter()),
$this->container,
'images',
$this->getCurrentEditionLocale()
$this->getRouter($this->getCurrentRouter()),
$this->container,
'images',
$this->getCurrentEditionLocale()
)
));
}
@@ -352,7 +410,7 @@ class FileController extends BaseAdminController
*/
public function viewDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
if (null !== $response = $this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE)) {
return $response;
}
@@ -369,10 +427,10 @@ class FileController extends BaseAdminController
'redirectUrl' => $redirectUrl,
'formId' => $documentModel->getUpdateFormId(),
'breadcrumb' => $document->getBreadcrumb(
$this->getRouter($this->getCurrentRouter()),
$this->container,
'documents',
$this->getCurrentEditionLocale()
$this->getRouter($this->getCurrentRouter()),
$this->container,
'documents',
$this->getCurrentEditionLocale()
)
));
}
@@ -387,7 +445,7 @@ class FileController extends BaseAdminController
*
* @return FileModelInterface
*/
public function updateFileAction($fileId, $parentType, $objectType, $eventName)
protected function updateFileAction($fileId, $parentType, $objectType, $eventName)
{
$message = false;
@@ -395,7 +453,7 @@ class FileController extends BaseAdminController
$fileModelInstance = $fileManager->getModelInstance($objectType, $parentType);
$fileUpdateForm = $fileModelInstance->getUpdateFormInstance($this->getRequest());
$fileUpdateForm = $this->createForm($fileModelInstance->getUpdateFormId());
/** @var FileModelInterface $file */
$file = $fileModelInstance->getQueryInstance()->findPk($fileId);
@@ -411,6 +469,10 @@ class FileController extends BaseAdminController
$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)) {
@@ -445,22 +507,31 @@ class FileController extends BaseAdminController
$fileUpdated = $event->getModel();
$this->adminLogAppend(AdminResources::retrieve($parentType), AccessManager::UPDATE,
sprintf('%s with Ref %s (ID %d) modified', ucfirst($objectType), $fileUpdated->getTitle(), $fileUpdated->getId())
$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')
if ($objectType == 'document') {
$tab = 'documents';
else
} else {
$tab = 'images';
}
$this->redirect(URL::getInstance()->absoluteUrl($file->getRedirectionUrl(), ['current_tab' => $tab]));
return $this->generateRedirect(
URL::getInstance()->absoluteUrl($file->getRedirectionUrl(), ['current_tab' => $tab])
);
} else {
$this->redirectSuccess($fileUpdateForm);
return $this->generateSuccessRedirect($fileUpdateForm);
}
} catch (FormValidationException $e) {
$message = sprintf('Please check your input: %s', $e->getMessage());
} catch (PropelException $e) {
@@ -492,18 +563,22 @@ class FileController extends BaseAdminController
*/
public function updateImageAction($imageId, $parentType)
{
if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
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);
return $this->render('image-edit', array(
'imageId' => $imageId,
'imageType' => $parentType,
'redirectUrl' => $imageInstance,
'formId' => $imageInstance->getUpdateFormId()
));
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()
));
}
}
/**
@@ -516,25 +591,29 @@ class FileController extends BaseAdminController
*/
public function updateDocumentAction($documentId, $parentType)
{
if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
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);
return $this->render('document-edit', array(
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 image has to be deleted (AJAX)
* Manage how a file has to be deleted
*
* @param int $fileId Parent id owning image being deleted
* @param string $parentType Parent Type owning image being 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.
*
@@ -544,7 +623,7 @@ class FileController extends BaseAdminController
{
$message = null;
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = $this->getFileManager();
@@ -564,7 +643,7 @@ class FileController extends BaseAdminController
$this->dispatch($eventName, $fileDeleteEvent);
$this->adminLogAppend(
AdminResources::retrieve($parentType),
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
$this->getTranslator()->trans(
'Deleting %obj% for %id% with parent id %parentId%',
@@ -573,7 +652,8 @@ class FileController extends BaseAdminController
'%id%' => $fileDeleteEvent->getFileToDelete()->getId(),
'%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(),
)
)
),
$fileDeleteEvent->getFileToDelete()->getId()
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
@@ -587,9 +667,10 @@ class FileController extends BaseAdminController
);
$this->adminLogAppend(
AdminResources::retrieve($parentType),
$this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT),
AccessManager::UPDATE,
$message
$message,
$fileDeleteEvent->getFileToDelete()->getId()
);
}
@@ -605,7 +686,7 @@ class FileController extends BaseAdminController
}
/**
* Manage how a image has to be deleted (AJAX)
* 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
@@ -636,7 +717,7 @@ class FileController extends BaseAdminController
$position = $this->getRequest()->request->get('position');
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkAuth($this->getAdminResources()->getResource($parentType, static::MODULE_RIGHT), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = $this->getFileManager();
@@ -657,13 +738,12 @@ class FileController extends BaseAdminController
// Dispatch Event to the Action
try {
$this->dispatch($eventName,$event);
$this->dispatch($eventName, $event);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Fail to update %type% position: %err%',
[ '%type%' => $objectType, '%err%' => $e->getMessage() ]
);
'Fail to update %type% position: %err%',
[ '%type%' => $objectType, '%err%' => $e->getMessage() ]
);
}
if (null === $message) {
@@ -689,4 +769,58 @@ class FileController extends BaseAdminController
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

@@ -11,35 +11,35 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Security\Resource\AdminResources;
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\Form\FolderCreationForm;
use Thelia\Form\FolderModificationForm;
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 <mraynaud@openstudio.fr>
* @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,
@@ -54,7 +54,7 @@ class FolderController extends AbstractSeoCrudController
*/
protected function getCreationForm()
{
return new FolderCreationForm($this->getRequest());
return $this->createForm(AdminForm::FOLDER_CREATION);
}
/**
@@ -62,13 +62,14 @@ class FolderController extends AbstractSeoCrudController
*/
protected function getUpdateForm()
{
return new FolderModificationForm($this->getRequest());
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)
{
@@ -88,13 +89,14 @@ class FolderController extends AbstractSeoCrudController
);
// Setup the object form
return new FolderModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::FOLDER_MODIFICATION, "form", $data);
}
/**
* Creates the creation event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return FolderCreateEvent
*/
protected function getCreationEvent($formData)
{
@@ -112,7 +114,8 @@ class FolderController extends AbstractSeoCrudController
/**
* Creates the update event with the provided form data
*
* @param unknown $formData
* @param array $formData
* @return FolderUpdateEvent
*/
protected function getUpdateEvent($formData)
{
@@ -165,6 +168,7 @@ class FolderController extends AbstractSeoCrudController
* 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)
{
@@ -201,7 +205,8 @@ class FolderController extends AbstractSeoCrudController
/**
* Returns the object label form the object event (name, title, etc.)
*
* @param unknown $object
* @param Folder $object
* @return string
*/
protected function getObjectLabel($object)
{
@@ -211,7 +216,8 @@ class FolderController extends AbstractSeoCrudController
/**
* Returns the object ID from the object
*
* @param unknown $object
* @param Folder $object
* @return int
*/
protected function getObjectId($object)
{
@@ -221,19 +227,22 @@ class FolderController extends AbstractSeoCrudController
/**
* Render the main list template
*
* @param unknown $currentOrder, if any, null otherwise.
* @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',
return $this->render(
'folders',
array(
'folder_order' => $currentOrder,
'content_order' => $content_order,
'parent' => $this->getRequest()->get('parent', 0)
));
)
);
}
/**
@@ -263,12 +272,12 @@ class FolderController extends AbstractSeoCrudController
protected function performAdditionalUpdateAction($updateEvent)
{
if ($this->getRequest()->get('save_mode') != 'stay') {
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $updateEvent->getFolder()->getParent())
['parent' => $updateEvent->getFolder()->getParent()]
);
} else {
return null;
}
}
@@ -280,10 +289,9 @@ class FolderController extends AbstractSeoCrudController
*/
protected function performAdditionalDeleteAction($deleteEvent)
{
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $deleteEvent->getFolder()->getParent())
['parent' => $deleteEvent->getFolder()->getParent()]
);
}
@@ -293,26 +301,27 @@ class FolderController extends AbstractSeoCrudController
*/
protected function performAdditionalUpdatePositionAction($event)
{
$folder = FolderQuery::create()->findPk($event->getObjectId());
if ($folder != null) {
// Redirect to parent category list
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $folder->getParent())
['parent' => $folder->getParent()]
);
} else {
return null;
}
return null;
}
/**
* Redirect to the edition template
*
* @param Request|null $request
* @return Response
*/
protected function redirectToEditionTemplate(Request $request = null)
{
$this->redirect($this->getRoute('admin.folders.update', $this->getEditionArguments($request)));
return $this->generateRedirectFromRoute('admin.folders.update', [], $this->getEditionArguments($request));
}
/**
@@ -320,9 +329,9 @@ class FolderController extends AbstractSeoCrudController
*/
protected function redirectToListTemplate()
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
'admin.folders.default',
array('parent' => $this->getRequest()->get('parent', 0))
['parent' => $this->getRequest()->get('parent', 0)]
);
}
}

View File

@@ -12,10 +12,7 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Model\CustomerQuery;
use Thelia\Model\OrderQuery;
class HomeController extends BaseAdminController
{
@@ -23,91 +20,11 @@ class HomeController extends BaseAdminController
public function defaultAction()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) {
return $response;
}
// Render the edition template.
return $this->render('home');
}
/**
* Get the latest available Thelia version from the Thelia web site.
*
* @return Thelia\Core\HttpFoundation\Response the response
*/
public function getLatestTheliaVersion()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) return $response;
// get the latest version
$version = @file_get_contents("http://thelia.net/version.php");
if ($version === false)
$version = $this->getTranslator()->trans("Not found");
else if (! preg_match("/^[0-9.]*$/", $version))
$version = $this->getTranslator()->trans("Unavailable");
return Response::create($version);
}
public function loadStatsAjaxAction()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) return $response;
$data = new \stdClass();
$data->title = $this->getTranslator()->trans("Stats on %month/%year", array('%month' => $this->getRequest()->query->get('month', date('m')), '%year' => $this->getRequest()->query->get('year', date('Y'))));
/* sales */
$saleSeries = new \stdClass();
$saleSeries->color = $this->getRequest()->query->get('sales_color', '#adadad');
$saleSeries->data = OrderQuery::getMonthlySaleStats(
$this->getRequest()->query->get('month', date('m')),
$this->getRequest()->query->get('year', date('Y'))
);
/* new customers */
$newCustomerSeries = new \stdClass();
$newCustomerSeries->color = $this->getRequest()->query->get('customers_color', '#f39922');
$newCustomerSeries->data = CustomerQuery::getMonthlyNewCustomersStats(
$this->getRequest()->query->get('month', date('m')),
$this->getRequest()->query->get('year', date('Y'))
);
/* orders */
$orderSeries = new \stdClass();
$orderSeries->color = $this->getRequest()->query->get('orders_color', '#5cb85c');
$orderSeries->data = OrderQuery::getMonthlyOrdersStats(
$this->getRequest()->query->get('month', date('m')),
$this->getRequest()->query->get('year', date('Y'))
);
/* first order */
$firstOrderSeries = new \stdClass();
$firstOrderSeries->color = $this->getRequest()->query->get('first_orders_color', '#5bc0de');
$firstOrderSeries->data = OrderQuery::getFirstOrdersStats(
$this->getRequest()->query->get('month', date('m')),
$this->getRequest()->query->get('year', date('Y'))
);
/* cancelled orders */
$cancelledOrderSeries = new \stdClass();
$cancelledOrderSeries->color = $this->getRequest()->query->get('cancelled_orders_color', '#d9534f');
$cancelledOrderSeries->data = OrderQuery::getMonthlyOrdersStats(
$this->getRequest()->query->get('month', date('m')),
$this->getRequest()->query->get('year', date('Y')),
array(5)
);
$data->series = array(
$saleSeries,
$newCustomerSeries,
$orderSeries,
$firstOrderSeries,
$cancelledOrderSeries,
);
$json = json_encode($data);
return $this->jsonResponse($json);
}
}

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

@@ -11,509 +11,232 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\ImportExport as ImportExportEvent;
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\FileFormat\Archive\AbstractArchiveBuilder;
use Thelia\Core\FileFormat\Archive\ArchiveBuilderManager;
use Thelia\Core\FileFormat\Archive\ArchiveBuilderManagerTrait;
use Thelia\Core\FileFormat\Formatting\AbstractFormatter;
use Thelia\Core\FileFormat\Formatting\FormatterManager;
use Thelia\Core\FileFormat\Formatting\FormatterManagerTrait;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Loop\Import as ImportLoop;
use Thelia\Exception\FileNotFoundException;
use Thelia\Form\Definition\AdminForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Form\ImportForm;
use Thelia\ImportExport\Import\ImportHandler;
use Thelia\Model\ImportCategoryQuery;
use Thelia\Model\ImportQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
/**
* Class ImportController
* @package Thelia\Controller\Admin
* @author Benjamin Perche <bperche@openstudio.fr>
* @author Jérôme Billiras <jbilliras@openstudio.fr>
*/
class ImportController extends BaseAdminController
{
use FormatterManagerTrait;
use ArchiveBuilderManagerTrait;
public function indexAction()
/**
* Handle default action, that is, list available imports
*
* @param string $_view View to render
*
* @return \Thelia\Core\HttpFoundation\Response
*/
public function indexAction($_view = 'import')
{
if (null !== $response = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::VIEW])) {
return $response;
$authResponse = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::VIEW]);
if ($authResponse !== null) {
return $authResponse;
}
$this->setOrders();
$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('import');
return $this->render($_view);
}
/**
* @param integer $id
* @return Response
* Handle import position change action
*
* This method is called when the route /admin/import/{id}
* is called with a POST request.
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function import($id)
public function changeImportPositionAction()
{
if (null === $import = $this->getImport($id)) {
$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();
}
$archiveBuilderManager = $this->getArchiveBuilderManager($this->container);
$formatterManager = $this->getFormatterManager($this->container);
$handler = $import->getHandleClassInstance($this->container);
$extensions = [];
$mimeTypes = [];
/**
* Get needed services
*/
$form = new ImportForm($this->getRequest());
$errorMessage = null;
$successMessage = null;
try {
$boundForm = $this->validateForm($form);
$lang = LangQuery::create()->findPk(
$boundForm->get("language")->getData()
);
/** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
$file = $boundForm->get("file_upload")->getData();
/**
* We have to check the extension manually because of composed file formats as tar.gz or tar.bz2
*/
$name = $file->getClientOriginalName();
$tools = $this->retrieveFormatTools(
$name,
$handler,
$formatterManager,
$archiveBuilderManager
);
/** @var AbstractArchiveBuilder $archiveBuilder */
$archiveBuilder = $tools["archive_builder"];
/** @var AbstractFormatter $formatter */
$formatter = $tools["formatter"];
if ($archiveBuilder !== null) {
/**
* If the file is an archive, load it and try to find the file.
*/
$archiveBuilder = $archiveBuilder->loadArchive($file->getPathname());
$contentAndFormat = $this->getFileContentInArchive(
$archiveBuilder,
$formatterManager,
$tools["types"]
);
$formatter = $contentAndFormat["formatter"];
$content = $contentAndFormat["content"];
} elseif ($formatter !== null) {
/**
* If the file isn't an archive
*/
$content = file_get_contents($file->getPathname());
} else {
throw new \ErrorException(
$this->getTranslator()->trans(
"There's a problem, the extension \"%ext\" has been found, but has no formatters nor archive builder",
[
"%ext" => $tools["extension"],
]
)
);
}
/**
* Process the import: dispatch events, format the file content and let the handler do it's job.
*/
$successMessage = $this->processImport(
$content,
$handler,
$formatter,
$archiveBuilder,
$lang
);
} catch (FormValidationException $e) {
$errorMessage = $this->createStandardFormValidationErrorMessage($e);
} catch (\Exception $e) {
$errorMessage = $e->getMessage();
/** @var \Thelia\Core\Serializer\AbstractSerializer $serializer */
foreach ($this->container->get(RegisterSerializerPass::MANAGER_SERVICE_ID)->getSerializers() as $serializer) {
$extensions[] = $serializer->getExtension();
$mimeTypes[] = $serializer->getMimeType();
}
if ($successMessage !== null) {
$this->getParserContext()->set("success_message", $successMessage);
/** @var \Thelia\Core\Archiver\AbstractArchiver $archiver */
foreach ($this->container->get(RegisterArchiverPass::MANAGER_SERVICE_ID)->getArchivers(true) as $archiver) {
$extensions[] = $archiver->getExtension();
$mimeTypes[] = $archiver->getMimeType();
}
if ($errorMessage !== null) {
$form->setErrorMessage($errorMessage);
$this->getParserContext()
->addForm($form)
->setGeneralError($errorMessage)
;
// Render standard view or ajax one
$templateName = 'import-page';
if ($this->getRequest()->isXmlHttpRequest()) {
$templateName = 'ajax/import-modal';
}
return $this->importView($id);
}
public function getFileContentInArchive(
AbstractArchiveBuilder $archiveBuilder,
FormatterManager $formatterManager,
array $types
) {
$content = null;
/**
* Check expected file names for each formatter
*/
$fileNames = [];
/** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter $formatter */
foreach ($formatterManager->getFormattersByTypes($types) as $formatter) {
$fileName = $formatter::FILENAME . "." . $formatter->getExtension();
$fileNames[] = $fileName;
if ($archiveBuilder->hasFile($fileName)) {
$content = $archiveBuilder->getFileContent($fileName);
break;
}
}
if ($content === null) {
throw new FileNotFoundException(
$this->getTranslator()->trans(
"Your archive must contain one of these file and doesn't: %files",
[
"%files" => implode(", ", $fileNames),
]
)
);
}
return array(
"formatter" => $formatter,
"content" => $content,
);
}
public function retrieveFormatTools(
$fileName,
ImportHandler $handler,
FormatterManager $formatterManager,
ArchiveBuilderManager $archiveBuilderManager
) {
$nameLength = strlen($fileName);
$types = $handler->getHandledTypes();
$formats =
$formatterManager->getExtensionsByTypes($types, true) +
$archiveBuilderManager->getExtensions(true)
;
$uploadFormat = null;
/** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter $formatter */
$formatter = null;
/** @var \Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder $archiveBuilder */
$archiveBuilder = null;
foreach ($formats as $objectName => $format) {
$formatLength = strlen($format);
$formatExtension = substr($fileName, -$formatLength);
if ($nameLength >= $formatLength && $formatExtension === $format) {
$uploadFormat = $format;
try {
$formatter = $formatterManager->get($objectName);
} catch (\OutOfBoundsException $e) {}
try {
$archiveBuilder = $archiveBuilderManager->get($objectName);
} catch (\OutOfBoundsException $e) {}
break;
}
}
$this->checkFileExtension($fileName, $uploadFormat);
return array(
"formatter" => $formatter,
"archive_builder" => $archiveBuilder,
"extension" => $uploadFormat,
"types" => $types,
);
}
public function checkFileExtension($fileName, $uploadFormat)
{
if ($uploadFormat === null) {
$splitName = explode(".", $fileName);
$ext = "";
if (1 < $limit = count($splitName)) {
$ext = "." . $splitName[$limit-1];
}
throw new FormValidationException(
$this->getTranslator()->trans(
"The extension \"%ext\" is not allowed",
[
"%ext" => $ext
]
)
);
}
}
public function processImport(
$content,
ImportHandler $handler,
AbstractFormatter $formatter = null,
AbstractArchiveBuilder $archiveBuilder = null,
Lang $lang = null
) {
$event = new ImportExportEvent($formatter, $handler, null, $archiveBuilder);
$event->setContent($content);
$this->dispatch(TheliaEvents::IMPORT_AFTER_DECODE, $event);
$data = $formatter
->decode($event->getContent())
->setLang($lang)
;
$event->setContent(null)->setData($data);
$this->dispatch(TheliaEvents::IMPORT_AFTER_DECODE, $event);
$errors = $handler->retrieveFromFormatterData($data);
if (!empty($errors)) {
throw new \Exception(
$this->getTranslator()->trans(
"Errors occurred while importing the file: %errors",
[
"%errors" => implode(", ", $errors),
]
)
);
}
return $this->getTranslator()->trans(
"Import successfully done, %numb row(s) have been changed",
return $this->render(
$templateName,
[
"%numb" => $handler->getImportedRows(),
'importId' => $id,
'ALLOWED_MIME_TYPES' => implode(', ', $mimeTypes),
'ALLOWED_EXTENSIONS' => implode(', ', $extensions),
]
);
}
/**
* @param integer $id
* @return Response
* Handle import action
*
* This method is called when the route /admin/import/{id}
* is called with a GET request.
* @param integer $id An import identifier
*
* It returns a modal view if the request is an AJAX one,
* otherwise it generates a "normal" back-office page
* @return \Thelia\Core\HttpFoundation\Response|\Symfony\Component\HttpFoundation\Response
*/
public function importView($id)
public function importAction($id)
{
if (null === $import = $this->getImport($id)) {
/** @var \Thelia\Handler\Importhandler $importHandler */
$importHandler = $this->container->get('thelia.import.handler');
$import = $importHandler->getImport($id);
if ($import === null) {
return $this->pageNotFound();
}
/**
* Use the loop to inject the same vars in Smarty
*/
$loop = new ImportLoop($this->container);
$form = $this->createForm(AdminForm::IMPORT);
$loop->initializeArgs([
"id" => $id
]);
try {
$validatedForm = $this->validateForm($form);
$query = $loop->buildModelCriteria();
$result= $query->find();
/** @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()
);
$results = $loop->parseResults(
new LoopResult($result)
);
$lang = (new LangQuery)->findPk($validatedForm->get('language')->getData());
$parserContext = $this->getParserContext();
$importEvent = $importHandler->import($import, $file, $lang);
/** @var \Thelia\Core\Template\Element\LoopResultRow $row */
foreach ($results as $row) {
foreach ($row->getVarVal() as $name=>$value) {
$parserContext->set($name, $value);
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())
]
)
);
}
}
/**
* Get allowed formats
*/
/** @var \Thelia\ImportExport\AbstractHandler $handler */
$handler = $import->getHandleClassInstance($this->container);
$types = $handler->getHandledTypes();
$formatterManager = $this->getFormatterManager($this->container);
$archiveBuilderManager = $this->getArchiveBuilderManager($this->container);
$formats =
$formatterManager->getExtensionsByTypes($types, true) +
$archiveBuilderManager->getExtensions(true)
;
/**
* Get allowed mime types (used for the "Search a file" window
*/
$mimeTypes =
$formatterManager->getMimeTypesByTypes($types) +
$archiveBuilderManager->getMimeTypes()
;
/**
* Inject them in smarty
*/
$parserContext
->set("ALLOWED_MIME_TYPES", implode(",", $mimeTypes))
->set("ALLOWED_EXTENSIONS", implode(", ", $formats))
->set("CURRENT_LANG_ID", $this->getSession()->getLang()->getId())
;
/** Then render the form */
if ($this->getRequest()->isXmlHttpRequest()) {
return $this->render("ajax/import-modal");
} else {
return $this->render("import-page");
}
}
protected function setOrders($category = null, $import = null)
{
if ($category === null) {
$category = $this->getRequest()->query->get("category_order", "manual");
}
if ($import === null) {
$import = $this->getRequest()->query->get("import_order", "manual");
}
$this->getParserContext()
->set("category_order", $category)
;
$this->getParserContext()
->set("import_order", $import)
;
}
public function changePosition()
{
if (null !== $response = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE])) {
return $response;
}
$query = $this->getRequest()->query;
$mode = $query->get("mode");
$id = $query->get("id");
$value = $query->get("value");
$this->getImport($id);
$event = new UpdatePositionEvent($id, $this->getMode($mode), $value);
$this->dispatch(TheliaEvents::IMPORT_CHANGE_POSITION, $event);
return $this->render('import');
}
public function changeCategoryPosition()
{
if (null !== $response = $this->checkAuth([AdminResources::IMPORT], [], [AccessManager::UPDATE])) {
return $response;
}
$query = $this->getRequest()->query;
$mode = $query->get("mode");
$id = $query->get("id");
$value = $query->get("value");
$this->getCategory($id);
$event = new UpdatePositionEvent($id, $this->getMode($mode), $value);
$this->dispatch(TheliaEvents::IMPORT_CATEGORY_CHANGE_POSITION, $event);
$this->setOrders("manual");
return $this->render('import');
}
public function getMode($action)
{
if ($action === "up") {
$mode = UpdatePositionEvent::POSITION_UP;
} elseif ($action === "down") {
$mode = UpdatePositionEvent::POSITION_DOWN;
} else {
$mode = UpdatePositionEvent::POSITION_ABSOLUTE;
}
return $mode;
}
protected function getImport($id)
{
$import = ImportQuery::create()->findPk($id);
if (null === $import) {
throw new \ErrorException(
$this->getSession()->getFlashBag()->add(
'thelia.import.success',
$this->getTranslator()->trans(
"There is no id \"%id\" in the imports",
'Import successfully done, %count row(s) have been changed',
[
"%id" => $id
'%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());
}
return $import;
}
$this->getParserContext()
->addForm($form)
;
protected function getCategory($id)
{
$category = ImportCategoryQuery::create()->findPk($id);
if (null === $category) {
throw new \ErrorException(
$this->getTranslator()->trans(
"There is no id \"%id\" in the import categories",
[
"%id" => $id
]
)
);
}
return $category;
return $this->configureAction($id);
}
}

View File

@@ -13,66 +13,74 @@
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\LangCreateForm;
use Thelia\Form\Lang\LangDefaultBehaviorForm;
use Thelia\Form\Lang\LangUpdateForm;
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 <mraynaud@openstudio.fr>
* @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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->renderDefault();
}
public function renderDefault(array $param = array())
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 = new LangUrlForm($this->getRequest(), 'form', $data);
$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::read("one_domain_foreach_lang", false)
)));
'one_domain_per_lang' => ConfigQuery::isMultiDomainActivated()
)), $status);
}
public function updateAction($lang_id)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$this->checkXmlHttpRequest();
$lang = LangQuery::create()->findPk($lang_id);
$langForm = new LangUpdateForm($this->getRequest(), 'form', array(
$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(),
@@ -89,11 +97,13 @@ class LangController extends BaseAdminController
public function processUpdateAction($lang_id)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$langForm = new LangUpdateForm($this->getRequest());
$langForm = $this->createForm(AdminForm::LANG_UPDATE);
try {
$form = $this->validateForm($langForm);
@@ -105,26 +115,49 @@ class LangController extends BaseAdminController
if (false === $event->hasLang()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang')));
$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()));
$this->redirectToRoute('admin.configuration.languages');
$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());
}
return $this->renderDefault(array('error_message' => $error_msg));
if (false !== $error_msg) {
$response = $this->renderDefault(array('error_message' => $error_msg));
}
return $response;
}
protected function hydrateEvent($event,Form $form)
/**
* @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())
@@ -135,42 +168,38 @@ class LangController extends BaseAdminController
public function toggleDefaultAction($lang_id)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) return $response;
return $this->toggleLangDispatch(
TheliaEvents::LANG_TOGGLEDEFAULT,
new LangToggleDefaultEvent($lang_id)
);
}
$this->checkXmlHttpRequest();
$error = false;
try {
$event = new LangToggleDefaultEvent($lang_id);
public function toggleActiveAction($lang_id)
{
return $this->toggleLangDispatch(
TheliaEvents::LANG_TOGGLEACTIVE,
new LangToggleActiveEvent($lang_id)
);
}
$this->dispatch(TheliaEvents::LANG_TOGGLEDEFAULT, $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()));
} catch (\Exception $e) {
Tlog::getInstance()->error(sprintf("Error on changing default languages with message : %s", $e->getMessage()));
$error = $e->getMessage();
}
if ($error) {
return $this->nullResponse(500);
} else {
return $this->nullResponse();
}
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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::CREATE)) {
return $response;
}
$createForm = new LangCreateForm($this->getRequest());
$createForm = $this->createForm(AdminForm::LANG_CREATE);
$error_msg = false;
$ex = null;
try {
$form = $this->validateForm($createForm);
@@ -182,14 +211,25 @@ class LangController extends BaseAdminController
if (false === $createEvent->hasLang()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', 'Lang')));
$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()));
$this->redirectToRoute('admin.configuration.languages');
$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);
@@ -198,45 +238,63 @@ class LangController extends BaseAdminController
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), $error_msg, $createForm, $ex);
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.
return $this->renderDefault();
// 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;
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);
$this->redirectToRoute('admin.configuration.languages');
$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();
}
return $this->renderDefault(array(
'error_message' => $error_msg
));
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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$ex = null;
$behaviorForm = new LangDefaultBehaviorForm($this->getRequest());
$behaviorForm = $this->createForm(AdminForm::LANG_DEFAULT_BEHAVIOR);
try {
$form = $this->validateForm($behaviorForm);
@@ -245,8 +303,7 @@ class LangController extends BaseAdminController
$this->dispatch(TheliaEvents::LANG_DEFAULTBEHAVIOR, $event);
$this->redirectToRoute('admin.configuration.languages');
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -255,19 +312,30 @@ class LangController extends BaseAdminController
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), $error_msg, $behaviorForm, $ex);
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.
return $this->renderDefault();
// 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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$langUrlForm = new LangUrlForm($this->getRequest());
$ex = null;
$langUrlForm = $this->createForm(AdminForm::LANG_URL);
try {
$form = $this->validateForm($langUrlForm);
@@ -276,13 +344,13 @@ class LangController extends BaseAdminController
$event = new LangUrlEvent();
foreach ($data as $key => $value) {
if (false !== strpos($key, LangUrlForm::LANG_PREFIX)) {
$event->addUrl(substr($key,strlen(LangUrlForm::LANG_PREFIX)), $value);
$event->addUrl(substr($key, strlen(LangUrlForm::LANG_PREFIX)), $value);
}
}
$this->dispatch(TheliaEvents::LANG_URL, $event);
$this->redirectToRoute('admin.configuration.languages');
$response = $this->generateRedirectFromRoute('admin.configuration.languages');
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -291,31 +359,98 @@ class LangController extends BaseAdminController
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj creation", array('%obj' => 'Lang')), $error_msg, $langUrlForm, $ex);
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.
return $this->renderDefault();
// At this point, the form has error, and should be redisplayed.
$response = $this->renderDefault();
}
return $response;
}
public function activateDomainAction()
{
$this->domainActivation(1);
return $this->domainActivation(1);
}
public function deactivateDomainAction()
{
$this->domainActivation(0);
return $this->domainActivation(0);
}
private function domainActivation($activate)
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
ConfigQuery::create()
->filterByName('one_domain_foreach_lang')
->update(array('Value' => $activate));
$this->redirectToRoute('admin.configuration.languages');
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

@@ -12,20 +12,21 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
/**
* Class LanguageController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::VIEW)) {
return $response;
}
return $this->render("languages");
}
}

View File

@@ -14,18 +14,21 @@ 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\Form\MailingSystemModificationForm;
use Thelia\Model\ConfigQuery;
class MailingSystemController extends BaseAdminController
{
const RESOURCE_CODE = "admin.mailing-system";
const RESOURCE_CODE = "admin.configuration.mailing-system";
public function defaultAction()
{
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) {
return $response;
}
// Hydrate the form abd pass it to the parser
$data = array(
@@ -41,7 +44,7 @@ class MailingSystemController extends BaseAdminController
);
// Setup the object form
$form = new MailingSystemModificationForm($this->getRequest(), "form", $data);
$form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION, "form", $data);
// Pass it to the parser
$this->getParserContext()->addForm($form);
@@ -53,15 +56,16 @@ class MailingSystemController extends BaseAdminController
public function updateAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
// Create the form from the request
$form = new MailingSystemModificationForm($this->getRequest());
$form = $this->createForm(AdminForm::MAILING_SYSTEM_MODIFICATION);
try {
// Check the form against constraints violations
$formData = $this->validateForm($form, "POST");
@@ -80,7 +84,7 @@ class MailingSystemController extends BaseAdminController
$this->dispatch(TheliaEvents::MAILING_SYSTEM_UPDATE, $event);
// Redirect to the success URL
$this->redirectToRoute("admin.configuration.mailing-system.view");
$response = $this->generateRedirectFromRoute("admin.configuration.mailing-system.view");
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -89,14 +93,64 @@ class MailingSystemController extends BaseAdminController
$error_msg = $ex->getMessage();
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("mailing system modification", array()),
$error_msg,
$form,
$ex
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" => "",
);
// At this point, the form has errors, and should be redisplayed.
return $this->render('mailing-system');
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

@@ -12,15 +12,21 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Message\MessageDeleteEvent;
use Thelia\Core\Event\TheliaEvents;use Thelia\Core\Event\Message\MessageUpdateEvent;
use Thelia\Core\Event\Message\MessageCreateEvent;
use Thelia\Model\MessageQuery;
use Thelia\Form\MessageModificationForm;
use Thelia\Form\MessageCreationForm;
use Symfony\Component\Finder\Finder;
use Thelia\Core\Template\TemplateHelper;
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
@@ -35,9 +41,7 @@ class MessageController extends AbstractCrudController
'message',
null, // no sort order change
null, // no sort order change
AdminResources::MESSAGE,
TheliaEvents::MESSAGE_CREATE,
TheliaEvents::MESSAGE_UPDATE,
TheliaEvents::MESSAGE_DELETE,
@@ -45,35 +49,35 @@ class MessageController extends AbstractCrudController
null // No position update
);
}
protected function getCreationForm()
{
return new MessageCreationForm($this->getRequest());
return $this->createForm(AdminForm::MESSAGE_CREATION);
}
protected function getUpdateForm()
{
return new MessageModificationForm($this->getRequest());
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'])
;
->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'])
@@ -88,109 +92,229 @@ class MessageController extends AbstractCrudController
->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(),
'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 new MessageModificationForm($this->getRequest(), "form", $data);
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));
->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();
$dir = TemplateHelper::getInstance()->getActiveMailTemplate()->getAbsolutePath();
$dir = $this->getTemplateHelper()->getActiveMailTemplate()->getAbsolutePath();
$finder = Finder::create()->files()->in($dir)->ignoreDotFiles(true)->sortByName()->name("*.$requiredExtension");
foreach ($finder as $file) {
$list[] = $file->getBasename();
}
// 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'),
'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()
{
$this->redirectToRoute("admin.configuration.messages.update", array(
return $this->generateRedirectFromRoute(
"admin.configuration.messages.update",
[
'message_id' => $this->getRequest()->get('message_id')
));
]
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.messages.default');
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

@@ -12,35 +12,44 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\Module\ModuleEvent;
use Thelia\Core\Security\Resource\AdminResources;
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\Form\ModuleModificationForm;
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;
use Thelia\Core\Event\UpdatePositionEvent;
/**
* Class ModuleController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @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,
@@ -56,7 +65,7 @@ class ModuleController extends AbstractCrudController
protected function getUpdateForm()
{
return new ModuleModificationForm($this->getRequest());
return $this->createForm(AdminForm::MODULE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -86,9 +95,9 @@ class ModuleController extends AbstractCrudController
protected function createUpdatePositionEvent($positionChangeMode, $positionValue)
{
return new UpdatePositionEvent(
$this->getRequest()->get('module_id', null),
$positionChangeMode,
$positionValue
$this->getRequest()->get('module_id', null),
$positionChangeMode,
$positionValue
);
}
@@ -110,7 +119,7 @@ class ModuleController extends AbstractCrudController
);
// Setup the object form
return new ModuleModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::MODULE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -130,11 +139,19 @@ class ModuleController extends AbstractCrudController
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();
@@ -147,8 +164,11 @@ class ModuleController extends AbstractCrudController
protected function getRouteArguments($module_id = null)
{
$request = $this->getRequest();
return array(
'module_id' => $module_id === null ? $this->getRequest()->get('module_id') : $module_id,
'module_id' => $module_id === null ? $request->get('module_id') : $module_id,
'current_tab' => $request->get('current_tab', 'general'),
);
}
@@ -157,7 +177,10 @@ class ModuleController extends AbstractCrudController
// We always return to the feature edition form
return $this->render(
'modules',
array('module_order' => $currentOrder)
array(
'module_order' => $currentOrder,
'module_errors' => $this->moduleErrors
)
);
}
@@ -169,8 +192,7 @@ class ModuleController extends AbstractCrudController
protected function redirectToEditionTemplate($request = null, $country = null)
{
// We always return to the module edition form
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.module.update",
$this->getViewArguments(),
$this->getRouteArguments()
@@ -179,17 +201,23 @@ class ModuleController extends AbstractCrudController
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.module"
);
return $this->generateRedirectFromRoute("admin.module");
}
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::VIEW)) {
return $response;
}
$moduleManagement = new ModuleManagement();
$moduleManagement->updateModules();
try {
$moduleManagement = new ModuleManagement();
$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();
}
@@ -202,7 +230,9 @@ class ModuleController extends AbstractCrudController
throw new \InvalidArgumentException(sprintf("Module `%s` does not exists", $module_code));
}
if (null !== $response = $this->checkAuth(array(), $module_code, AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(array(), $module_code, AccessManager::VIEW)) {
return $response;
}
return $this->render(
"module-configure",
array(
@@ -213,7 +243,9 @@ class ModuleController extends AbstractCrudController
public function toggleActivationAction($module_id)
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
try {
$event = new ModuleToggleActivationEvent($module_id);
@@ -221,7 +253,8 @@ class ModuleController extends AbstractCrudController
if (null === $event->getModule()) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module')));
$this->getTranslator()->trans("No %obj was updated.", array('%obj' => 'Module'))
);
}
} catch (\Exception $e) {
$message = $e->getMessage();
@@ -237,9 +270,8 @@ class ModuleController extends AbstractCrudController
} else {
$response = $this->nullResponse();
}
} else {
$this->redirectToRoute('admin.module');
$response = $this->generateRedirectFromRoute('admin.module');
}
return $response;
@@ -247,36 +279,202 @@ class ModuleController extends AbstractCrudController
public function deleteAction()
{
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::DELETE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::MODULE, array(), AccessManager::DELETE)) {
return $response;
}
$message = false;
$message = null;
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('delete-module-data', '0'));
$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')));
$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 ($message) {
return $this->render("modules", array(
if (false !== $message) {
$response = $this->render("modules", array(
"error_message" => $message
));
} else {
$this->redirectToRoute('admin.module');
$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

@@ -12,28 +12,29 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
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;
use Thelia\Tools\URL;
/**
* Class OrderController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @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;
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")
@@ -49,18 +50,20 @@ class OrderController extends BaseAdminController
public function updateStatus($order_id = null)
{
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) return $response;
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_id = $this->getRequest()->get("order_id");
}
$order = OrderQuery::create()->findPk($order_id);
$statusId = $this->getRequest()->request->get("status_id");
$statusId = $this->getRequest()->get("status_id");
$status = OrderStatusQuery::create()->findPk($statusId);
if (null === $order) {
@@ -85,20 +88,30 @@ class OrderController extends BaseAdminController
}
$browsedPage = $this->getRequest()->get("order_page");
$currentStatus = $this->getRequest()->get("status");
if ($browsedPage) {
$params["order_page"] = $browsedPage;
$this->redirectToRoute("admin.order.list", $params);
if (null !== $currentStatus) {
$params["status"] = $currentStatus;
}
$response = $this->generateRedirectFromRoute("admin.order.list", $params);
} else {
$params["order_id"] = $order_id;
$params["tab"] = $this->getRequest()->get("tab", 'cart');
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params)));
$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;
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
@@ -125,15 +138,20 @@ class OrderController extends BaseAdminController
$params["update_status_error_message"] = $message;
}
$params["order_id"] = $order_id;
$params["tab"] = $this->getRequest()->get("tab", 'bill');
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params)));
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;
if (null !== $response = $this->checkAuth(AdminResources::ORDER, array(), AccessManager::UPDATE)) {
return $response;
}
$message = null;
@@ -165,7 +183,9 @@ class OrderController extends BaseAdminController
$form->get("city")->getData(),
$form->get("country")->getData(),
$form->get("phone")->getData(),
$form->get("company")->getData()
$form->get("company")->getData(),
$form->get("cellphone")->getData(),
$form->get("state")->getData()
);
$event->setOrderAddress($orderAddress);
$event->setOrder($order);
@@ -181,33 +201,41 @@ class OrderController extends BaseAdminController
$params["update_status_error_message"] = $message;
}
$params["order_id"] = $order_id;
$params["tab"] = $this->getRequest()->get("tab", 'bill');
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params)));
return $this->generateRedirectFromRoute(
"admin.order.update.view",
$params,
[ 'order_id' => $order_id ]
);
}
public function generateInvoicePdf($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'));
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)
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'));
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)
private function generateBackOfficeOrderPdf($order_id, $fileName, $browser)
{
if (null === $response = $this->generateOrderPdf($order_id, $fileName)) {
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", array(
'order_id' => $order_id
))));
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

@@ -12,15 +12,16 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
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\ProfileCreationForm;
use Thelia\Form\ProfileModificationForm;
use Thelia\Form\ProfileUpdateModuleAccessForm;
use Thelia\Form\ProfileUpdateResourceAccessForm;
use Thelia\Model\Profile;
use Thelia\Model\ProfileQuery;
class ProfileController extends AbstractCrudController
@@ -31,9 +32,7 @@ class ProfileController extends AbstractCrudController
'profile',
'manual',
'order',
AdminResources::PROFILE,
TheliaEvents::PROFILE_CREATE,
TheliaEvents::PROFILE_UPDATE,
TheliaEvents::PROFILE_DELETE
@@ -42,12 +41,12 @@ class ProfileController extends AbstractCrudController
protected function getCreationForm()
{
return new ProfileCreationForm($this->getRequest());
return $this->createForm(AdminForm::PROFILE_CREATION);
}
protected function getUpdateForm()
{
return new ProfileModificationForm($this->getRequest());
return $this->createForm(AdminForm::PROFILE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -105,9 +104,13 @@ class ProfileController extends AbstractCrudController
);
// Setup the object form
return new ProfileModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::PROFILE_MODIFICATION, "form", $data);
}
/**
* @param Profile $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateResourceUpdateForm($object)
{
$data = array(
@@ -115,9 +118,13 @@ class ProfileController extends AbstractCrudController
);
// Setup the object form
return new ProfileUpdateResourceAccessForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS, "form", $data);
}
/**
* @param Profile $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateModuleUpdateForm($object)
{
$data = array(
@@ -125,7 +132,7 @@ class ProfileController extends AbstractCrudController
);
// Setup the object form
return new ProfileUpdateModuleAccessForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -145,11 +152,19 @@ class ProfileController extends AbstractCrudController
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();
@@ -185,7 +200,7 @@ class ProfileController extends AbstractCrudController
protected function redirectToEditionTemplate($request = null, $country = null)
{
// We always return to the feature edition form
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.profiles.update",
$this->getViewArguments($country),
$this->getRouteArguments()
@@ -200,7 +215,7 @@ class ProfileController extends AbstractCrudController
*/
protected function performAdditionalCreateAction($createEvent)
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.profiles.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getProfile()->getId())
@@ -209,19 +224,18 @@ class ProfileController extends AbstractCrudController
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.configuration.profiles.list"
);
return $this->generateRedirectFromRoute("admin.configuration.profiles.list");
}
public function updateAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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);
@@ -264,7 +278,7 @@ class ProfileController extends AbstractCrudController
$explosion = explode(':', $data);
$prefix = array_shift ( $explosion );
$prefix = array_shift($explosion);
if ($prefix != ProfileUpdateResourceAccessForm::RESOURCE_ACCESS_FIELD_PREFIX) {
continue;
@@ -286,7 +300,7 @@ class ProfileController extends AbstractCrudController
$explosion = explode(':', $data);
$prefix = array_shift ( $explosion );
$prefix = array_shift($explosion);
if ($prefix != ProfileUpdateModuleAccessForm::MODULE_ACCESS_FIELD_PREFIX) {
continue;
@@ -301,12 +315,14 @@ class ProfileController extends AbstractCrudController
public function processUpdateResourceAccess()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
// Create the form from the request
$changeForm = new ProfileUpdateResourceAccessForm($this->getRequest());
$changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_RESOURCE_ACCESS);
try {
// Check the form against constraints violations
@@ -319,17 +335,29 @@ class ProfileController extends AbstractCrudController
$this->dispatch(TheliaEvents::PROFILE_RESOURCE_ACCESS_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent))
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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) {
$this->redirectToEditionTemplate($this->getRequest(), isset($data['country_list'][0]) ? $data['country_list'][0] : null);
return $this->redirectToEditionTemplate($this->getRequest(), isset($data['country_list'][0]) ? $data['country_list'][0] : null);
} else {
return $response;
}
@@ -350,12 +378,14 @@ class ProfileController extends AbstractCrudController
public function processUpdateModuleAccess()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
// Create the form from the request
$changeForm = new ProfileUpdateModuleAccessForm($this->getRequest());
$changeForm = $this->createForm(AdminForm::PROFILE_UPDATE_MODULE_ACCESS);
try {
// Check the form against constraints violations
@@ -368,17 +398,29 @@ class ProfileController extends AbstractCrudController
$this->dispatch(TheliaEvents::PROFILE_MODULE_ACCESS_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent))
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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) {
$this->redirectToEditionTemplate($this->getRequest(), isset($data['country_list'][0]) ? $data['country_list'][0] : null);
return $this->redirectToEditionTemplate($this->getRequest(), isset($data['country_list'][0]) ? $data['country_list'][0] : null);
} else {
return $response;
}

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

@@ -12,67 +12,201 @@
namespace Thelia\Controller\Admin;
use Thelia\Form\AdminLogin;
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\Core\Security\Exception\AuthenticationException;
use Thelia\Model\AdminQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Authentication\AdminTokenAuthenticator;
use Thelia\Core\Security\Exception\TokenAuthenticationException;
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()
{
// Check if we can authenticate the user with a cookie-based token
if (null !== $key = $this->getRememberMeKeyFromCookie()) {
// Create the authenticator
$authenticator = new AdminTokenAuthenticator($key);
try {
// If have found a user, store it in the security context
$user = $authenticator->getAuthentifiedUser();
$this->getSecurityContext()->setAdminUser($user);
$this->adminLogAppend("admin", "LOGIN", "Successful token authentication");
// Update the cookie
$this->createAdminRememberMeCookie($user);
$this->applyUserLocale($user);
// Render the home page
return $this->render("home");
} catch (TokenAuthenticationException $ex) {
$this->adminLogAppend("admin", "LOGIN", "Token based authentication failed.");
// Clear the cookie
$this->clearRememberMeCookie();
}
if (null !== $response = $this->checkAdminLoggedIn()) {
return $response;
}
return $this->render("login");
}
protected function applyUserLocale(Admin $user)
public function showLostPasswordAction()
{
// Set the current language according to Admin locale preference
$locale = $user->getLocale();
if (null === $lang = LangQuery::create()->findOneByLocale($locale)) {
$lang = Lang::getDefaultLanguage();
if ((null !== $response = $this->checkPasswordRecoveryEnabled()) || (null !== $response = $this->checkAdminLoggedIn())) {
return $response;
}
$this->getSession()->setLang($lang);
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()
@@ -82,10 +216,10 @@ class SessionController extends BaseAdminController
$this->getSecurityContext()->clearAdminUser();
// Clear the remember me cookie, if any
$this->clearRememberMeCookie();
$this->clearRememberMeCookie($this->getRememberMeCookieName());
// Go back to login page.
$this->redirectToRoute('admin.login');
return $this->generateRedirectFromRoute('admin.login');
}
public function checkLoginAction()
@@ -95,11 +229,11 @@ class SessionController extends BaseAdminController
$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
@@ -110,44 +244,74 @@ class SessionController extends BaseAdminController
$this->applyUserLocale($user);
/**
* we have tou find a way to send cookie
*/
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->createAdminRememberMeCookie($user);
$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.
$this->redirect($adminLoginForm->getSuccessUrl());
} catch (FormValidationException $ex) {
// Validation problem
return $this->generateSuccessRedirect($adminLoginForm);
} catch (FormValidationException $ex) {
// Validation problem
$message = $this->createStandardFormValidationErrorMessage($ex);
} catch (AuthenticationException $ex) {
// Log authentication failure
} 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
$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())
);
}
$message = $this->getTranslator()->trans(
"Unable to process your request. Please try again (%err).",
array("%err" => $ex->getMessage())
);
}
$this->setupFormErrorContext("Login process", $message, $adminLoginForm, $ex);
$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

@@ -11,11 +11,12 @@
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
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;
@@ -23,7 +24,7 @@ use Thelia\Form\ShippingZone\ShippingZoneRemoveArea;
/**
* Class ShippingZoneController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ShippingZoneController extends BaseAdminController
{
@@ -31,16 +32,22 @@ class ShippingZoneController extends BaseAdminController
public function indexAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::VIEW)) return $response;
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", array(
"delivery_module_id" => $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]
);
}
/**
@@ -48,7 +55,9 @@ class ShippingZoneController extends BaseAdminController
*/
public function addArea()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) {
return $response;
}
$shippingAreaForm = new ShippingZoneAddArea($this->getRequest());
$error_msg = null;
@@ -64,8 +73,7 @@ class ShippingZoneController extends BaseAdminController
$this->dispatch(TheliaEvents::SHIPPING_ZONE_ADD_AREA, $event);
// Redirect to the success URL
$this->redirect($shippingAreaForm->getSuccessUrl());
return $this->generateSuccessRedirect($shippingAreaForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -75,7 +83,10 @@ class ShippingZoneController extends BaseAdminController
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), $error_msg, $shippingAreaForm);
$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();
@@ -83,7 +94,9 @@ class ShippingZoneController extends BaseAdminController
public function removeArea()
{
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::SHIPPING_ZONE, array(), AccessManager::UPDATE)) {
return $response;
}
$shippingAreaForm = new ShippingZoneRemoveArea($this->getRequest());
$error_msg = null;
@@ -99,8 +112,7 @@ class ShippingZoneController extends BaseAdminController
$this->dispatch(TheliaEvents::SHIPPING_ZONE_REMOVE_AREA, $event);
// Redirect to the success URL
$this->redirect($shippingAreaForm->getSuccessUrl());
return $this->generateSuccessRedirect($shippingAreaForm);
} catch (FormValidationException $ex) {
// Form cannot be validated
$error_msg = $this->createStandardFormValidationErrorMessage($ex);
@@ -110,7 +122,10 @@ class ShippingZoneController extends BaseAdminController
}
$this->setupFormErrorContext(
$this->getTranslator()->trans("%obj modification", array('%obj' => $this->objectName)), $error_msg, $shippingAreaForm);
$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();
@@ -121,14 +136,14 @@ class ShippingZoneController extends BaseAdminController
*/
protected function renderEditionTemplate()
{
return $this->render("shipping-zones-edit", array(
"delivery_module_id" => $this->getDeliveryModuleId()
));
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

@@ -12,19 +12,19 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\SystemLogConfigurationForm;
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 <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class SystemLogController extends BaseAdminController
{
protected function renderTemplate()
{
$destinations = array();
@@ -37,12 +37,13 @@ class SystemLogController extends BaseAdminController
$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
)
return $this->render(
'system-logs',
array(
'ip_address' => $this->getRequest()->getClientIp(),
'destinations' => $destinations,
'active_destinations' => $active_destinations
)
);
}
@@ -50,17 +51,16 @@ class SystemLogController extends BaseAdminController
{
try {
foreach (new \DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) continue;
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();
@@ -77,10 +77,12 @@ class SystemLogController extends BaseAdminController
*/
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::VIEW)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::VIEW)) {
return $response;
}
// Hydrate the general configuration form
$systemLogForm = new SystemLogConfigurationForm($this->getRequest(), 'form', array(
$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),
@@ -95,22 +97,24 @@ class SystemLogController extends BaseAdminController
public function saveAction()
{
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::SYSTEM_LOG, array(), AccessManager::UPDATE)) {
return $response;
}
$error_msg = false;
$systemLogForm = new SystemLogConfigurationForm($this->getRequest());
$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']);
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');
@@ -119,13 +123,11 @@ class SystemLogController extends BaseAdminController
$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);
@@ -136,21 +138,28 @@ class SystemLogController extends BaseAdminController
// Update active destinations list
ConfigQuery::write(Tlog::VAR_DESTINATIONS, implode(';', $active_destinations));
$this->adminLogAppend(AdminResources::SYSTEM_LOG, AccessManager::UPDATE, "System log configuration changed");
$this->redirectToRoute('admin.configuration.system-logs.default');
$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();
}
$this->setupFormErrorContext(
if (false !== $error_msg) {
$this->setupFormErrorContext(
$this->getTranslator()->trans("System log configuration failed."),
$error_msg,
$systemLogForm,
$ex
);
);
return $this->renderTemplate();
$response = $this->renderTemplate();
}
return $response;
}
}

View File

@@ -12,13 +12,13 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Tax\TaxEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Form\TaxCreationForm;
use Thelia\Form\TaxModificationForm;
use Thelia\Model\TaxQuery;
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
{
@@ -28,9 +28,7 @@ class TaxController extends AbstractCrudController
'tax',
'manual',
'order',
AdminResources::TAX,
TheliaEvents::TAX_CREATE,
TheliaEvents::TAX_UPDATE,
TheliaEvents::TAX_DELETE
@@ -39,14 +37,14 @@ class TaxController extends AbstractCrudController
protected function getCreationForm()
{
$form = new TaxCreationForm($this->getRequest(), 'form', array(), array(), $this->container->get('thelia.taxEngine'));
$form = $this->createForm(AdminForm::TAX_CREATION);
return $form;
}
protected function getUpdateForm()
{
return new TaxModificationForm($this->getRequest(), 'form', array(), array(), $this->container->get('thelia.taxEngine'));
return $this->createForm(AdminForm::TAX_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -103,7 +101,11 @@ class TaxController extends AbstractCrudController
);
// Setup the object form
return new TaxModificationForm($this->getRequest(), "form", $data, array(), $this->container->get('thelia.taxEngine'));
return $this->createForm(
AdminForm::TAX_MODIFICATION,
"form",
$data
);
}
protected function getObjectFromEvent($event)
@@ -123,11 +125,19 @@ class TaxController extends AbstractCrudController
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();
@@ -161,8 +171,7 @@ class TaxController extends AbstractCrudController
protected function redirectToEditionTemplate($request = null, $country = null)
{
// We always return to the feature edition form
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.taxes.update",
$this->getViewArguments($country),
$this->getRouteArguments()
@@ -177,7 +186,7 @@ class TaxController extends AbstractCrudController
*/
protected function performAdditionalCreateAction($createEvent)
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.taxes.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getTax()->getId())
@@ -186,16 +195,13 @@ class TaxController extends AbstractCrudController
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.configuration.taxes-rules.list"
);
return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list");
}
protected function getRequirements($type, $formData)
{
$requirements = array();
foreach ($formData as $data => $value) {
if (!strstr($data, ':')) {
continue;
}

View File

@@ -12,17 +12,18 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
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\Form\TaxRuleCreationForm;
use Thelia\Form\TaxRuleModificationForm;
use Thelia\Form\TaxRuleTaxListUpdateForm;
use Thelia\Model\CountryQuery;
use Thelia\Model\ProductQuery;
use Thelia\Model\TaxRule;
use Thelia\Model\TaxRuleCountryQuery;
use Thelia\Model\TaxRuleQuery;
use Thelia\Form\TaxCreationForm;
class TaxRuleController extends AbstractCrudController
{
@@ -32,9 +33,7 @@ class TaxRuleController extends AbstractCrudController
'taxrule',
'manual',
'order',
AdminResources::TAX,
TheliaEvents::TAX_RULE_CREATE,
TheliaEvents::TAX_RULE_UPDATE,
TheliaEvents::TAX_RULE_DELETE
@@ -50,7 +49,7 @@ class TaxRuleController extends AbstractCrudController
//
// 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 = new TaxCreationForm($this->getRequest(), 'form', array(), array(), $this->container->get('thelia.taxEngine'));
$taxCreationForm = $this->createForm(AdminForm::TAX_CREATION);
$this->getParserContext()->addForm($taxCreationForm);
@@ -59,12 +58,12 @@ class TaxRuleController extends AbstractCrudController
protected function getCreationForm()
{
return new TaxRuleCreationForm($this->getRequest());
return $this->createForm(AdminForm::TAX_RULE_CREATION);
}
protected function getUpdateForm()
{
return new TaxRuleModificationForm($this->getRequest());
return $this->createForm(AdminForm::TAX_RULE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -97,6 +96,7 @@ class TaxRuleController extends AbstractCrudController
$event->setId($formData['id']);
$event->setTaxList($formData['tax_list']);
$event->setCountryList($formData['country_list']);
$event->setCountryDeletedList($formData['country_deleted_list']);
return $event;
}
@@ -127,9 +127,13 @@ class TaxRuleController extends AbstractCrudController
);
// Setup the object form
return new TaxRuleModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::TAX_RULE_MODIFICATION, "form", $data);
}
/**
* @param TaxRule $object
* @return \Thelia\Form\BaseForm
*/
protected function hydrateTaxUpdateForm($object)
{
$data = array(
@@ -137,7 +141,7 @@ class TaxRuleController extends AbstractCrudController
);
// Setup the object form
return new TaxRuleTaxListUpdateForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -157,21 +161,30 @@ class TaxRuleController extends AbstractCrudController
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)
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,
);
}
@@ -197,12 +210,11 @@ class TaxRuleController extends AbstractCrudController
return $this->render('tax-rule-edit', array_merge($this->getViewArguments(), $this->getRouteArguments()));
}
protected function redirectToEditionTemplate($request = null, $country = null)
protected function redirectToEditionTemplate($request = null, $country = null, $state = null)
{
// We always return to the feature edition form
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.taxes-rules.update",
$this->getViewArguments($country),
$this->getViewArguments($country, null, $state),
$this->getRouteArguments()
);
}
@@ -215,7 +227,7 @@ class TaxRuleController extends AbstractCrudController
*/
protected function performAdditionalCreateAction($createEvent)
{
$this->redirectToRoute(
return $this->generateRedirectFromRoute(
"admin.configuration.taxes-rules.update",
$this->getViewArguments(),
$this->getRouteArguments($createEvent->getTaxRule()->getId())
@@ -224,19 +236,18 @@ class TaxRuleController extends AbstractCrudController
protected function redirectToListTemplate()
{
$this->redirectToRoute(
"admin.configuration.taxes-rules.list"
);
return $this->generateRedirectFromRoute("admin.configuration.taxes-rules.list");
}
public function updateAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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);
@@ -249,7 +260,9 @@ class TaxRuleController extends AbstractCrudController
public function setDefaultAction()
{
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) {
return $response;
}
$setDefaultEvent = new TaxRuleEvent();
@@ -261,18 +274,25 @@ class TaxRuleController extends AbstractCrudController
$this->dispatch(TheliaEvents::TAX_RULE_SET_DEFAULT, $setDefaultEvent);
$this->redirectToListTemplate();
return $this->redirectToListTemplate();
}
public function processUpdateTaxesAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth($this->resourceCode, array(), AccessManager::UPDATE)) return $response;
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 = new TaxRuleTaxListUpdateForm($this->getRequest());
$changeForm = $this->createForm(AdminForm::TAX_RULE_TAX_LIST_UPDATE);
try {
// Check the form against constraints violations
@@ -285,20 +305,33 @@ class TaxRuleController extends AbstractCrudController
$this->dispatch(TheliaEvents::TAX_RULE_TAXES_UPDATE, $changeEvent);
if (! $this->eventContainsObject($changeEvent))
if (! $this->eventContainsObject($changeEvent)) {
throw new \LogicException(
$this->getTranslator()->trans("No %obj was updated.", array('%obj', $this->objectName)));
$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->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) {
$this->redirectToEditionTemplate($this->getRequest(), isset($data['country_list'][0]) ? $data['country_list'][0] : null);
} else {
return $response;
}
$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);
@@ -310,6 +343,80 @@ class TaxRuleController extends AbstractCrudController
$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();
$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

@@ -12,21 +12,23 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Template\TemplateDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Event\Template\TemplateUpdateEvent;
use Thelia\Core\Event\Template\TemplateCreateEvent;
use Thelia\Core\Security\AccessManager;
use Thelia\Model\TemplateQuery;
use Thelia\Form\TemplateModificationForm;
use Thelia\Form\TemplateCreationForm;
use Thelia\Core\Event\Template\TemplateDeleteAttributeEvent;
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\Model\FeatureTemplateQuery;
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
@@ -41,9 +43,7 @@ class TemplateController extends AbstractCrudController
'template',
null,
null,
AdminResources::TEMPLATE,
TheliaEvents::TEMPLATE_CREATE,
TheliaEvents::TEMPLATE_UPDATE,
TheliaEvents::TEMPLATE_DELETE,
@@ -54,12 +54,12 @@ class TemplateController extends AbstractCrudController
protected function getCreationForm()
{
return new TemplateCreationForm($this->getRequest());
return $this->createForm(AdminForm::TEMPLATE_CREATION);
}
protected function getUpdateForm()
{
return new TemplateModificationForm($this->getRequest());
return $this->createForm(AdminForm::TEMPLATE_MODIFICATION);
}
protected function getCreationEvent($formData)
@@ -100,7 +100,6 @@ class TemplateController extends AbstractCrudController
protected function hydrateObjectForm($object)
{
$data = array(
'id' => $object->getId(),
'locale' => $object->getLocale(),
@@ -108,7 +107,7 @@ class TemplateController extends AbstractCrudController
);
// Setup the object form
return new TemplateModificationForm($this->getRequest(), "form", $data);
return $this->createForm(AdminForm::TEMPLATE_MODIFICATION, "form", $data);
}
protected function getObjectFromEvent($event)
@@ -128,11 +127,19 @@ class TemplateController extends AbstractCrudController
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();
@@ -146,36 +153,45 @@ class TemplateController extends AbstractCrudController
protected function renderEditionTemplate()
{
return $this->render(
'template-edit',
array(
'template_id' => $this->getRequest()->get('template_id'),
)
'template-edit',
array(
'template_id' => $this->getRequest()->get('template_id'),
)
);
}
protected function redirectToEditionTemplate()
/**
* @param Request $request
* @param int $id
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function redirectToEditionTemplate($request = null, $id = null)
{
$this->redirectToRoute(
"admin.configuration.templates.update",
array(
'template_id' => $this->getRequest()->get('template_id'),
)
return $this->generateRedirectFromRoute(
"admin.configuration.templates.update",
[
'template_id' => $id ?: $this->getRequest()->get('template_id'),
]
);
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.configuration.templates.default');
return $this->generateRedirectFromRoute('admin.configuration.templates.default');
}
// Process delete failure, which may occurs if template is in use.
/**
* 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."
"This template is in use in some of your products, and cannot be deleted. Delete it from all your products and try again."
)
);
@@ -186,33 +202,62 @@ class TemplateController extends AbstractCrudController
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'))
'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'))
'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;
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
$this->getExistingObject(),
$attribute_id
);
try {
@@ -223,17 +268,19 @@ class TemplateController extends AbstractCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
public function deleteAttributeAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new TemplateDeleteAttributeEvent(
$this->getExistingObject(),
intval($this->getRequest()->get('attribute_id'))
$this->getExistingObject(),
intval($this->getRequest()->get('attribute_id'))
);
try {
@@ -243,7 +290,7 @@ class TemplateController extends AbstractCrudController
return $this->errorPage($ex);
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
public function updateAttributePositionAction()
@@ -256,22 +303,24 @@ class TemplateController extends AbstractCrudController
;
return $this->genericUpdatePositionAction(
$attributeTemplate,
TheliaEvents::TEMPLATE_CHANGE_ATTRIBUTE_POSITION
$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;
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
$this->getExistingObject(),
$feature_id
);
try {
@@ -282,17 +331,19 @@ class TemplateController extends AbstractCrudController
}
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
public function deleteFeatureAction()
{
// Check current user authorization
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) return $response;
if (null !== $response = $this->checkAuth(AdminResources::TEMPLATE, array(), AccessManager::UPDATE)) {
return $response;
}
$event = new TemplateDeleteFeatureEvent(
$this->getExistingObject(),
intval($this->getRequest()->get('feature_id'))
$this->getExistingObject(),
intval($this->getRequest()->get('feature_id'))
);
try {
@@ -302,7 +353,7 @@ class TemplateController extends AbstractCrudController
return $this->errorPage($ex);
}
$this->redirectToEditionTemplate();
return $this->redirectToEditionTemplate();
}
public function updateFeaturePositionAction()
@@ -315,8 +366,8 @@ class TemplateController extends AbstractCrudController
;
return $this->genericUpdatePositionAction(
$featureTemplate,
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION
$featureTemplate,
TheliaEvents::TEMPLATE_CHANGE_FEATURE_POSITION
);
}
}

View File

@@ -18,7 +18,7 @@ use Thelia\Core\Security\Resource\AdminResources;
/**
* Class ToolsController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class ToolsController extends BaseAdminController
{

View File

@@ -13,47 +13,52 @@
namespace Thelia\Controller\Admin;
use Symfony\Component\Finder\Finder;
use Thelia\Core\Security\Resource\AdminResources;
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\Core\Template\TemplateHelper;
use Thelia\Core\Template\TemplateDefinition;
use Thelia\Tools\URL;
/**
* Class LangController
* Class TranslationsController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
*/
class TranslationsController extends BaseAdminController
{
/**
* @param string $item_name the modume code
* @param string $itemName the modume code
* @return Module the module object
* @throws \InvalidArgumentException if module was not found
*/
protected function getModule($item_name)
protected function getModule($itemName)
{
if (null !== $module = ModuleQuery::create()->findPk($item_name))
if (null !== $module = ModuleQuery::create()->findPk($itemName)) {
return $module;
}
throw new \InvalidArgumentException(
$this->getTranslator()->trans("No module found for code '%item'", ['%item' => $item_name])
$this->getTranslator()->trans("No module found for code '%item'", ['%item' => $itemName])
);
}
protected function getModuleTemplateNames(Module $module, $template_type)
protected function getModuleTemplateNames(Module $module, $templateType)
{
$templates =
TemplateHelper::getInstance()->getList(
$template_type,
$this->getTemplateHelper()->getList(
$templateType,
$module->getAbsoluteTemplateBasePath()
);
$names = [];
foreach($templates as $template) $names[] = $template->getName();
foreach ($templates as $template) {
$names[] = $template->getName();
}
return $names;
}
@@ -61,72 +66,84 @@ class TranslationsController extends BaseAdminController
protected function renderTemplate()
{
// Get related strings, if all input data are here
$item_to_translate = $this->getRequest()->get('item_to_translate');
$itemToTranslate = $this->getRequest()->get('item_to_translate');
$item_name = $this->getRequest()->get('item_name', '');
$itemName = $this->getRequest()->get('item_name', '');
if ($item_to_translate == 'mo' && ! empty($item_name))
$module_part = $this->getRequest()->get('module_part', '');
else
$module_part = false;
if ($itemToTranslate == 'mo' && ! empty($itemName)) {
$modulePart = $this->getRequest()->get('module_part', '');
} else {
$modulePart = false;
}
$all_strings = array();
$template = $directory = $i18nDirectory = false;
$template = $directory = $i18n_directory = false;
$walkMode = TemplateHelper::WALK_MODE_TEMPLATE;
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
$templateArguments = array(
'item_to_translate' => $item_to_translate,
'item_name' => $item_name,
'module_part' => $module_part,
'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only', 0),
'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($item_name) || $item_to_translate == 'co') {
switch ($item_to_translate) {
if (! empty($itemName) || $itemToTranslate == 'co' || $itemToTranslate == 'in' || $itemToTranslate == 'wi') {
switch ($itemToTranslate) {
// Module core
case 'mo' :
$module = $this->getModule($item_name);
case 'mo':
$module = $this->getModule($itemName);
if ($module_part == 'core') {
if ($modulePart == 'core') {
$directory = $module->getAbsoluteBaseDir();
$domain = $module->getTranslationDomain();
$i18n_directory = $module->getAbsoluteI18nPath();
$walkMode = TemplateHelper::WALK_MODE_PHP;
} elseif ($module_part == 'admin-includes') {
$i18nDirectory = $module->getAbsoluteI18nPath();
$walkMode = TranslationEvent::WALK_MODE_PHP;
} elseif ($modulePart == 'admin-includes') {
$directory = $module->getAbsoluteAdminIncludesPath();
$domain = $module->getAdminIncludesTranslationDomain();
$i18n_directory = $module->getAbsoluteAdminIncludesI18nPath();
$walkMode = TemplateHelper::WALK_MODE_TEMPLATE;
} elseif (! empty($module_part)) {
// Front or back office template, form of $module_part is [bo|fo].subdir-name
list($type, $subdir) = explode('.', $module_part);
$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);
if ($type == 'bo') {
$directory = $module->getAbsoluteBackOfficeTemplatePath($subdir);
$domain = $module->getBackOfficeTemplateTranslationDomain($subdir);
$i18n_directory = $module->getAbsoluteBackOfficeI18nTemplatePath($subdir);
} elseif ($type == 'fo') {
$directory = $module->getAbsoluteFrontOfficeTemplatePath($subdir);
$domain = $module->getFrontOfficeTemplateTranslationDomain($subdir);
$i18n_directory = $module->getAbsoluteFrontOfficeI18nTemplatePath($subdir);
} else {
throw new \InvalidArgumentException("Undefined module template type: '$type'.");
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 = TemplateHelper::WALK_MODE_TEMPLATE;
$walkMode = TranslationEvent::WALK_MODE_TEMPLATE;
}
// If the module is not active, load the translation file,
// as it is not already loaded in Thelia.php
if (! empty ($domain) && ! $module->getActivate()) {
$this->loadTranslation($i18n_directory, $domain);
// 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
@@ -136,13 +153,19 @@ class TranslationsController extends BaseAdminController
$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')
->files()
->depth(0)
->in($module->getAbsoluteAdminIncludesPath())
->name('/\.html$/i')
;
$hasAdminIncludes = $finder->count() > 0;
@@ -155,111 +178,163 @@ class TranslationsController extends BaseAdminController
break;
// Thelia Core
case 'co' :
$directory = THELIA_ROOT . 'core/lib/Thelia';
case 'co':
$directory = THELIA_LIB;
$domain = 'core';
$i18n_directory = THELIA_ROOT . 'core/lib/Thelia/Config/I18n';
$walkMode = TemplateHelper::WALK_MODE_PHP;
break;
$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($item_name, TemplateDefinition::FRONT_OFFICE);
break;
case 'fo':
$template = new TemplateDefinition($itemName, TemplateDefinition::FRONT_OFFICE);
break;
// Back-office template
case 'bo' :
$template = new TemplateDefinition($item_name, TemplateDefinition::BACK_OFFICE);
break;
case 'bo':
$template = new TemplateDefinition($itemName, TemplateDefinition::BACK_OFFICE);
break;
// PDF templates
case 'pf' :
$template = new TemplateDefinition($item_name, TemplateDefinition::PDF);
break;
case 'pf':
$template = new TemplateDefinition($itemName, TemplateDefinition::PDF);
break;
// Email templates
case 'ma' :
$template = new TemplateDefinition($item_name, TemplateDefinition::EMAIL);
break;
case 'ma':
$template = new TemplateDefinition($itemName, TemplateDefinition::EMAIL);
break;
}
if ($template) {
$directory = $template->getAbsolutePath();
$i18n_directory = $template->getAbsoluteI18nPath();
$i18nDirectory = $template->getAbsoluteI18nPath();
$domain = $template->getTranslationDomain();
// Load translations files is this template is not the current template
// as it is not loaded in Thelia.php
if (! TemplateHelper::getInstance()->isActive($template)) {
$this->loadTranslation($i18n_directory, $domain);
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 ($i18n_directory) {
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
);
$file = sprintf("%s".DS."%s.php", $i18n_directory, $this->getCurrentEditionLocale());
$event
->setDomain($domain)
->setLocale($this->getCurrentEditionLocale())
->setCustomFallbackStrings($this->getRequest()->get('translation_custom', []))
->setGlobalFallbackStrings($this->getRequest()->get('translation_global', []));
$translations = $this->getRequest()->get('translation', array());
$this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_WRITE_FILE, $event);
TemplateHelper::getInstance()->writeTranslation($file, $texts, $translations, true);
if ($save_mode == 'stay')
$this->redirectToRoute("admin.configuration.translations", $templateArguments);
else
$this->redirect(URL::getInstance()->adminViewUrl('configuration'));
if ($save_mode == 'stay') {
return $this->generateRedirectFromRoute(
"admin.configuration.translations",
$templateArguments
);
} else {
return $this->generateRedirect(URL::getInstance()->adminViewUrl('configuration'));
}
}
}
}
// Load strings
$stringsCount = TemplateHelper::getInstance()->walkDir(
$directory,
$walkMode,
$this->getTranslator(),
$this->getCurrentEditionLocale(),
$domain,
$all_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 = $stringsCount * 2 + 6;
$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');
$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'] = $all_strings;
$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;
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;
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, array(), AccessManager::UPDATE)) {
return $response;
}
return $this->renderTemplate();
}
@@ -281,5 +356,4 @@ class TranslationsController extends BaseAdminController
// 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::COUNTRY_ID)
->find()
->toArray()
;
$taxes = TaxRuleCountryQuery::create()
->filterByTaxRuleId($taxRuleId)
->distinct()
->select(TaxRuleCountryTableMap::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

@@ -12,31 +12,30 @@
namespace Thelia\Controller;
use Thelia\Core\Event\PdfEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Symfony\Component\DependencyInjection\ContainerAware;
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\Template\TemplateHelper;
use Thelia\Core\Translation\Translator;
use Thelia\Form\FirewallForm;
use Thelia\Model\OrderQuery;
use Thelia\Tools\Redirect;
use Thelia\Core\Template\ParserContext;
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 Symfony\Component\EventDispatcher\Event;
use Thelia\Core\Event\DefaultActionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Thelia\Log\Tlog;
use Thelia\Mailer\MailerFactory;
use Thelia\Model\OrderQuery;
use Thelia\Tools\URL;
/**
*
@@ -44,11 +43,28 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* 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 <mraynaud@openstudio.fr>
* @author Manuel Raynaud <manu@raynaud.io>
* @author Benjamin Perche <bperche@openstudio.fr>
*/
abstract class BaseController extends ContainerAware
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)
@@ -61,37 +77,45 @@ abstract class BaseController extends ContainerAware
}
/**
* Return a JSON response
* @param $jsonData
* @param int $status
* @return Response Return a JSON response
*/
protected function jsonResponse($json_data, $status = 200)
protected function jsonResponse($jsonData, $status = 200)
{
return new Response($json_data, $status, array('content-type' => 'application/json'));
return new Response($jsonData, $status, array('content-type' => 'application/json'));
}
/**
* @param $pdf
* @param $fileName
* @param $status
* @param int $status
* @param bool $browser
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function pdfResponse($pdf, $fileName, $status = 200)
protected function pdfResponse($pdf, $fileName, $status = 200, $browser = false)
{
return Response::create($pdf, $status,
return Response::create(
$pdf,
$status,
array(
'Content-type' => "application/pdf",
'Content-Disposition' => sprintf('Attachment;filename=%s.pdf', $fileName),
));
'Content-Disposition' => $browser === false ? sprintf('Attachment;filename=%s.pdf', $fileName) : '',
)
);
}
/**
* Dispatch a Thelia event
*
* @param string $eventName a TheliaEvent name, as defined in TheliaEvents class
* @param Event $event the action event, or null (a DefaultActionEvent will be dispatched)
* @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();
if ($event == null) {
$event = new DefaultActionEvent();
}
$this->getDispatcher()->dispatch($eventName, $event);
}
@@ -107,14 +131,16 @@ abstract class BaseController extends ContainerAware
}
/**
*
* return the Translator
*
* @return Translator
*/
public function getTranslator()
{
return $this->container->get('thelia.translator');
if (null === $this->translator) {
$this->translator = $this->container->get('thelia.translator');
}
return $this->translator;
}
/**
@@ -142,7 +168,7 @@ abstract class BaseController extends ContainerAware
*/
protected function getRequest()
{
return $this->container->get('request');
return $this->container->get('request_stack')->getCurrentRequest();
}
/**
@@ -152,36 +178,55 @@ abstract class BaseController extends ContainerAware
*/
protected function getSession()
{
$request = $this->getRequest();
return $request->getSession();
return $this->container->get('request_stack')->getCurrentRequest()->getSession();
}
/**
* Get all errors that occured in a form
* @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
*/
private function getErrorMessages(\Symfony\Component\Form\Form $form)
protected function getErrorMessages(Form $form)
{
$errors = '';
foreach ($form->getErrors() as $key => $error) {
$errors .= $error->getMessage() . ', ';
}
foreach ($form->all() as $child) {
if (!$child->isValid()) {
$fieldName = $child->getConfig()->getOption('label', $child->getName());
$errors .= sprintf("[%s] %s, ", $fieldName, $this->getErrorMessages($child));
}
}
return rtrim($errors, ', ');
return $this->getTheliaFormValidator()->getErrorMessages($form);
}
/**
@@ -194,97 +239,225 @@ abstract class BaseController extends ContainerAware
*/
protected function validateForm(BaseForm $aBaseForm, $expectedMethod = null)
{
$form = $aBaseForm->getForm();
$form = $this->getTheliaFormValidator()->validateForm($aBaseForm, $expectedMethod);
if ($expectedMethod == null || $aBaseForm->getRequest()->isMethod($expectedMethod)) {
// At this point, the form is valid (no exception was thrown). Remove it from the error context.
$this->getParserContext()->clearForm($aBaseForm);
$form->bind($aBaseForm->getRequest());
if ($form->isValid()) {
$env = $this->container->getParameter("kernel.environment");
if ($aBaseForm instanceof FirewallForm && !$aBaseForm->isFirewallOk($env)) {
throw new FormValidationException(
$this->getTranslator()->trans(
"You've submitted this form too many times. Further submissions will be ignored during %time",
[
"%time" => $aBaseForm->getWaitingTime(),
]
)
);
}
return $form;
} else {
$errorMessage = null;
if ($form->get("error_message")->getData() != null) {
$errorMessage = $form->get("error_message")->getData();
} else {
$errorMessage = sprintf($this->getTranslator()->trans("Missing or invalid data: %s"), $this->getErrorMessages($form));
}
throw new FormValidationException($errorMessage);
}
} else {
throw new FormValidationException(sprintf($this->getTranslator()->trans("Wrong form method, %s expected."), $expectedMethod));
}
return $form;
}
protected function generateOrderPdf($order_id, $fileName)
/**
* @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
),
TemplateHelper::getInstance()->getActivePdfTemplate()
$this->getTemplateHelper()->getActivePdfTemplate()
);
$order = OrderQuery::create()->findPk($order_id);
try {
$pdfEvent = new PdfEvent($html);
$this->dispatch(TheliaEvents::GENERATE_PDF, $pdfEvent);
if ($pdfEvent->hasPdf()) {
return $this->pdfResponse($pdfEvent->getPdf(), $order->getRef());
return $this->pdfResponse($pdfEvent->getPdf(), $order->getRef(), 200, $browser);
}
} catch (\Exception $e) {
\Thelia\Log\Tlog::getInstance()->error(sprintf('error during generating invoice pdf for order id : %d with message "%s"', $order_id, $e->getMessage()));
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
*
* redirect request to the specified url
*
* @param string $url
* @param int $status http status. Must be a 30x status
* @param array $cookies
* @param BaseForm $form
* @return mixed|null|string
*/
public function redirect($url, $status = 302, $cookies = array())
protected function retrieveSuccessUrl(BaseForm $form = null)
{
Redirect::exec($url, $status, $cookies);
return $this->retrieveFormBasedUrl('success_url', $form);
}
/**
* If success_url param is present in request or in the provided form, redirect to this URL.
* Search error url in a form if present, in the query string otherwise
*
* @param BaseForm $form a base form, which may contains the success URL
* @param BaseForm $form
* @return mixed|null|string
*/
protected function redirectSuccess(BaseForm $form = null)
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->getSuccessUrl();
$url = $form->getFormDefinedUrl($parameterName);
} else {
$url = $this->getRequest()->get("success_url");
$url = $this->container->get('request_stack')->getCurrentRequest()->get($parameterName);
}
if (null !== $url) $this->redirect($url);
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
);
}
/**
@@ -293,7 +466,7 @@ abstract class BaseController extends ContainerAware
* @param string $routerName Router name
* @param string $routeId The name of the route
* @param mixed $parameters An array of parameters
* @param Boolean|string $referenceType The type of reference to be generated (one of the constants)
* @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
@@ -302,8 +475,12 @@ abstract class BaseController extends ContainerAware
* @throws \InvalidArgumentException When the router doesn't exist
* @return string The generated URL
*/
protected function getRouteFromRouter($routerName, $routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_URL)
{
protected function getRouteFromRouter(
$routerName,
$routeId,
$parameters = array(),
$referenceType = Router::ABSOLUTE_URL
) {
/** @var Router $router */
$router = $this->getRouter($routerName);
@@ -354,7 +531,7 @@ abstract class BaseController extends ContainerAware
*/
protected function checkXmlHttpRequest()
{
if (false === $this->getRequest()->isXmlHttpRequest() && false === $this->isDebug()) {
if (false === $this->container->get('request_stack')->getCurrentRequest()->isXmlHttpRequest() && false === $this->isDebug()) {
$this->accessDenied();
}
}
@@ -363,24 +540,74 @@ abstract class BaseController extends ContainerAware
*
* return an instance of \Swift_Mailer with good Transporter configured.
*
* @return \Swift_Mailer
* @return MailerFactory
*/
public function getMailer()
{
$mailer = $this->container->get('mailer');
return $this->container->get('mailer');
}
return $mailer->getSwiftMailer();
protected function getCurrentRouter()
{
return $this->currentRouter;
}
protected function setCurrentRouter($routerId)
{
$this->currentRouter = $routerId;
}
/**
* @return a ParserInterface instance parser
* @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 $templateName the complete template name, with extension
* @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
@@ -390,7 +617,7 @@ abstract class BaseController extends ContainerAware
/**
* Render the given template, and returns the result as a string.
*
* @param $templateName the complete template name, with extension
* @param string $templateName the complete template name, with extension
* @param array $args the template arguments
* @param null $templateDir
*

View File

@@ -12,67 +12,40 @@
namespace Thelia\Controller\Front;
use Symfony\Component\Routing\Router;
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\Core\Template\TemplateHelper;
use Thelia\Model\AddressQuery;
use Thelia\Model\ModuleQuery;
use Thelia\Tools\URL;
class BaseFrontController extends BaseController
{
/**
* Return the route path defined for the givent route ID
*
* @param string $routeId a route ID, as defines in Config/Resources/routing/front.xml
*
* @see \Thelia\Controller\BaseController::getRouteFromRouter()
*/
const CONTROLLER_TYPE = 'front';
/**
* Return the route path defined for the givent route ID
*
* @param string $routeId the route ID, as found in Config/Resources/routing/admin.xml
* @param array $parameters the Route parameters, as a var/value pair array
* @param bool $referenceType Router::ABSOLUTE_PATH or Router::ABSOLUTE_URL
*
* @see \Thelia\Controller\BaseController::getRouteFromRouter()
*
* @return string the route path
*/
protected function getRoute($routeId, $parameters = array(), $referenceType = Router::ABSOLUTE_PATH)
{
return $this->getRouteFromRouter('router.front', $routeId, $parameters, $referenceType);
}
/**
* Redirect to a specific route.
*
* @param string $routeId the route ID, as found in Config/Resources/routing/admin.xml
* @param array $urlParameters the URL parameters, as a var/value pair array
* @param array $routeParameters the Route parameters, as a var/value pair array
* @param bool $referenceType Router::ABSOLUTE_PATH or Router::ABSOLUTE_URL
*/
public function redirectToRoute($routeId, array $urlParameters = [], array $routeParameters = [], $referenceType = Router::ABSOLUTE_PATH)
{
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute($routeId, $routeParameters, $referenceType), $urlParameters));
}
protected $currentRouter = "router.front";
public function checkAuth()
{
if ($this->getSecurityContext()->hasCustomerUser() === false) {
$this->redirectToRoute('customer.login.process');
throw new RedirectException($this->retrieveUrlFromRouteId('customer.login.process'));
}
}
/**
* @return string
*/
public function getControllerType()
{
return self::CONTROLLER_TYPE;
}
protected function checkCartNotEmpty()
{
$cart = $this->getSession()->getCart();
$cart = $this->getSession()->getSessionCart($this->getDispatcher());
if ($cart===null || $cart->countCartItems() == 0) {
$this->redirectToRoute('cart.view');
throw new RedirectException($this->retrieveUrlFromRouteId('cart.view'));
}
}
@@ -88,7 +61,7 @@ class BaseFrontController extends BaseController
null === AddressQuery::create()->findPk($order->getChoosenDeliveryAddress())
||
null === ModuleQuery::create()->findPk($order->getDeliveryModuleId())) {
$this->redirectToRoute("order.delivery");
throw new RedirectException($this->retrieveUrlFromRouteId('order.delivery'));
}
}
@@ -104,7 +77,7 @@ class BaseFrontController extends BaseController
null === AddressQuery::create()->findPk($order->getChoosenInvoiceAddress())
||
null === ModuleQuery::create()->findPk($order->getPaymentModuleId())) {
$this->redirectToRoute("order.invoice");
throw new RedirectException($this->retrieveUrlFromRouteId('order.invoice'));
}
}
@@ -118,7 +91,10 @@ class BaseFrontController extends BaseController
$parser = $this->container->get("thelia.parser");
// Define the template that should be used
$parser->setTemplateDefinition($template ?: TemplateHelper::getInstance()->getActiveFrontTemplate());
$parser->setTemplateDefinition(
$template ?: $this->getTemplateHelper()->getActiveFrontTemplate(),
$this->useFallbackTemplate
);
return $parser;
}
@@ -147,25 +123,12 @@ class BaseFrontController extends BaseController
*/
protected function renderRaw($templateName, $args = array(), $templateDir = null)
{
// Add the template standard extension
$templateName .= '.html';
$session = $this->getSession();
// Prepare common template variables
$args = array_merge($args, array(
'locale' => $session->getLang()->getLocale(),
'lang_code' => $session->getLang()->getCode(),
'lang_id' => $session->getLang()->getId(),
'current_url' => $this->getRequest()->getUri()
));
// Render the template.
$data = $this->getParser($templateDir)->render($templateName, $args);
return $data;
}
}

View File

@@ -12,14 +12,14 @@
namespace Thelia\Controller\Front;
use Symfony\Component\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\HttpKernel\Exception\RedirectException;
use Thelia\Model\ConfigQuery;
use Thelia\Tools\URL;
/**
*
* Must be the last controller call. It fixes default values
* This is the defualt Thelia controller, which is called when no controller was found to process the request.
*
* @author Manuel Raynaud <mraynadu@openstudio.fr>
*/
@@ -27,12 +27,17 @@ use Thelia\Tools\URL;
class DefaultController extends BaseFrontController
{
/**
* This is the default Thelia behaviour if no action is defined.
*
* set the default value for thelia
* 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.
*
* In this case there is no action so we have to verify if some needed params are not missing
* Additionaly, if the URL rewriting is enabled, the method will check if a redirect to the pâge rewritten URL should
* be done.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Thelia\Core\HttpFoundation\Request $request
* @throw RedirectException if a redirection to the rewritted URL shoud be done.
*/
public function noAction(Request $request)
{
@@ -55,11 +60,17 @@ class DefaultController extends BaseFrontController
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 */
$this->redirect($rewrittenUrl->rewrittenUrl, 301);
throw new RedirectException($rewrittenUrl->rewrittenUrl, 301);
}
}
}
}
public function emptyRoute()
{
return new Response(null, 204);
}
}