瀏覽代碼

SiteSettings : paramètres globaux

feature/ticket
Guillaume 3 年之前
父節點
當前提交
d4da8f9518
共有 21 個檔案被更改,包括 763 行新增25 行删除
  1. +43
    -4
      Controller/Setting/SettingAdminController.php
  2. +127
    -0
      Definition/AbstractSettingDefinition.php
  3. +17
    -0
      Definition/SiteSettingDefinition.php
  4. +8
    -0
      Definition/SiteSettingDefinitionInterface.php
  5. +108
    -0
      EventSubscriber/SiteSettingEventSubscriber.php
  6. +14
    -0
      Factory/Setting/SiteSettingFactory.php
  7. +15
    -0
      Factory/Site/SiteFactory.php
  8. +117
    -0
      Form/Setting/BaseSettingType.php
  9. +45
    -0
      Form/Setting/SettingType.php
  10. +63
    -0
      Form/Setting/SiteSettingsFormType.php
  11. +1
    -1
      Model/Setting/SiteSettingInterface.php
  12. +31
    -0
      Model/Setting/SiteSettingModel.php
  13. +9
    -0
      Model/Site/SiteInterface.php
  14. +60
    -0
      Model/Site/SiteModel.php
  15. +0
    -20
      Repository/Setting/SettingRepository.php
  16. +20
    -0
      Repository/Setting/SiteSettingRepository.php
  17. +21
    -0
      Repository/Site/SiteRepository.php
  18. +4
    -0
      Resources/config/routes.yaml
  19. +1
    -0
      Resources/translations/admin.fr.yaml
  20. +49
    -0
      Resources/views/admin/setting/form.html.twig
  21. +10
    -0
      Resources/views/admin/setting/global.html.twig

+ 43
- 4
Controller/Setting/SettingAdminController.php 查看文件

@@ -3,21 +3,60 @@
namespace Lc\SovBundle\Controller\Setting;

use Doctrine\ORM\EntityManagerInterface;
use Lc\CaracoleBundle\Form\Setting\MerchantSettingsFormType;
use Lc\CaracoleBundle\Form\Setting\SectionSettingsFormType;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Form\Setting\SiteSettingsFormType;
use Lc\SovBundle\Repository\Setting\SiteSettingRepository;
use Lc\SovBundle\Repository\Site\SiteRepository;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class SettingAdminController extends AbstractController
{
protected $em;
protected $translatorAdmin;
protected $siteSettingRepository;
protected $siteSettingDefinition;
protected $siteRepository;

public function __construct(
EntityManagerInterface $em,
TranslatorAdmin $translatorAdmin
)
{
EntityManagerInterface $em,
TranslatorAdmin $translatorAdmin,
SiteSettingRepository $siteSettingRepository,
SiteSettingDefinitionInterface $siteSettingDefinition,
SiteRepository $siteRepository
) {
$this->em = $em;
$this->translatorAdmin = $translatorAdmin;
$this->siteSettingRepository = $siteSettingRepository;
$this->siteSettingDefinition = $siteSettingDefinition;
$this->siteRepository = $siteRepository;
}

public function manageGlobal(Request $request)
{
$site = $this->siteRepository->findOneByDevAlias('default') ;
$form = $this->createForm(SiteSettingsFormType::class, $site);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {

$this->em->update($site);
$this->em->flush();

$this->addFlash('success', $this->translatorAdmin->transFlashMessage('settings_saved'));
}

return $this->render(
'@LcSov/admin/setting/global.html.twig' ,
[
'setting_definition' => $this->siteSettingDefinition,
'form' => $form->createView()
]
);
}

}

+ 127
- 0
Definition/AbstractSettingDefinition.php 查看文件

@@ -0,0 +1,127 @@
<?php

namespace Lc\SovBundle\Definition;

