Completed the backoffice variable management

This commit is contained in:
franck
2013-09-02 00:17:27 +02:00
parent 6d5d0f6606
commit 5670855dd6
51 changed files with 1144 additions and 288 deletions

View File

@@ -49,34 +49,4 @@ class BaseAction
{
return $this->container->get('event_dispatcher');
}
/**
* Check current user authorisations.
*
* @param mixed $roles a single role or an array of roles.
* @param mixed $permissions a single permission or an array of permissions.
*
* @throws AuthenticationException if permissions are not granted to the current user.
*/
protected function checkAuth($roles, $permissions) {
if (! $this->getSecurityContext()->isGranted(
is_array($roles) ? $roles : array($roles),
is_array($permissions) ? $permissions : array($permissions)) ) {
Tlog::getInstance()->addAlert("Authorization roles:", $roles, " permissions:", $permissions, " refused.");
throw new AuthorizationException("Sorry, you're not allowed to perform this action");
}
}
/**
* Return the security context
*
* @return Thelia\Core\Security\SecurityContext
*/
protected function getSecurityContext()
{
return $this->container->get('thelia.securityContext');
}
}

View File

@@ -42,8 +42,6 @@ class Category extends BaseAction implements EventSubscriberInterface
{
public function create(CategoryCreateEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.create");
$category = new CategoryModel();
$category
@@ -57,9 +55,6 @@ class Category extends BaseAction implements EventSubscriberInterface
public function modify(CategoryChangeEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.change");
// TODO !!
}
/**
@@ -69,8 +64,6 @@ class Category extends BaseAction implements EventSubscriberInterface
*/
public function delete(CategoryDeleteEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.delete");
$category = CategoryQuery::create()->findPk($event->getCategoryId());
if ($category !== null) {
@@ -86,8 +79,6 @@ class Category extends BaseAction implements EventSubscriberInterface
*/
public function toggleVisibility(CategoryToggleVisibilityEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
$category = CategoryQuery::create()->findPk($event->getCategoryId());
if ($category !== null) {
@@ -107,8 +98,6 @@ class Category extends BaseAction implements EventSubscriberInterface
*/
public function changePosition(CategoryChangePositionEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
if ($event->getMode() == CategoryChangePositionEvent::POSITION_ABSOLUTE)
return $this->changeAbsolutePosition($event);
else
@@ -177,8 +166,6 @@ class Category extends BaseAction implements EventSubscriberInterface
*/
protected function changeAbsolutePosition(CategoryChangePositionEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
$category = CategoryQuery::create()->findPk($event->getCategoryId());
if ($category !== null) {

View File

@@ -44,26 +44,20 @@ class Config extends BaseAction implements EventSubscriberInterface
*/
public function create(ConfigCreateEvent $event)
{
$this->checkAuth("ADMIN", "admin.configuration.variables.create");
$config = new ConfigModel();
$config
->setDispatcher($this->getDispatcher())
->setName($event->getName())
->setName($event->getEventName())
->setValue($event->getValue())
->setHidden($evetn->getHidden())
->setSecured($event->getSecured())
->setLocale($event->getLocale())
->setTitle($event->getTitle())
->setDescription($event->getDescription())
->setChapo($event->getChapo())
->setPostscriptum($event->getPostscriptum())
->save()
;
$event->setConfig($config);
}
/**
@@ -73,17 +67,20 @@ class Config extends BaseAction implements EventSubscriberInterface
*/
public function setValue(ConfigChangeEvent $event)
{
$this->checkAuth("ADMIN", "admin.configuration.variables.change");
$search = ConfigQuery::create();
if (null !== $config = $search->findOneById($event->getConfigId())) {
if (null !== $config = $search->findOneById($event->getConfigId())
&&
$event->getValue() != $config->getValue()) {
$config
->setDispatcher($this->getDispatcher())
->setValue($event->getValue())
->save()
;
$event->setConfig($config);
}
}
@@ -94,8 +91,6 @@ class Config extends BaseAction implements EventSubscriberInterface
*/
public function modify(ConfigChangeEvent $event)
{
$this->checkAuth("ADMIN", "admin.configuration.variables.change");
$search = ConfigQuery::create();
if (null !== $config = ConfigQuery::create()->findOneById($event->getConfigId())) {
@@ -103,9 +98,9 @@ class Config extends BaseAction implements EventSubscriberInterface
$config
->setDispatcher($this->getDispatcher())
->setName($event->getName())
->setName($event->getEventName())
->setValue($event->getValue())
->setHidden($evetn->getHidden())
->setHidden($event->getHidden())
->setSecured($event->getSecured())
->setLocale($event->getLocale())
@@ -115,6 +110,8 @@ class Config extends BaseAction implements EventSubscriberInterface
->setPostscriptum($event->getPostscriptum())
->save();
$event->setConfig($config);
}
}
@@ -125,22 +122,22 @@ class Config extends BaseAction implements EventSubscriberInterface
*/
public function delete(ConfigDeleteEvent $event)
{
$this->checkAuth("ADMIN", "admin.configuration.variables.delete");
if (null !== ($config = ConfigQuery::create()->findOneById($event->getConfigId()))) {
if (! $config->getSecured()) {
$config->setDispatcher($this->getDispatcher());
$config->delete();
$config
->setDispatcher($this->getDispatcher())
->delete()
;
$event->setConfig($config);
}
}
}
/**
* Returns an array of event names this subscriber listens to.
*
* @return array The event names to listen to
*
* @api
* {@inheritDoc}
*/
public static function getSubscribedEvents()
{

View File

@@ -109,6 +109,16 @@ class Customer extends BaseAction implements EventSubscriberInterface
// TODO
}
/**
* Return the security context
*
* @return Thelia\Core\Security\SecurityContext
*/
protected function getSecurityContext()
{
return $this->container->get('thelia.securityContext');
}
/**
* Returns an array of event names this subscriber wants to listen to.
*

View File

@@ -46,6 +46,9 @@
<form name="thelia.admin.category.deletion" class="Thelia\Form\CategoryDeletionForm"/>
<form name="thelia.cart.add" class="Thelia\Form\CartAdd"/>
<form name="thelia.admin.variable.creation" class="Thelia\Form\VariableCreationForm"/>
<form name="thelia.admin.variable.modification" class="Thelia\Form\VariableModificationForm"/>
</forms>

View File

@@ -41,6 +41,10 @@
<default key="_controller">Thelia\Controller\Admin\VariablesController::defaultAction</default>
</route>
<route id="admin.configuration.variables.change-values" path="/admin/configuration/variables/change-values">
<default key="_controller">Thelia\Controller\Admin\VariablesController::changeValuesAction</default>
</route>
<route id="admin.configuration.variables.create" path="/admin/configuration/variables/create">
<default key="_controller">Thelia\Controller\Admin\VariablesController::createAction</default>
</route>
@@ -49,6 +53,10 @@
<default key="_controller">Thelia\Controller\Admin\VariablesController::changeAction</default>
</route>
<route id="admin.configuration.variables.save-change" path="/admin/configuration/variables/save-change">
<default key="_controller">Thelia\Controller\Admin\VariablesController::saveChangeAction</default>
</route>
<route id="admin.configuration.variables.delete" path="/admin/configuration/variables/delete">
<default key="_controller">Thelia\Controller\Admin\VariablesController::deleteAction</default>
</route>

View File

@@ -29,10 +29,4 @@ class AdminController extends BaseAdminController
{
return $this->render("home");
}
public function processAction()
{
echo "not yet coded !";
exit();
}
}

View File

@@ -32,6 +32,8 @@ use Thelia\Tools\URL;
use Thelia\Tools\Redirect;
use Thelia\Core\Security\SecurityContext;
use Thelia\Model\AdminLog;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
class BaseAdminController extends BaseController
{
@@ -46,6 +48,12 @@ class BaseAdminController extends BaseController
AdminLog::append($message, $this->getRequest(), $this->getSecurityContext()->getAdminUser());
}
/**
* This method process the rendering of view called from an admin page
*
* @param unknown $template
* @return Response the reponse which contains the rendered view
*/
public function processTemplateAction($template)
{
try {
@@ -89,19 +97,31 @@ class BaseAdminController extends BaseController
/**
* Check current admin user authorisations. An ADMIN role is assumed.
*
* @param unknown $permissions a single permission or an array of permissions.
* @param mixed $permissions a single permission or an array of permissions.
*
* @return mixed null if authorization is granted, or a Response object which contains the error page otherwise
*
* @throws AuthenticationException if permissions are not granted ti the current user.
*/
protected function checkAuth($permissions)
{
if (! $this->getSecurityContext()->isGranted(array("ADMIN"), is_array($permissions) ? $permissions : array($permissions))) {
throw new AuthorizationException("Sorry, you're not allowed to perform this action");
}
$permArr = is_array($permissions) ? $permissions : array($permissions);
if ($this->getSecurityContext()->isGranted(array("ADMIN"), $permArr)) {
// Okay !
return null;
}
// Log the problem
$this->adminLogAppend("User is not granted for permissions %s", implode(", ", $permArr));
// Generate the proper response
$response = new Response();
return $response->setContent($this->errorPage("Sorry, you're not allowed to perform this action"));
}
/**
* @return a ParserInterfac instance parser
* @return a ParserInterface instance parser
*/
protected function getParser()
{
@@ -130,6 +150,23 @@ class BaseAdminController extends BaseController
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
/**
* Get the current edition lang ID, checking if a change was requested in the current request
*/
protected function getCurrentEditionLangId() {
return $this->getRequest()->get(
'edition_language',
$this->getSession()->getAdminEditionLangId()
);
}
/**
* A simple helper to get the current edition locale, from the session edition language ID
*/
protected function getCurrentEditionLocale() {
return LangQuery::create()->findOneById($this->getCurrentEditionLangId())->getLocale();
}
/**
* Render the given template, and returns the result as an Http Response.
*
@@ -153,26 +190,40 @@ class BaseAdminController extends BaseController
*/
protected function renderRaw($templateName, $args = array())
{
// Add the template standard extension
$templateName .= '.html';
$session = $this->getSession();
// Find the current edit language ID
$edition_language = $this->getCurrentEditionLangId();
// Prepare common template variables
$args = array_merge($args, array(
'locale' => $session->getLocale(),
'lang' => $session->getLang()
'locale' => $session->getLocale(),
'lang' => $session->getLang(),
'edition_language' => $edition_language,
'current_url' => htmlspecialchars($this->getRequest()->getUri())
));
// Update the current edition language in session
$this->getSession()->setAdminEditionLangId($edition_language);
// Render the template.
try {
$data = $this->getParser()->render($templateName, $args);
return $data;
} catch (AuthenticationException $ex) {
}
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.
Redirect::exec(URL::absoluteUrl($ex->getLoginTemplate()));
}
catch (AuthorizationException $ex) {
// User is not allowed to perform the required action. Return the error page instead of the requested page.
return $this->errorPage("Sorry, you are not allowed to perform this action.");
}
}
}

View File

@@ -66,7 +66,7 @@ class CategoryController extends BaseAdminController
}
catch (FormValidationException $e) {
$categoryCreationForm->setErrorMessage($e->getMessage());
$this->getParserContext()->setErrorForm($categoryCreationForm);
$this->getParserContext()->addForm($categoryCreationForm);
}
catch (Exception $e) {
Tlog::getInstance()->error(sprintf("Failed to create category: %s", $e->getMessage()));
@@ -79,7 +79,7 @@ class CategoryController extends BaseAdminController
protected function editCategory($args)
{
$this->checkAuth("ADMIN", "admin.category.edit");
if (null !== $response = $this->checkAuth("admin.category.edit")) return $response;
return $this->render('edit_category', $args);
}
@@ -107,7 +107,7 @@ class CategoryController extends BaseAdminController
}
catch (FormValidationException $e) {
$categoryDeletionForm->setErrorMessage($e->getMessage());
$this->getParserContext()->setErrorForm($categoryDeletionForm);
$this->getParserContext()->addForm($categoryDeletionForm);
}
catch (Exception $e) {
Tlog::getInstance()->error(sprintf("Failed to delete category: %s", $e->getMessage()));
@@ -120,7 +120,7 @@ class CategoryController extends BaseAdminController
protected function browseCategory($args)
{
$this->checkAuth("AMIN", "admin.catalog.view");
if (null !== $response = $this->checkAuth("admin.catalog.view")) return $response;
return $this->render('categories', $args);
}
@@ -203,9 +203,6 @@ class CategoryController extends BaseAdminController
'current_category_id' => $id,
'category_order' => $category_order,
'edition_language' => $edition_language,
'date_format' => Lang::getDefaultLanguage()->getDateFormat(),
'time_format' => Lang::getDefaultLanguage()->getTimeFormat(),
'datetime_format' => Lang::getDefaultLanguage()->getDateTimeFormat(),
);
// Store the current sort order in session

View File

@@ -96,7 +96,7 @@ class SessionController extends BaseAdminController
$adminLoginForm->setErrorMessage($message);
// Store the form name in session (see Form Smarty plugin to find usage of this parameter)
$this->getParserContext()->setErrorForm($adminLoginForm);
$this->getParserContext()->addForm($adminLoginForm);
// Display the login form again
return $this->render("login");

View File

@@ -26,23 +26,272 @@ namespace Thelia\Controller\Admin;
use Thelia\Core\Event\ConfigDeleteEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Tools\URL;
use Thelia\Core\Event\ConfigChangeEvent;
use Thelia\Form\VariableCreationForm;
use Thelia\Core\Event\ConfigCreateEvent;
use Thelia\Log\Tlog;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Core\Security\Exception\AuthorizationException;
use Thelia\Form\VariableModificationForm;
use Thelia\Model\ConfigQuery;
/**
* Manages Thelmia system variables, aka Config objects.
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class VariablesController extends BaseAdminController
{
/**
* The default action is displaying the variables list.
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function defaultAction() {
if (null !== $response = $this->checkAuth("admin.configuration.variables.view")) return $response;
return $this->render('variables');
}
/**
* Create a new config object
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function createAction() {
// Check current user authorization
if (null !== $response = $this->checkAuth("admin.configuration.variables.create")) return $response;
$message = false;
// Create the Creation Form
$creationForm = new VariableCreationForm($this->getRequest());
try {
// Validate the form, create the ConfigCreation event and dispatch it.
$form = $this->validateForm($creationForm, "POST");
$data = $form->getData();
$createEvent = new ConfigCreateEvent();
$createEvent
->setEventName($data['name'])
->setValue($data['value'])
->setLocale($data["locale"])
->setTitle($data['title'])
;
$this->dispatch(TheliaEvents::CONFIG_CREATE, $createEvent);
$createdObject = $createEvent->getConfig();
// Log config creation
$this->adminLogAppend(sprintf("Variable %s (ID %s) created", $createdObject->getName(), $createdObject->getId()));
// Substitute _ID_ in the URL with the ID of the created object
$successUrl = str_replace('_ID_', $createdObject->getId(), $creationForm->getSuccessUrl());
// Redirect to the success URL
$this->redirect($successUrl);
}
catch (FormValidationException $ex) {
// Form cannot be validated
$message = sprintf("Please check your input: %s", $ex->getMessage());
}
catch (\Exception $ex) {
// Any other error
$message = sprintf("Sorry, an error occured: %s", $ex->getMessage());
}
if ($message !== false) {
// An error has been detected: log it
Tlog::getInstance()->error(sprintf("Error during variable creation process : %s. Exception was %s", $message, $ex->getMessage()));
// Mark the form as errored
$creationForm->setErrorMessage($message);
// Pass it to the parser, along with the error message
$this->getParserContext()
->addForm($creationForm)
->setGeneralError($message)
;
}
// At this point, the form has error, and should be redisplayed.
return $this->render('variables');
}
/**
* Load a config object for modification, and display the edit template.
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function changeAction() {
// Check current user authorization
if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response;
// Load the config object
$config = ConfigQuery::create()
->joinWithI18n($this->getCurrentEditionLocale())
->findOneById($this->getRequest()->get('variable_id'));
if ($config != null) {
// Prepare the data that will hydrate the form
$data = array(
'id' => $config->getId(),
'name' => $config->getName(),
'value' => $config->getValue(),
'hidden' => $config->getHidden(),
'secured' => $config->getSecured(),
'locale' => $config->getLocale(),
'title' => $config->getTitle(),
'chapo' => $config->getChapo(),
'description' => $config->getDescription(),
'postscriptum' => $config->getPostscriptum()
);
// Setup the object form
$changeForm = new VariableModificationForm($this->getRequest(), "form", $data);
// Pass it to the parser
$this->getParserContext()->addForm($changeForm);
}
// Render the edition template.
return $this->render('variable-edit', array('variable_id' => $this->getRequest()->get('variable_id')));
}
/**
* Save changes on a modified config object, and either go back to the variable list, or stay on the edition page.
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function saveChangeAction() {
// Check current user authorization
if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response;
$message = false;
// Create the form from the request
$changeForm = new VariableModificationForm($this->getRequest());
// Get the variable ID
$variable_id = $this->getRequest()->get('variable_id');
try {
// Check the form against constraints violations
$form = $this->validateForm($changeForm, "POST");
// Get the form field values
$data = $form->getData();
$changeEvent = new ConfigChangeEvent($data['id']);
// Create and dispatch the change event
$changeEvent
->setEventName($data['name'])
->setValue($data['value'])
->setHidden($data['hidden'])
->setSecured($data['secured'])
->setLocale($data["locale"])
->setTitle($data['title'])
->setChapo($data['chapo'])
->setDescription($data['description'])
->setPostscriptum($data['postscriptum'])
;
$this->dispatch(TheliaEvents::CONFIG_MODIFY, $changeEvent);
// Log config modification
$changedObject = $changeEvent->getConfig();
$this->adminLogAppend(sprintf("Variable %s (ID %s) modified", $changedObject->getName(), $changedObject->getId()));
// If we have to stay on the same page, do not redirect to the succesUrl,
// just redirect to the edit page again.
if ($this->getRequest()->get('save_mode') == 'stay') {
$this->redirect(URL::absoluteUrl(
"admin/configuration/variables/change",
array('variable_id' => $variable_id)
));
}
// Redirect to the success URL
$this->redirect($changeForm->getSuccessUrl());
}
catch (FormValidationException $ex) {
// Invalid data entered
$message = sprintf("Please check your input: %s", $ex->getMessage());
}
catch (\Exception $ex) {
// Any other error
$message = sprintf("Sorry, an error occured: %s", $ex->getMessage());
}
if ($message !== false) {
// Log error message
Tlog::getInstance()->error(sprintf("Error during variable creation process : %s. Exception was %s", $message, $ex->getMessage()));
// Mark the form as errored
$changeForm->setErrorMessage($message);
// Pas the form and the error to the parser
$this->getParserContext()
->addForm($changeForm)
->setGeneralError($message)
;
}
// At this point, the form has errors, and should be redisplayed.
return $this->render('variable-edit', array('variable_id' => $variable_id));
}
/**
* Change values modified directly from the variable list
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function changeValuesAction() {
// Check current user authorization
if (null !== $response = $this->checkAuth("admin.configuration.variables.change")) return $response;
$variables = $this->getRequest()->get('variable', array());
// Process all changed variables
foreach($variables as $id => $value) {
$event = new ConfigChangeEvent($id);
$event->setValue($value);
$this->dispatch(TheliaEvents::CONFIG_SETVALUE, $event);
}
$this->redirect(URL::adminViewUrl('variables'));
}
/**
* Delete a config object
*
* @return Symfony\Component\HttpFoundation\Response the response
*/
public function deleteAction() {
// Check current user authorization
if (null !== $response = $this->checkAuth("admin.configuration.variables.delete")) return $response;
// Get the config id, and dispatch the delet request
$event = new ConfigDeleteEvent($this->getRequest()->get('id'));
$this->dispatch(TheliaEvents::CONFIG_DELETE, $event);
$this->redirect(URL::adminViewUrl('variables'));
}
public function updateAction() {
}
}
}

View File

@@ -63,7 +63,7 @@ class CartController extends BaseFrontController
if ($message) {
$cartAdd->setErrorMessage($message);
$this->getParserContext()->setErrorForm($cartAdd);
$this->getParserContext()->addForm($cartAdd);
}
}

View File

@@ -75,10 +75,10 @@ class CustomerController extends BaseFrontController
if ($message !== false) {
Tlog::getInstance()->error(sprintf("Error during customer creation process : %s. Exception was %s", $message, $e->getMessage()));
$customerLoginForm->setErrorMessage($message);
$customerCreation->setErrorMessage($message);
$this->getParserContext()
->setErrorForm($customerLoginForm)
->addForm($customerCreation)
->setGeneralError($message)
;
}
@@ -123,10 +123,10 @@ class CustomerController extends BaseFrontController
if ($message !== false) {
Tlog::getInstance()->error(sprintf("Error during customer modification process : %s. Exception was %s", $message, $e->getMessage()));
$customerLoginForm->setErrorMessage($message);
$customerModification->setErrorMessage($message);
$this->getParserContext()
->setErrorForm($customerLoginForm)
->addForm($customerModification)
->setGeneralError($message)
;
}
@@ -183,7 +183,7 @@ class CustomerController extends BaseFrontController
$customerLoginForm->setErrorMessage($message);
$this->getParserContext()->setErrorForm($customerLoginForm);
$this->getParserContext()->addForm($customerLoginForm);
}
}
}

View File

@@ -29,6 +29,12 @@ class ConfigChangeEvent extends ConfigCreateEvent
{
protected $config_id;
protected $hidden;
protected $secured;
protected $description;
protected $chapo;
protected $postscriptum;
public function __construct($config_id)
{
$this->setConfigId($config_id);
@@ -45,4 +51,64 @@ class ConfigChangeEvent extends ConfigCreateEvent
return $this;
}
}
public function getHidden()
{
return $this->hidden;
}
public function setHidden($hidden)
{
$this->hidden = $hidden;
return $this;
}
public function getSecured()
{
return $this->secured;
}
public function setSecured($secured)
{
$this->secured = $secured;
return $this;
}
public function getDescription()
{
return $this->description;
}
public function setDescription($description)
{
$this->description = $description;
return $this;
}
public function getChapo()
{
return $this->chapo;
}
public function setChapo($chapo)
{
$this->chapo = $chapo;
return $this;
}
public function getPostscriptum()
{
return $this->postscriptum;
}
public function setPostscriptum($postscriptum)
{
$this->postscriptum = $postscriptum;
return $this;
}
}

View File

@@ -24,26 +24,22 @@
namespace Thelia\Core\Event;
use Thelia\Model\Config;
class ConfigCreateEvent extends ActionEvent
class ConfigCreateEvent extends ConfigEvent
{
protected $name;
protected $event_name;
protected $value;
protected $hidden;
protected $secured;
protected $locale;
protected $title;
protected $description;
protected $chapo;
protected $postscriptum;
public function getName()
// Use event_name to prevent conflict with Event::name property.
public function getEventName()
{
return $this->name;
return $this->event_name;
}
public function setName($name)
public function setEventName($event_name)
{
$this->name = $name;
$this->event_name = $event_name;
return $this;
}
@@ -60,30 +56,6 @@ class ConfigCreateEvent extends ActionEvent
return $this;
}
public function getHidden()
{
return $this->hidden;
}
public function setHidden($hidden)
{
$this->hidden = $hidden;
return $this;
}
public function getSecured()
{
return $this->secured;
}
public function setSecured($secured)
{
$this->secured = $secured;
return $this;
}
public function getLocale()
{
return $this->locale;
@@ -107,40 +79,4 @@ class ConfigCreateEvent extends ActionEvent
return $this;
}
public function getDescription()
{
return $this->description;
}
public function setDescription($description)
{
$this->description = $description;
return $this;
}
public function getChapo()
{
return $this->chapo;
}
public function setChapo($chapo)
{
$this->chapo = $chapo;
return $this;
}
public function getPostscriptum()
{
return $this->postscriptum;
}
public function setPostscriptum($postscriptum)
{
$this->postscriptum = $postscriptum;
return $this;
}
}

View File

@@ -25,24 +25,10 @@ namespace Thelia\Core\Event;
use Thelia\Model\Config;
class ConfigDeleteEvent extends ActionEvent
class ConfigDeleteEvent extends ConfigEvent
{
protected $config_id;
public function __construct($config_id)
{
$this->setConfigId($config_id);
}
public function getConfigId()
{
return $this->config_id;
}
public function setConfigId($config_id)
{
$this->config_id = $config_id;
return $this;
}
}

View File

@@ -22,13 +22,26 @@
/*************************************************************************************/
namespace Thelia\Core\Event;
use Thelia\Model\Config;
class ConfigEvent extends ActionEvent
{
public function __construct(Config $config)
protected $config;
public function __construct(Config $config = null)
{
$this->config = $config;
}
public function getConfig()
{
return $this->config;
}
public function setConfig($config)
{
$this->config = $config;
return $this;
}
}

View File

@@ -29,6 +29,7 @@ use Thelia\Exception\InvalidCartException;
use Thelia\Model\CartQuery;
use Thelia\Model\Cart;
use Thelia\Tools\URL;
use Thelia\Model\Lang;
class Session extends BaseSession
{
@@ -39,9 +40,35 @@ class Session extends BaseSession
return $this->get("locale", "en_US");
}
public function setLocale($locale)
{
$this->set("locale", $locale);
return $this;
}
public function getLang()
{
return substr($this->getLocale(), 0, 2);
return $this->get("lang", substr($this->getLocale(), 0, 2));
}
public function setLang($lang)
{
$this->set("lang", $lang);
return $this;
}
public function getAdminEditionLangId()
{
return $this->get('admin.edition_language', Lang::getDefaultLanguage()->getId());
}
public function setAdminEditionLangId($langId)
{
$this->set('admin.edition_language', $langId);
return $this;
}
// -- Customer user --------------------------------------------------------
@@ -49,6 +76,7 @@ class Session extends BaseSession
public function setCustomerUser(UserInterface $user)
{
$this->set('customer_user', $user);
return $this;
}
public function getCustomerUser()
@@ -66,6 +94,7 @@ class Session extends BaseSession
public function setAdminUser(UserInterface $user)
{
$this->set('admin_user', $user);
return $this;
}
public function getAdminUser()
@@ -83,6 +112,7 @@ class Session extends BaseSession
public function setReturnToUrl($url)
{
$this->set('return_to_url', $url);
return $this;
}
/**
@@ -141,6 +171,6 @@ class Session extends BaseSession
public function setCart($cart_id)
{
$this->set("cart_id", $cart_id);
return $this;
}
}

View File

@@ -90,7 +90,7 @@ class Attribute extends BaseI18nLoop
$lang = $this->getLang();
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -156,6 +156,7 @@ class Attribute extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $attribute->getId())
->set("IS_TRANSLATED",$attribute->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$attribute->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $attribute->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $attribute->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -77,7 +77,7 @@ class AttributeAvailability extends BaseI18nLoop
$search = AttributeAvQuery::create();
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -125,6 +125,7 @@ class AttributeAvailability extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $attributeAv->getId())
->set("IS_TRANSLATED",$attributeAv->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$attributeAv->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $attributeAv->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $attributeAv->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -77,7 +77,7 @@ class AttributeCombination extends BaseI18nLoop
$search = AttributeCombinationQuery::create();
/* manage attribute translations */
$this->configureI18nProcessing(
$locale = $this->configureI18nProcessing(
$search,
array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
AttributeTableMap::TABLE_NAME,
@@ -85,7 +85,7 @@ class AttributeCombination extends BaseI18nLoop
);
/* manage attributeAv translations */
$this->configureI18nProcessing(
$locale = $this->configureI18nProcessing(
$search,
array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
AttributeAvTableMap::TABLE_NAME,
@@ -117,6 +117,7 @@ class AttributeCombination extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow
->set("LOCALE",$locale)
->set("ATTRIBUTE_TITLE", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_TITLE'))
->set("ATTRIBUTE_CHAPO", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_CHAPO'))
->set("ATTRIBUTE_DESCRIPTION", $attributeCombination->getVirtualColumn(AttributeTableMap::TABLE_NAME . '_i18n_DESCRIPTION'))

View File

@@ -178,6 +178,7 @@ class Category extends BaseI18nLoop
$loopResultRow
->set("ID", $category->getId())
->set("IS_TRANSLATED",$category->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE", $category->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $category->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $category->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -101,6 +101,7 @@ class CategoryPath extends BaseI18nLoop
->set("TITLE",$category->getVirtualColumn('i18n_TITLE'))
->set("URL", $category->getUrl($locale))
->set("ID", $category->getId())
->set("LOCALE",$locale)
;
$results[] = $loopResultRow;

View File

@@ -72,10 +72,11 @@ class Config extends BaseI18nLoop
{
$id = $this->getId();
$name = $this->getVariable();
$secured = $this->getSecured();
$search = ConfigQuery::create();
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
if (! is_null($id))
$search->filterById($id);
@@ -90,8 +91,8 @@ class Config extends BaseI18nLoop
if ($this->getHidden() != BooleanOrBothType::ANY)
$search->filterByHidden($this->getHidden() ? 1 : 0);
if ($this->getSecured() != BooleanOrBothType::ANY)
$search->filterBySecured($this->getSecured() ? 1 : 0);
if (! is_null($secured) && $secured != BooleanOrBothType::ANY)
$search->filterBySecured($secured ? 1 : 0);
$search->orderByName(Criteria::ASC);
@@ -108,6 +109,7 @@ class Config extends BaseI18nLoop
->set("NAME" , $result->getName())
->set("VALUE" , $result->getValue())
->set("IS_TRANSLATED", $result->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE" , $result->getVirtualColumn('i18n_TITLE'))
->set("CHAPO" , $result->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION" , $result->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -214,6 +214,7 @@ class Content extends BaseI18nLoop
$loopResultRow->set("ID", $content->getId())
->set("IS_TRANSLATED",$content->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$content->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $content->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $content->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -68,7 +68,7 @@ class Country extends BaseI18nLoop
$search = CountryQuery::create();
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -107,6 +107,7 @@ class Country extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $country->getId())
->set("IS_TRANSLATED",$country->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$country->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $country->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $country->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -67,7 +67,7 @@ class Currency extends BaseI18nLoop
$search = CurrencyQuery::create();
/* manage translations */
$this->configureI18nProcessing($search, array('NAME'));
$locale = $this->configureI18nProcessing($search, array('NAME'));
$id = $this->getId();
@@ -98,6 +98,7 @@ class Currency extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $currency->getId())
->set("IS_TRANSLATED",$currency->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("NAME",$currency->getVirtualColumn('i18n_NAME'))
->set("ISOCODE", $currency->getCode())
->set("SYMBOL", $currency->getSymbol())

View File

@@ -82,7 +82,7 @@ class Feature extends BaseI18nLoop
$search = FeatureQuery::create();
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -148,6 +148,7 @@ class Feature extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $feature->getId())
->set("IS_TRANSLATED",$feature->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$feature->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $feature->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $feature->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -75,7 +75,7 @@ class FeatureAvailability extends BaseI18nLoop
$search = FeatureAvQuery::create();
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -123,6 +123,7 @@ class FeatureAvailability extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $featureAv->getId())
->set("IS_TRANSLATED",$featureAv->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$featureAv->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $featureAv->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $featureAv->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -82,7 +82,7 @@ class FeatureValue extends BaseI18nLoop
$search = FeatureProductQuery::create();
/* manage featureAv translations */
$this->configureI18nProcessing(
$locale = $this->configureI18nProcessing(
$search,
array('TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM'),
FeatureAvTableMap::TABLE_NAME,
@@ -141,7 +141,9 @@ class FeatureValue extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $featureValue->getId());
$loopResultRow->set("PERSONAL_VALUE", $featureValue->getByDefault())
$loopResultRow
->set("LOCALE",$locale)
->set("PERSONAL_VALUE", $featureValue->getByDefault())
->set("TITLE",$featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_TITLE'))
->set("CHAPO", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_CHAPO'))
->set("DESCRIPTION", $featureValue->getVirtualColumn(FeatureAvTableMap::TABLE_NAME . '_i18n_DESCRIPTION'))

View File

@@ -156,6 +156,7 @@ class Folder extends BaseI18nLoop
$loopResultRow
->set("ID", $folder->getId())
->set("IS_TRANSLATED",$folder->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$folder->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $folder->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -164,7 +164,7 @@ class Image extends BaseI18nLoop
$search = $this->getSearchQuery($object_type, $object_id);
/* manage translations */
$this->configureI18nProcessing($search);
$locale = $this->configureI18nProcessing($search);
$id = $this->getId();
@@ -186,7 +186,7 @@ class Image extends BaseI18nLoop
$background_color = $this->getBackgroundColor();
$quality = $this->getQuality();
$effects = $this->getEffects();
$effects = $this->getEffects();
if (! is_null($effects)) {
$effects = explode(',', $effects);
}
@@ -245,14 +245,15 @@ class Image extends BaseI18nLoop
$loopResultRow
->set("ID", $result->getId())
->set("LOCALE",$locale)
->set("IMAGE_URL", $event->getFileUrl())
->set("ORIGINAL_IMAGE_URL", $event->getOriginalFileUrl())
->set("IMAGE_PATH", $event->getCacheFilepath())
->set("ORIGINAL_IMAGE_PATH", $source_filepath)
->set("TITLE", $result->getTitle())
->set("CHAPO", $result->getChapo())
->set("DESCRIPTION", $result->getDescription())
->set("POSTSCRIPTUM", $result->getPostscriptum())
->set("TITLE",$folder->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $folder->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $folder->getVirtualColumn('i18n_DESCRIPTION'))
->set("POSTSCRIPTUM", $folder->getVirtualColumn('i18n_POSTSCRIPTUM'))
->set("POSITION", $result->getPosition())
->set("OBJECT_TYPE", $object_type)
->set("OBJECT_ID", $object_id)

View File

@@ -509,6 +509,7 @@ class Product extends BaseI18nLoop
$loopResultRow->set("ID", $product->getId())
->set("REF",$product->getRef())
->set("IS_TRANSLATED",$product->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("TITLE",$product->getVirtualColumn('i18n_TITLE'))
->set("CHAPO", $product->getVirtualColumn('i18n_CHAPO'))
->set("DESCRIPTION", $product->getVirtualColumn('i18n_DESCRIPTION'))

View File

@@ -65,7 +65,7 @@ class Title extends BaseI18nLoop
$search = CustomerTitleQuery::create();
/* manage translations */
$this->configureI18nProcessing($search, array('SHORT', 'LONG'));
$locale = $this->configureI18nProcessing($search, array('SHORT', 'LONG'));
$id = $this->getId();
@@ -84,6 +84,7 @@ class Title extends BaseI18nLoop
$loopResultRow = new LoopResultRow();
$loopResultRow->set("ID", $title->getId())
->set("IS_TRANSLATED",$title->getVirtualColumn('IS_TRANSLATED'))
->set("LOCALE",$locale)
->set("DEFAULT", $title->getByDefault())
->set("SHORT", $title->getVirtualColumn('i18n_SHORT'))
->set("LONG", $title->getVirtualColumn('i18n_LONG'));

View File

@@ -49,13 +49,18 @@ class ParserContext implements \IteratorAggregate
/**
* @param BaseForm $form the errored form
*/
public function setErrorForm(BaseForm $form)
public function addForm(BaseForm $form)
{
$this->set('error_form', $form);
$this->set($form->getName(), $form);
return $this;
}
public function getForm($name)
{
return $this->get($name, null);
}
public function setGeneralError($error)
{
$this->set('general_error', $error);
@@ -63,16 +68,6 @@ class ParserContext implements \IteratorAggregate
return $this;
}
public function getErrorForm()
{
return $this->get('error_form', null);
}
public function clearErrorForm()
{
return $this->remove('error_form');
}
// -- Internal table manipulation ------------------------------------------
public function set($name, $value)

View File

@@ -82,6 +82,7 @@ class Form extends AbstractSmartyPlugin
public function generateForm($params, $content, \Smarty_Internal_Template $template, &$repeat)
{
if ($repeat) {
$name = $this->getParam($params, 'name');
@@ -93,15 +94,11 @@ class Form extends AbstractSmartyPlugin
$instance = $this->createInstance($name);
// Check if parser context contains our form
$errorForm = $this->parserContext->getErrorForm();
$form = $this->parserContext->getForm($instance->getName());
if (null != $errorForm && $errorForm->getName() == $instance->getName()) {
// Re-use the errored form
$instance = $errorForm;
// Don't do that, as we may want to use this form firther in the template code
//$this->parserContext->clearErrorForm();
if (null != $form) {
// Re-use the form
$instance = $form;
}
$instance->createView();
@@ -110,7 +107,8 @@ class Form extends AbstractSmartyPlugin
$template->assign("form_error", $instance->hasError() ? true : false);
$template->assign("form_error_message", $instance->getErrorMessage());
} else {
}
else {
return $content;
}
}

View File

@@ -311,13 +311,13 @@ class TheliaLoop extends AbstractSmartyPlugin
$type = strtolower($smartyParams['type']);
if (! isset($this->loopDefinition[$type])) {
throw new ElementNotFoundException(sprintf("%s loop does not exists", $type));
throw new ElementNotFoundException(sprintf("'%s' loop type does not exists", $type));
}
$class = new \ReflectionClass($this->loopDefinition[$type]);
if ($class->isSubclassOf("Thelia\Core\Template\Element\BaseLoop") === false) {
throw new InvalidElementException(sprintf("%s Loop class have to extends Thelia\Core\Template\Element\BaseLoop",
throw new InvalidElementException(sprintf("'%s' Loop class should extends Thelia\Core\Template\Element\BaseLoop",
$type));
}

View File

@@ -212,14 +212,14 @@ class SmartyParser extends Smarty implements ParserInterface
$templateDir = realpath(THELIA_TEMPLATE_DIR . rtrim($this->template, "/") . "/");
if (strpos($pathFileName, $templateDir) !== 0) {
throw new ResourceNotFoundException(sprintf("%s view does not exists", $file));
throw new ResourceNotFoundException(sprintf("'%s' view does not exists", $file));
}
if (!file_exists($fileName)) {
$fileName .= ".html";
if (!file_exists($fileName)) {
throw new ResourceNotFoundException(sprintf("%s file not found in %s template", $file, $this->template));
throw new ResourceNotFoundException(sprintf("'%s' file not found in %s template", $file, $this->template));
}
}

View File

@@ -125,8 +125,10 @@ class TheliaHttpKernel extends HttpKernel
$lang = $this->detectLang($request);
if ($lang) {
$request->getSession()->set("lang", $lang->getCode());
$request->getSession()->set("locale", $lang->getLocale());
$request->getSession()
->setLang($lang->getCode())
->setLocale($lang->getLocale())
;
}
}
@@ -164,7 +166,7 @@ class TheliaHttpKernel extends HttpKernel
}
//check if lang is not defined. If not we have to search the good one.
if (null === $request->getSession()->get("lang")) {
if (null === $request->getSession()->getLang()) {
if (Model\ConfigQuery::read("one_domain_foreach_lang", false) == 1) {
//find lang with domain
@@ -173,9 +175,7 @@ class TheliaHttpKernel extends HttpKernel
//find default lang
return Model\LangQuery::create()->findOneByByDefault(1);
}
}
protected function initSession(Request $request)

View File

@@ -0,0 +1,54 @@
<?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\Form;
use Symfony\Component\Validator\Constraints\NotBlank;
/**
* A base form for all objects with standard contents.
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
abstract class BaseDescForm extends BaseForm
{
protected function buildForm()
{
$this->formBuilder
->add("locale", "hidden", array(
"constraints" => array(
new NotBlank()
)
)
)
->add("title", "text", array(
"constraints" => array(
new NotBlank()
)
)
)
->add("chapo", "text", array())
->add("description", "text", array())
->add("postscriptum", "text", array())
;
}
}

View File

@@ -0,0 +1,57 @@
<?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\Form;
use Symfony\Component\Validator\Constraints\NotBlank;
use Thelia\Model\LangQuery;
use Propel\Runtime\ActiveQuery\Criteria;
class VariableCreationForm extends BaseForm
{
protected function buildForm()
{
$this->formBuilder
->add("name", "text", array(
"constraints" => array(
new NotBlank()
)
))
->add("title", "text", array(
"constraints" => array(
new NotBlank()
)
))
->add("locale", "hidden", array(
"constraints" => array(
new NotBlank()
)
))
->add("value", "text", array())
;
}
public function getName()
{
return "thelia_variable_creation";
}
}

View File

@@ -0,0 +1,59 @@
<?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\Form;
use Symfony\Component\Validator\Constraints\NotBlank;
use Thelia\Model\LangQuery;
use Propel\Runtime\ActiveQuery\Criteria;
use Symfony\Component\Validator\Constraints\GreaterThan;
class VariableModificationForm extends BaseDescForm
{
protected function buildForm()
{
parent::buildForm();
$this->formBuilder
->add("id", "hidden", array(
"constraints" => array(
new GreaterThan(
array('value' => 0)
)
)
))
->add("name", "text", array(
"constraints" => array(
new NotBlank()
)
))
->add("value", "text", array())
->add("hidden", "hidden", array())
->add("secured", "hidden", array())
;
}
public function getName()
{
return "thelia_variable_creation";
}
}

View File

@@ -32,6 +32,9 @@ class Config extends BaseConfig {
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
/**
* {@inheritDoc}
*/
public function preInsert(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::BEFORE_CREATECONFIG, new ConfigEvent($this));
@@ -39,11 +42,17 @@ class Config extends BaseConfig {
return true;
}
/**
* {@inheritDoc}
*/
public function postInsert(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::AFTER_CREATECONFIG, new ConfigEvent($this));
}
/**
* {@inheritDoc}
*/
public function preUpdate(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::BEFORE_CHANGECONFIG, new ConfigEvent($this));
@@ -51,11 +60,17 @@ class Config extends BaseConfig {
return true;
}
/**
* {@inheritDoc}
*/
public function postUpdate(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::AFTER_CHANGECONFIG, new ConfigEvent($this));
}
/**
* {@inheritDoc}
*/
public function preDelete(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::BEFORE_DELETECONFIG, new ConfigEvent($this));
@@ -63,6 +78,9 @@ class Config extends BaseConfig {
return true;
}
/**
* {@inheritDoc}
*/
public function postDelete(ConnectionInterface $con = null)
{
$this->dispatchEvent(TheliaEvents::AFTER_DELETECONFIG, new ConfigEvent($this));

View File

@@ -575,6 +575,11 @@ form .info .input-append .add-on {
line-height: 30px;
}
.title-without-tabs {
border-bottom: 2px solid #A5CED8;
margin-bottom: 0.5em;
}
// The action bar on the right
.actions {
text-align: right;
@@ -594,6 +599,8 @@ form .info .input-append .add-on {
line-height: 30px;
margin-bottom: 1em;
border-bottom: 1px dotted #A5CED8;
padding-bottom: 0.5em;
.inner-actions {
text-align: right;
@@ -633,7 +640,7 @@ label {
}
.input-append.input-block-level .add-on img {
max-height: 18px;
max-height: 16px;
}
// Information in field label
@@ -739,6 +746,10 @@ label {
border-radius: 4px 4px 4px 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
&.actions {
text-align: right;
}
}
}
@@ -770,4 +781,9 @@ label {
select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input {
margin-bottom: 0;
}
}
// Modal is no longer limited
.modal-body {
max-height: none;
}

View File

@@ -4,7 +4,7 @@
{include file='includes/header.inc.html'}
<div class="catalog">
<div class="catalog edit-category">
<div id="wrapper" class="container">
<ul class="breadcrumb">
{include file="includes/category_breadcrumb.html"}

View File

@@ -1,26 +1,13 @@
{* Breadcrumb for categories browsing and editing *}
<li><a href="{url path='admin/home'}">Home</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/catalog'}">Catalog</a>
<li><a href="{url path='admin/catalog'}">Catalog</a> {ifloop rel="category_path"} <span class="divider">/</span></li>
{ifloop rel="category_path"}
<span class="divider">/</span></li>
{loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"}
{if $ID == $current_category_id}
<li class="active">
{if $action == 'edit'}
{intl l='Editing %cat' cat="{$TITLE}"}
{else}
{$TITLE} <a href="{url path='admin/catalog/category' id="$ID" action='edit'}" title="{intl l='Edit this category'}">{intl l="(edit)"}</a>
{/if}
</li>
{else}
<li><a href="{url path='admin/catalog/category' id="$ID" action='browse'}">{$TITLE}</a> <span class="divider">/</span></li>
{/if}
{/loop}
{/ifloop}
{elseloop rel="category_path"}
</li>
{/elseloop}
{loop name="category_path" type="category-path" visible="*" category="{$current_category_id}"} {if $ID == $current_category_id}
<li class="active">{if $action == 'edit'} {intl l='Editing %cat' cat="{$TITLE}"} {else} {$TITLE} <a href="{url path='admin/catalog/category' id=" $ID" action='edit' }" title="{intl l='Edit this category'}">{intl l="(edit)"}</a> {/if}
</li>
{else}
<li><a href="{url path='admin/catalog/category' id=" $ID" action='browse'}">{$TITLE}</a> <span class="divider">/</span></li>
{/if} {/loop} {/ifloop} {elseloop rel="category_path"}
</li>
{/elseloop}

View File

@@ -55,7 +55,7 @@
{module_include location='inside_topbar'}
<div class="user-info">
<a class="profile" href="href="{url path='admin/edit_profile'}">{admin attr="firstname"} {admin attr="lastname"}</a>
<a class="profile" href="{url path='admin/edit_profile'}">{admin attr="firstname"} {admin attr="lastname"}</a>
<a class="logout" href="{url path='admin/logout'}" title="{intl l='Close administation session'}">{intl l="Logout"}</a></div>
{loop name="top-bar-search" type="auth" context="admin" roles="ADMIN" permissions="admin.search"}

View File

@@ -11,17 +11,17 @@
<ul class="nav nav-pills">
{loop name="lang_list" type="lang" default_only={$default_only}}
<li {if $IS_DEFAULT}class="active"{/if}>
<a href="#" title="{intl l="Edit information in %lng" lng=$TITLE}">
<li {if $ID == $edition_language}class="active"{/if}>
<a href="{$current_url}&amp;edition_language={$ID}" title="{intl l="Edit information in %lng" lng=$TITLE}">
<img src="{image file="../assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" />
</a>
</a>
</li>
{/loop}
</ul>
</div>
<div class="span6 inner-actions">
<button class="btn btn-primary" title="{intl l='Save'}">{intl l='Save'} <i class="icon icon-white icon-ok"></i></button>
<button class="btn btn-info" title="{intl l='Save and close'}">{intl l='Save and close'} <i class="icon icon-remove icon-white"></i></button>
<button type="submit" name="save_mode" value="stay" class="btn btn-primary" title="{intl l='Save'}">{intl l='Save'} <i class="icon icon-white icon-ok"></i></button>
<button type="submit" name="save_mode" value="close" class="btn btn-info" title="{intl l='Save and close'}">{intl l='Save and close'} <i class="icon icon-remove icon-white"></i></button>
</div>
</div>

View File

@@ -0,0 +1,60 @@
{* The standard description fields, used by many Thelia objects *}
{form_field form=$form field='title'}
<div class="control-group">
<label class="control-label">
{intl l='Title *'}
</label>
<div class="controls">
<span {if $error}class="error"{/if}>
<input type="text" name="{$name}" required="required" title="{intl l='Title'}" placeholder="{intl l='Title'}" class="input-block-level" value="{$value|htmlspecialchars}">
</span>
</div>
</div>
{/form_field}
{form_field form=$form field='chapo'}
<div class="control-group">
<label class="control-label">
{intl l='Summary'}
<span class="label-help-block">{intl l="A short description, used when a summary or an introduction is required"}</span>
</label>
<div class="controls">
<span {if $error}class="error"{/if}>
<textarea name="{$name}" rows="3" title="{intl l='Short description'}" placeholder="{intl l='Short description'}" class="input-block-level">{$value|htmlspecialchars}</textarea>
</span>
</div>
</div>
{/form_field}
{form_field form=$form field='description'}
<div class="control-group">
<label class="control-label">
{intl l='Detailed description'}
<span class="label-help-block">{intl l="The détailed description."}</span>
</label>
<div class="controls">
<span {if $error}class="error"{/if}>
<textarea name="{$name}" rows="10" class="input-block-level">{$value|htmlspecialchars}</textarea>
</span>
</div>
</div>
{/form_field}
{form_field form=$form field='postscriptum'}
<div class="control-group">
<label class="control-label">
{intl l='Conclusion'}
<span class="label-help-block">{intl l="A short post-description information"}</span>
</label>
<div class="controls">
<span {if $error}class="error"{/if}>
<textarea name="{$name}" rows="3" title="{intl l='Short conclusion'}" placeholder="{intl l='Short conclusion'}" class="input-block-level">{$value|htmlspecialchars}</textarea>
</span>
</div>
</div>
{/form_field}

View File

@@ -0,0 +1,136 @@
{check_auth context="admin" roles="ADMIN" permissions="admin.configuration.variables.edit" login_tpl="admin/login"}
{$page_title={intl l='Edit a system variable'}}
{include file='includes/header.inc.html'}
<div class="variables edit-variable">
<div id="wrapper" class="container">
{loop name="config_edit" type="config" hidden="*" id="$variable_id" backend_context="1" lang="$edition_language"}
<ul class="breadcrumb">
<li><a href="{url path='admin/home'}">{intl l="Home"}</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/configuration'}">{intl l="Configuration"}</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/configuration/variables'}">{intl l="System variables"}</a> <span class="divider">/</span></li>
<li>{intl l='Editing variable "%name"' name="{$NAME}"}</li>
</ul>
<div class="row-fluid">
<div class="span12 general-block-decorator">
<div class="row-fluid">
<div class="span12 title title-without-tabs">
{intl l="Edit variable $NAME"}
</div>
<div class="form-container">
<div class="form-horizontal span12">
<fieldset>
{form name="thelia.admin.variable.modification"}
<form method="POST" action="{url path='admin/configuration/variables/save-change'}" {form_enctype form=$form}>
{* Be sure to get the variable ID, even if the form could not be validated *}
<input type="hidden" name="variable_id" value="{$variable_id}" />
{include file="includes/inner-form-toolbar.html"}
{form_hidden_fields form=$form}
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path='admin/configuration/variables'}" />
{/form_field}
{* We do not allow creation of hidden variables *}
{form_field form=$form field='id'}
<input type="hidden" name="{$name}" value="{$value|htmlspecialchars}" />
{/form_field}
{form_field form=$form field='hidden'}
<input type="hidden" name="{$name}" value="0" />
{/form_field}
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$value|htmlspecialchars}" />
{/form_field}
{if #form_error}<div class="alert alert-block alert-error">#form_error_message</div>{/if}
<div class="control-group">
<label class="control-label">
{intl l='Name *'}
</label>
<div class="controls">
{form_field form=$form field='name'}
<span {if $error}class="error"{/if}>
<input type="text" required="required" name="{$name}" value="{$value|htmlspecialchars}" title="{intl l='Variable name'}" placeholder="{intl l='Variable name'}" class="input-block-level">
</span>
{/form_field}
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Value'}
</label>
<div class="controls">
{form_field form=$form field='value'}
<span {if $error}class="error"{/if}>
<input type="text" name="{$name}" value="{$value|htmlspecialchars}" title="{intl l='Variable value'}" placeholder="{intl l='Variable value'}" class="input-block-level">
</span>
{/form_field}
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Secured'}
</label>
<div class="controls">
{form_field form=$form field='value'}
<span {if $error}class="error"{/if}>
<label class="checkbox">
<input type="checkbox" name="{$name}" value="1" {if $value == 1}checked="checked"{/if}>
{intl l="Prevent variable modification or deletion, except for super-admin"}
</label>
</span>
{/form_field}
</div>
</div>
{include file="includes/standard-description-form-fields.html"}
</form>
{/form}
</fieldset>
</div>
</div>
</div>
</div>
</div>
{/loop}
{elseloop rel="config_edit"}
<div class="row-fluid">
<div class="span12">
<div class="alert alert-error">
{intl l="Sorry, variable ID=$variable_id was not found."}
</div>
</div>
</div>
{/elseloop}
</div>
</div>
{include file='includes/js.inc.html'}
{include file='includes/footer.inc.html'}

View File

@@ -1,6 +1,6 @@
{check_auth context="admin" roles="ADMIN" permissions="admin.configuration.variables.view" login_tpl="/admin/login"}
{check_auth context="admin" roles="ADMIN" permissions="admin.configuration.variables.view" login_tpl="admin/login"}
{$page_title={intl l='Configuration'}}
{$page_title={intl l='Thelia System Variables'}}
{include file='includes/header.inc.html'}
@@ -8,20 +8,26 @@
<div id="wrapper" class="container">
{module_include location='config_top'}
<ul class="breadcrumb">
<li><a href="{url path='admin/home'}">{intl l="Home"}</a> <span class="divider">/</span></li>
<li><a href="{url path='admin/configuration'}">{intl l="Configuration"}</a> <span class="divider">/</span></li>
<li>{intl l="System variables"}</li>
</ul>
{module_include location='variables_top'}
<h2>{intl l="Thelia system variables configuration"}</h2>
<div class="row-fluid">
<div class="span6">
<form>
<div class="span12">
<form action="{url path='admin/configuration/variables/change-values'}" method="post">
<div class="general-block-decorator">
<table class="table table-striped table-condensed table-left-aligned">
<caption>
{intl l='Thelia system variables'}
{loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.category.create"}
<a class="btn btn-primary action-btn" title="{intl l='Add a new variable'}" href="#">
{loop type="auth" name="can_create" context="admin" roles="ADMIN" permissions="admin.configuration.variables.create"}
<a class="btn btn-primary action-btn" title="{intl l='Add a new variable'}" href="#add_variable_dialog" data-toggle="modal">
<i class="icon-plus-sign icon-white"></i>
</a>
<button class="btn btn-primary action-btn" title="{intl l='Save chages'}">{intl l='Save changes'} <i class="icon icon-white icon-ok"></i></button>
@@ -32,6 +38,9 @@
<th>{intl l="Purpose"}</th>
<th>{intl l="Name"}</th>
<th>{intl l="Value"}</th>
{module_include location='variables_table_header'}
<th>&nbsp;</th>
</tr>
{loop name="config" type="config" hidden="0" secured="*" backend_context="1"}
@@ -42,14 +51,25 @@
{if $SECURED}
{$VALUE}
{else}
<input type="text" name="value" value="{$VALUE|htmlspecialchars}" />
<input id="cancelable_edit_{$ID}" class="js-edit" data-id="{$ID}" type="text" name="variable[{$ID}]" value="{$VALUE|htmlspecialchars}" />
{/if}
</td>
<td>
{module_include location='variables_table_row'}
<td class="actions">
{if ! $SECURED}
{loop type="auth" name="can_delete" context="admin" roles="ADMIN" permissions="admin.configuration.variables.delete"}
<a class="btn btn-mini config-delete" title="{intl l='Delete this configuration variable'}" href="{url path='/admin/configuration/variables/delete' id="$ID"}"><i class="icon-trash"></i></a>
{/loop}
<div class="btn-group">
<a class="btn btn-mini cancel-edit" id="cancel_edit_btn_{$ID}" data-id="{$ID}" title="{intl l='Cancel changes and revert to original value'}" href="#"><i class="icon-remove-circle"></i></a>
{loop type="auth" name="can_change" context="admin" roles="ADMIN" permissions="admin.configuration.variables.change"}
<a class="btn btn-mini config-change" title="{intl l='Change this variable'}" href="{url path='admin/configuration/variables/change' variable_id="$ID"}"><i class="icon-edit"></i></a>
{/loop}
{loop type="auth" name="can_delete" context="admin" roles="ADMIN" permissions="admin.configuration.variables.delete"}
<a class="btn btn-mini config-delete" title="{intl l='Delete this configuration variable'}" href="{url path='admin/configuration/variables/delete' id="$ID"}"><i class="icon-trash"></i></a>
{/loop}
</div>
{/if}
</td>
</tr>
@@ -59,19 +79,160 @@
</form>
</div>
</div>
{module_include location='variables_bottom'}
</div>
</div>
{* Adding a new variable *}
<div class="modal hide fade" id="add_variable_dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{intl l="Create a new variable"}</h3>
</div>
{form name="thelia.admin.variable.creation"}
<form method="POST" action="{url path='admin/configuration/variables/create'}" {form_enctype form=$form}>
{form_hidden_fields form=$form}
{form_field form=$form field='success_url'}
{* on success, redirect to the edition page, _ID_ is replaced with the created variable ID, see controller *}
<input type="hidden" name="{$name}" value="{url path='admin/configuration/variables/change' variable_id='_ID_'}" />
{/form_field}
<div class="modal-body">
{if #form_error}<div class="alert alert-block alert-error" id="add_variable_dialog_error">#form_error_message</div>{/if}
<div class="control-group">
<label class="control-label">
{intl l='Name *'}
</label>
<div class="controls">
{form_field form=$form field='name'}
<span {if $error}class="error"{/if}>
<input type="text" required="required" name="{$name}" value="{$value}" title="{intl l='Variable name'}" placeholder="{intl l='Variable name'}" class="input-block-level">
</span>
{/form_field}
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Value'}
</label>
<div class="controls">
{form_field form=$form field='value'}
<span {if $error}class="error"{/if}>
<input type="text" name="{$name}" value="{$value}" title="{intl l='Variable value'}" placeholder="{intl l='Variable value'}" class="input-block-level">
</span>
{/form_field}
</div>
</div>
<div class="control-group">
<label class="control-label">
{intl l='Purpose *'}
</label>
<div class="controls">
{loop type="lang" name="default-lang" default_only="1"}
{form_field form=$form field='locale'}
<input type="hidden" name="{$name}" value="{$LOCALE}" />
{/form_field}
<div class="input-append input-block-level">
{form_field form=$form field='title'}
<span {if $error}class="error"{/if}>
<input type="text" required="required" name="{$name}" value="{$value}" title="{intl l='Variable purpose'}" placeholder="{intl l='Variable purpose'}" class="input-block-level">
</span>
{/form_field}
<span class="add-on"><img src="{image file="assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" /></span>
</div>
<div class="help-block">{intl l="Enter here the variable purpose in the default language ($TITLE)"}</div>
{/loop}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal" aria-hidden="true">{intl l="Cancel"}</button>
<button type="submit" class="btn btn-primary">{intl l="Create this variable"}</button>
</div>
</form>
{/form}
</div>
{include file='includes/js.inc.html'}
<script>
$(function() {
// Variable delete confirmation
$('a.config-delete').click(function(ev) {
if (! confirm("{intl l='Do you really want to delete this variable ?'}")) {
ev.preventDefault();
}
}
)})
});
{* display the form creation dialog if it contains errors *}
{form name="thelia.admin.variable.creation"}
{if #form_error}
$('#add_variable_dialog').modal();
{/if}
{/form}
{* Always reset create dialog on close *}
$('#add_variable_dialog').on('hidden',function() {
// Hide error message
$('#add_variable_dialog_error').remove();
// Clear error status
$("#add_variable_dialog .error").removeClass('error');
// Empty field values
$("#add_variable_dialog input[type=text]").val('');
});
// Edition canceling management
$('.cancel-edit').each(function() {
var zis = $(this);
var field = $('#cancelable_edit_' + $(this).data('id'));
zis.addClass('disabled');
zis.data('original-value', field.val());
zis.click(function(ev) {
if (!zis.is('.disabled')) {
zis.addClass('disabled');
field.val(zis.data('original-value'));
}
ev.preventDefault();
});
})
$('.js-edit').keyup(function() {
$('#cancel_edit_btn_' + $(this).data('id')).removeClass('disabled');
});
});
</script>
{include file='includes/footer.inc.html'}