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; namespace Thelia\Action;
use Symfony\Component\HttpFoundation\RedirectResponse; 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 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); $response = new RedirectResponse($url, $status);

View File

@@ -33,71 +33,51 @@ use Thelia\Tools\Redirect;
use Thelia\Model\CategoryQuery; use Thelia\Model\CategoryQuery;
use Thelia\Model\AdminLog; use Thelia\Model\AdminLog;
use Thelia\Form\CategoryDeletionForm; use Thelia\Form\CategoryDeletionForm;
use Thelia\Action\Exception\FormValidationException;
class Category implements EventSubscriberInterface class Category extends BaseAction implements EventSubscriberInterface
{ {
public function create(ActionEvent $event) 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 { $categoryEvent = new CategoryEvent($category);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event);
$category->create( $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $categoryEvent);
$data["title"],
$data["parent"],
$data["locale"]
);
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 $message = "Failed to create this category, please try again.";
$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 !";
} }
// The form has an error // The form has errors, propagate it.
$categoryCreationForm->setError(true); $this->propagateFormError($categoryCreationForm, $message, $event);
$categoryCreationForm->setErrorMessage($message);
// Store the form in the parser context
$event->setErrorForm($categoryCreationForm);
// Stop event propagation
$event->stopPropagation();
} }
public function modify(ActionEvent $event) public function modify(ActionEvent $event)
@@ -176,63 +156,45 @@ class Category implements EventSubscriberInterface
{ {
$request = $event->getRequest(); $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->delete();
$category = CategoryQuery::create()->findPk($data['id']);
$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 $message = "Failed to change your account, please try again.";
$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";
}
} }
else { catch(FormValidationException $e) {
$message = "Wrong form method !";
$message = $e->getMessage();
} }
// The form has an error $this->propagateFormError($categoryDeletionForm, $message, $event);
$categoryDeletionForm->setError(true);
$categoryDeletionForm->setErrorMessage($message);
// Store the form in the parser context
$event->setErrorForm($categoryDeletionForm);
// Stop event propagation
$event->stopPropagation();
} }
/** /**

View File

@@ -41,107 +41,89 @@ use Symfony\Component\Validator\Exception\ValidatorException;
use Thelia\Core\Security\Exception\AuthenticationException; use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\Exception\UsernameNotFoundException; use Thelia\Core\Security\Exception\UsernameNotFoundException;
use Propel\Runtime\Exception\PropelException; use Propel\Runtime\Exception\PropelException;
use Thelia\Action\Exception\FormValidationException;
class Customer extends BaseAction implements EventSubscriberInterface class Customer extends BaseAction implements EventSubscriberInterface
{ {
/** /**
* @var Thelia\Core\Security\SecurityContext * @var Thelia\Core\Security\SecurityContext
*/ */
protected $securityContext; protected $securityContext;
public function __construct(SecurityContext $securityContext) { public function __construct(SecurityContext $securityContext) {
$this->securityContext = $securityContext; $this->securityContext = $securityContext;
} }
public function create(ActionEvent $event) 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()) { $customer->createOrUpdate(
$data = $form->getData(); $data["title"],
$customer = new CustomerModel(); $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 { $customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECUSTOMER, $event); $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECUSTOMER, $customerEvent);
$customer->createOrUpdate( // Connect the newly created user,and redirect to the success URL
$data["title"], $this->processSuccessfulLogin($event, $customer, $customerCreationForm, true);
$data["firstname"], }
$data["lastname"], catch (PropelException $e) {
$data["address1"], Tlog::getInstance()->error(sprintf('error during creating customer on action/createCustomer with message "%s"', $e->getMessage()));
$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 $message = "Failed to create your account, please try again.";
$this->processSuccessfulLogin($event, $customer, $customerCreationForm, true); }
catch(FormValidationException $e) {
} catch (PropelException $e) { $message = $e->getMessage();
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 !";
} }
// The form has an error // The form has errors, propagate it.
$customerCreationForm->setError(true); $this->propagateFormError($customerCreationForm, $message, $event);
$customerCreationForm->setErrorMessage($message); }
// Store the form in the parser context
$event->setErrorForm($customerCreationForm);
// Stop event propagation
$event->stopPropagation();
}
public function modify(ActionEvent $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()) { $customerEvent = new CustomerEvent($customer);
$data = $form->getData(); $event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$customer = CustomerQuery::create()->findPk(1); $data = $form->getData();
try {
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$data = $form->getData(); $customer->createOrUpdate(
$customer->createOrUpdate(
$data["title"], $data["title"],
$data["firstname"], $data["firstname"],
$data["lastname"], $data["lastname"],
@@ -152,37 +134,29 @@ class Customer extends BaseAction implements EventSubscriberInterface
$data["cellphone"], $data["cellphone"],
$data["zipcode"], $data["zipcode"],
$data["country"] $data["country"]
); );
$customerEvent->customer = $customer; $customerEvent->customer = $customer;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent); $event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
// Update the logged-in user, and redirect to the success URL (exits) // 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. // We don-t send the login event, as the customer si already logged.
$this->processSuccessfulLogin($event, $customer, $customerModification); $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";
}
} }
else { catch(PropelException $e) {
$message = "Wrong form method !";
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 // The form has errors, propagate it.
$customerModification->setError(true); $this->propagateFormError($customerModification, $message, $event);
$customerModification->setErrorMessage($message); }
// Dispatch the errored form
$event->setErrorForm($customerModification);
}
/** /**
@@ -192,9 +166,9 @@ class Customer extends BaseAction implements EventSubscriberInterface
*/ */
public function logout(ActionEvent $event) 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) 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 { try {
$user = $authenticator->getAuthentifiedUser(); $user = $authenticator->getAuthentifiedUser();
$this->processSuccessfulLogin($event, $user, $customerLoginForm); $this->processSuccessfulLogin($event, $user, $customerLoginForm);
} }
catch (ValidatorException $ex) { catch (ValidatorException $ex) {
$message = "Missing or invalid information. Please check your input."; $message = "Missing or invalid information. Please check your input.";
} }
catch (UsernameNotFoundException $ex) { catch (UsernameNotFoundException $ex) {
$message = "This email address was not found."; $message = "This email address was not found.";
} }
catch (AuthenticationException $ex) { catch (AuthenticationException $ex) {
$message = "Login failed. Please check your username and password."; $message = "Login failed. Please check your username and password.";
} }
catch (\Exception $ex) { catch (\Exception $ex) {
$message = sprintf("Unable to process your request. Please try again (%s in %s).", $ex->getMessage(), $ex->getFile()); $message = sprintf("Unable to process your request. Please try again (%s in %s).", $ex->getMessage(), $ex->getFile());
} }
// The for has an error // The for has an error
$customerLoginForm->setError(true); $customerLoginForm->setError(true);
$customerLoginForm->setErrorMessage($message); $customerLoginForm->setErrorMessage($message);
// Dispatch the errored form // Dispatch the errored form
$event->setErrorForm($customerLoginForm); $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) 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) protected function processSuccessfulLogin(ActionEvent $event, CustomerModel $user, BaseForm $form, $sendLoginEvent = false)
{ {
// Success -> store user in security context // Success -> store user in security context
$this->getSecurityContext()->setUser($user); $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 // Redirect to the success URL
$this->redirect($form->getSuccessUrl()); $this->redirect($form->getSuccessUrl());
} }
/** /**
@@ -299,8 +273,8 @@ class Customer extends BaseAction implements EventSubscriberInterface
* @return SecurityContext the security context * @return SecurityContext the security context
*/ */
protected function getSecurityContext() { 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(); $actionEvent = $eventFactory->createActionEvent();
$this->getDispatcher()->dispatch("action.$action", $actionEvent); $this->dispatch("action.$action", $actionEvent);
if ($actionEvent->hasErrorForm()) { if ($actionEvent->hasErrorForm()) {
$this->getParserContext()->setErrorForm($actionEvent->getErrorForm()); $this->getParserContext()->setErrorForm($actionEvent->getErrorForm());
@@ -163,6 +163,17 @@ class BaseAdminController extends ContainerAware
return $actionEvent; 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, * Return the event dispatcher,
* *

View File

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

View File

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