abstract class AbstractSettingDefinition
{
protected $settings = [];

public function addSettingText(array $params): self
{
$params['type'] = 'text';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingTextarea(array $params): self
{
$params['type'] = 'textarea';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingTextareaAdvanced(array $params): self
{
$params['type'] = 'textarea_advanced';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingDate(array $params): self
{
$params['type'] = 'date';
$params['field'] = 'date';
return $this->addSetting($params);
}

public function addSettingTime(array $params): self
{
$params['type'] = 'time';
$params['field'] = 'date';
return $this->addSetting($params);
}

public function addSettingFile(array $params): self
{
$params['type'] = 'file';
$params['field'] = 'file';
return $this->addSetting($params);
}

public function addSettingImage(array $params): self
{
$params['type'] = 'image';
$params['field'] = 'file';
return $this->addSetting($params);
}

public function addSettingSelect(array $params): self
{
$params['type'] = 'select';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSettingRadio(array $params): self
{
$params['type'] = 'radio';
$params['field'] = 'text';
return $this->addSetting($params);
}

public function addSetting($params)
{
$name = $params['name'];
$category = $params['category'];

if (!isset($this->settings[$category])) {
$this->settings[$category] = [];
}

$this->settings[$category][$name] = $params;

return $this;
}

public function getSettings(): array
{
return $this->settings;
}

public function getSettingsByCategory($category)
{
$settings = $this->getSettings();

if (isset($settings[$category])) {
return $settings[$category];
}

return [];
}

public function getSettingByName($name): ?array
{
$settings = $this->getSettings();

foreach ($settings as $category => $settingsCategory) {
foreach ($settingsCategory as $nameSetting => $setting) {
if ($nameSetting == $name) {
return $setting;
}
}
}

return null;
}

public function getSettingType($name): ?string
{
$setting = $this->getSettingByName($name);

if ($setting) {
return $setting['type'];
}

return null;
}
}

+ 17
- 0
Definition/SiteSettingDefinition.php 查看文件

@@ -0,0 +1,17 @@
<?php

namespace Lc\SovBundle\Definition;


class SiteSettingDefinition extends AbstractSettingDefinition implements SiteSettingDefinitionInterface
{
public function __construct()
{
}

public function getCategories()
{
return [] ;
}

}

+ 8
- 0
Definition/SiteSettingDefinitionInterface.php 查看文件

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Definition;

interface SiteSettingDefinitionInterface
{

}

+ 108
- 0
EventSubscriber/SiteSettingEventSubscriber.php 查看文件

@@ -0,0 +1,108 @@
<?php

namespace Lc\SovBundle\EventSubscriber;

use Doctrine\ORM\EntityManagerInterface;
use Lc\CaracoleBundle\Definition\MerchantSettingDefinitionInterface;
use Lc\CaracoleBundle\Factory\Setting\MerchantSettingFactory;
use Lc\CaracoleBundle\Factory\Setting\SectionSettingFactory;
use Lc\CaracoleBundle\Factory\User\UserMerchantFactory;
use Lc\CaracoleBundle\Model\Section\SectionInterface;
use Lc\CaracoleBundle\Repository\Merchant\MerchantRepository;
use Lc\CaracoleBundle\Definition\SectionSettingDefinitionInterface;
use Lc\CaracoleBundle\Repository\Section\SectionRepository;
use Lc\CaracoleBundle\Resolver\MerchantResolver;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Factory\Setting\SiteSettingFactory;
use Lc\SovBundle\Factory\Site\SiteFactory;
use Lc\SovBundle\Repository\Setting\SiteSettingRepository;
use Lc\SovBundle\Repository\Site\SiteRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;

class SiteSettingEventSubscriber implements EventSubscriberInterface
{
protected $em;
protected $siteSettingDefinition;
protected $siteSettingFactory;
protected $siteSettingRepository;
protected $siteRepository;
protected $siteFactory;

public function __construct(
EntityManagerInterface $em,
SiteSettingRepository $siteSettingRepository,
SiteRepository $siteRepository,
SiteSettingDefinitionInterface $siteSettingDefinition,
SiteSettingFactory $siteSettingFactory,
SiteFactory $siteFactory
) {
$this->em = $em;
$this->siteSettingDefinition = $siteSettingDefinition;
$this->siteSettingFactory = $siteSettingFactory;
$this->siteSettingRepository = $siteSettingRepository;
$this->siteRepository = $siteRepository;
$this->siteFactory = $siteFactory;
}

public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => ['initSettings']
];
}

public function initSettings()
{
$site = $this->getSiteDefault();
if (!$site) {
$site = $this->siteFactory->create(
[
'devAlias' => 'default'
]
);
$this->em->persist($site);
$this->em->flush($site);
}


$settings = $this->siteSettingDefinition->getSettings();
$factory = $this->siteSettingFactory;

foreach ($settings as $category => $settingList) {
foreach ($settingList as $settingName => $setting) {
$entitySetting = $site->getSetting($settingName);

if (!$entitySetting) {
$entitySetting = $factory->create(
[
'site' => $site,
'name' => $setting['name'],
$setting['field'] => isset($setting['default']) ? $setting['default'] : null,
]
);

$this->em->persist($entitySetting);
} else {
if ($entitySetting->getValue() === null
&& isset($setting['default'])
&& $setting['default'] !== null) {
$methodSetValue = 'set' . ucfirst($setting['field']);
$entitySetting->$methodSetValue($setting['default']);
$this->em->update($entitySetting);
}
}
}
}


$this->em->flush();
}

public function getSiteDefault()
{
return $this->siteRepository->findOneByDevAlias('default');
}

}

+ 14
- 0
Factory/Setting/SiteSettingFactory.php 查看文件

@@ -0,0 +1,14 @@
<?php

namespace Lc\SovBundle\Factory\Setting;

use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Setting\SiteSettingInterface;

class SiteSettingFactory extends AbstractFactory
{
public function getEntityClass()
{
return SiteSettingInterface::class;
}
}

+ 15
- 0
Factory/Site/SiteFactory.php 查看文件

@@ -0,0 +1,15 @@
<?php

namespace Lc\SovBundle\Factory\Site;

use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Setting\SiteSettingInterface;
use Lc\SovBundle\Model\Site\SiteInterface;

class SiteFactory extends AbstractFactory
{
public function getEntityClass()
{
return SiteInterface::class;
}
}

+ 117
- 0
Form/Setting/BaseSettingType.php 查看文件

@@ -0,0 +1,117 @@
<?php

namespace Lc\SovBundle\Form\Setting;

use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Lc\SovBundle\Definition\SiteSettingDefinitionInterface;
use Lc\SovBundle\Form\Common\FileManagerType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;

abstract class BaseSettingType extends AbstractType
{
protected $em;
protected $settingDefinition;

public function __construct(
EntityManagerInterface $entityManager,
SiteSettingDefinitionInterface $settingDefinition
) {
$this->em = $entityManager;
$this->settingDefinition = $settingDefinition;
}

public function buildFormSetting($label, $form, $settingDefinition, $settingEntity)
{
$settingName = $settingEntity->getName();
$setting = $settingDefinition->getSettingByName($settingName);
$settingType = $settingDefinition->getSettingType($settingName);

if ($settingType == 'text') {
$form->add(
'text',
TextType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'textarea') {
$form->add(
'text',
TextareaType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'textarea_advanced') {
$form->add(
'text',
CKEditorType::class,
[
'label' => $label
]
);
} elseif ($settingType == 'select') {
$form->add(
'text',
ChoiceType::class,
[
'label' => $label,
'expanded' => false,
'multiple' => false,
'placeholder' => false,
'choices' => $setting['choices']
]
);
} elseif ($settingType == 'radio') {
$form->add(
'text',
ChoiceType::class,
[
'label' => $label,
'expanded' => true,
'multiple' => false,
'placeholder' => false,
'choices' => $setting['choices']
]
);
} elseif ($settingType == 'date') {
$form->add(
'date',
DateType::class,
[
'label' => $label,
'widget' => 'single_text',
]
);
} elseif ($settingType == 'time') {
$form->add(
'date',
TimeType::class,
[
'label' => $label,
'input' => 'datetime',
'widget' => 'single_text',
]
);
} elseif ($settingType == 'file' || $settingType == 'image') {
$form->add(
'file',
FileManagerType::class,
[
'label' => $label,
'attr' => [
'type' => $settingType
]
]
);
}
}

}


+ 45
- 0
Form/Setting/SettingType.php 查看文件

@@ -0,0 +1,45 @@
<?php

namespace Lc\SovBundle\Form\Setting;

use Lc\SovBundle\Model\Setting\SiteSettingInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SettingType extends BaseSettingType
{

public function buildForm(FormBuilderInterface $builder, array $options)
{
$settingDefinition = $this->settingDefinition;

$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($settingDefinition) {
$form = $event->getForm();
$settingEntity = $event->getData();

if ($settingEntity) {
$form->add('name', HiddenType::class);
$settingName = $settingEntity->getName();
$label = 'setting_definition.global.settings.' . $settingName;
$this->buildFormSetting($label, $form, $settingDefinition, $settingEntity);
}
}
);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'label' => false,
'data_class' => $this->em->getEntityName(SiteSettingInterface::class),
]
);
}
}


+ 63
- 0
Form/Setting/SiteSettingsFormType.php 查看文件

@@ -0,0 +1,63 @@
<?php

namespace Lc\SovBundle\Form\Setting;

use Doctrine\ORM\EntityManagerInterface;
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface;
use Lc\SovBundle\Model\Site\SiteInterface;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SiteSettingsFormType extends AbstractType
{
protected $em;
protected $translatorAdmin;

public function __construct(EntityManagerInterface $em, TranslatorAdmin $translatorAdmin)
{
$this->em = $em;
$this->translatorAdmin = $translatorAdmin;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{

$builder->add(
'settings',
CollectionType::class,
[
'entry_type' => SettingType::class,
'required' => false,
'allow_add' => false,
'allow_delete' => false,
'by_reference' => false,
]
);

$builder->add('submit', SubmitType::class, [
'label' => $this->translatorAdmin->transAction('save'),
'attr' => [
'class' => 'btn btn-primary float-right'
]
]) ;
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => $this->em->getEntityName(SiteInterface::class),
]
);
}

}

