');
- $('body').append(container);
+ body.append(container);
}
- container.html('');
+ const loader = $('
')
+ loader.html('
Loading...
')
+ body.append(loader)
+
+ container.html();
const url = $(e.target).attr('data-modal');
+ $(container).modal('show');
container.load(url, function() {
- $(container).modal('show');
+ loader.remove()
});
});
diff --git a/core/Cache/SymfonyCacheManager.php b/core/Cache/SymfonyCacheManager.php
index f296142..6ddba95 100644
--- a/core/Cache/SymfonyCacheManager.php
+++ b/core/Cache/SymfonyCacheManager.php
@@ -10,6 +10,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpClient\Exception\ClientException;
+use Symfony\Component\Console\Output\OutputInterface;
/**
* class SymfonyCacheManager.
@@ -51,11 +52,14 @@ class SymfonyCacheManager
}
}
- public function cleanAll()
+ public function cleanAll(OutputInterface $output = null)
{
$application = new Application($this->kernel);
$application->setAutoExit(false);
- $output = new BufferedOutput();
+
+ if (null === $output) {
+ $output = new BufferedOutput();
+ }
$input = new ArrayInput([
'command' => 'cache:clear',
diff --git a/core/Controller/Site/PageController.php b/core/Controller/Site/PageController.php
index 4a16fa8..6798495 100644
--- a/core/Controller/Site/PageController.php
+++ b/core/Controller/Site/PageController.php
@@ -31,6 +31,14 @@ class PageController extends AbstractController
{
$parameters = array_merge($this->getDefaultRenderParameters(), $parameters);
+ if ($response === null) {
+ $contentType = $this->siteRequest->getNode()->getContentType();
+
+ $response = new Response(null, 200, [
+ 'Content-Type' => $contentType ?? 'text/html',
+ ]);
+ }
+
return parent::render($view, $parameters, $response);
}
diff --git a/core/Controller/Task/TaskAdminController.php b/core/Controller/Task/TaskAdminController.php
new file mode 100644
index 0000000..51a3098
--- /dev/null
+++ b/core/Controller/Task/TaskAdminController.php
@@ -0,0 +1,59 @@
+dispatch($event, TaskInitEvent::INIT_EVENT);
+
+ return $this->render('@Core/task/task_admin/index.html.twig', [
+ 'pager' => $event->getTasks(),
+ ]);
+ }
+
+ /**
+ * @Route("/run/{task}", name="admin_task_run", methods={"GET"})
+ */
+ public function run(
+ string $task,
+ Request $request,
+ EventDispatcherInterface $eventDispatcher
+ ): Response {
+ if (!$this->isCsrfTokenValid('task_run', $request->query->get('_token'))) {
+ throw $this->createAccessDeniedException();
+ }
+
+ $output = new BufferedOutput();
+ $event = new TaskRunRequestedEvent($task, $request->query, $output);
+ $eventDispatcher->dispatch($event, TaskRunRequestedEvent::RUN_REQUEST_EVENT);
+
+ $content = $output->fetch();
+
+ return $this->render('@Core/task/task_admin/run.html.twig', [
+ 'output' => $content,
+ ]);
+ }
+
+ public function getSection(): string
+ {
+ return 'task';
+ }
+}
diff --git a/core/Entity/Site/Node.php b/core/Entity/Site/Node.php
index 134e870..99b63e9 100644
--- a/core/Entity/Site/Node.php
+++ b/core/Entity/Site/Node.php
@@ -133,6 +133,11 @@ class Node implements EntityInterface
*/
protected $aliasNodes;
+ /**
+ * @ORM\Column(type="string", length=255, nullable=true)
+ */
+ private $contentType;
+
public function __construct()
{
$this->children = new ArrayCollection();
@@ -491,4 +496,16 @@ class Node implements EntityInterface
return $this;
}
+
+ public function getContentType(): ?string
+ {
+ return $this->contentType;
+ }
+
+ public function setContentType(?string $contentType): self
+ {
+ $this->contentType = $contentType;
+
+ return $this;
+ }
}
diff --git a/core/Event/Task/TaskInitEvent.php b/core/Event/Task/TaskInitEvent.php
new file mode 100644
index 0000000..ce9a45f
--- /dev/null
+++ b/core/Event/Task/TaskInitEvent.php
@@ -0,0 +1,37 @@
+
+ */
+class TaskInitEvent extends Event
+{
+ const INIT_EVENT = 'task_event.init';
+
+ protected array $tasks = [];
+
+ public function getTasks(): array
+ {
+ usort($this->tasks, function ($t1, $t2) {
+ return $t1['section'] != $t2['section'];
+ });
+
+ return $this->tasks;
+ }
+
+ public function addTask(string $task, string $label, string $section): self
+ {
+ $this->tasks[$task] = [
+ 'label' => $label,
+ 'section' => $section,
+ 'task' => $task,
+ ];
+
+ return $this;
+ }
+}
diff --git a/core/Event/Task/TaskRunRequestedEvent.php b/core/Event/Task/TaskRunRequestedEvent.php
new file mode 100644
index 0000000..d25ed89
--- /dev/null
+++ b/core/Event/Task/TaskRunRequestedEvent.php
@@ -0,0 +1,44 @@
+
+ */
+class TaskRunRequestedEvent extends Event
+{
+ const RUN_REQUEST_EVENT = 'task_event.run_request';
+
+ protected string $task;
+ protected InputBag $parameters;
+ protected BufferedOutput $output;
+
+ public function __construct(string $task, InputBag $parameters, BufferedOutput $output)
+ {
+ $this->task = $task;
+ $this->parameters = $parameters;
+ $this->output = $output;
+ }
+
+ public function getTask(): string
+ {
+ return $this->task;
+ }
+
+ public function getParameters(): ParameterBagInterface
+ {
+ return $this->parameters;
+ }
+
+ public function getOutput(): BufferedOutput
+ {
+ return $this->output;
+ }
+}
diff --git a/core/EventSuscriber/SettingEventSubscriber.php b/core/EventSuscriber/SettingEventSubscriber.php
index d65e783..d8db765 100644
--- a/core/EventSuscriber/SettingEventSubscriber.php
+++ b/core/EventSuscriber/SettingEventSubscriber.php
@@ -10,7 +10,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*
* @author Simon Vieille
*/
-class SettingEventSubscriber implements EventSubscriberInterface
+abstract class SettingEventSubscriber implements EventSubscriberInterface
{
protected static int $priority = 0;
diff --git a/core/EventSuscriber/Task/CacheCleanTaskEventSubscriber.php b/core/EventSuscriber/Task/CacheCleanTaskEventSubscriber.php
new file mode 100644
index 0000000..d682d48
--- /dev/null
+++ b/core/EventSuscriber/Task/CacheCleanTaskEventSubscriber.php
@@ -0,0 +1,36 @@
+
+ */
+class CacheCleanTaskEventSubscriber extends TaskEventSubscriber
+{
+ protected SymfonyCacheManager $cacheManager;
+
+ public function __construct(SymfonyCacheManager $cacheManager)
+ {
+ $this->cacheManager = $cacheManager;
+ }
+
+ public function onInit(TaskInitEvent $event)
+ {
+ $event->addTask('cache:clear', 'Clean all cache', '♻️ Cache');
+ }
+
+ public function onRunRequest(TaskRunRequestedEvent $event)
+ {
+ if ('cache:clear' !== $event->getTask()) {
+ return;
+ }
+
+ $this->cacheManager->cleanAll($event->getOutput());
+ }
+}
diff --git a/core/EventSuscriber/Task/TaskEventSubscriber.php b/core/EventSuscriber/Task/TaskEventSubscriber.php
new file mode 100644
index 0000000..a6ab5d8
--- /dev/null
+++ b/core/EventSuscriber/Task/TaskEventSubscriber.php
@@ -0,0 +1,33 @@
+
+ */
+abstract class TaskEventSubscriber implements EventSubscriberInterface
+{
+ protected static int $priority = 0;
+
+ public static function getSubscribedEvents()
+ {
+ return [
+ TaskInitEvent::INIT_EVENT => ['onInit', self::$priority],
+ TaskRunRequestedEvent::RUN_REQUEST_EVENT => ['onRunRequest', self::$priority],
+ ];
+ }
+
+ public function onInit(TaskInitEvent $event)
+ {
+ }
+
+ public function onRunRequest(TaskRunRequestedEvent $event)
+ {
+ }
+}
diff --git a/core/Form/Site/NodeType.php b/core/Form/Site/NodeType.php
index e652931..7998567 100644
--- a/core/Form/Site/NodeType.php
+++ b/core/Form/Site/NodeType.php
@@ -73,6 +73,20 @@ class NodeType extends AbstractType
]
);
+ $builder->add(
+ 'contentType',
+ TextType::class,
+ [
+ 'label' => 'Content type',
+ 'required' => false,
+ 'help' => 'Leave blank equals "text/html"',
+ 'attr' => [
+ ],
+ 'constraints' => [
+ ],
+ ]
+ );
+
$builder->add(
'controller',
TextType::class,
diff --git a/core/Resources/translations/messages.fr.yaml b/core/Resources/translations/messages.fr.yaml
index 9ad1233..b6fe635 100644
--- a/core/Resources/translations/messages.fr.yaml
+++ b/core/Resources/translations/messages.fr.yaml
@@ -151,3 +151,9 @@
"Force this domain": "Forcer ce nom de domaine"
"Additional domains": "Domaines additionnels"
"Regular expression: do not add the delimiter": "Expréssion régulière : ne pas ajouter de délimiteur"
+"Content type": "Type de contenu"
+'Leave blank equals "text/html"': 'Laissez vide équivaut à "text/html"'
+"Close": "Fermer"
+"Tasks": "Tâches"
+"Results": "Résultats"
+"Clean all cache": "Nettoyer tout le cache"
diff --git a/core/Resources/views/admin/module/menu.html.twig b/core/Resources/views/admin/module/menu.html.twig
index e684a6b..d09222d 100644
--- a/core/Resources/views/admin/module/menu.html.twig
+++ b/core/Resources/views/admin/module/menu.html.twig
@@ -68,6 +68,16 @@
+
+
+
+