From 03f1eb97e00a5686a053b37c5cf661ffcf0099d8 Mon Sep 17 00:00:00 2001 From: Benjamin Perche Date: Thu, 17 Jul 2014 14:04:40 +0200 Subject: [PATCH] =?UTF-8?q?Refactor=20ImportExportController::export=20=09?= =?UTF-8?q?modifi=C3=A9:=20=20=20=20=20=20=20=20=20core/lib/Thelia/Control?= =?UTF-8?q?ler/Admin/ImportExportController.php=20=09renomm=C3=A9:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20core/lib/Thelia/Core/Event/ImportExport/Ex?= =?UTF-8?q?port.php=20->=20core/lib/Thelia/Core/Event/ImportExport.php=20?= =?UTF-8?q?=09modifi=C3=A9:=20=20=20=20=20=20=20=20=20core/lib/Thelia/Core?= =?UTF-8?q?/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php=20?= =?UTF-8?q?=09modifi=C3=A9:=20=20=20=20=20=20=20=20=20core/lib/Thelia/Core?= =?UTF-8?q?/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php=20?= =?UTF-8?q?=09modifi=C3=A9:=20=20=20=20=20=20=20=20=20core/lib/Thelia/Core?= =?UTF-8?q?/FileFormat/Archive/ArchiveBuilderManager.php=20=09modifi=C3=A9?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=20core/lib/Thelia/Core/FileFormat/For?= =?UTF-8?q?matting/FormatterManager.php=20=09modifi=C3=A9:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20core/lib/Thelia/Model/Import.php=20=09modifi=C3=A9:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20templates/backOffice/default/ajax/im?= =?UTF-8?q?port-modal.html=20=09modifi=C3=A9:=20=20=20=20=20=20=20=20=20te?= =?UTF-8?q?mplates/backOffice/default/import-page.html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/ImportExportController.php | 368 ++++++++++++++---- .../Export.php => ImportExport.php} | 29 +- .../ArchiveBuilder/TarBz2ArchiveBuilder.php | 2 +- .../ArchiveBuilder/TarGzArchiveBuilder.php | 2 +- .../Archive/ArchiveBuilderManager.php | 13 +- .../Formatting/FormatterManager.php | 21 +- core/lib/Thelia/Model/Import.php | 5 + .../backOffice/default/ajax/import-modal.html | 2 +- templates/backOffice/default/import-page.html | 2 +- 9 files changed, 354 insertions(+), 90 deletions(-) rename core/lib/Thelia/Core/Event/{ImportExport/Export.php => ImportExport.php} (84%) diff --git a/core/lib/Thelia/Controller/Admin/ImportExportController.php b/core/lib/Thelia/Controller/Admin/ImportExportController.php index c6320c1fc..685910200 100644 --- a/core/lib/Thelia/Controller/Admin/ImportExportController.php +++ b/core/lib/Thelia/Controller/Admin/ImportExportController.php @@ -11,15 +11,22 @@ /*************************************************************************************/ namespace Thelia\Controller\Admin; -use Thelia\Core\Event\ImportExport\Export as ExportEvent; +use Thelia\Core\Event\ImportExport as ImportExportEvent; use Thelia\Core\Event\TheliaEvents; +use Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder; +use Thelia\Core\FileFormat\Formatting\AbstractFormatter; use Thelia\Core\HttpFoundation\Response; use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Loop\ArchiveBuilder; use Thelia\Core\Template\Loop\Export as ExportLoop; use Thelia\Core\Template\Loop\Import as ImportLoop; +use Thelia\Core\Translation\Translator; use Thelia\Form\Exception\FormValidationException; use Thelia\Form\ExportForm; +use Thelia\Form\ImportForm; +use Thelia\ImportExport\AbstractHandler; use Thelia\ImportExport\Export\DocumentsExportInterface; +use Thelia\ImportExport\Export\ExportHandler; use Thelia\ImportExport\Export\ImagesExportInterface; use Thelia\Model\ExportQuery; use Thelia\Model\ImportQuery; @@ -61,7 +68,137 @@ class ImportExportController extends BaseAdminController */ $this->hydrate(); + $form = new ImportForm($this->getRequest()); + $errorMessage = null; + $successMessage = null; + + try { + $boundForm = $this->validateForm($form); + + /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */ + $file = $boundForm->get("file_upload")->getData(); + + /** + * We have to check the extension manually because of composed file formats as tar.gz or tar.bz2 + */ + $name = $file->getClientOriginalName(); + $nameLength = strlen($name); + + + $handler = $import->getHandleClassInstance($this->container); + $types = $handler->getHandledTypes(); + + $formats = + $this->formatterManager->getExtensionsByTypes($types, true) + + $this->archiveBuilderManager->getExtensions(true) + ; + + $uploadFormat = null; + + /** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter $formatter */ + $formatter = null; + + /** @var \Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder $archiveBuilder */ + $archiveBuilder = null; + + foreach ($formats as $format) { + $formatLength = strlen($format); + if ($nameLength >= $formatLength && substr($name, -$formatLength) === $formatLength) { + $uploadFormat = $format; + + $flip = array_flip($format); + + try { + $formatter = $this->formatterManager->get($flip[$format]); + } catch(\OutOfBoundsException $e) {} + + try { + $archiveBuilder = $this->archiveBuilderManager->get($flip[$format]); + } catch(\OutOfBoundsException $e) {} + + break; + } + } + + $splitName = explode(".", $name); + $ext = ""; + + if (1 < $limit = count($splitName)) { + $ext = "." . $splitName[$limit-1]; + } + + if ($uploadFormat === null) { + + + throw new FormValidationException( + $this->getTranslator()->trans( + "The extension \"%ext\" is not allowed", + [ + "%ext" => $ext + ] + ) + ); + } + + if ($archiveBuilder !== null) { + /** + * If the file is an archive + */ + $archiveBuilder->loadArchive($file->getPathname()); + $content = null; + + /** + * TODO: HANDLE + */ + + } elseif ($formatter !== null) { + /** + * If the file isn't + */ + + $content = file_get_contents($file->getPathname()); + + } else { + throw new \ErrorException( + $this->getTranslator()->trans( + "There's a problem, the extension \"%ext\" has been found, ". + "but has no formatters nor archive builder", + [ + "%ext" => $ext + ] + ) + ); + } + + $data = $formatter->decode($content); + + // Dispatch event + + $handler->retrieveFromFormatterData($data); + + $successMessage = $this->getTranslator()->trans("Import successfully done"); + + } catch(FormValidationException $e) { + $errorMessage = $this->createStandardFormValidationErrorMessage($e); + } catch(\Exception $e) { + $errorMessage = $e->getMessage(); + } + + if ($successMessage !== null) { + $this->getParserContext()->set("success_message", $successMessage); + } + + if ($errorMessage !== null) { + $form->setErrorMessage($errorMessage); + + $this->getParserContext() + ->addForm($form) + ->setGeneralError($errorMessage) + ; + } + + return $this->importView($id); } /** @@ -90,101 +227,45 @@ class ImportExportController extends BaseAdminController $archiveBuilders[$archiveBuilder] = $archiveBuilder; } - /** - * Get the allowed formatters to inject them into the form - */ - $handler = $export->getHandleClassInstance($this->container); - - $types = $handler->getHandledTypes(); - - $formatters = $this->formatterManager->getFormattersByTypes($types); - /** * Define and validate the form */ $form = new ExportForm($this->getRequest()); - $errorMessage = null; try { $boundForm = $this->validateForm($form); - $data = $handler->buildFormatterData(); + $archiveBuilder = null; + + /** + * Get the formatter and the archive builder if we have to compress the file(s) + */ /** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter $formatter */ $formatter = $this->formatterManager->get( $boundForm->get("formatter")->getData() ); - /** - * Build an event containing the formatter and the handler. - * Used for specific configuration (e.g: XML node names) - */ - $event = new ExportEvent($formatter, $handler); - - $filename = $formatter::FILENAME . "." . $formatter->getExtension(); - - if (!$boundForm->get("do_compress")->getData()) { - - if (!$boundForm->get("do_compress")->getData()) { - /** - * Dispatch the event - */ - $this->dispatch(TheliaEvents::BEFORE_EXPORT, $event); - - $formattedContent = $formatter->encode($data); - - return new Response( - $formattedContent, - 200, - [ - "Content-Type" => $formatter->getMimeType(), - "Content-Disposition" => - "attachment; filename=\"" . $filename . "\"", - ] - ); - } - } else { + if ($boundForm->get("do_compress")->getData()) { /** @var \Thelia\Core\FileFormat\Archive\ArchiveBuilderInterface $archiveBuilder */ $archiveBuilder = $this->archiveBuilderManager->get( $boundForm->get("archive_builder")->getData() ); - - $event->setArchiveBuilder($archiveBuilder); - $this->dispatch(TheliaEvents::BEFORE_EXPORT, $event); - - $formattedContent = $formatter->encode($data); - - $includeImages = $boundForm->get("images")->getData(); - $includeDocuments = $boundForm->get("documents")->getData(); - - if ($includeImages && $handler instanceof ImagesExportInterface) { - foreach ($handler->getImagesPaths() as $name => $documentPath) { - $archiveBuilder->addFile( - $documentPath, - $handler::IMAGES_DIRECTORY, - is_integer($name) ? null : $name - ); - } - } - - if ($includeDocuments && $handler instanceof DocumentsExportInterface) { - foreach ($handler->getDocumentsPaths() as $name => $documentPath) { - $archiveBuilder->addFile( - $documentPath, - $handler::DOCUMENTS_DIRECTORY, - is_integer($name) ? null : $name - ); - } - } - - $archiveBuilder->addFileFromString( - $formattedContent, $filename - ); - - return $archiveBuilder->buildArchiveResponse($formatter::FILENAME); } + /** + * Return the generated Response + */ + + return $this->processExport( + $formatter, + $export->getHandleClassInstance($this->container), + $archiveBuilder, + $boundForm->get("images")->getData(), + $boundForm->get("documents")->getData() + ); + } catch (FormValidationException $e) { $errorMessage = $this->createStandardFormValidationErrorMessage($e); } catch (\Exception $e) { @@ -206,6 +287,102 @@ class ImportExportController extends BaseAdminController return $this->exportView($id); } + /** + * @param AbstractFormatter $formatter + * @param ExportHandler $handler + * @param AbstractArchiveBuilder $archiveBuilder + * @param bool $includeImages + * @param bool $includeDocuments + * @return Response + * + * Processes an export by returning a response with the export's content. + */ + protected function processExport( + AbstractFormatter $formatter, + ExportHandler $handler, + AbstractArchiveBuilder $archiveBuilder = null, + $includeImages = false, + $includeDocuments = false + ) { + /** + * Build an event containing the formatter and the handler. + * Used for specific configuration (e.g: XML node names) + */ + $data = $handler->buildFormatterData(); + $event = new ImportExportEvent($formatter, $handler , $data); + + $filename = $formatter::FILENAME . "." . $formatter->getExtension(); + + if ($archiveBuilder === null) { + $this->dispatch(TheliaEvents::BEFORE_EXPORT, $event); + + $formattedContent = $formatter->encode($data); + + return new Response( + $formattedContent, + 200, + [ + "Content-Type" => $formatter->getMimeType(), + "Content-Disposition" => + "attachment; filename=\"" . $filename . "\"", + ] + ); + } else { + $event->setArchiveBuilder($archiveBuilder); + $this->dispatch(TheliaEvents::BEFORE_EXPORT, $event); + + $formattedContent = $formatter->encode($data); + + if ($includeImages && $handler instanceof ImagesExportInterface) { + $this->processExportImages($handler, $archiveBuilder); + } + + if ($includeDocuments && $handler instanceof DocumentsExportInterface) { + $this->processExportDocuments($handler, $archiveBuilder); + } + + $archiveBuilder->addFileFromString( + $formattedContent, $filename + ); + + return $archiveBuilder->buildArchiveResponse($formatter::FILENAME); + } + } + + /** + * @param ImagesExportInterface $handler + * @param AbstractArchiveBuilder $archiveBuilder + * + * Procedure that add images in the export's archive + */ + protected function processExportImages(ImagesExportInterface $handler, AbstractArchiveBuilder $archiveBuilder) + { + foreach ($handler->getImagesPaths() as $name => $documentPath) { + $archiveBuilder->addFile( + $documentPath, + $handler::IMAGES_DIRECTORY, + is_integer($name) ? null : $name + ); + } + } + + /** + * @param DocumentsExportInterface $handler + * @param AbstractArchiveBuilder $archiveBuilder + * + * Procedure that add documents in the export's archive + */ + protected function processExportDocuments(DocumentsExportInterface $handler, AbstractArchiveBuilder $archiveBuilder) + { + foreach ($handler->getDocumentsPaths() as $name => $documentPath) { + $archiveBuilder->addFile( + $documentPath, + $handler::DOCUMENTS_DIRECTORY, + is_integer($name) ? null : $name + ); + } + } + /** * @param integer $id * @return Response @@ -248,20 +425,34 @@ class ImportExportController extends BaseAdminController } /** - * Inject allowed formats + * Get allowed formats */ /** @var \Thelia\ImportExport\AbstractHandler $handler */ $this->hydrate(); $handler = $import->getHandleClassInstance($this->container); + $types = $handler->getHandledTypes(); + $formats = - $this->formatterManager->getExtensionsByTypes($handler->getHandledTypes(), true) + + $this->formatterManager->getExtensionsByTypes($types, true) + $this->archiveBuilderManager->getExtensions(true) ; - $parserContext->set( - "ALLOWED_EXTENSIONS", implode(", ", $formats) - ); + /** + * Get allowed mime types (used for the "Search a file" window + */ + $mimeTypes = + $this->formatterManager->getMimeTypesByTypes($types) + + $this->archiveBuilderManager->getMimeTypes() + ; + + /** + * Inject them in smarty + */ + $parserContext + ->set( "ALLOWED_MIME_TYPES", implode(",", $mimeTypes)) + ->set("ALLOWED_EXTENSIONS", implode(", ", $formats)) + ; /** Then render the form */ if ($this->getRequest()->isXmlHttpRequest()) { @@ -312,6 +503,11 @@ class ImportExportController extends BaseAdminController } } + /** + * Inject conditions in smarty, + * It is used to display or not the checkboxes "Include images" + * and "Include documents" + */ $this->getParserContext() ->set("HAS_IMAGES", $export->hasImages($this->container)) ->set("HAS_DOCUMENTS", $export->hasDocuments($this->container)) @@ -325,6 +521,12 @@ class ImportExportController extends BaseAdminController } } + /** + * @param $id + * @return array|mixed|\Thelia\Model\Export + * + * This method is a shortcut to get an export model + */ protected function getExport($id) { $export = ExportQuery::create() @@ -334,6 +536,12 @@ class ImportExportController extends BaseAdminController return $export; } + /** + * @param $id + * @return array|mixed|\Thelia\Model\Import + * + * This method is a shortcut to get an import model + */ protected function getImport($id) { $export = ImportQuery::create() diff --git a/core/lib/Thelia/Core/Event/ImportExport/Export.php b/core/lib/Thelia/Core/Event/ImportExport.php similarity index 84% rename from core/lib/Thelia/Core/Event/ImportExport/Export.php rename to core/lib/Thelia/Core/Event/ImportExport.php index 33f9ccc63..1c867ca69 100644 --- a/core/lib/Thelia/Core/Event/ImportExport/Export.php +++ b/core/lib/Thelia/Core/Event/ImportExport.php @@ -10,10 +10,11 @@ /* file that was distributed with this source code. */ /*************************************************************************************/ -namespace Thelia\Core\Event\ImportExport; +namespace Thelia\Core\Event; use Thelia\Core\Event\ActionEvent; use Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder; use Thelia\Core\FileFormat\Formatting\AbstractFormatter; +use Thelia\Core\FileFormat\Formatting\FormatterData; use Thelia\ImportExport\Export\ExportHandler; /** @@ -21,7 +22,7 @@ use Thelia\ImportExport\Export\ExportHandler; * @package Thelia\Core\Event\ImportExport * @author Benjamin Perche */ -class Export extends ActionEvent +class ImportExport extends ActionEvent { /** @var \Thelia\ImportExport\Export\ExportHandler */ protected $handler; @@ -29,17 +30,22 @@ class Export extends ActionEvent /** @var \Thelia\Core\FileFormat\Formatting\AbstractFormatter */ protected $formatter; + /** @var FormatterData */ + protected $data; + /** @var \Thelia\Core\FileFormat\Archive\AbstractArchiveBuilder */ protected $archiveBuilder; public function __construct( AbstractFormatter $formatter, \Thelia\ImportExport\Export\ExportHandler $handler, + FormatterData $data, AbstractArchiveBuilder $archiveBuilder = null ) { $this->archiveBuilder = $archiveBuilder; $this->formatter = $formatter; $this->handler = $handler; + $this->data = $data; } /** @@ -98,4 +104,23 @@ class Export extends ActionEvent { return $this->handler; } + + /** + * @param FormatterData $data + * @return $this + */ + public function setData(FormatterData $data) + { + $this->data = $data; + + return $this; + } + + /** + * @return \Thelia\Core\FileFormat\Formatting\FormatterData + */ + public function getData() + { + return $this->data; + } } diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php index 774d082df..081e38a09 100644 --- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php +++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php @@ -26,7 +26,7 @@ class TarBz2ArchiveBuilder extends TarArchiveBuilder public function getMimeType() { - return "application/x-gtar"; + return "application/x-bzip2"; } public function getExtension() diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php index 4722417fa..b8519c539 100644 --- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php +++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php @@ -26,7 +26,7 @@ class TarGzArchiveBuilder extends TarArchiveBuilder public function getMimeType() { - return "application/x-gtar"; + return "application/x-gzip"; } public function getExtension() diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilderManager.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilderManager.php index 31c9fa4d9..e872d9e74 100644 --- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilderManager.php +++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilderManager.php @@ -117,7 +117,7 @@ class ArchiveBuilderManager foreach ($this->archiveBuilders as $archiveBuilder) { $extensionName = $withDot ? ".": ""; $extensionName .= $archiveBuilder->getExtension(); - $extensions += [$archiveBuilder->getName() => $extensionName]; + $extensions[$archiveBuilder->getName()] = $extensionName; } return $extensions; @@ -140,4 +140,15 @@ class ArchiveBuilderManager return $this->archiveBuilders[$archiveBuilderName]; } } + + public function getMimeTypes() { + $mimeTypes = []; + + /** @var AbstractArchiveBuilder $formatter */ + foreach ($this->archiveBuilders as $formatter) { + $mimeTypes[$formatter->getName()] = $formatter->getMimeType(); + } + + return $mimeTypes; + } } diff --git a/core/lib/Thelia/Core/FileFormat/Formatting/FormatterManager.php b/core/lib/Thelia/Core/FileFormat/Formatting/FormatterManager.php index 4932f8ff3..90c0c755e 100644 --- a/core/lib/Thelia/Core/FileFormat/Formatting/FormatterManager.php +++ b/core/lib/Thelia/Core/FileFormat/Formatting/FormatterManager.php @@ -113,7 +113,7 @@ class FormatterManager foreach ($this->formatters as $formatter) { $extensionName = $withDot ? ".": ""; $extensionName .= $formatter->getExtension(); - $extensions += [$formatter->getName() => $extensionName]; + $extensions[$formatter->getName()] = $extensionName; } return $extensions; @@ -126,7 +126,7 @@ class FormatterManager foreach ($this->getFormattersByTypes($types) as $formatter) { $extensionName = $withDot ? ".": ""; $extensionName .= $formatter->getExtension(); - $extensions += [$formatter->getName() => $extensionName]; + $extensions[$formatter->getName()] = $extensionName; } return $extensions; @@ -167,10 +167,25 @@ class FormatterManager $handledType = $formatter->getHandledType(); if (in_array($handledType, $types)) { - $selectedFormatters += [$formatter->getName() => $formatter]; + $selectedFormatters[$formatter->getName()] = $formatter; } } return $selectedFormatters; } + + public function getMimeTypesByTypes($types) { + if (!is_array($types)) { + $types = [$types]; + } + + $mimeTypes = []; + + /** @var AbstractFormatter $formatter */ + foreach ($this->getFormattersByTypes($types) as $formatter) { + $mimeTypes[$formatter->getName()] = $formatter->getMimeType(); + } + + return $mimeTypes; + } } diff --git a/core/lib/Thelia/Model/Import.php b/core/lib/Thelia/Model/Import.php index f24e9ff02..5993e3d34 100644 --- a/core/lib/Thelia/Model/Import.php +++ b/core/lib/Thelia/Model/Import.php @@ -92,6 +92,11 @@ class Import extends BaseImport return $this; } + /** + * @param ContainerInterface $container + * @return ImportHandler + * @throws \ErrorException + */ public function getHandleClassInstance(ContainerInterface $container) { $class = $this->getHandleClass(); diff --git a/templates/backOffice/default/ajax/import-modal.html b/templates/backOffice/default/ajax/import-modal.html index e7942e825..dfbdded49 100644 --- a/templates/backOffice/default/ajax/import-modal.html +++ b/templates/backOffice/default/ajax/import-modal.html @@ -9,7 +9,7 @@ diff --git a/templates/backOffice/default/import-page.html b/templates/backOffice/default/import-page.html index e584e9c38..63a2b9b55 100644 --- a/templates/backOffice/default/import-page.html +++ b/templates/backOffice/default/import-page.html @@ -40,7 +40,7 @@
{custom_render_form_field form=$form field="file_upload"} - +
Accepted formats: {$ALLOWED_EXTENSIONS}
{/custom_render_form_field}