Model/Setting/SettingInterface.php → Model/Setting/SiteSettingInterface.php 查看文件

@@ -2,7 +2,7 @@

namespace Lc\SovBundle\Model\Setting;

interface SettingInterface
interface SiteSettingInterface
{

}

+ 31
- 0
Model/Setting/SiteSettingModel.php 查看文件

@@ -0,0 +1,31 @@
<?php

namespace Lc\SovBundle\Model\Setting;

use Doctrine\ORM\Mapping as ORM;
use Lc\CaracoleBundle\Model\Setting\SettingTrait;
use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Model\Site\SiteInterface;

abstract class SiteSettingModel implements SiteSettingInterface, EntityInterface
{
use SettingTrait;

/**
* @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\Site\SiteInterface", inversedBy="settings")
* @ORM\JoinColumn(nullable=false)
*/
protected $site;

public function getSite(): ?SiteInterface
{
return $this->site;
}

public function setSite(?SiteInterface $site): self
{
$this->site = $site;

return $this;
}
}

+ 9
- 0
Model/Site/SiteInterface.php 查看文件

@@ -0,0 +1,9 @@
<?php

namespace Lc\SovBundle\Model\Site;

interface SiteInterface
{

}

+ 60
- 0
Model/Site/SiteModel.php 查看文件

