Skip to content

Commit

Permalink
feat!: Changed all node exports to CSV format.
Browse files Browse the repository at this point in the history
  • Loading branch information
roadiz-ci committed Jul 24, 2024
1 parent 0d97633 commit 63fdcb6
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 117 deletions.
59 changes: 30 additions & 29 deletions src/Controllers/Nodes/ExportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -83,8 +86,6 @@ public function exportAllXlsxAction(Request $request, int $translationId, ?int $
)
);

$response->prepare($request);

return $response;
}
}
170 changes: 83 additions & 87 deletions src/Controllers/SearchController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
) {
}

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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"]);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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();

Expand All @@ -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;
Expand Down Expand Up @@ -657,6 +654,5 @@ private function extendForm(FormBuilderInterface $builder, NodeType $nodetype):
$builder->add($field->getVarName(), $type, $option);
}
}
return $builder;
}
}
Loading

0 comments on commit 63fdcb6

Please sign in to comment.