diff --git a/src/Controllers/Nodes/ExportController.php b/src/Controllers/Nodes/ExportController.php
index abc4d1f1..3b1f02ef 100644
--- a/src/Controllers/Nodes/ExportController.php
+++ b/src/Controllers/Nodes/ExportController.php
@@ -4,77 +4,80 @@
namespace Themes\Rozier\Controllers\Nodes;
-use PhpOffice\PhpSpreadsheet\Writer\Exception;
+use Doctrine\Persistence\ManagerRegistry;
use RZ\Roadiz\CoreBundle\Entity\Node;
use RZ\Roadiz\CoreBundle\Entity\NodesSources;
use RZ\Roadiz\CoreBundle\Entity\Translation;
use RZ\Roadiz\CoreBundle\Security\Authorization\Voter\NodeVoter;
-use RZ\Roadiz\CoreBundle\Xlsx\NodeSourceXlsxSerializer;
-use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\Serializer\SerializerInterface;
use Themes\Rozier\RozierApp;
class ExportController extends RozierApp
{
- public function __construct(private readonly NodeSourceXlsxSerializer $xlsxSerializer)
- {
+ public function __construct(
+ private readonly ManagerRegistry $managerRegistry,
+ private readonly SerializerInterface $serializer
+ ) {
}
/**
- * Export all Node in a XLSX file (Excel).
+ * Export all Node in a CSV file.
*
- * @param Request $request
* @param int $translationId
* @param int|null $parentNodeId
*
* @return Response
- * @throws \PhpOffice\PhpSpreadsheet\Exception
- * @throws Exception
*/
- public function exportAllXlsxAction(Request $request, int $translationId, ?int $parentNodeId = null): Response
+ public function exportAllAction(int $translationId, ?int $parentNodeId = null): Response
{
- $translation = $this->em()
- ->find(Translation::class, $translationId);
+ $translation = $this->managerRegistry
+ ->getRepository(Translation::class)
+ ->find($translationId);
if (null === $translation) {
- $translation = $this->em()
+ $translation = $this->managerRegistry
->getRepository(Translation::class)
->findDefault();
}
$criteria = ["translation" => $translation];
$order = ['node.nodeType' => 'ASC'];
- $filename = 'nodes-' . date("YmdHis") . '.' . $translation->getLocale() . '.xlsx';
+ $filename = 'nodes-' . date("YmdHis") . '.' . $translation->getLocale() . '.csv';
if (null !== $parentNodeId) {
/** @var Node|null $parentNode */
- $parentNode = $this->em()->find(Node::class, $parentNodeId);
+ $parentNode = $this->managerRegistry
+ ->getRepository(Node::class)
+ ->find($parentNodeId);
if (null === $parentNode) {
throw $this->createNotFoundException();
}
$this->denyAccessUnlessGranted(NodeVoter::READ, $parentNode);
$criteria['node.parent'] = $parentNode;
- $filename = $parentNode->getNodeName() . '-' . date("YmdHis") . '.' . $translation->getLocale() . '.xlsx';
+ $filename = $parentNode->getNodeName() . '-' . date("YmdHis") . '.' . $translation->getLocale() . '.csv';
} else {
$this->denyAccessUnlessGranted(NodeVoter::READ_AT_ROOT);
}
- $sources = $this->em()
+ $sources = $this->managerRegistry
->getRepository(NodesSources::class)
->setDisplayingAllNodesStatuses(true)
->setDisplayingNotPublishedNodes(true)
->findBy($criteria, $order);
- $this->xlsxSerializer->setOnlyTexts(true);
- $this->xlsxSerializer->addUrls();
- $xlsx = $this->xlsxSerializer->serialize($sources);
-
- $response = new Response(
- $xlsx,
- Response::HTTP_OK,
- []
- );
-
+ $response = new StreamedResponse(function () use ($sources) {
+ echo $this->serializer->serialize($sources, 'csv', [
+ 'groups' => [
+ 'nodes_sources',
+ 'urls',
+ 'tag_base',
+ 'document_display',
+ ],
+ ]);
+ });
+ $response->headers->set('Content-Type', 'text/csv');
$response->headers->set(
'Content-Disposition',
$response->headers->makeDisposition(
@@ -83,8 +86,6 @@ public function exportAllXlsxAction(Request $request, int $translationId, ?int $
)
);
- $response->prepare($request);
-
return $response;
}
}
diff --git a/src/Controllers/SearchController.php b/src/Controllers/SearchController.php
index e615d884..34529eb9 100644
--- a/src/Controllers/SearchController.php
+++ b/src/Controllers/SearchController.php
@@ -5,7 +5,7 @@
namespace Themes\Rozier\Controllers;
use DateTime;
-use PhpOffice\PhpSpreadsheet\Exception;
+use Doctrine\Persistence\ManagerRegistry;
use RZ\Roadiz\Core\AbstractEntities\AbstractField;
use RZ\Roadiz\CoreBundle\Entity\Node;
use RZ\Roadiz\CoreBundle\Entity\NodeType;
@@ -17,7 +17,6 @@
use RZ\Roadiz\CoreBundle\Form\NodeStatesType;
use RZ\Roadiz\CoreBundle\Form\NodeTypesType;
use RZ\Roadiz\CoreBundle\Form\SeparatorType;
-use RZ\Roadiz\CoreBundle\Xlsx\NodeSourceXlsxSerializer;
use Symfony\Component\Form\ClickableInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@@ -28,11 +27,14 @@
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Constraints\GreaterThan;
use Themes\Rozier\Forms\NodeSource\NodeSourceType;
use Themes\Rozier\RozierApp;
@@ -43,8 +45,11 @@ class SearchController extends RozierApp
protected bool $pagination = true;
protected ?int $itemPerPage = null;
- public function __construct(protected readonly NodeSourceXlsxSerializer $xlsxSerializer)
- {
+ public function __construct(
+ protected readonly ManagerRegistry $managerRegistry,
+ protected readonly FormFactoryInterface $formFactory,
+ protected readonly SerializerInterface $serializer
+ ) {
}
/**
@@ -87,9 +92,9 @@ protected function appendDateTimeCriteria(array &$data, string $fieldName): arra
/**
* @param array $data
* @param string $prefix
- * @return mixed
+ * @return array
*/
- protected function processCriteria($data, string $prefix = ""): mixed
+ protected function processCriteria(array $data, string $prefix = ""): array
{
if (!empty($data[$prefix . "nodeName"])) {
if (!isset($data[$prefix . "nodeName_exact"]) || $data[$prefix . "nodeName_exact"] !== true) {
@@ -131,7 +136,7 @@ protected function processCriteria($data, string $prefix = ""): mixed
if (isset($data["tags"])) {
$data["tags"] = array_map('trim', explode(',', $data["tags"]));
foreach ($data["tags"] as $key => $value) {
- $data["tags"][$key] = $this->em()->getRepository(Tag::class)->findByPath($value);
+ $data["tags"][$key] = $this->managerRegistry->getRepository(Tag::class)->findByPath($value);
}
array_filter($data["tags"]);
}
@@ -255,14 +260,12 @@ public function searchNodeAction(Request $request): Response
* @param int $nodetypeId
*
* @return Response
- * @throws Exception
- * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
* @throws RuntimeError
*/
public function searchNodeSourceAction(Request $request, int $nodetypeId): Response
{
/** @var NodeType|null $nodetype */
- $nodetype = $this->em()->find(NodeType::class, $nodetypeId);
+ $nodetype = $this->managerRegistry->getRepository(NodeType::class)->find($nodetypeId);
$builder = $this->buildSimpleForm("__node__");
$this->extendForm($builder, $nodetype);
@@ -279,7 +282,7 @@ public function searchNodeSourceAction(Request $request, int $nodetypeId): Respo
return $response;
}
- if (null !== $response = $this->handleNodeForm($request, $form, $nodetype)) {
+ if (null !== $response = $this->handleNodeForm($form, $nodetype)) {
return $response;
}
@@ -298,7 +301,7 @@ public function searchNodeSourceAction(Request $request, int $nodetypeId): Respo
*/
protected function buildNodeTypeForm(?int $nodetypeId = null): FormBuilderInterface
{
- $builderNodeType = $this->createNamedFormBuilder('nodeTypeForm', [], ["method" => "get"]);
+ $builderNodeType = $this->formFactory->createNamedBuilder('nodeTypeForm', FormType::class, [], ["method" => "get"]);
$builderNodeType->add(
"nodetype",
NodeTypesType::class,
@@ -365,87 +368,84 @@ protected function handleNodeTypeForm(FormInterface $nodeTypeForm): ?RedirectRes
}
/**
- * @param Request $request
* @param FormInterface $form
* @param NodeType $nodetype
*
* @return null|Response
- * @throws Exception
- * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/
- protected function handleNodeForm(Request $request, FormInterface $form, NodeType $nodetype): ?Response
+ protected function handleNodeForm(FormInterface $form, NodeType $nodetype): ?Response
{
- if ($form->isSubmitted() && $form->isValid()) {
- $data = [];
- foreach ($form->getData() as $key => $value) {
- if (
- (!is_array($value) && $this->notBlank($value))
- || (is_array($value) && isset($value["compareDatetime"]))
- || (is_array($value) && isset($value["compareDate"]))
- || (is_array($value) && $value != [] && !isset($value["compareOp"]))
- ) {
- if (\is_string($key) & \str_contains($key, "__node__")) {
- /** @var string $newKey */
- $newKey = \str_replace("__node__", "node.", $key);
- $data[$newKey] = $value;
- } else {
- $data[$key] = $value;
- }
- }
- }
- $data = $this->processCriteria($data, "node.");
- $data = $this->processCriteriaNodetype($data, $nodetype);
-
- $listManager = $this->createEntityListManager(
- $nodetype->getSourceEntityFullQualifiedClassName(),
- $data
- );
- $listManager->setDisplayingNotPublishedNodes(true);
- $listManager->setDisplayingAllNodesStatuses(true);
- if ($this->pagination === false) {
- $listManager->setItemPerPage($this->itemPerPage ?? 999);
- $listManager->disablePagination();
- }
- $listManager->handle();
- $entities = $listManager->getEntities();
- $nodes = [];
- foreach ($entities as $nodesSource) {
- if (!in_array($nodesSource->getNode(), $nodes)) {
- $nodes[] = $nodesSource->getNode();
+ if (!$form->isSubmitted() || !$form->isValid()) {
+ return null;
+ }
+ $data = [];
+ foreach ($form->getData() as $key => $value) {
+ if (
+ (!is_array($value) && $this->notBlank($value))
+ || (is_array($value) && isset($value["compareDatetime"]))
+ || (is_array($value) && isset($value["compareDate"]))
+ || (is_array($value) && $value != [] && !isset($value["compareOp"]))
+ ) {
+ if (\is_string($key) & \str_contains($key, "__node__")) {
+ /** @var string $newKey */
+ $newKey = \str_replace("__node__", "node.", $key);
+ $data[$newKey] = $value;
+ } else {
+ $data[$key] = $value;
}
}
- /*
- * Export all entries into XLSX format
- */
- $button = $form->get('export');
- if ($button instanceof ClickableInterface && $button->isClicked()) {
- $filename = 'search-' . $nodetype->getName() . '-' . date("YmdHis") . '.xlsx';
- $this->xlsxSerializer->setOnlyTexts(true);
- $this->xlsxSerializer->addUrls();
- $xlsx = $this->xlsxSerializer->serialize($entities);
-
- $response = new Response(
- $xlsx,
- Response::HTTP_OK,
- []
- );
-
- $response->headers->set(
- 'Content-Disposition',
- $response->headers->makeDisposition(
- ResponseHeaderBag::DISPOSITION_ATTACHMENT,
- $filename
- )
- );
+ }
+ $data = $this->processCriteria($data, "node.");
+ $data = $this->processCriteriaNodetype($data, $nodetype);
- $response->prepare($request);
- return $response;
+ $listManager = $this->createEntityListManager(
+ $nodetype->getSourceEntityFullQualifiedClassName(),
+ $data
+ );
+ $listManager->setDisplayingNotPublishedNodes(true);
+ $listManager->setDisplayingAllNodesStatuses(true);
+ if ($this->pagination === false) {
+ $listManager->setItemPerPage($this->itemPerPage ?? 999);
+ $listManager->disablePagination();
+ }
+ $listManager->handle();
+ $entities = $listManager->getEntities();
+ $nodes = [];
+ foreach ($entities as $nodesSource) {
+ if (!in_array($nodesSource->getNode(), $nodes)) {
+ $nodes[] = $nodesSource->getNode();
}
-
- $this->assignation['filters'] = $listManager->getAssignation();
- $this->assignation['nodesSources'] = $entities;
- $this->assignation['nodes'] = $nodes;
}
+ /*
+ * Export all entries into XLSX format
+ */
+ $button = $form->get('export');
+ if ($button instanceof ClickableInterface && $button->isClicked()) {
+ $filename = 'search-' . $nodetype->getName() . '-' . date("YmdHis") . '.csv';
+ $response = new StreamedResponse(function () use ($entities) {
+ echo $this->serializer->serialize($entities, 'csv', [
+ 'groups' => [
+ 'nodes_sources',
+ 'urls',
+ 'tag_base',
+ 'document_display',
+ ],
+ ]);
+ });
+ $response->headers->set('Content-Type', 'text/csv');
+ $response->headers->set(
+ 'Content-Disposition',
+ $response->headers->makeDisposition(
+ ResponseHeaderBag::DISPOSITION_ATTACHMENT,
+ $filename
+ )
+ );
+ return $response;
+ }
+
+ $this->assignation['filters'] = $listManager->getAssignation();
+ $this->assignation['nodesSources'] = $entities;
+ $this->assignation['nodes'] = $nodes;
return null;
}
@@ -559,9 +559,8 @@ protected function createTextSearchForm(
/**
* @param FormBuilderInterface $builder
* @param NodeType $nodetype
- * @return FormBuilderInterface
*/
- private function extendForm(FormBuilderInterface $builder, NodeType $nodetype): FormBuilderInterface
+ private function extendForm(FormBuilderInterface $builder, NodeType $nodetype): void
{
$fields = $nodetype->getFields();
@@ -587,8 +586,6 @@ private function extendForm(FormBuilderInterface $builder, NodeType $nodetype):
);
}
-
- /** @var NodeTypeField $field */
foreach ($fields as $field) {
$option = ["label" => $field->getLabel()];
$option['required'] = false;
@@ -657,6 +654,5 @@ private function extendForm(FormBuilderInterface $builder, NodeType $nodetype):
$builder->add($field->getVarName(), $type, $option);
}
}
- return $builder;
}
}
diff --git a/src/Resources/translations/messages.en.xlf b/src/Resources/translations/messages.en.xlf
index c4378271..30bc0cc2 100644
--- a/src/Resources/translations/messages.en.xlf
+++ b/src/Resources/translations/messages.en.xlf
@@ -4069,6 +4069,10 @@
Excel file format (%language%)
+
+
+ CSV file format (%language%)
+
diff --git a/src/Resources/translations/messages.fr.xlf b/src/Resources/translations/messages.fr.xlf
index 1142ebc5..bc91e2e1 100644
--- a/src/Resources/translations/messages.fr.xlf
+++ b/src/Resources/translations/messages.fr.xlf
@@ -4069,6 +4069,10 @@
Format de fichier Excel (%language%)
+
+
+ Format de fichier CSV (%language%)
+
diff --git a/src/Resources/translations/messages.xlf b/src/Resources/translations/messages.xlf
index e2b993d9..0914a9cd 100644
--- a/src/Resources/translations/messages.xlf
+++ b/src/Resources/translations/messages.xlf
@@ -1151,6 +1151,7 @@
+
diff --git a/src/Resources/views/nodes/list.html.twig b/src/Resources/views/nodes/list.html.twig
index 6797b9ab..4ee76478 100644
--- a/src/Resources/views/nodes/list.html.twig
+++ b/src/Resources/views/nodes/list.html.twig
@@ -25,7 +25,7 @@