Completed the backoffice variable management
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -29,10 +29,4 @@ class AdminController extends BaseAdminController
|
||||
{
|
||||
return $this->render("home");
|
||||
}
|
||||
|
||||
public function processAction()
|
||||
{
|
||||
echo "not yet coded !";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class CartController extends BaseFrontController
|
||||
|
||||
if ($message) {
|
||||
$cartAdd->setErrorMessage($message);
|
||||
$this->getParserContext()->setErrorForm($cartAdd);
|
||||
$this->getParserContext()->addForm($cartAdd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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'));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
54
core/lib/Thelia/Form/BaseDescForm.php
Normal file
54
core/lib/Thelia/Form/BaseDescForm.php
Normal 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())
|
||||
;
|
||||
}
|
||||
}
|
||||
57
core/lib/Thelia/Form/VariableCreationForm.php
Normal file
57
core/lib/Thelia/Form/VariableCreationForm.php
Normal 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";
|
||||
}
|
||||
}
|
||||
59
core/lib/Thelia/Form/VariableModificationForm.php
Normal file
59
core/lib/Thelia/Form/VariableModificationForm.php
Normal 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";
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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}&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>
|
||||
|
||||
@@ -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}
|
||||
136
templates/admin/default/variable-edit.html
Normal file
136
templates/admin/default/variable-edit.html
Normal 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'}
|
||||
@@ -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> </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">×</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'}
|
||||
Reference in New Issue
Block a user