@@ -0,0 +1,60 @@
<?php

namespace Lc\SovBundle\Model\Site;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\CaracoleBundle\Model\Setting\EntitySettingTrait;
use Lc\SovBundle\Model\Setting\SiteSettingInterface;
use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
use Lc\SovBundle\Doctrine\Extension\DevAliasTrait;

abstract class SiteModel implements SiteInterface, EntityInterface, DevAliasInterface
{
use EntitySettingTrait;
use DevAliasTrait;

/**
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Setting\SiteSettingInterface", mappedBy="site", orphanRemoval=true, cascade={"persist"}, fetch="EAGER")
*/
protected $settings;

public function __construct()
{
$this->settings = new ArrayCollection();
}

/**
* @return Collection|SiteSettingInterface[]
*/
public function getSettings(): Collection
{
return $this->settings;
}

public function addSetting(SiteSettingInterface $setting): self
{
if (!$this->settings->contains($setting)) {
$this->settings[] = $setting;
$setting->setSite($this);
}

return $this;
}

public function removeSetting(SiteSettingInterface $setting): self
{
if ($this->settings->contains($setting)) {
$this->settings->removeElement($setting);
// set the owning side to null (unless already changed)
if ($setting->getSite() === $this) {
$setting->setSite(null);
}
}

return $this;
}

}

+ 0
- 20
Repository/Setting/SettingRepository.php 查看文件

@@ -1,20 +0,0 @@
<?php

namespace Lc\SovBundle\Repository\Setting;

use Lc\SovBundle\Repository\AbstractRepository;
use Lc\SovBundle\Model\Setting\SettingInterface;

