1717
1818namespace RocketWeb \CmsImportExport \Model \Service ;
1919
20+ use Magento \Cms \Api \Data \BlockInterface ;
21+ use Magento \Cms \Api \Data \PageInterface ;
2022use Magento \Framework \App \Filesystem \DirectoryList ;
2123
2224class ImportCmsDataService
@@ -39,7 +41,9 @@ public function __construct(
3941 \Magento \Framework \Filesystem \DirectoryList $ directoryList ,
4042 \Magento \Framework \Filesystem $ filesystem ,
4143 \Magento \Framework \Serialize \SerializerInterface $ serializer ,
42- \Magento \Store \Api \StoreRepositoryInterface $ storeRepository
44+ \Magento \Store \Api \StoreRepositoryInterface $ storeRepository ,
45+ private readonly \Magento \Cms \Api \GetBlockByIdentifierInterface $ getBlockByIdentifier ,
46+ private readonly \Magento \Cms \Api \GetPageByIdentifierInterface $ getPageByIdentifier
4347 ) {
4448 $ this ->pageRepository = $ pageRepository ;
4549 $ this ->blockRepository = $ blockRepository ;
@@ -51,7 +55,7 @@ public function __construct(
5155 $ this ->storeRepository = $ storeRepository ;
5256 }
5357
54- public function execute (array $ types , ?array $ identifiers , bool $ importAll )
58+ public function execute (array $ types , ?array $ identifiers , bool $ importAll, ? string $ storeCode = null )
5559 {
5660 $ workingDirPath = 'sync_cms_data ' ;
5761
@@ -70,9 +74,9 @@ public function execute(array $types, ?array $identifiers, bool $importAll)
7074 }
7175
7276 if ($ type == 'block ' ) {
73- $ this ->importBlocks ($ typeDirPath , $ identifiers );
77+ $ this ->importBlocks ($ typeDirPath , $ identifiers, $ storeCode );
7478 } else if ($ type == 'page ' ) {
75- $ this ->importPages ($ typeDirPath , $ identifiers );
79+ $ this ->importPages ($ typeDirPath , $ identifiers, $ storeCode );
7680 }
7781 }
7882 }
@@ -97,7 +101,7 @@ private function getStoreIds($storeCodes): array
97101 return $ storeIds ;
98102 }
99103
100- private function importBlocks (string $ dirPath , ?array $ identifiers ): void
104+ private function importBlocks (string $ dirPath , ?array $ identifiers, ? string $ storeCode = null ): void
101105 {
102106 $ filePaths = $ this ->directoryRead ->read ($ this ->varPath . $ dirPath );
103107 foreach ($ filePaths as $ filePath ) {
@@ -112,12 +116,17 @@ private function importBlocks(string $dirPath, ?array $identifiers): void
112116 // If we have a list of items, we skip if its not in the list
113117 continue ;
114118 }
115-
116- try {
117- $ block = $ this ->blockRepository ->getById ($ identifier );
118- } catch (\Magento \Framework \Exception \NoSuchEntityException $ exception ) {
119- $ block = $ this ->blockFactory ->create ();
119+ if ($ storeCode !== null && ($ this ->getStoreCode ($ filePath ) !== $ storeCode )) {
120+ // Skip identifiers not assigned to specific store when storeCode parameter is set
121+ echo sprintf (
122+ 'Skipping identifier %s because requested update only for store %s %s ' ,
123+ $ identifier ,
124+ $ storeCode ,
125+ PHP_EOL
126+ );
127+ continue ;
120128 }
129+
121130 $ content = $ this ->directoryRead ->readFile ($ filePath );
122131 $ jsonData = $ this ->directoryRead ->readFile (str_replace ('.html ' , '.json ' , $ filePath ));
123132 $ jsonData = $ this ->serializer ->unserialize ($ jsonData );
@@ -128,6 +137,13 @@ private function importBlocks(string $dirPath, ?array $identifiers): void
128137 'is_active' => $block->isActive()
129138 ];*/
130139 $ storeIds = $ this ->getStoreIds ($ jsonData ['stores ' ]);
140+ try {
141+ $ block = $ this ->getBlockByIdentifier ->execute ($ identifier , (int )reset ($ storeIds ));
142+ $ this ->validateStoreAssociation ($ filePath , $ block , $ storeIds , 'Block ' );
143+ } catch (\Magento \Framework \Exception \NoSuchEntityException $ exception ) {
144+ $ block = $ this ->blockFactory ->create ();
145+ }
146+
131147 $ block ->setTitle ($ jsonData ['title ' ]);
132148 $ block ->setContent ($ content );
133149 $ block ->setIdentifier ($ jsonData ['identifier ' ]);
@@ -145,7 +161,7 @@ private function importBlocks(string $dirPath, ?array $identifiers): void
145161 }
146162 }
147163
148- private function importPages (string $ dirPath , ?array $ identifiers ): void
164+ private function importPages (string $ dirPath , ?array $ identifiers, ? string $ storeCode = null ): void
149165 {
150166 $ filePaths = $ this ->directoryRead ->read ($ this ->varPath . $ dirPath );
151167 foreach ($ filePaths as $ filePath ) {
@@ -155,23 +171,35 @@ private function importPages(string $dirPath, ?array $identifiers): void
155171 }
156172 $ identifier = str_replace ($ dirPath , '' , $ filePath );
157173 $ identifier = str_replace ('.html ' , '' , $ identifier );
158- $ identifier = substr_replace ($ identifier , '' , strpos ($ identifier , '--- ' ));
174+ $ identifier = substr_replace ($ identifier , '' , strrpos ($ identifier , '--- ' ));
159175 $ identifier = str_replace ('--- ' , '/ ' , $ identifier );
160176 $ identifier = str_replace ('_html ' , '.html ' , $ identifier );
161177 if ($ identifiers !== null && !in_array ($ identifier , $ identifiers )) {
162178 // If we have a list of items, we skip if its not in the list
163179 continue ;
164180 }
165181
166- try {
167- $ page = $ this ->pageRepository ->getById ($ identifier );
168- } catch (\Magento \Framework \Exception \NoSuchEntityException $ exception ) {
169- $ page = $ this ->pageFactory ->create ();
182+ if ($ storeCode !== null && ($ this ->getStoreCode ($ filePath ) !== $ storeCode )) {
183+ // Skip identifiers not assigned to specific store when storeCode parameter is set
184+ echo sprintf (
185+ 'Skipping identifier %s because requested update only for store %s %s ' ,
186+ $ identifier ,
187+ $ storeCode ,
188+ PHP_EOL
189+ );
190+ continue ;
170191 }
192+
171193 $ content = $ this ->directoryRead ->readFile ($ filePath );
172194 $ jsonData = $ this ->directoryRead ->readFile (str_replace ('.html ' , '.json ' , $ filePath ));
173195 $ jsonData = $ this ->serializer ->unserialize ($ jsonData );
174196 $ storeIds = $ this ->getStoreIds ($ jsonData ['stores ' ]);
197+ try {
198+ $ page = $ this ->getPageByIdentifier ->execute ($ identifier , (int )reset ($ storeIds ));
199+ $ this ->validateStoreAssociation ($ filePath , $ page , $ storeIds , 'Page ' );
200+ } catch (\Magento \Framework \Exception \NoSuchEntityException $ exception ) {
201+ $ page = $ this ->pageFactory ->create ();
202+ }
175203 /*$jsonContent = [
176204 'title' => $page->getTitle(),
177205 'is_active' => $page->isActive(),
@@ -193,8 +221,54 @@ private function importPages(string $dirPath, ?array $identifiers): void
193221 try {
194222 $ this ->pageRepository ->save ($ page );
195223 } catch (\Exception $ exception ) {
196- echo $ exception ->getMessage () . ' | Block ID: ' . $ identifier . "\n" ;
224+ echo $ exception ->getMessage () . ' | Page ID: ' . $ identifier . "\n" ;
225+ }
226+ }
227+ }
228+
229+ /**
230+ * We are validating here is store association is correct
231+ * string $filePath - HTML filename, may contain either store code or _all_
232+ * BlockInterface | PageInterface $entity - either block or page if already exists
233+ * array $storeIds - array of stores to associate from JSON file
234+ * string $entityType - either "block" or "page", for accurate messaging
235+ *
236+ * We load store by store code specified in $filePath
237+ * Further we validate it against the data we have in JSON and if currently existing block/page
238+ */
239+ private function validateStoreAssociation (
240+ string $ filePath ,
241+ BlockInterface | PageInterface $ entity ,
242+ array $ storeIds ,
243+ string $ entityType
244+ ) : void {
245+ $ exceptionMessage = sprintf ('%s with path %s has inconsistent store data ' , $ entityType , $ filePath );
246+ if (count ($ storeIds ) > 1 ) {
247+ throw new \LogicException ($ exceptionMessage );
248+ }
249+ $ storeCode = $ this ->getStoreCode ($ filePath );
250+ $ storeId = (int )reset ($ storeIds );
251+ $ currentStoreIds = $ entity ->getStoreId ();
252+ if ($ storeCode === '_all_ ' ) {
253+ if ($ storeId !== 0 || count ($ currentStoreIds ) > 1 || (int )reset ($ currentStoreIds ) !== 0 ) {
254+ throw new \LogicException ($ exceptionMessage );
197255 }
256+ return ;
257+ }
258+ $ store = $ this ->storeRepository ->get ($ storeId );
259+ if ($ store ->getCode () !== $ storeCode ) {
260+ throw new \LogicException ($ exceptionMessage );
261+ }
262+
263+ if (array_diff ($ currentStoreIds , $ storeIds ) !== []) {
264+ throw new \LogicException ($ exceptionMessage );
198265 }
199266 }
267+
268+ private function getStoreCode (string $ filePath ) : string
269+ {
270+ $ storeCode = str_replace ('.html ' , '' , $ filePath );
271+ $ storeCode = substr ($ storeCode , strrpos ($ storeCode , '--- ' ) + 3 );
272+ return $ storeCode ;
273+ }
200274}
0 commit comments