-
Notifications
You must be signed in to change notification settings - Fork 2
IP-314 Expand the CMS import / export module to cover store blocks/pages #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e77bc6b
e767da6
eb1919b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,8 @@ | |
|
||
namespace RocketWeb\CmsImportExport\Model\Service; | ||
|
||
use Magento\Cms\Api\Data\BlockInterface; | ||
use Magento\Cms\Api\Data\PageInterface; | ||
use Magento\Framework\App\Filesystem\DirectoryList; | ||
|
||
class ImportCmsDataService | ||
|
@@ -39,7 +41,9 @@ public function __construct( | |
\Magento\Framework\Filesystem\DirectoryList $directoryList, | ||
\Magento\Framework\Filesystem $filesystem, | ||
\Magento\Framework\Serialize\SerializerInterface $serializer, | ||
\Magento\Store\Api\StoreRepositoryInterface $storeRepository | ||
\Magento\Store\Api\StoreRepositoryInterface $storeRepository, | ||
private readonly \Magento\Cms\Api\GetBlockByIdentifierInterface $getBlockByIdentifier, | ||
private readonly \Magento\Cms\Api\GetPageByIdentifierInterface $getPageByIdentifier | ||
) { | ||
$this->pageRepository = $pageRepository; | ||
$this->blockRepository = $blockRepository; | ||
|
@@ -51,7 +55,7 @@ public function __construct( | |
$this->storeRepository = $storeRepository; | ||
} | ||
|
||
public function execute(array $types, ?array $identifiers, bool $importAll) | ||
public function execute(array $types, ?array $identifiers, bool $importAll, ?string $storeCode = null) | ||
{ | ||
$workingDirPath = 'sync_cms_data'; | ||
|
||
|
@@ -70,9 +74,9 @@ public function execute(array $types, ?array $identifiers, bool $importAll) | |
} | ||
|
||
if ($type == 'block') { | ||
$this->importBlocks($typeDirPath, $identifiers); | ||
$this->importBlocks($typeDirPath, $identifiers, $storeCode); | ||
} else if ($type == 'page') { | ||
$this->importPages($typeDirPath, $identifiers); | ||
$this->importPages($typeDirPath, $identifiers, $storeCode); | ||
} | ||
} | ||
} | ||
|
@@ -97,7 +101,7 @@ private function getStoreIds($storeCodes): array | |
return $storeIds; | ||
} | ||
|
||
private function importBlocks(string $dirPath, ?array $identifiers): void | ||
private function importBlocks(string $dirPath, ?array $identifiers, ?string $storeCode = null): void | ||
{ | ||
$filePaths = $this->directoryRead->read($this->varPath . $dirPath); | ||
foreach ($filePaths as $filePath) { | ||
|
@@ -112,12 +116,17 @@ private function importBlocks(string $dirPath, ?array $identifiers): void | |
// If we have a list of items, we skip if its not in the list | ||
continue; | ||
} | ||
|
||
try { | ||
$block = $this->blockRepository->getById($identifier); | ||
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { | ||
$block = $this->blockFactory->create(); | ||
if ($storeCode !== null && ($this->getStoreCode($filePath) !== $storeCode)) { | ||
// Skip identifiers not assigned to specific store when storeCode parameter is set | ||
echo sprintf( | ||
'Skipping identifier %s because requested update only for store %s %s', | ||
$identifier, | ||
$storeCode, | ||
PHP_EOL | ||
); | ||
continue; | ||
} | ||
|
||
$content = $this->directoryRead->readFile($filePath); | ||
$jsonData = $this->directoryRead->readFile(str_replace('.html', '.json', $filePath)); | ||
$jsonData = $this->serializer->unserialize($jsonData); | ||
|
@@ -128,6 +137,13 @@ private function importBlocks(string $dirPath, ?array $identifiers): void | |
'is_active' => $block->isActive() | ||
];*/ | ||
$storeIds = $this->getStoreIds($jsonData['stores']); | ||
try { | ||
$block = $this->getBlockByIdentifier->execute($identifier, (int)reset($storeIds)); | ||
$this->validateStoreAssociation($filePath, $block, $storeIds, 'Block'); | ||
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { | ||
$block = $this->blockFactory->create(); | ||
} | ||
|
||
$block->setTitle($jsonData['title']); | ||
$block->setContent($content); | ||
$block->setIdentifier($jsonData['identifier']); | ||
|
@@ -145,7 +161,7 @@ private function importBlocks(string $dirPath, ?array $identifiers): void | |
} | ||
} | ||
|
||
private function importPages(string $dirPath, ?array $identifiers): void | ||
private function importPages(string $dirPath, ?array $identifiers, ?string $storeCode = null): void | ||
{ | ||
$filePaths = $this->directoryRead->read($this->varPath . $dirPath); | ||
foreach ($filePaths as $filePath) { | ||
|
@@ -155,23 +171,35 @@ private function importPages(string $dirPath, ?array $identifiers): void | |
} | ||
$identifier = str_replace($dirPath, '', $filePath); | ||
$identifier = str_replace('.html', '', $identifier); | ||
$identifier = substr_replace($identifier, '', strpos($identifier, '---')); | ||
$identifier = substr_replace($identifier, '', strrpos($identifier, '---')); | ||
$identifier = str_replace('---', '/', $identifier); | ||
$identifier = str_replace('_html', '.html', $identifier); | ||
if ($identifiers !== null && !in_array($identifier, $identifiers)) { | ||
// If we have a list of items, we skip if its not in the list | ||
continue; | ||
} | ||
|
||
try { | ||
$page = $this->pageRepository->getById($identifier); | ||
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { | ||
$page = $this->pageFactory->create(); | ||
if ($storeCode !== null && ($this->getStoreCode($filePath) !== $storeCode)) { | ||
// Skip identifiers not assigned to specific store when storeCode parameter is set | ||
echo sprintf( | ||
mihai-RW marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'Skipping identifier %s because requested update only for store %s %s', | ||
$identifier, | ||
$storeCode, | ||
PHP_EOL | ||
); | ||
continue; | ||
} | ||
|
||
$content = $this->directoryRead->readFile($filePath); | ||
$jsonData = $this->directoryRead->readFile(str_replace('.html', '.json', $filePath)); | ||
$jsonData = $this->serializer->unserialize($jsonData); | ||
$storeIds = $this->getStoreIds($jsonData['stores']); | ||
try { | ||
$page = $this->getPageByIdentifier->execute($identifier, (int)reset($storeIds)); | ||
$this->validateStoreAssociation($filePath, $page, $storeIds, 'Page'); | ||
} catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { | ||
$page = $this->pageFactory->create(); | ||
} | ||
/*$jsonContent = [ | ||
'title' => $page->getTitle(), | ||
'is_active' => $page->isActive(), | ||
|
@@ -193,8 +221,54 @@ private function importPages(string $dirPath, ?array $identifiers): void | |
try { | ||
$this->pageRepository->save($page); | ||
} catch (\Exception $exception) { | ||
echo $exception->getMessage() . ' | Block ID: ' . $identifier . "\n"; | ||
echo $exception->getMessage() . ' | Page ID: ' . $identifier . "\n"; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* We are validating here is store association is correct | ||
* string $filePath - HTML filename, may contain either store code or _all_ | ||
* BlockInterface | PageInterface $entity - either block or page if already exists | ||
* array $storeIds - array of stores to associate from JSON file | ||
* string $entityType - either "block" or "page", for accurate messaging | ||
* | ||
* We load store by store code specified in $filePath | ||
* Further we validate it against the data we have in JSON and if currently existing block/page | ||
*/ | ||
private function validateStoreAssociation( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docblocks, thanks! also add a small readme of how this should work from top to bottom using the store parameter, like how to export and how to import. Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry if i was confusing about the README, i actually meant, create a small docblock comment but add a .README file to the module which explains how the store parameter works (not in the docblocks :P ) |
||
string $filePath, | ||
BlockInterface | PageInterface $entity, | ||
array $storeIds, | ||
string $entityType | ||
) : void { | ||
$exceptionMessage = sprintf('%s with path %s has inconsistent store data', $entityType, $filePath); | ||
if (count($storeIds) > 1) { | ||
throw new \LogicException($exceptionMessage); | ||
} | ||
$storeCode = $this->getStoreCode($filePath); | ||
$storeId = (int)reset($storeIds); | ||
$currentStoreIds = $entity->getStoreId(); | ||
if ($storeCode === '_all_') { | ||
if ($storeId !== 0 || count($currentStoreIds) > 1 || (int)reset($currentStoreIds) !== 0) { | ||
throw new \LogicException($exceptionMessage); | ||
} | ||
return ; | ||
} | ||
$store = $this->storeRepository->get($storeId); | ||
if ($store->getCode() !== $storeCode) { | ||
throw new \LogicException($exceptionMessage); | ||
} | ||
|
||
if (array_diff($currentStoreIds, $storeIds) !== []) { | ||
throw new \LogicException($exceptionMessage); | ||
} | ||
} | ||
|
||
private function getStoreCode(string $filePath) : string | ||
{ | ||
$storeCode = str_replace('.html', '', $filePath); | ||
$storeCode = substr($storeCode, strrpos($storeCode, '---') + 3); | ||
return $storeCode; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.