Refactor ImportExportController::export

modifié:         core/lib/Thelia/Controller/Admin/ImportExportController.php
	renommé:         core/lib/Thelia/Core/Event/ImportExport/Export.php -> core/lib/Thelia/Core/Event/ImportExport.php
	modifié:         core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarBz2ArchiveBuilder.php
	modifié:         core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php
	modifié:         core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilderManager.php
	modifié:         core/lib/Thelia/Core/FileFormat/Formatting/FormatterManager.php
	modifié:         core/lib/Thelia/Model/Import.php
	modifié:         templates/backOffice/default/ajax/import-modal.html
	modifié:         templates/backOffice/default/import-page.html
This commit is contained in:
Benjamin Perche
2014-07-17 14:04:40 +02:00
parent a16b481059
commit 03f1eb97e0
9 changed files with 354 additions and 90 deletions

View File

@@ -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()

View File

@@ -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 <bperche@openstudio.fr>
*/
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;
}
}

View File

@@ -26,7 +26,7 @@ class TarBz2ArchiveBuilder extends TarArchiveBuilder
public function getMimeType()
{
return "application/x-gtar";
return "application/x-bzip2";
}
public function getExtension()

View File

@@ -26,7 +26,7 @@ class TarGzArchiveBuilder extends TarArchiveBuilder
public function getMimeType()
{
return "application/x-gtar";
return "application/x-gzip";
}
public function getExtension()

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -9,7 +9,7 @@
</div>
<div class="modal-body">
{custom_render_form_field form=$form field="file_upload"}
<input type="file" required aria-required="true" name="{$name}" id="{$label_attr.for}" />
<input type="file" required aria-required="true" name="{$name}" id="{$label_attr.for}" accept="{$ALLOWED_MIME_TYPES}"/>
<div class="small">Accepted formats: {$ALLOWED_EXTENSIONS}</div>
{/custom_render_form_field}
</div>

View File

@@ -40,7 +40,7 @@
<form action="{$URL}" method="post" {form_enctype form=$form}>
{custom_render_form_field form=$form field="file_upload"}
<input type="file" required aria-required="true" name="{$name}" id="{$label_attr.for}" />
<input type="file" required aria-required="true" name="{$name}" id="{$label_attr.for}" accept="{$ALLOWED_MIME_TYPES}"/>
<div class="small">Accepted formats: {$ALLOWED_EXTENSIONS}</div>
{/custom_render_form_field}