diff --git a/core/lib/Thelia/Config/Resources/export.xml b/core/lib/Thelia/Config/Resources/export.xml
index b212b8dbc..9d7bf8949 100644
--- a/core/lib/Thelia/Config/Resources/export.xml
+++ b/core/lib/Thelia/Config/Resources/export.xml
@@ -13,6 +13,10 @@
Products
Produits
+
+ Content
+ Contenu
+
@@ -64,5 +68,20 @@
+
+
+
+ Contents and folder
+
+ Export your contents and their related folders
+
+
+
+ Contenus et dossiers
+
+ Exportez vos contenus et les dossiers associƩs
+
+
+
diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarArchiveBuilder.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarArchiveBuilder.php
index b455a6e0b..99b6dcded 100644
--- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarArchiveBuilder.php
+++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarArchiveBuilder.php
@@ -72,8 +72,14 @@ class TarArchiveBuilder extends AbstractArchiveBuilder
*/
public function addFile($filePath, $directoryInArchive = "/", $name = null, $isOnline = false)
{
+ if (!empty($name)) {
+ $directoryInArchive .= DS . dirname($name);
+ }
+
if (empty($name) || !is_scalar($name)) {
$name = basename($filePath);
+ } else {
+ $name = basename($name);
}
/**
diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php
index b8519c539..bdb95e432 100644
--- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php
+++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/TarGzArchiveBuilder.php
@@ -34,14 +34,10 @@ class TarGzArchiveBuilder extends TarArchiveBuilder
return "tar.gz";
}
- public function setEnvironment($environment)
+ protected function compressionEntryPoint()
{
- parent::setEnvironment($environment);
-
- $this->previousFile = $this->cacheFile;
-
if ($this->compression != \Phar::GZ) {
- $this->tar = $this->tar->compress(\Phar::BZ2, $this->getExtension());
+ $this->tar = $this->tar->compress(\Phar::GZ, $this->getExtension());
}
$this->compression = \Phar::GZ;
diff --git a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/ZipArchiveBuilder.php b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/ZipArchiveBuilder.php
index ab31d2a51..dcaac183e 100644
--- a/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/ZipArchiveBuilder.php
+++ b/core/lib/Thelia/Core/FileFormat/Archive/ArchiveBuilder/ZipArchiveBuilder.php
@@ -74,6 +74,10 @@ class ZipArchiveBuilder extends AbstractArchiveBuilder
*/
public function addFile($filePath, $directoryInArchive = null, $name = null, $isOnline = false)
{
+ if (!empty($name)) {
+ $directoryInArchive .= DS . dirname($name) ;
+ }
+
$directoryInArchive = $this->formatDirectoryPath($directoryInArchive);
/**
@@ -86,6 +90,8 @@ class ZipArchiveBuilder extends AbstractArchiveBuilder
if (empty($name) || !is_scalar($name)) {
$name = basename($filePath);
+ } else {
+ $name = basename($name);
}
/**
@@ -178,7 +184,10 @@ class ZipArchiveBuilder extends AbstractArchiveBuilder
$directoryInArchive = $this->formatDirectoryPath($directoryPath);
if (!empty($directoryInArchive)) {
- if (!$this->zip->addEmptyDir($directoryInArchive)) {
+ $this->zip->addEmptyDir($directoryInArchive);
+ $this->commit();
+
+ if (!$this->hasDirectory($directoryInArchive)) {
throw new \ErrorException(
$this->translator->trans(
"The directory %dir has not been created in the archive",
diff --git a/core/lib/Thelia/Core/FileFormat/Formatting/Formatter/CSVFormatter.php b/core/lib/Thelia/Core/FileFormat/Formatting/Formatter/CSVFormatter.php
index b8ef4b69d..af977be57 100644
--- a/core/lib/Thelia/Core/FileFormat/Formatting/Formatter/CSVFormatter.php
+++ b/core/lib/Thelia/Core/FileFormat/Formatting/Formatter/CSVFormatter.php
@@ -116,7 +116,9 @@ class CSVFormatter extends AbstractFormatter
ksort($row);
foreach ($keys as $key) {
- $string .= $this->formatField($row[$key]);
+ if (array_key_exists($key, $row)) {
+ $string .= $this->formatField($row[$key]);
+ }
}
$string = substr($string,0, -$delimiterLength) . $this->lineReturn;
diff --git a/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php b/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php
new file mode 100644
index 000000000..8c6ddcaae
--- /dev/null
+++ b/core/lib/Thelia/ImportExport/Export/Type/ContentExport.php
@@ -0,0 +1,303 @@
+
+ */
+class ContentExport extends ExportHandler implements
+ ImagesExportInterface,
+ DocumentsExportInterface
+{
+ const DIRECTORY_NAME = "content";
+
+ /**
+ * @return string|array
+ *
+ * Define all the type of formatters that this can handle
+ * return a string if it handle a single type ( specific exports ),
+ * or an array if multiple.
+ *
+ * Thelia types are defined in \Thelia\Core\FileFormat\FormatType
+ *
+ * example:
+ * return array(
+ * FormatType::TABLE,
+ * FormatType::UNBOUNDED,
+ * );
+ */
+ public function getHandledTypes()
+ {
+ return array(
+ FormatType::TABLE,
+ FormatType::UNBOUNDED,
+ );
+ }
+
+ /**
+ * @param Lang $lang
+ * @return ModelCriteria|array|BaseLoop
+ */
+ public function buildDataSet(Lang $lang)
+ {
+ $locale = $lang->getLocale();
+
+ $contentI18nJoin = new Join(ContentTableMap::ID, ContentI18nTableMap::ID, Criteria::LEFT_JOIN);
+ $folderI18nJoin = new Join(FolderTableMap::ID, FolderI18nTableMap::ID, Criteria::LEFT_JOIN);
+ $urlJoin = new Join(ContentTableMap::ID, RewritingUrlTableMap::VIEW_ID, Criteria::LEFT_JOIN);
+
+
+ $query = ContentQuery::create()
+ ->_if($this->isImageExport())
+ ->useContentImageQuery("content_image_join", Criteria::LEFT_JOIN)
+ ->addAsColumn("content_IMAGES", "GROUP_CONCAT(DISTINCT `content_image_join`.FILE)")
+ ->endUse()
+ ->_endif()
+ ->_if($this->isDocumentExport())
+ ->useContentDocumentQuery()
+ ->addAsColumn("content_DOCUMENTS", "GROUP_CONCAT(DISTINCT ".ContentDocumentTableMap::FILE.")")
+ ->endUse()
+ ->_endif()
+ ->useContentFolderQuery(null, Criteria::LEFT_JOIN)
+ ->useFolderQuery(null, Criteria::LEFT_JOIN)
+ ->_if($this->isDocumentExport())
+ ->useFolderDocumentQuery()
+ ->addAsColumn("folder_DOCUMENTS", "GROUP_CONCAT(DISTINCT ".FolderDocumentTableMap::FILE.")")
+ ->endUse()
+ ->_endif()
+ ->_if($this->isImageExport())
+ ->useFolderImageQuery(null, Criteria::LEFT_JOIN)
+ ->addAsColumn("folder_IMAGES", "GROUP_CONCAT(DISTINCT ".FolderImageTableMap::FILE.")")
+ ->endUse()
+ ->_endif()
+ ->addJoinObject($folderI18nJoin, "folder_i18n_join")
+ ->addJoinCondition("folder_i18n_join", FolderI18nTableMap::LOCALE . "=" . $this->real_escape($locale))
+ ->addAsColumn("folder_TITLE", FolderI18nTableMap::TITLE)
+ ->addAsColumn("folder_ID", FolderTableMap::ID)
+ ->endUse()
+ ->endUse()
+ ->addJoinObject($contentI18nJoin, "content_i18n_join")
+ ->addJoinCondition("content_i18n_join", ContentI18nTableMap::LOCALE . "=" . $this->real_escape($locale))
+ ->addAsColumn("content_TITLE", ContentI18nTableMap::TITLE)
+ ->addAsColumn("content_CHAPO", ContentI18nTableMap::CHAPO)
+ ->addAsColumn("content_DESCRIPTION", ContentI18nTableMap::DESCRIPTION)
+ ->addAsColumn("content_CONCLUSION", ContentI18nTableMap::POSTSCRIPTUM)
+ ->addAsColumn("content_seo_TITLE", ContentI18nTableMap::META_TITLE)
+ ->addAsColumn("content_seo_DESCRIPTION", ContentI18nTableMap::META_DESCRIPTION)
+ ->addAsColumn("content_seo_KEYWORDS", ContentI18nTableMap::META_KEYWORDS)
+ ->addJoinObject($urlJoin, "url_rewriting_join")
+ ->addJoinCondition(
+ "url_rewriting_join",
+ RewritingUrlTableMap::VIEW . "=" .
+ $this->real_escape((new Content())->getRewrittenUrlViewName())
+ )
+ ->addJoinCondition(
+ "url_rewriting_join",
+ RewritingUrlTableMap::VIEW_LOCALE . "=" . $this->real_escape($locale)
+ )
+ ->addAsColumn("url_URL", RewritingUrlTableMap::URL)
+ ->select([
+ ContentTableMap::ID,
+ ContentTableMap::VISIBLE,
+ "content_TITLE",
+ "content_CHAPO",
+ "content_DESCRIPTION",
+ "content_CONCLUSION",
+ "content_seo_TITLE",
+ "content_seo_DESCRIPTION",
+ "content_seo_KEYWORDS",
+ "url_URL",
+ "folder_TITLE",
+ "folder_ID",
+ ])
+ ->groupBy(ContentTableMap::ID)
+ ->groupBy("folder_ID")
+ ;
+
+ /**
+ * @var ContentQuery $query
+ */
+ if ($this->isDocumentExport()) {
+ $query->select($query->getSelect() + [
+ "folder_DOCUMENTS",
+ "content_DOCUMENTS",
+ ]);
+ }
+
+ /**
+ * @var ContentQuery $query
+ */
+ if ($this->isImageExport()) {
+ $query->select($query->getSelect() + [
+ "folder_IMAGES",
+ "content_IMAGES",
+ ]);
+ }
+
+ $dataSet = $query
+ ->find()
+ ->toArray()
+ ;
+
+ $previous = null;
+ foreach ($dataSet as &$line) {
+ if ($previous === null || $previous !== $line[ContentTableMap::ID]) {
+ $previous = $line[ContentTableMap::ID];
+ } else {
+ /**
+ * Do not repeat content values
+ */
+ $line["content_TITLE"] = "";
+ $line["content_VISIBLE"] = "";
+ $line["content_CHAPO"] = "";
+ $line["content_DESCRIPTION"] = "";
+ $line["content_CONCLUSION"] = "";
+ $line["content_seo_TITLE"] = "";
+ $line["content_seo_DESCRIPTION"] = "";
+ $line["content_seo_KEYWORDS"] = "";
+ $line["url_URL"] = "";
+ $line["content_IMAGES"] = "";
+ $line["content_DOCUMENTS"] = "";
+
+ if (isset($line["content_IMAGES"])) {
+ $line["content_IMAGES"] = "";
+ }
+
+ if (isset($line["content_DOCUMENTS"])) {
+ $line["content_IMAGES"] = "";
+ }
+ }
+ }
+
+ return $dataSet;
+ }
+
+ protected function getDefaultOrder()
+ {
+ return [
+ "id",
+ "title",
+ "chapo",
+ "description",
+ "conclusion",
+ "visible",
+ "seo_title",
+ "seo_description",
+ "seo_keywords",
+ "url",
+ "folder_id",
+ "folder_title",
+ ];
+ }
+
+ protected function getAliases()
+ {
+ return [
+ ContentTableMap::ID => "id",
+ ContentTableMap::VISIBLE => "visible",
+ "content_TITLE" => "title",
+ "content_CHAPO" => "chapo",
+ "content_DESCRIPTION" => "description",
+ "content_CONCLUSION" => "conclusion",
+ "content_seo_TITLE" => "seo_title",
+ "content_seo_DESCRIPTION" => "seo_description",
+ "content_seo_KEYWORDS" => "seo_keywords",
+ "url_URL" => "url",
+ "folder_TITLE" => "folder_title",
+ "folder_ID" => "folder_id",
+ ];
+ }
+
+
+ /**
+ * @return array
+ *
+ * return an array with the paths to the documents to include in the archive
+ */
+ public function getDocumentsPaths()
+ {
+ $documentPaths = [];
+
+ $folderDocuments = FolderDocumentQuery::create()
+ ->find();
+ /** @var \Thelia\Model\FolderDocument $folderDocument */
+ foreach ($folderDocuments as $folderDocument) {
+ $this->addFileToArray($folderDocument, $documentPaths);
+
+ }
+
+ $contentDocuments = ContentDocumentQuery::create()
+ ->find();
+
+ /** @var \Thelia\Model\ContentDocument $contentDocument */
+ foreach ($contentDocuments as $contentDocument) {
+ $this->addFileToArray($contentDocument, $documentPaths);
+ }
+
+ return $documentPaths;
+ }
+
+ /**
+ * @return array
+ *
+ * return an array with the paths to the images to include in the archive
+ */
+ public function getImagesPaths()
+ {
+ $imagePaths = [];
+
+ $folderImages = FolderImageQuery::create()
+ ->find();
+
+ /** @var \Thelia\Model\FolderDocument $folderImage */
+ foreach ($folderImages as $folderImage) {
+ $this->addFileToArray($folderImage, $imagePaths);
+ }
+
+ $contentImages = ContentImageQuery::create()
+ ->find();
+
+ /** @var \Thelia\Model\ContentImage $contentImage */
+ foreach ($contentImages as $contentImage) {
+ $this->addFileToArray($contentImage, $imagePaths);
+ }
+
+ return $imagePaths;
+ }
+}
\ No newline at end of file
diff --git a/core/lib/Thelia/Tests/ImportExport/Export/ContentExportTest.php b/core/lib/Thelia/Tests/ImportExport/Export/ContentExportTest.php
new file mode 100644
index 000000000..827b11408
--- /dev/null
+++ b/core/lib/Thelia/Tests/ImportExport/Export/ContentExportTest.php
@@ -0,0 +1,138 @@
+
+ */
+class ContentExportTest extends \PHPUnit_Framework_TestCase
+{
+ protected $lang;
+
+ /** @var ContentExport */
+ protected $handler;
+
+ public function setUp()
+ {
+ new Translator(new Container());
+
+ $this->lang = Lang::getDefaultLanguage();
+ $this->handler = new ContentExport(new Container());
+ }
+
+ public function testQuery()
+ {
+ $data = $this->handler->buildData($this->lang)->getData();
+
+ $max = count($data);
+ if ($max > 50) {
+ $max = 50;
+ }
+
+ for ($i = 0; $i < $max;) {
+ $content = ContentQuery::create()->findPk($data[$i]["id"]);
+
+ $this->assertNotNull($content);
+
+ $this->assertEquals($content->getTitle(), $data[$i]["title"]);
+ $this->assertEquals($content->getDescription(), $data[$i]["description"]);
+ $this->assertEquals($content->getChapo(), $data[$i]["chapo"]);
+ $this->assertEquals($content->getPostscriptum(), $data[$i]["conclusion"]);
+ $this->assertEquals($content->getMetaTitle(), $data[$i]["seo_title"]);
+ $this->assertEquals($content->getMetaDescription(), $data[$i]["seo_description"]);
+ $this->assertEquals($content->getMetaKeywords(), $data[$i]["seo_keywords"]);
+
+
+ do {
+ if (null !== $data[$i]["folder_id"]) {
+ $folder = FolderQuery::create()->findPk($data[$i]["folder_id"]);
+
+ $this->assertNotNull($folder);
+
+ $contentFolder = ContentFolderQuery::create()
+ ->filterByContent($content)
+ ->filterByFolder($folder)
+ ->findOne()
+ ;
+
+ $this->assertNotNull($contentFolder);
+
+ $this->assertEquals(
+ $folder->getTitle(),
+ $data[$i]["folder_title"]
+ );
+ }
+ } while (
+ isset($data[++$i]["id"]) &&
+ $data[$i-1]["id"] === $data[$i]["id"] &&
+ ++$max
+ );
+ }
+ }
+
+ public function testQueryImages()
+ {
+ $data = $this->handler
+ ->setImageExport(true)
+ ->buildData($this->lang)
+ ->getData()
+ ;
+
+ $max = count($data);
+ if ($max > 50) {
+ $max = 50;
+ }
+
+ for ($i = 0; $i < $max; ++$i) {
+ $images = ContentImageQuery::create()
+ ->filterByContentId($data[$i]["id"])
+ ->select(ContentImageTableMap::FILE)
+ ->find()
+ ->toArray()
+ ;
+
+ $imagesString = implode(",", $images);
+
+ $this->assertEquals($imagesString, $data[$i]["content_images"]);
+
+ $folderImages = FolderImageQuery::create()
+ ->useFolderQuery()
+ ->useContentFolderQuery()
+ ->filterByContentId($data[$i]["id"])
+ ->endUse()
+ ->endUse()
+ ->select(FolderImageTableMap::FILE)
+ ->find()
+ ->toArray()
+ ;
+
+ $folderImages = implode(",", $folderImages);
+
+ $this->assertEquals($folderImages, $data[$i]["folder_images"]);
+ }
+ }
+}
\ No newline at end of file