From f48166132e1fbe21d01bfbe489cc50ead5eba5c9 Mon Sep 17 00:00:00 2001 From: Danilo Argentiero Date: Wed, 27 Mar 2019 10:11:31 +0100 Subject: [PATCH] Fix media upload, Rewrite some module parts, Change License, update file composer.json --- .gitignore | 1 - Api/ContentInterface.php | 44 +- Block/Adminhtml/Import.php | 20 +- Block/Adminhtml/Import/Upload/Form.php | 18 +- COPYNG.txt | 5 + Command/ImportPage.php | 20 +- Controller/Adminhtml/Block/MassExport.php | 18 +- Controller/Adminhtml/Import/Index.php | 18 +- Controller/Adminhtml/Import/Post.php | 18 +- Controller/Adminhtml/Page/MassExport.php | 18 +- Model/Content.php | 475 +++++++++--------- Model/Filesystem.php | 18 +- Model/Source/CmsMode.php | 18 +- Model/Source/MediaMode.php | 18 +- composer.json | 12 +- etc/acl.xml | 22 +- etc/adminhtml/menu.xml | 22 +- etc/adminhtml/routes.xml | 22 +- etc/di.xml | 22 +- etc/module.xml | 24 +- registration.php | 20 +- view/adminhtml/layout/cms_import_index.xml | 22 +- .../ui_component/cms_block_listing.xml | 22 +- .../ui_component/cms_page_listing.xml | 22 +- 24 files changed, 311 insertions(+), 608 deletions(-) create mode 100644 COPYNG.txt diff --git a/.gitignore b/.gitignore index 62e7820..723ef36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -# Created by .ignore support plugin (hsz.mobi) .idea \ No newline at end of file diff --git a/Api/ContentInterface.php b/Api/ContentInterface.php index 9088fc3..a17cd1b 100644 --- a/Api/ContentInterface.php +++ b/Api/ContentInterface.php @@ -1,23 +1,11 @@ buttonList->update('save', 'label', __('Import')); } - public function getHeaderText() + public function getHeaderText(): string { return __('Import CMS'); } diff --git a/Block/Adminhtml/Import/Upload/Form.php b/Block/Adminhtml/Import/Upload/Form.php index b7cd554..70e2a20 100644 --- a/Block/Adminhtml/Import/Upload/Form.php +++ b/Block/Adminhtml/Import/Upload/Form.php @@ -1,21 +1,7 @@ storesMap as $to => $from) { - if ($storeCode == $from) { - $return[] = $to; - } - } - } + $pagesArray = $this->pagesToArray($pageInterfaces); + $blocksArray = $this->blocksToArray($blockInterfaces); - return $return; - } + $contentArray = array_merge_recursive($pagesArray, $blocksArray); - /** - * Get store codes - * @param array $storeIds - * @return array - */ - public function getStoreCodes($storeIds) - { - $return = []; + $jsonPayload = $this->encoderInterface->encode($contentArray); - foreach ($storeIds as $storeId) { - $return[] = $this->storeRepositoryInterface->getById($storeId)->getCode(); - } + $exportPath = $this->filesystem->getExportPath(); - return $return; - } + $zipFile = $exportPath . '/' . sprintf('cms_%s.zip', $this->dateTime->date('Ymd_His')); + $relativeZipFile = Filesystem::EXPORT_PATH . '/' . sprintf('cms_%s.zip', $this->dateTime->date('Ymd_His')); - /** - * Get store ids by codes - * @param array $storeCodes - * @return array - */ - public function getStoreIdsByCodes(array $storeCodes) - { - $return = []; - foreach ($storeCodes as $storeCode) { - if ($storeCode == 'admin') { - $return[] = 0; - } else { - $store = $this->storeRepositoryInterface->get($storeCode); - if ($store && $store->getId()) { - $return[] = $store->getId(); - } + $zipArchive = new \ZipArchive(); + $zipArchive->open($zipFile, \ZipArchive::CREATE); + + // Add pages json + $zipArchive->addFromString(self::JSON_FILENAME, $jsonPayload); + + // Add media files + foreach ($contentArray['media'] as $mediaFile) { + $absMediaPath = $this->filesystem->getMediaPath($mediaFile); + if ($this->file->fileExists($absMediaPath, true)) { + $zipArchive->addFile($absMediaPath, self::MEDIA_ARCHIVE_PATH . '/' . $mediaFile); } } - return $return; - } + $zipArchive->close(); - /** - * Get media attachments from content - * @param $content - * @return array - */ - public function getMediaAttachments($content) - { - if (preg_match_all('/\{\{media.+?url\s*=\s*"(.+?)".*?\}\}/', $content, $matches)) { - return $matches[1]; - } + // Clear export path + $this->file->rm($exportPath, true); - return []; + return $relativeZipFile; } /** - * Return CMS block to array - * @param \Magento\Cms\Api\Data\BlockInterface $blockInterface + * Return CMS pages as array + * @param \Magento\Cms\Api\Data\PageInterface[] $pageInterfaces * @return array */ - public function blockToArray(CmsBlockInterface $blockInterface) + public function pagesToArray(array $pageInterfaces): array { - // Extract attachments - $media = $this->getMediaAttachments($blockInterface->getContent()); + $pages = []; + $media = []; - $payload = [ - 'cms' => [ - CmsBlockInterface::IDENTIFIER => $blockInterface->getIdentifier(), - CmsBlockInterface::TITLE => $blockInterface->getTitle(), - CmsBlockInterface::CONTENT => $blockInterface->getContent(), - CmsBlockInterface::IS_ACTIVE => $blockInterface->isActive(), - ], - 'stores' => $this->getStoreCodes($blockInterface->getStoreId()), + foreach ($pageInterfaces as $pageInterface) { + $pageInfo = $this->pageToArray($pageInterface); + $pages[$this->_getPageKey($pageInterface)] = $pageInfo; + $media = array_merge($media, $pageInfo['media']); + } + + return [ + 'pages' => $pages, 'media' => $media, ]; - - return $payload; } /** @@ -190,7 +147,7 @@ public function blockToArray(CmsBlockInterface $blockInterface) * @param \Magento\Cms\Api\Data\PageInterface $pageInterface * @return array */ - public function pageToArray(CmsPageInterface $pageInterface) + public function pageToArray(CmsPageInterface $pageInterface): array { // Extract attachments $media = $this->getMediaAttachments($pageInterface->getContent()); @@ -221,27 +178,44 @@ public function pageToArray(CmsPageInterface $pageInterface) } /** - * Get page unique key - * @param CmsPageInterface $pageInterface - * @return mixed + * Get media attachments from content + * @param $content + * @return array */ - protected function _getPageKey(CmsPageInterface $pageInterface) + public function getMediaAttachments($content): array { - $keys = $this->getStoreCodes($pageInterface->getStoreId()); - $keys[] = $pageInterface->getIdentifier(); + if (preg_match_all('/\{\{media.+?url\s*=\s*("|")(.+?)("|").*?\}\}/', $content, $matches)) { + return $matches[2]; + } - return implode(':', $keys); + return []; } /** - * Get block unique key - * @param CmsBlockInterface $blockInterface - * @return mixed + * Get store codes + * @param array $storeIds + * @return array */ - protected function _getBlockKey(CmsBlockInterface $blockInterface) + public function getStoreCodes($storeIds): array { - $keys = $this->getStoreCodes($blockInterface->getStoreId()); - $keys[] = $blockInterface->getIdentifier(); + $return = []; + + foreach ($storeIds as $storeId) { + $return[] = $this->storeRepositoryInterface->getById($storeId)->getCode(); + } + + return $return; + } + + /** + * Get page unique key + * @param CmsPageInterface $pageInterface + * @return string + */ + protected function _getPageKey(CmsPageInterface $pageInterface): string + { + $keys = $this->getStoreCodes($pageInterface->getStoreId()); + $keys[] = $pageInterface->getIdentifier(); return implode(':', $keys); } @@ -251,7 +225,7 @@ protected function _getBlockKey(CmsBlockInterface $blockInterface) * @param \Magento\Cms\Api\Data\BlockInterface[] $blockInterfaces * @return array */ - public function blocksToArray(array $blockInterfaces) + public function blocksToArray(array $blockInterfaces): array { $blocks = []; $media = []; @@ -269,67 +243,139 @@ public function blocksToArray(array $blockInterfaces) } /** - * Return CMS pages as array - * @param \Magento\Cms\Api\Data\PageInterface[] $pageInterfaces + * Return CMS block to array + * @param \Magento\Cms\Api\Data\BlockInterface $blockInterface * @return array */ - public function pagesToArray(array $pageInterfaces) + public function blockToArray(CmsBlockInterface $blockInterface): array { - $pages = []; - $media = []; - - foreach ($pageInterfaces as $pageInterface) { - $pageInfo = $this->pageToArray($pageInterface); - $pages[$this->_getPageKey($pageInterface)] = $pageInfo; - $media = array_merge($media, $pageInfo['media']); - } + // Extract attachments + $media = $this->getMediaAttachments($blockInterface->getContent()); - return [ - 'pages' => $pages, + $payload = [ + 'cms' => [ + CmsBlockInterface::IDENTIFIER => $blockInterface->getIdentifier(), + CmsBlockInterface::TITLE => $blockInterface->getTitle(), + CmsBlockInterface::CONTENT => $blockInterface->getContent(), + CmsBlockInterface::IS_ACTIVE => $blockInterface->isActive(), + ], + 'stores' => $this->getStoreCodes($blockInterface->getStoreId()), 'media' => $media, ]; + + return $payload; } /** - * Create a zip file and return its name - * @param \Magento\Cms\Api\Data\PageInterface[] $pageInterfaces - * @param \Magento\Cms\Api\Data\BlockInterface[] $blockInterfaces + * Get block unique key + * @param CmsBlockInterface $blockInterface * @return string */ - public function asZipFile(array $pageInterfaces, array $blockInterfaces) + protected function _getBlockKey(CmsBlockInterface $blockInterface): string { - $pagesArray = $this->pagesToArray($pageInterfaces); - $blocksArray = $this->blocksToArray($blockInterfaces); + $keys = $this->getStoreCodes($blockInterface->getStoreId()); + $keys[] = $blockInterface->getIdentifier(); - $contentArray = array_merge_recursive($pagesArray, $blocksArray); + return implode(':', $keys); + } - $jsonPayload = $this->encoderInterface->encode($contentArray); + /** + * Import contents from zip archive and return number of imported records (-1 on error) + * @param string $fileName + * @param bool $rm = true + * @return int + * @throws \Exception + */ + public function importFromZipFile($fileName, $rm = false): int + { + // Unzip archive + $zipArchive = new \ZipArchive(); + $res = $zipArchive->open($fileName); + if ($res !== true) { + throw new \Exception('Cannot open ZIP archive'); + } - $exportPath = $this->filesystem->getExportPath(); + $subPath = md5(date(DATE_RFC2822)); + $extractPath = $this->filesystem->getExtractPath($subPath); - $zipFile = $exportPath.'/'.sprintf('cms_%s.zip', $this->dateTime->date('Ymd_His')); - $relativeZipFile = Filesystem::EXPORT_PATH.'/'.sprintf('cms_%s.zip', $this->dateTime->date('Ymd_His')); + $zipArchive->extractTo($extractPath); + $zipArchive->close(); - $zipArchive = new \ZipArchive(); - $zipArchive->open($zipFile, \ZipArchive::CREATE); + // Check if pages.json exists + $pagesFile = $extractPath . '/' . self::JSON_FILENAME; + if (!$this->file->fileExists($pagesFile, true)) { + throw new \Exception(self::JSON_FILENAME . ' is missing'); + } - // Add pages json - $zipArchive->addFromString(self::JSON_FILENAME, $jsonPayload); + // Read and import + $jsonString = $this->file->read($pagesFile); + $cmsData = $this->decoderInterface->decode($jsonString); - // Add media files - foreach ($contentArray['media'] as $mediaFile) { - $absMediaPath = $this->filesystem->getMediaPath($mediaFile); - if ($this->file->fileExists($absMediaPath, true)) { - $zipArchive->addFile($absMediaPath, self::MEDIA_ARCHIVE_PATH . '/' . $mediaFile); + $count = $this->importFromArray($cmsData, $extractPath); + + // Remove if necessary + if ($rm) { + $this->file->rm($fileName); + } + + // Clear archive + $this->file->rmdir($extractPath, true); + + return $count; + } + + /** + * Import contents from array and return number of imported records (-1 on error) + * @param array $payload + * @param string $archivePath = null + * @return int + * @throws \Exception + */ + public function importFromArray(array $payload, $archivePath = null): int + { + if (!isset($payload['pages']) && !isset($payload['blocks'])) { + throw new \Exception('Invalid json archive'); + } + + $count = 0; + + // Import pages + foreach ($payload['pages'] as $key => $pageData) { + if ($this->importPageFromArray($pageData)) { + $count++; } } - $zipArchive->close(); + // Import blocks + foreach ($payload['blocks'] as $key => $blockData) { + if ($this->importBlockFromArray($blockData)) { + $count++; + } + } - // Clear export path - $this->file->rm($exportPath, true); + // Import media + if ($archivePath && ($count > 0) && ($this->mediaMode != ContentInterface::MEDIA_MODE_NONE)) { + foreach ($payload['media'] as $mediaFile) { + $sourceFile = $archivePath . '/' . self::MEDIA_ARCHIVE_PATH . '/' . $mediaFile; + $destFile = $this->filesystem->getMediaPath($mediaFile); - return $relativeZipFile; + if ($this->file->fileExists($sourceFile, true)) { + if ($this->file->fileExists($destFile, true) && + ($this->mediaMode == ContentInterface::MEDIA_MODE_SKIP) + ) { + continue; + } + + if (!$this->file->mkdir(dirname($destFile)) || + !$this->file->cp($sourceFile, $destFile)) { + throw new \Exception('Unable to save image: ' . $mediaFile); + } + $count++; + } + } + } + + return $count; } /** @@ -337,7 +383,7 @@ public function asZipFile(array $pageInterfaces, array $blockInterfaces) * @param array $pageData * @return bool */ - public function importPageFromArray(array $pageData) + public function importPageFromArray(array $pageData): bool { // Will not use repositories to save pages because it does not allow stores selection @@ -393,12 +439,53 @@ public function importPageFromArray(array $pageData) return true; } + /** + * Get store ids by codes + * @param array $storeCodes + * @return array + */ + public function getStoreIdsByCodes(array $storeCodes): array + { + $return = []; + foreach ($storeCodes as $storeCode) { + if ($storeCode == 'admin') { + $return[] = 0; + } else { + $store = $this->storeRepositoryInterface->get($storeCode); + if ($store && $store->getId()) { + $return[] = $store->getId(); + } + } + } + + return $return; + } + + /** + * Map stores + * @param $storeCodes + * @return array + */ + protected function _mapStores($storeCodes): array + { + $return = []; + foreach ($storeCodes as $storeCode) { + foreach ($this->storesMap as $to => $from) { + if ($storeCode == $from) { + $return[] = $to; + } + } + } + + return $return; + } + /** * Import a single block from an array and return false on error and true on success * @param array $blockData * @return bool */ - public function importBlockFromArray(array $blockData) + public function importBlockFromArray(array $blockData): bool { // Will not use repositories to save blocks because it does not allow stores selection @@ -443,108 +530,12 @@ public function importBlockFromArray(array $blockData) return true; } - /** - * Import contents from array and return number of imported records (-1 on error) - * @param array $payload - * @param string $archivePath = null - * @return int - * @throws \Exception - */ - public function importFromArray(array $payload, $archivePath = null) - { - if (!isset($payload['pages']) && !isset($payload['blocks'])) { - throw new \Exception('Invalid json archive'); - } - - $count = 0; - - // Import pages - foreach ($payload['pages'] as $key => $pageData) { - if ($this->importPageFromArray($pageData)) { - $count++; - } - } - - // Import blocks - foreach ($payload['blocks'] as $key => $blockData) { - if ($this->importBlockFromArray($blockData)) { - $count++; - } - } - - // Import media - if ($archivePath && ($count > 0) && ($this->mediaMode != ContentInterface::MEDIA_MODE_NONE)) { - foreach ($payload['media'] as $mediaFile) { - $sourceFile = $archivePath.'/'.self::MEDIA_ARCHIVE_PATH.'/'.$mediaFile; - $destFile = $this->filesystem->getMediaPath($mediaFile); - - if ($this->file->fileExists($sourceFile, true)) { - if ($this->file->fileExists($destFile, true) && - ($this->mediaMode == ContentInterface::MEDIA_MODE_SKIP) - ) { - continue; - } - - $this->file->cp($sourceFile, $destFile); - $count++; - } - } - } - - return $count; - } - - /** - * Import contents from zip archive and return number of imported records (-1 on error) - * @param string $fileName - * @param bool $rm = true - * @return int - * @throws \Exception - */ - public function importFromZipFile($fileName, $rm = false) - { - // Unzip archive - $zipArchive = new \ZipArchive(); - $res = $zipArchive->open($fileName); - if ($res !== true) { - throw new \Exception('Cannot open ZIP archive'); - } - - $subPath = md5(uniqid(time())); - $extractPath = $this->filesystem->getExtractPath($subPath); - - $zipArchive->extractTo($extractPath); - $zipArchive->close(); - - // Check if pages.json exists - $pagesFile = $extractPath.'/'.self::JSON_FILENAME; - if (!$this->file->fileExists($pagesFile, true)) { - throw new \Exception(self::JSON_FILENAME.' is missing'); - } - - // Read and import - $jsonString = $this->file->read($pagesFile); - $cmsData = $this->decoderInterface->decode($jsonString); - - $count = $this->importFromArray($cmsData, $extractPath); - - // Remove if necessary - if ($rm) { - $this->file->rm($fileName); - } - - // Clear archive - $this->file->rmdir($extractPath, true); - - return $count; - } - /** * Set CMS mode * @param $mode - * @return $this + * @return ContentInterface */ - public function setCmsMode($mode) + public function setCmsMode($mode): ContentInterface { $this->cmsMode = $mode; return $this; @@ -553,9 +544,9 @@ public function setCmsMode($mode) /** * Set media mode * @param $mode - * @return $this + * @return ContentInterface */ - public function setMediaMode($mode) + public function setMediaMode($mode): ContentInterface { $this->mediaMode = $mode; return $this; @@ -566,7 +557,7 @@ public function setMediaMode($mode) * @param array $storesMap * @return ContentInterface */ - public function setStoresMap(array $storesMap) + public function setStoresMap(array $storesMap): ContentInterface { return $this; } diff --git a/Model/Filesystem.php b/Model/Filesystem.php index 3837773..719aba1 100644 --- a/Model/Filesystem.php +++ b/Model/Filesystem.php @@ -1,21 +1,7 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/etc/adminhtml/menu.xml b/etc/adminhtml/menu.xml index 68213fb..d096bf5 100644 --- a/etc/adminhtml/menu.xml +++ b/etc/adminhtml/menu.xml @@ -1,24 +1,8 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml index 6a3992d..303d571 100644 --- a/etc/adminhtml/routes.xml +++ b/etc/adminhtml/routes.xml @@ -1,24 +1,8 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/etc/di.xml b/etc/di.xml index 1276991..39594a0 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -1,24 +1,8 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/etc/module.xml b/etc/module.xml index d19c081..bf4fea2 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,27 +1,11 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> - + diff --git a/registration.php b/registration.php index bb6583d..10807aa 100644 --- a/registration.php +++ b/registration.php @@ -1,23 +1,11 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/view/adminhtml/ui_component/cms_block_listing.xml b/view/adminhtml/ui_component/cms_block_listing.xml index fc777d8..0f1e3f2 100644 --- a/view/adminhtml/ui_component/cms_block_listing.xml +++ b/view/adminhtml/ui_component/cms_block_listing.xml @@ -1,24 +1,8 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + --> diff --git a/view/adminhtml/ui_component/cms_page_listing.xml b/view/adminhtml/ui_component/cms_page_listing.xml index a636b35..f7b8828 100644 --- a/view/adminhtml/ui_component/cms_page_listing.xml +++ b/view/adminhtml/ui_component/cms_page_listing.xml @@ -1,24 +1,8 @@ + ~ Copyright © MageSpecialist - Skeeller srl. All rights reserved. + ~ See COPYING.txt for license details. + -->