@@ -3309,29 +3309,35 @@ private function normalizeBucketsForRestorer(object $course): void
33093309 return ;
33103310 }
33113311
3312- // Canonical keys -> constants used by the restorer (reference only)
3313- $ allowed = [
3314- 'link ' => \defined ('RESOURCE_LINK ' ) ? RESOURCE_LINK : null ,
3315- 'link_category ' => \defined ('RESOURCE_LINKCATEGORY ' ) ? RESOURCE_LINKCATEGORY : null ,
3316- 'forum ' => \defined ('RESOURCE_FORUM ' ) ? RESOURCE_FORUM : null ,
3317- 'forum_category ' => \defined ('RESOURCE_FORUMCATEGORY ' ) ? RESOURCE_FORUMCATEGORY : null ,
3318- 'forum_topic ' => \defined ('RESOURCE_FORUMTOPIC ' ) ? RESOURCE_FORUMTOPIC : null ,
3319- 'forum_post ' => \defined ('RESOURCE_FORUMPOST ' ) ? RESOURCE_FORUMPOST : null ,
3320- 'document ' => \defined ('RESOURCE_DOCUMENT ' ) ? RESOURCE_DOCUMENT : null ,
3321- 'quiz ' => \defined ('RESOURCE_QUIZ ' ) ? RESOURCE_QUIZ : null ,
3322- 'exercise_question ' => \defined ('RESOURCE_QUIZQUESTION ' ) ? RESOURCE_QUIZQUESTION : null ,
3323- 'survey ' => \defined ('RESOURCE_SURVEY ' ) ? RESOURCE_SURVEY : null ,
3324- 'survey_question ' => \defined ('RESOURCE_SURVEYQUESTION ' ) ? RESOURCE_SURVEYQUESTION : null ,
3325- 'tool_intro ' => \defined ('RESOURCE_TOOL_INTRO ' ) ? RESOURCE_TOOL_INTRO : null ,
3326- ];
3312+ // Split meta buckets
3313+ $ all = $ course ->resources ;
3314+ $ meta = [];
3315+ foreach ($ all as $ k => $ v ) {
3316+ if (\is_string ($ k ) && str_starts_with ($ k , '__ ' )) {
3317+ $ meta [$ k ] = $ v ;
3318+ unset($ all [$ k ]);
3319+ }
3320+ }
33273321
3328- // Minimal, well-scoped alias map (input -> canonical)
3329- $ alias = [
3330- // docs
3331- 'documents ' => 'document ' ,
3332- 'document ' => 'document ' ,
3333- 'document ' => 'document ' ,
3334- 'Document ' => 'document ' ,
3322+ // Start from current
3323+ $ out = $ all ;
3324+
3325+ // merge array buckets preserving numeric/string ids
3326+ $ merge = static function (array $ dst , array $ src ): array {
3327+ foreach ($ src as $ id => $ obj ) {
3328+ if (!\array_key_exists ($ id , $ dst )) {
3329+ $ dst [$ id ] = $ obj ;
3330+ }
3331+ }
3332+ return $ dst ;
3333+ };
3334+
3335+ // safe alias map (input -> canonical). Extend only if needed.
3336+ $ aliases = [
3337+ // documents
3338+ 'documents ' => 'document ' ,
3339+ 'Document ' => 'document ' ,
3340+ 'document ' => 'document ' ,
33353341
33363342 // tool intro
33373343 'tool introduction ' => 'tool_intro ' ,
@@ -3341,96 +3347,70 @@ private function normalizeBucketsForRestorer(object $course): void
33413347 'Tool introduction ' => 'tool_intro ' ,
33423348
33433349 // forums
3344- 'forum ' => 'forum ' ,
3345- 'forums ' => 'forum ' ,
3346- 'forum_category ' => 'forum_category ' ,
3347- 'Forum_Category ' => 'forum_category ' ,
3348- 'forumcategory ' => 'forum_category ' ,
3349- 'forum_topic ' => 'forum_topic ' ,
3350- 'forumtopic ' => 'forum_topic ' ,
3351- 'thread ' => 'forum_topic ' ,
3352- 'forum_post ' => 'forum_post ' ,
3353- 'forumpost ' => 'forum_post ' ,
3354- 'post ' => 'forum_post ' ,
3350+ 'forums ' => 'forum ' ,
3351+ 'Forum ' => 'forum ' ,
3352+ 'Forum_Category ' => 'forum_category ' ,
3353+ 'forumcategory ' => 'forum_category ' ,
3354+ 'thread ' => 'forum_topic ' ,
3355+ 'Thread ' => 'forum_topic ' ,
3356+ 'forumtopic ' => 'forum_topic ' ,
3357+ 'post ' => 'forum_post ' ,
3358+ 'Post ' => 'forum_post ' ,
3359+ 'forumpost ' => 'forum_post ' ,
33553360
33563361 // links
3357- 'link ' => 'link ' ,
3358- 'links ' => 'link ' ,
3359- 'link_category ' => 'link_category ' ,
3360- 'link category ' => 'link_category ' ,
3362+ 'links ' => 'link ' ,
3363+ 'link category ' => 'link_category ' ,
33613364
33623365 // quiz + questions
3363- 'quiz ' => 'quiz ' ,
3364- 'exercise_question ' => 'exercise_question ' ,
3365- 'Exercise_Question ' => 'exercise_question ' ,
3366- 'exercisequestion ' => 'exercise_question ' ,
3366+ 'Exercise_Question ' => 'exercise_question ' ,
3367+ 'exercisequestion ' => 'exercise_question ' ,
33673368
33683369 // surveys
3369- 'survey ' => 'survey ' ,
3370- 'surveys ' => 'survey ' ,
3371- 'survey_question ' => 'survey_question ' ,
3372- 'surveyquestion ' => 'survey_question ' ,
3373- ];
3374-
3375- $ before = $ course ->resources ;
3376-
3377- // Keep meta buckets verbatim
3378- $ meta = [];
3379- foreach ($ before as $ k => $ v ) {
3380- if (\is_string ($ k ) && str_starts_with ($ k , '__ ' )) {
3381- $ meta [$ k ] = $ v ;
3382- unset($ before [$ k ]);
3383- }
3384- }
3385-
3386- $ hadDocument =
3387- isset ($ before ['document ' ]) ||
3388- isset ($ before ['Document ' ]) ||
3389- isset ($ before ['documents ' ]);
3370+ 'surveys ' => 'survey ' ,
3371+ 'surveyquestion ' => 'survey_question ' ,
33903372
3391- // Merge helper (preserve numeric/string ids)
3392- $ merge = static function (array $ dst , array $ src ): array {
3393- foreach ($ src as $ id => $ obj ) {
3394- if (!array_key_exists ($ id , $ dst )) {
3395- $ dst [$ id ] = $ obj ;
3396- }
3397- }
3398- return $ dst ;
3399- };
3400-
3401- $ out = [];
3373+ // announcements
3374+ 'announcements ' => 'announcement ' ,
3375+ 'Announcements ' => 'announcement ' ,
3376+ ];
34023377
3403- foreach ( $ before as $ rawKey => $ bucket ) {
3404- if (! \is_array ( $ bucket ) ) {
3405- // Unexpected shape; skip silently (defensive)
3406- continue ;
3378+ // Normalize keys (case/spacing) and apply alias merges
3379+ foreach ( $ all as $ rawKey => $ _bucket ) {
3380+ if (! \is_array ( $ _bucket )) {
3381+ continue ; // defensive
34073382 }
3408-
3409- // Normalize key shape first
34103383 $ k = (string ) $ rawKey ;
3411- $ norm = strtolower (trim ($ k ));
3412- $ norm = strtr ($ norm , ['\\' => '/ ' , '- ' => '_ ' ]); // cheap normalization
3413- // Map via alias table if present
3414- $ canon = $ alias [$ norm ] ?? $ alias [str_replace ('/ ' , '_ ' , $ norm )] ?? null ;
3384+ $ norm = strtolower (trim (strtr ($ k , ['\\' => '/ ' , '- ' => '_ ' ])));
3385+ $ norm2 = str_replace ('/ ' , '_ ' , $ norm );
34153386
3416- // If still unknown, try a sane guess: underscores + lowercase
3417- if (null === $ canon ) {
3418- $ guess = str_replace (['/ ' , ' ' ], '_ ' , $ norm );
3419- $ canon = \array_key_exists ($ guess , $ allowed ) ? $ guess : null ;
3387+ $ canonical = null ;
3388+ if (isset ($ aliases [$ norm ])) {
3389+ $ canonical = $ aliases [$ norm ];
3390+ } elseif (isset ($ aliases [$ norm2 ])) {
3391+ $ canonical = $ aliases [$ norm2 ];
34203392 }
34213393
3422- // Only produce buckets with canonical keys we support; unknown keys are ignored here
3423- if (null !== $ canon && \array_key_exists ($ canon , $ allowed )) {
3424- $ out [$ canon ] = isset ($ out [$ canon ]) ? $ merge ($ out [$ canon ], $ bucket ) : $ bucket ;
3394+ if ($ canonical && $ canonical !== $ rawKey ) {
3395+ // Merge into canonical and drop the alias key
3396+ $ out [$ canonical ] = isset ($ out [$ canonical ]) && \is_array ($ out [$ canonical ])
3397+ ? $ merge ($ out [$ canonical ], $ _bucket )
3398+ : $ _bucket ;
3399+ unset($ out [$ rawKey ]);
34253400 }
3401+ // else: leave as-is (pass-through)
34263402 }
34273403
3428- // Hard safety net: if a "document" bucket existed before, ensure it remains.
3429- if ($ hadDocument && !isset ($ out ['document ' ])) {
3430- $ out ['document ' ] = (array ) ($ before ['document ' ] ?? $ before ['Document ' ] ?? $ before ['documents ' ] ?? []);
3404+ // Safety: if there was any docs bucket under an alias, ensure 'document' is present.
3405+ if (!isset ($ out ['document ' ])) {
3406+ if (isset ($ all ['documents ' ]) && \is_array ($ all ['documents ' ])) {
3407+ $ out ['document ' ] = $ all ['documents ' ];
3408+ } elseif (isset ($ all ['Document ' ]) && \is_array ($ all ['Document ' ])) {
3409+ $ out ['document ' ] = $ all ['Document ' ];
3410+ }
34313411 }
34323412
3433- // Gentle ordering to keep things readable
3413+ // Gentle ordering for readability only (does not affect presence)
34343414 $ order = [
34353415 'announcement ' , 'document ' , 'link ' , 'link_category ' ,
34363416 'forum ' , 'forum_category ' , 'forum_topic ' , 'forum_post ' ,
@@ -3444,11 +3424,14 @@ private function normalizeBucketsForRestorer(object $course): void
34443424 uksort ($ out , static function ($ a , $ b ) use ($ w ) {
34453425 $ wa = $ w [$ a ] ?? 9999 ;
34463426 $ wb = $ w [$ b ] ?? 9999 ;
3447- return $ wa <=> $ wb ?: strcasecmp ($ a , $ b );
3427+ return $ wa <=> $ wb ?: strcasecmp (( string ) $ a , ( string ) $ b );
34483428 });
34493429
3450- // Final assign ( meta first, then normalized buckets)
3430+ // Final assign: meta first, then normalized buckets
34513431 $ course ->resources = $ meta + $ out ;
3432+
3433+ // Debug trace to verify we didn't lose keys
3434+ $ this ->logDebug ('[normalizeBucketsForRestorer] final keys ' , array_keys ((array ) $ course ->resources ));
34523435 }
34533436
34543437 /**
0 commit comments