/**
* @method SettingInterface|null find($id, $lockMode = null, $lockVersion = null)
* @method SettingInterface|null findOneBy(array $criteria, array $orderBy = null)
* @method SettingInterface[] findAll()
* @method SettingInterface[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SettingRepository extends AbstractRepository
{
public function getInterfaceClass()
{
return SettingInterface::class;
}
}

+ 20
- 0
Repository/Setting/SiteSettingRepository.php 查看文件

@@ -0,0 +1,20 @@
<?php

namespace Lc\SovBundle\Repository\Setting;

use Lc\SovBundle\Repository\AbstractRepository;
use Lc\SovBundle\Model\Setting\SiteSettingInterface;

/**
* @method SiteSettingInterface|null find($id, $lockMode = null, $lockVersion = null)
* @method SiteSettingInterface|null findOneBy(array $criteria, array $orderBy = null)
* @method SiteSettingInterface[] findAll()
* @method SiteSettingInterface[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SiteSettingRepository extends AbstractRepository
{
public function getInterfaceClass()
{
return SiteSettingInterface::class;
}
}

+ 21
- 0
Repository/Site/SiteRepository.php 查看文件

@@ -0,0 +1,21 @@
<?php

namespace Lc\SovBundle\Repository\Site;

use Lc\SovBundle\Model\File\FileInterface;
use Lc\SovBundle\Model\Site\SiteInterface;
use Lc\SovBundle\Repository\AbstractRepository;
/**
* @method SiteInterface|null find($id, $lockMode = null, $lockVersion = null)
* @method SiteInterface|null findOneBy(array $criteria, array $orderBy = null)
* @method SiteInterface[] findAll()
* @method SiteInterface[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SiteRepository extends AbstractRepository
{
public function getInterfaceClass()
{
return SiteInterface::class;
}

}

+ 4
- 0
Resources/config/routes.yaml 查看文件

@@ -22,3 +22,7 @@ sov_admin_account_password:
path: /admin/account/password
controller: Lc\SovBundle\Controller\User\AccountAdminController::changePassword

sov_admin_setting_global:
path: /admin/setting/global
controller: Lc\SovBundle\Controller\Setting\SettingAdminController::manageGlobal


+ 1
- 0
Resources/translations/admin.fr.yaml 查看文件

@@ -7,6 +7,7 @@ menu:
account: Mon compte
account_profile: Informations personnelles
account_password: Mot de passe
setting_global: Global

title:
dashboard: Tableau de bord

+ 49
- 0
Resources/views/admin/setting/form.html.twig 查看文件

@@ -0,0 +1,49 @@

{% embed '@LcSov/adminlte/embed/tabs/tabs.html.twig' %}
{# items menu #}
{% import '@LcSov/adminlte/macro/tabs.html.twig' as mtabs %}
{% block menu_items %}
{% for index, category in setting_definition.getCategories() %}
{{ mtabs.menu_item(category, loop.first, ('setting_definition.'~trans_category~'.categories.'~category)|trans({}, 'admin')) }}
{% endfor %}
{% endblock %}

{# content #}
{% block content %}
{% form_theme form '@LcSov/adminlte/crud/form_theme.html.twig' %}
{{ form_start(form) }}

{# panes #}
{% for index, category in setting_definition.getCategories() %}
{% embed '@LcSov/adminlte/embed/tabs/pane.html.twig' %}
{% block class %}{{ index == 0 ? 'active' }}{% endblock %}
{% block id %}{{ category }}{% endblock %}
{% block content %}
{% set count = 0 %}
{% for name, setting in setting_definition.getSettingsByCategory(category) %}
{% for child in form.settings %}
{% if child.children.name.vars.value == name %}
{{ form_widget(child) }}
{% set count = count + 1 %}
{% endif %}
{% endfor %}
{% endfor %}
{% if count == 0 %}
{% import '@LcSov/adminlte/macro/callout.html.twig' as mcallout %}
{{ mcallout.callout_warning('Aucun paramètre disponible dans cet onglet.') }}
{% endif %}
{% endblock %}
{% endembed %}
{% endfor %}

{# form footer #}
{% embed '@LcSov/adminlte/embed/form_footer.html.twig' %}
{% block width %}12{% endblock %}
{% block content %}
{{ form_widget(form.submit) }}
{% endblock %}
{% endembed %}

{{ form_end(form) }}
{% endblock %}
{% endembed %}

+ 10
- 0
Resources/views/admin/setting/global.html.twig 查看文件

@@ -0,0 +1,10 @@
{% extends '@LcSov/adminlte/layout.html.twig' %}

{% block content_title %}
Paramètres globaux
{% endblock %}

{% block main %}
{% set trans_category = 'global' %}
{% include '@LcSov/admin/setting/form.html.twig' %}
{% endblock %}

Loading…
取消
儲存