Form processing is now factorized in BaseAction

This commit is contained in:
franck
2013-08-08 11:13:46 +02:00
parent 13bed6d3fc
commit 4e83466bc0
7 changed files with 250 additions and 225 deletions

View File

@@ -23,11 +23,55 @@
namespace Thelia\Action;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Form\CategoryDeletionForm;
use Thelia\Form\BaseForm;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Action\Exception\FormValidationException;
use Thelia\Core\Event\ActionEvent;
abstract class BaseAction
{
protected function validateForm(BaseForm $aBaseForm, $expectedMethod = 'POST')
{
$form = $aBaseForm->getForm();
public function redirect($url, $status = 302)
if ($aBaseForm->getRequest()->isMethod($expectedMethod)) {
$form->bind($aBaseForm->getRequest());
if ($form->isValid()) {
return $form;
}
else {
throw new FormValidationException("Missing or invalid data");
}
}
else {
throw new FormValidationException(sprintf("Wrong form method, %s expected.", $expectedMethod));
}
}
/**
*
* @param BaseForm $aBaseForm
* @param string $error_message
* @param ActionEvent $event
*/
protected function propagateFormError(BaseForm $aBaseForm, $error_message, ActionEvent $event) {
// The form has an error
$aBaseForm->setError(true);
$aBaseForm->setErrorMessage($error_message);
// Store the form in the parser context
$event->setErrorForm($aBaseForm);
// Stop event propagation
$event->stopPropagation();
}
protected function redirect($url, $status = 302)
{
$response = new RedirectResponse($url, $status);

View File

@@ -33,71 +33,51 @@ use Thelia\Tools\Redirect;
use Thelia\Model\CategoryQuery;
use Thelia\Model\AdminLog;
use Thelia\Form\CategoryDeletionForm;
use Thelia\Action\Exception\FormValidationException;
class Category implements EventSubscriberInterface
class Category extends BaseAction implements EventSubscriberInterface
{
public function create(ActionEvent $event)
{
$request = $event->getRequest();
$request = $event->getRequest();
$categoryCreationForm = new CategoryCreationForm($request);
try {
$categoryCreationForm = new CategoryCreationForm($request);
$form = $categoryCreationForm->getForm();
$form = $this->validateForm($categoryCreationForm, "POST");
if ($request->isMethod("post")) {
$data = $form->getData();
$form->bind($request);
$category = new CategoryModel();
if ($form->isValid()) {
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event);
$data = $form->getData();
$category->create(
$data["title"],
$data["parent"],
$data["locale"]
);
$category = new CategoryModel();
AdminLog::append(sprintf("Category %s (ID %s) created", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
try {
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event);
$categoryEvent = new CategoryEvent($category);
$category->create(
$data["title"],
$data["parent"],
$data["locale"]
);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $categoryEvent);
AdminLog::append(sprintf("Category %s (ID %s) created", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getId(), $categoryCreationForm->getSuccessUrl());
$categoryEvent = new CategoryEvent($category);
// Redirect to the success URL
Redirect::exec($successUrl);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $categoryEvent);
} catch (PropelException $e) {
Tlog::getInstance()->error(sprintf('error during creating category with message "%s"', $e->getMessage()));
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getId(), $categoryCreationForm->getSuccessUrl());
// Redirect to the success URL
Redirect::exec($successUrl);
} catch (Exception $e) {
Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage()));
$message = "Failed to create this category, please try again.";
}
}
else {
$message = "Missing or invalid data";
}
}
else {
$message = "Wrong form method !";
$message = "Failed to create this category, please try again.";
}
// The form has an error
$categoryCreationForm->setError(true);
$categoryCreationForm->setErrorMessage($message);
// Store the form in the parser context
$event->setErrorForm($categoryCreationForm);
// Stop event propagation
$event->stopPropagation();
// The form has errors, propagate it.
$this->propagateFormError($categoryCreationForm, $message, $event);
}
public function modify(ActionEvent $event)
@@ -176,63 +156,45 @@ class Category implements EventSubscriberInterface
{
$request = $event->getRequest();
$categoryDeletionForm = new CategoryDeletionForm($request);
try {
$categoryDeletionForm = new CategoryDeletionForm($request);
$form = $categoryDeletionForm->getForm();
$form = $this->validateForm($categoryDeletionForm, "POST");
if ($request->isMethod("post")) {
$data = $form->getData();
$form->bind($request);
$category = CategoryQuery::create()->findPk($data['id']);
if ($form->isValid()) {
$categoryEvent = new CategoryEvent($category);
$data = $form->getData();
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $categoryEvent);
try {
$category = CategoryQuery::create()->findPk($data['id']);
$category->delete();
$categoryEvent = new CategoryEvent($category);
AdminLog::append(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $categoryEvent);
$categoryEvent->category = $category;
$category->delete();
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $categoryEvent);
AdminLog::append(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getParent(), $categoryDeletionForm->getSuccessUrl());
$categoryEvent->category = $category;
// Redirect to the success URL
Redirect::exec($successUrl);
}
catch(PropelException $e) {
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $categoryEvent);
Tlog::getInstance()->error(sprintf('error during deleting category ID=%s on action/modifyCustomer with message "%s"', $data['id'], $e->getMessage()));
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getParent(), $categoryDeletionForm->getSuccessUrl());
// Redirect to the success URL
Redirect::exec($successUrl);
}
catch(PropelException $e) {
Tlog::getInstance()->error(sprintf('error during deleting category ID=%s on action/modifyCustomer with message "%s"', $data['id'], $e->getMessage()));
$message = "Failed to change your account, please try again.";
}
}
else {
$message = "Missing or invalid data";
}
$message = "Failed to change your account, please try again.";
}
else {
$message = "Wrong form method !";
catch(FormValidationException $e) {
$message = $e->getMessage();
}
// The form has an error
$categoryDeletionForm->setError(true);
$categoryDeletionForm->setErrorMessage($message);
// Store the form in the parser context
$event->setErrorForm($categoryDeletionForm);
// Stop event propagation
$event->stopPropagation();
$this->propagateFormError($categoryDeletionForm, $message, $event);
}
/**

View File

@@ -41,107 +41,89 @@ use Symfony\Component\Validator\Exception\ValidatorException;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\Exception\UsernameNotFoundException;
use Propel\Runtime\Exception\PropelException;
use Thelia\Action\Exception\FormValidationException;
class Customer extends BaseAction implements EventSubscriberInterface
{
/**
* @var Thelia\Core\Security\SecurityContext
*/
protected $securityContext;
/**
* @var Thelia\Core\Security\SecurityContext
*/
protected $securityContext;
public function __construct(SecurityContext $securityContext) {
$this->securityContext = $securityContext;
}
public function __construct(SecurityContext $securityContext) {
$this->securityContext = $securityContext;
}
public function create(ActionEvent $event)
{
$request = $event->getRequest();
$request = $event->getRequest();
$customerCreationForm = new CustomerCreation($request);
try {
$customerCreationForm = new CustomerCreation($request);
$form = $customerCreationForm->getForm();
$form = $this->validateForm($customerCreationForm, "POST");
if ($request->isMethod("post")) {
$data = $form->getData();
$customer = new CustomerModel();
$form->bind($request);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECUSTOMER, $event);
if ($form->isValid()) {
$data = $form->getData();
$customer = new CustomerModel();
$customer->createOrUpdate(
$data["title"],
$data["firstname"],
$data["lastname"],
$data["address1"],
$data["address2"],
$data["address3"],
$data["phone"],
$data["cellphone"],
$data["zipcode"],
$data["country"],
$data["email"],
$data["password"],
$request->getSession()->getLang()
);
try {
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECUSTOMER, $event);
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent);
$customer->createOrUpdate(
$data["title"],
$data["firstname"],
$data["lastname"],
$data["address1"],
$data["address2"],
$data["address3"],
$data["phone"],
$data["cellphone"],
$data["zipcode"],
$data["country"],
$data["email"],
$data["password"],
$request->getSession()->getLang()
);
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent);
// Connect the newly created user,and redirect to the success URL
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
}
catch (PropelException $e) {
Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage()));
// Connect the newly created user,and redirect to the success URL
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
$message = "Failed to create your account, please try again.";
}
catch(FormValidationException $e) {
} catch (PropelException $e) {
Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage()));
$message = "Failed to create your account, please try again.";
}
}
else {
$message = "Missing or invalid data";
}
}
else {
$message = "Wrong form method !";
$message = $e->getMessage();
}
// The form has an error
$customerCreationForm->setError(true);
$customerCreationForm->setErrorMessage($message);
// Store the form in the parser context
$event->setErrorForm($customerCreationForm);
// Stop event propagation
$event->stopPropagation();
}
// The form has errors, propagate it.
$this->propagateFormError($customerCreationForm, $message, $event);
}
public function modify(ActionEvent $event)
{
$request = $event->getRequest();
$request = $event->getRequest();
$customerModification = new CustomerModification($request);
try {
$customerModification = new CustomerModification($request);
$form = $customerModification->getForm();
$form = $this->validateForm($customerModification, "POST");
if ($request->isMethod("post")) {
$data = $form->getData();
$form->bind($request);
$customer = CustomerQuery::create()->findPk(1);
if ($form->isValid()) {
$data = $form->getData();
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$customer = CustomerQuery::create()->findPk(1);
try {
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$data = $form->getData();
$data = $form->getData();
$customer->createOrUpdate(
$customer->createOrUpdate(
$data["title"],
$data["firstname"],
$data["lastname"],
@@ -152,37 +134,29 @@ class Customer extends BaseAction implements EventSubscriberInterface
$data["cellphone"],
$data["zipcode"],
$data["country"]
);
);
$customerEvent->customer = $customer;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
$customerEvent->customer = $customer;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
// Update the logged-in user, and redirect to the success URL (exits)
// We don-t send the login event, as the customer si already logged.
$this->processSuccessfulLogin($event, $customer, $customerModification);
}
catch(PropelException $e) {
Tlog::getInstance()->error(sprintf('error during modifying customer on action/modifyCustomer with message "%s"', $e->getMessage()));
$message = "Failed to change your account, please try again.";
}
}
else {
$message = "Missing or invalid data";
}
// Update the logged-in user, and redirect to the success URL (exits)
// We don-t send the login event, as the customer si already logged.
$this->processSuccessfulLogin($event, $customer, $customerModification);
}
else {
$message = "Wrong form method !";
catch(PropelException $e) {
Tlog::getInstance()->error(sprintf('error during modifying customer on action/modifyCustomer with message "%s"', $e->getMessage()));
$message = "Failed to change your account, please try again.";
}
catch(FormValidationException $e) {
$message = $e->getMessage();
}
// The form has an error
$customerModification->setError(true);
$customerModification->setErrorMessage($message);
// Dispatch the errored form
$event->setErrorForm($customerModification);
}
// The form has errors, propagate it.
$this->propagateFormError($customerModification, $message, $event);
}
/**
@@ -192,9 +166,9 @@ class Customer extends BaseAction implements EventSubscriberInterface
*/
public function logout(ActionEvent $event)
{
$event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event);
$event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event);
$this->getSecurityContext()->clear();
$this->getSecurityContext()->clear();
}
/**
@@ -207,43 +181,43 @@ class Customer extends BaseAction implements EventSubscriberInterface
*/
public function login(ActionEvent $event)
{
$request = $event->getRequest();
$request = $event->getRequest();
$customerLoginForm = new CustomerLogin($request);
$customerLoginForm = new CustomerLogin($request);
$authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm);
$authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm);
try {
$user = $authenticator->getAuthentifiedUser();
try {
$user = $authenticator->getAuthentifiedUser();
$this->processSuccessfulLogin($event, $user, $customerLoginForm);
}
catch (ValidatorException $ex) {
$message = "Missing or invalid information. Please check your input.";
}
$this->processSuccessfulLogin($event, $user, $customerLoginForm);
}
catch (ValidatorException $ex) {
$message = "Missing or invalid information. Please check your input.";
}
catch (UsernameNotFoundException $ex) {
$message = "This email address was not found.";
}
catch (AuthenticationException $ex) {
$message = "Login failed. Please check your username and password.";
}
catch (\Exception $ex) {
$message = sprintf("Unable to process your request. Please try again (%s in %s).", $ex->getMessage(), $ex->getFile());
}
$message = "This email address was not found.";
}
catch (AuthenticationException $ex) {
$message = "Login failed. Please check your username and password.";
}
catch (\Exception $ex) {
$message = sprintf("Unable to process your request. Please try again (%s in %s).", $ex->getMessage(), $ex->getFile());
}
// The for has an error
$customerLoginForm->setError(true);
$customerLoginForm->setErrorMessage($message);
// The for has an error
$customerLoginForm->setError(true);
$customerLoginForm->setErrorMessage($message);
// Dispatch the errored form
$event->setErrorForm($customerLoginForm);
// Dispatch the errored form
$event->setErrorForm($customerLoginForm);
// A this point, the same view is displayed again.
// A this point, the same view is displayed again.
}
public function changePassword(ActionEvent $event)
{
// TODO
// TODO
}
/**
@@ -284,13 +258,13 @@ class Customer extends BaseAction implements EventSubscriberInterface
*/
protected function processSuccessfulLogin(ActionEvent $event, CustomerModel $user, BaseForm $form, $sendLoginEvent = false)
{
// Success -> store user in security context
$this->getSecurityContext()->setUser($user);
// Success -> store user in security context
$this->getSecurityContext()->setUser($user);
if ($sendLoginEvent) $event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGIN, $event);
if ($sendLoginEvent) $event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGIN, $event);
// Redirect to the success URL
$this->redirect($form->getSuccessUrl());
// Redirect to the success URL
$this->redirect($form->getSuccessUrl());
}
/**
@@ -299,8 +273,8 @@ class Customer extends BaseAction implements EventSubscriberInterface
* @return SecurityContext the security context
*/
protected function getSecurityContext() {
$this->securityContext->setContext(SecurityContext::CONTEXT_FRONT_OFFICE);
$this->securityContext->setContext(SecurityContext::CONTEXT_FRONT_OFFICE);
return $this->securityContext;
return $this->securityContext;
}
}
}

