@@ -12,7 +12,7 @@ public class ContentFolderService(IImporter importer, ILogger<ContentFolderServi
1212 /// <summary>
1313 /// Folder tree path as key
1414 /// </summary>
15- private readonly Dictionary < string , Guid > folderGuidCache = [ ] ;
15+ private readonly Dictionary < string , ContentFolderInfo > folderCache = [ ] ;
1616
1717 /// <summary>
1818 /// Iterates over the folder path. If a folder doesn't exist, it gets created
@@ -22,23 +22,27 @@ public class ContentFolderService(IImporter importer, ILogger<ContentFolderServi
2222 /// <exception cref="InvalidOperationException"></exception>
2323 public async Task < Guid ? > EnsureFolderStructure ( IEnumerable < ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) > folderPathTemplate , Guid ? workspaceGuid = null )
2424 {
25- workspaceGuid ??= workspaceService . FallbackWorkspace . Value . WorkspaceGUID ;
26- Guid ? parentGuid = GetWorkspaceRootFolder ( workspaceGuid . Value ) ;
25+ var workspaceInfo = workspaceGuid is not null
26+ ? ( workspaceService . GetWorkspace ( workspaceGuid ! . Value ) ?? workspaceService . FallbackWorkspace . Value )
27+ : workspaceService . FallbackWorkspace . Value ;
2728
28- var currentPath = string . Empty ;
29+ ContentFolderInfo ? parentFolderInfo = GetWorkspaceRootFolder ( workspaceInfo . WorkspaceGUID ) ;
30+
31+ string currentPath = string . Empty ;
2932 foreach ( var folderTemplate in folderPathTemplate )
3033 {
31- Guid newParentGuid ;
34+ ContentFolderInfo newParentFolder ;
3235 currentPath += $ "/{ folderTemplate . PathSegmentName } ";
33- if ( folderGuidCache . TryGetValue ( currentPath . ToString ( ) , out var folderGuid ) )
36+ var folderCacheKey = $ "{ workspaceInfo . WorkspaceGUID } |{ currentPath } ";
37+ if ( folderCache . TryGetValue ( folderCacheKey , out var folderGuid ) )
3438 {
35- newParentGuid = folderGuid ;
39+ newParentFolder = folderGuid ;
3640 }
3741 else
3842 {
3943 var folderInfo = ContentFolderInfo . Provider . Get ( )
40- . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderGUID ) , folderTemplate . Guid )
4144 . And ( ) . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderDisplayName ) , folderTemplate . DisplayName )
45+ . And ( ) . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderWorkspaceID ) , workspaceInfo . WorkspaceID )
4246 . FirstOrDefault ( ) ;
4347
4448 if ( folderInfo is null )
@@ -49,15 +53,15 @@ public class ContentFolderService(IImporter importer, ILogger<ContentFolderServi
4953 ContentFolderName = UniqueNameHelper . MakeUnique ( folderTemplate . Name , x => ! ContentFolderInfo . Provider . Get ( ) . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderName ) , x ) . Any ( ) ) ,
5054 ContentFolderDisplayName = folderTemplate . DisplayName ,
5155 ContentFolderTreePath = currentPath ,
52- ContentFolderParentFolderGUID = parentGuid ,
53- ContentFolderWorkspaceGUID = workspaceGuid
56+ ContentFolderParentFolderGUID = parentFolderInfo . ContentFolderGUID ,
57+ ContentFolderWorkspaceGUID = workspaceInfo . WorkspaceGUID
5458 } ;
5559
5660 switch ( await importer . ImportAsync ( newFolderModel ) )
5761 {
58- case { Success : true } :
62+ case { Success : true , Imported : ContentFolderInfo importedInfo } :
5963 {
60- newParentGuid = folderGuidCache [ currentPath ] = folderTemplate . Guid ;
64+ newParentFolder = folderCache [ folderCacheKey ] = importedInfo ;
6165 break ;
6266 }
6367 case { Success : false , Exception : { } exception } :
@@ -81,35 +85,42 @@ public class ContentFolderService(IImporter importer, ILogger<ContentFolderServi
8185 }
8286 else
8387 {
84- newParentGuid = folderInfo . ContentFolderGUID ;
88+ // The following inconsistency may exist in database due to migrations by previous versions of MT. If so, we patch it.
89+ if ( folderInfo . ContentFolderParentFolderID != parentFolderInfo . ContentFolderID )
90+ {
91+ folderInfo . ContentFolderParentFolderID = parentFolderInfo . ContentFolderID ;
92+ ContentFolderInfo . Provider . Set ( folderInfo ) ;
93+ }
94+
95+ newParentFolder = folderInfo ;
8596 }
8697 }
8798
88- parentGuid = newParentGuid ;
99+ parentFolderInfo = newParentFolder ;
89100 }
90101
91- return parentGuid ;
102+ return parentFolderInfo . ContentFolderGUID ;
92103 }
93104
94- private readonly Dictionary < Guid , Guid > workspaceRootFolderCache = [ ] ;
95- public Guid GetWorkspaceRootFolder ( Guid workspaceGuid )
105+ private readonly Dictionary < Guid , ContentFolderInfo > workspaceRootFolderCache = [ ] ;
106+ public ContentFolderInfo GetWorkspaceRootFolder ( Guid workspaceGuid )
96107 {
97- if ( workspaceRootFolderCache . TryGetValue ( workspaceGuid , out var folderGuid ) )
108+ if ( workspaceRootFolderCache . TryGetValue ( workspaceGuid , out var info ) )
98109 {
99- return folderGuid ;
110+ return info ;
100111 }
101112
102113 var workspace = workspaceService . GetWorkspace ( workspaceGuid ) ?? throw new Exception ( $ "Required workspace(GUID={ workspaceGuid } ) not found") ;
103114
104- folderGuid = ContentFolderInfo . Provider . Get ( )
115+ info = ContentFolderInfo . Provider . Get ( )
105116 . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderWorkspaceID ) , workspace . WorkspaceID )
106117 . And ( ) . WhereEquals ( nameof ( ContentFolderInfo . ContentFolderParentFolderID ) , null )
107- . FirstOrDefault ( ) ? . ContentFolderGUID
108- ?? throw new Exception ( $ "Root folder for workspace(GUID={ workspaceGuid } ) not found") ;
118+ . FirstOrDefault ( )
119+ ?? throw new Exception ( $ "Root folder for workspace(GUID={ workspaceGuid } ) not found") ;
109120
110- workspaceRootFolderCache [ workspaceGuid ] = folderGuid ;
121+ workspaceRootFolderCache [ workspaceGuid ] = info ;
111122
112- return folderGuid ;
123+ return info ;
113124 }
114125
115126 private static string DisplayNamePathToTreePath ( string displayNamePath ) => string . Join ( "/" , displayNamePath . Split ( '/' ) . Select ( x => ValidationHelper . GetCodeName ( x , 0 ) ) ) ;
@@ -118,8 +129,8 @@ public Guid GetWorkspaceRootFolder(Guid workspaceGuid)
118129 /// <summary>
119130 /// Returns standard attributes of a new folder derived from its display name
120131 /// </summary>
121- public static ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) StandardFolderTemplate ( string siteHash , string folderDisplayName , string absoluteDisplayNamePath )
122- => ( GuidHelper . CreateFolderGuid ( $ "{ siteHash } |{ DisplayNamePathToTreePath ( absoluteDisplayNamePath ) } ") , FolderDisplayNameToName ( folderDisplayName ) , folderDisplayName , FolderDisplayNameToName ( folderDisplayName ) ) ;
132+ public static ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) StandardFolderTemplate ( string siteHash , string folderDisplayName , string absoluteDisplayNamePath , Guid workspaceGuid )
133+ => ( GuidHelper . CreateFolderGuid ( $ "{ workspaceGuid } | { siteHash } |{ DisplayNamePathToTreePath ( absoluteDisplayNamePath ) } ") , FolderDisplayNameToName ( folderDisplayName ) , folderDisplayName , FolderDisplayNameToName ( folderDisplayName ) ) ;
123134
124135 public delegate void FolderPathSegmentCallback ( string segmentDisplayName , string path ) ;
125136
@@ -141,10 +152,10 @@ public static void WalkFolderPath(string path, FolderPathSegmentCallback segment
141152 /// Accepts path where segments represent folder display names and returns path template,
142153 /// i.e. sequence of folder templates, composed of standard folder templates derived from the display names
143154 /// </summary>
144- public static List < ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) > StandardPathTemplate ( string siteHash , string absolutePath )
155+ public static List < ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) > StandardPathTemplate ( string siteHash , string absolutePath , Guid workspaceGuid )
145156 {
146157 var pathTemplate = new List < ( Guid Guid , string Name , string DisplayName , string PathSegmentName ) > ( ) ;
147- WalkFolderPath ( absolutePath , ( segmentDisplayName , path ) => pathTemplate . Add ( StandardFolderTemplate ( siteHash , segmentDisplayName , path ) ) ) ;
158+ WalkFolderPath ( absolutePath , ( segmentDisplayName , path ) => pathTemplate . Add ( StandardFolderTemplate ( siteHash , segmentDisplayName , path , workspaceGuid ) ) ) ;
148159 return pathTemplate ;
149160 }
150161
@@ -153,13 +164,13 @@ public static void WalkFolderPath(string path, FolderPathSegmentCallback segment
153164 /// of the folders and the attributes of a folder that is to be created are derived from its display name
154165 /// in a defined standard way
155166 /// </summary>
156- public Task < Guid ? > EnsureStandardFolderStructure ( string siteHash , string absolutePath , Guid ? workspaceGuid = null ) => EnsureFolderStructure ( StandardPathTemplate ( siteHash , absolutePath ) , workspaceGuid ) ;
167+ public Task < Guid ? > EnsureStandardFolderStructure ( string siteHash , string absolutePath , Guid ? workspaceGuid = null ) => EnsureFolderStructure ( StandardPathTemplate ( siteHash , absolutePath , workspaceGuid ! . Value ) , workspaceGuid ) ;
157168
158169 public Guid ? EnsureFolder ( ContentFolderOptions ? options , bool isReusableItem , Guid ? workspaceGuid = null ) =>
159170 isReusableItem
160171 ? options switch
161172 {
162- null => GetWorkspaceRootFolder ( workspaceService . FallbackWorkspace . Value . WorkspaceGUID ) ,
173+ null => GetWorkspaceRootFolder ( workspaceService . FallbackWorkspace . Value . WorkspaceGUID ) . ContentFolderGUID ,
163174 { Guid : { } guid } => guid ,
164175 { DisplayNamePath : { } displayNamePath } => EnsureStandardFolderStructure ( "customtables" , displayNamePath , workspaceGuid ) . GetAwaiter ( ) . GetResult ( ) ,
165176 _ => throw new InvalidOperationException ( $ "{ nameof ( ContentFolderOptions ) } has neither { nameof ( ContentFolderOptions . Guid ) } nor { nameof ( ContentFolderOptions . DisplayNamePath ) } specified")
0 commit comments