55use Joomla \CMS \Http \HttpFactory ;
66use \Joomla \CMS \Http \Http ;
77use Joomla \CMS \Factory ;
8+ use Joomla \CMS \Filter \OutputFilter ;
89use Reem \Component \CCM \Administrator \Helper \MigrationHelper ;
910
1011/**
@@ -18,6 +19,7 @@ class MigrationModel extends FormModel
1819 // 'categories' => ['ids' => [oldId => newId, ...]]
1920 // 'users' => ['ids' => [oldId => newId, ...]]
2021 // 'media' => ['ids' => [oldId => newId, ...], 'urls' => [oldUrl => newUrl, ...]]
22+ // 'menus' => ['ids' => [oldId => [newId, menuType], ...]]
2123 ];
2224 protected $ migrationMapFile ;
2325 protected $ http ;
@@ -126,17 +128,67 @@ private function getSourceItems($sourceCms, $sourceType) {
126128 $ schemaPath = dirname (__DIR__ , 1 ) . '/Schema/ ' ;
127129 $ schema = json_decode (file_get_contents ($ schemaPath . $ sourceSchemaFile ), true );
128130
129- // Find the endpoint for this source type
130- $ endpoint = $ sourceType ;
131+ $ endpointConfig = null ;
131132 if (isset ($ schema ['ContentItem ' ]) && is_array ($ schema ['ContentItem ' ])) {
132133 foreach ($ schema ['ContentItem ' ] as $ contentItem ) {
133134 if (isset ($ contentItem ['type ' ]) && $ contentItem ['type ' ] === $ sourceType ) {
134- $ endpoint = $ contentItem ['config ' ]['endpoint ' ] ?? $ sourceType ;
135+ $ endpointConfig = $ contentItem ['config ' ] ?? ['endpoint ' => $ sourceType] ;
135136 break ;
136137 }
137138 }
138139 }
139140
141+ if (!$ endpointConfig ) {
142+ throw new \RuntimeException ("No endpoint configuration found for source type: $ sourceType " );
143+ }
144+
145+ $ endpoint = $ endpointConfig ['endpoint ' ];
146+ $ dependsOn = $ endpointConfig ['depends_on ' ] ?? null ;
147+
148+ // If the endpoint depends on another migrated type (e.g., menu items depending on menus)
149+ if ($ dependsOn && isset ($ dependsOn ['type ' ]) && isset ($ dependsOn ['param ' ])) {
150+ if (file_exists ($ this ->migrationMapFile )) {
151+ $ this ->migrationMap = json_decode (file_get_contents ($ this ->migrationMapFile ), true ) ?: [];
152+ }
153+
154+ $ dependencyType = $ dependsOn ['type ' ];
155+ $ dependencyParam = $ dependsOn ['param ' ];
156+ $ dependencyIds = $ this ->migrationMap [$ dependencyType ]['ids ' ] ?? [];
157+
158+ if (empty ($ dependencyIds )) {
159+ throw new \RuntimeException ("No migrated items of type ' {$ dependencyType }' found, which is a dependency for ' {$ sourceType }'. " );
160+ }
161+
162+ $ allItems = [];
163+ foreach ($ dependencyIds as $ oldId => $ newId ) {
164+ $ dependencyEndpoint = str_replace (': ' . $ dependencyParam , (string ) $ oldId , $ endpoint );
165+ $ sourceEndpoint = $ sourceUrl . '/ ' . $ dependencyEndpoint ;
166+ error_log ("[MigrationModel] Fetching source items from: $ sourceEndpoint " );
167+
168+ $ headers = ['Accept ' => 'application/json ' ];
169+ if ($ sourceAuthentication ) {
170+ $ authHeaders = MigrationHelper::parseAuthentication ($ sourceAuthentication );
171+ $ headers = array_merge ($ headers , $ authHeaders );
172+ }
173+
174+ $ sourceResponse = $ this ->http ->get ($ sourceEndpoint , $ headers );
175+ $ sourceResponseBody = json_decode ($ sourceResponse ->body , true );
176+ error_log ("[MigrationModel] Menu Items - Source response body: " . $ sourceResponse ->body );
177+
178+ $ items = $ sourceResponseBody ['items ' ] ?? ($ sourceResponseBody [$ sourceType ] ?? $ sourceResponseBody );
179+
180+ if (is_array ($ items )) {
181+ foreach ($ items as &$ item ) {
182+ // Inject the original dependency ID for later mapping
183+ $ item [$ dependencyParam ] = $ oldId ;
184+ }
185+ $ allItems = array_merge ($ allItems , $ items );
186+ }
187+ }
188+ return $ allItems ;
189+ }
190+
191+ // Default flow for endpoints without dependencies
140192 $ sourceEndpoint = $ sourceUrl . '/ ' . $ endpoint ;
141193
142194 $ headers = [
@@ -292,9 +344,84 @@ private function convertCcmToTargetCms($ccmItems, $targetCms, $targetType) {
292344 $ value = $ ccmMap ['default ' ];
293345 }
294346
347+ if (empty ($ value ) && $ format ) {
348+ switch ($ format ) {
349+ case 'alias ' :
350+ error_log ("[MigrationModel] Formatting alias for the title: " . $ ccmItem ['title ' ]);
351+ $ value = OutputFilter::stringURLSafe ($ ccmItem ['title ' ]);
352+ break ;
353+
354+
355+ case 'name_map ' :
356+ // Look through menus mapping to find the matching menutype
357+ foreach ($ this ->migrationMap ['menus ' ]['ids ' ] as $ mapping ) {
358+ if (is_array ($ mapping ) && isset ($ mapping [1 ])) {
359+ $ value = $ mapping [1 ]; // Get the menutype value
360+ error_log ("[MigrationModel] Found menutype: $ value " );
361+ break ; // Use the first menutype found
362+ }
363+ }
364+ if (empty ($ value )) {
365+ error_log ("[MigrationModel] No menutype found in menus mapping " );
366+ }
367+ break ;
368+ }
369+ }
370+
295371 // Format handling (array, url_replace, id_map)
296372 if (!empty ($ value ) && $ format ) {
297373 switch ($ format ) {
374+ case 'link_builder ' :
375+ $ template = $ ccmMap ['template ' ] ?? '' ;
376+ $ params = $ ccmMap ['params ' ] ?? [];
377+ $ builtLink = $ template ;
378+ foreach ($ params as $ paramKey => $ paramSource ) {
379+ $ replaceValue = '' ;
380+ if ($ paramSource ['source ' ] === 'id_map ' ) {
381+ $ sourceId = $ ccmItem [$ paramSource ['ccm_key ' ]] ?? null ;
382+ if ($ sourceId ) {
383+ $ mapType = $ paramSource ['map_type ' ];
384+ // Determine map_type based on content type if needed
385+ if ($ mapType === 'articles ' && isset ($ ccmItem ['type ' ]) && $ ccmItem ['type ' ] === 'category ' ) {
386+ $ mapType = 'categories ' ;
387+ }
388+ $ replaceValue = $ this ->migrationMap [$ mapType ]['ids ' ][$ sourceId ] ?? '' ;
389+ error_log ("[MigrationModel] Mapping ID for $ mapType: $ sourceId -> $ replaceValue " );
390+ }
391+ } elseif ($ paramSource ['source ' ] === 'map ' ) {
392+ $ sourceValue = $ ccmItem [$ paramSource ['ccm_key ' ]] ?? null ;
393+ if ($ sourceValue && isset ($ paramSource ['map ' ][$ sourceValue ])) {
394+ $ replaceValue = $ paramSource ['map ' ][$ sourceValue ];
395+ }
396+ }
397+ $ builtLink = str_replace (': ' . $ paramKey , $ replaceValue , $ builtLink );
398+ }
399+ $ value = $ builtLink ;
400+ error_log ("[MigrationModel] Built link for key ' $ targetKey': " . json_encode ($ value ));
401+ break ;
402+ case 'object_builder ' :
403+ $ params = $ ccmMap ['params ' ] ?? [];
404+ $ requestObject = [];
405+ foreach ($ params as $ paramKey => $ paramSource ) {
406+ if ($ paramSource ['source ' ] === 'id_map ' ) {
407+ $ sourceId = $ ccmItem [$ paramSource ['ccm_key ' ]] ?? null ;
408+ if ($ sourceId ) {
409+ $ mapType = $ paramSource ['map_type ' ];
410+ // Determine map_type based on content type if needed
411+ if ($ mapType === 'articles ' && isset ($ ccmItem ['type ' ]) && $ ccmItem ['type ' ] === 'category ' ) {
412+ $ mapType = 'categories ' ;
413+ }
414+ $ mappedId = $ this ->migrationMap [$ mapType ]['ids ' ][$ sourceId ] ?? null ;
415+ if ($ mappedId ) {
416+ $ requestObject [$ paramKey ] = $ mappedId ;
417+ error_log ("[MigrationModel] Mapped ID for request object: $ sourceId -> $ mappedId ( $ mapType) " );
418+ }
419+ }
420+ }
421+ }
422+ $ value = $ requestObject ;
423+ error_log ("[MigrationModel] Built object for key ' $ targetKey': " . json_encode ($ value ));
424+ break ;
298425 case 'array ' :
299426 if (is_array ($ value )) {
300427 $ mappedValues = [];
@@ -462,7 +589,15 @@ private function migrateItemsToTargetCms($targetCms, $targetType, $ccmToTargetIt
462589 if (!isset ($ this ->migrationMap [$ targetType ]['ids ' ])) {
463590 $ this ->migrationMap [$ targetType ]['ids ' ] = [];
464591 }
465- $ this ->migrationMap [$ targetType ]['ids ' ][$ oldId ] = $ newId ;
592+
593+ // For menus, store both newId and menutype
594+ if ($ targetType === 'menus ' ) {
595+ error_log ("[MigrationModel] Storing menu item with menutype for item: " . json_encode ($ item ));
596+ $ menutype = $ item ['menutype ' ] ?? $ item ['alias ' ] ?? $ item ['slug ' ] ?? '' ;
597+ $ this ->migrationMap [$ targetType ]['ids ' ][$ oldId ] = [$ newId , $ menutype ];
598+ } else {
599+ $ this ->migrationMap [$ targetType ]['ids ' ][$ oldId ] = $ newId ;
600+ }
466601 error_log ("[MigrationModel] Added to ID map: $ targetType.ids[ $ oldId] = $ newId " );
467602 } else {
468603 error_log ("[MigrationModel] Warning: Could not extract old/new IDs for mapping " );
0 commit comments