View File

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

View File

@@ -154,7 +154,7 @@ class BaseAdminController extends ContainerAware
$actionEvent = $eventFactory->createActionEvent();
$this->getDispatcher()->dispatch("action.$action", $actionEvent);
$this->dispatch("action.$action", $actionEvent);
if ($actionEvent->hasErrorForm()) {
$this->getParserContext()->setErrorForm($actionEvent->getErrorForm());
@@ -163,6 +163,17 @@ class BaseAdminController extends ContainerAware
return $actionEvent;
}
/**
* Dispatch a Thelia event to modules
*
* @param string $eventName a TheliaEvent name, as defined in TheliaEvents class
* @param ActionEvent $event the event
*/
protected function dispatch($eventName, ActionEvent $event = null) {
$this->getDispatcher()->dispatch($eventName, $event);
}
/**
* Return the event dispatcher,
*

View File

@@ -33,14 +33,11 @@
<form name="thelia.customer.login" class="Thelia\Form\CustomerLogin"/>
<form name="thelia.admin.login" class="Thelia\Form\AdminLogin"/>
<<<<<<< HEAD
<form name="thelia.admin.category.creation" class="Thelia\Form\CategoryCreationForm"/>
<form name="thelia.admin.category.deletion" class="Thelia\Form\CategoryDeletionForm"/>
=======
<form name="thelia.cart.add" class="Thelia\Form\CartAdd"/>
>>>>>>> cart
</forms>

View File

@@ -44,6 +44,8 @@ abstract class BaseForm {
*/
protected $form;
protected $request;
private $view = null;
/**
@@ -60,6 +62,8 @@ abstract class BaseForm {
public function __construct(Request $request, $type= "form", $data = array(), $options = array())
{
$this->request = $request;
$validator = Validation::createValidator();
if(!isset($options["attr"]["name"])) {
@@ -94,6 +98,10 @@ abstract class BaseForm {
$this->form = $this->formBuilder->getForm();
}
public function getRequest() {
return $this->request;
}
protected function cleanOptions($options)
{
unset($options["csrf_protection"]);