1- using Newtonsoft . Json ;
2- using PerplexUmbraco . Forms . Code ;
3- using System ;
4- using System . Collections . Generic ;
5- using System . IO ;
1+ using System ;
62using System . Linq ;
73using System . Net . Http . Formatting ;
8- using System . Text ;
9- using System . Threading . Tasks ;
104using System . Web ;
11- using System . Web . Hosting ;
12- using System . Web . Http ;
13- using Umbraco . Forms . Data ;
5+
6+ using PerplexUmbraco . Forms . Code ;
7+ using PerplexUmbraco . Forms . Code . Configuration ;
8+
9+ using umbraco ;
10+ using umbraco . BusinessLogic . Actions ;
1411using Umbraco . Forms . Web . Trees ;
12+ using Umbraco . Web ;
1513using Umbraco . Web . Models . Trees ;
1614using Umbraco . Web . Mvc ;
1715using Umbraco . Web . Trees ;
18- using Umbraco . Web ;
19- using umbraco . BusinessLogic . Actions ;
20- using umbraco ;
2116
2217namespace PerplexUmbraco . Forms . Controllers
2318{
@@ -41,92 +36,126 @@ public class PerplexFormTreeController : FormTreeController
4136 {
4237 // We load our custom menu actions from our own folder
4338 private const string VIEWS_ROOT = "/App_Plugins/PerplexUmbracoForms/views/" ;
39+ private readonly PerplexCacheConfig _cacheConfig ;
4440
45- public PerplexFormTreeController ( ) { }
41+ public PerplexFormTreeController ( )
42+ {
43+ _cacheConfig = PerplexUmbracoFormsConfig . Get . PerplexCacheConfig ;
44+ }
4645
47- protected override Umbraco . Web . Models . Trees . TreeNodeCollection GetTreeNodes ( string id , System . Net . Http . Formatting . FormDataCollection queryStrings )
46+ protected override TreeNodeCollection GetTreeNodes ( string id , FormDataCollection queryStrings )
4847 {
48+ var cacheKey = $ "PerplexFormTreeController_GetTreeNodes_id:{ queryStrings [ "id" ] } ";
49+ var rtCache = ApplicationContext . ApplicationCache . RuntimeCache ;
50+
4951 // If this is a form, use Umbraco's default behavior
5052 var folder = PerplexFolder . Get ( id ) ;
5153 if ( folder == null )
5254 {
53- return base . GetTreeNodes ( id , queryStrings ) ;
54- }
55+ var treeNodeCollection = _cacheConfig . EnableCache ? ( TreeNodeCollection ) rtCache . GetCacheItem ( cacheKey ) : ( TreeNodeCollection ) null ;
5556
56- // This is a folder
57+ if ( treeNodeCollection == null )
58+ {
59+ treeNodeCollection = base . GetTreeNodes ( id , queryStrings ) ;
5760
58- // We require all forms, and apply filtering based on folders later
59- var baseTreeNodes = base . GetTreeNodes ( "-1" , queryStrings ) ;
61+ if ( _cacheConfig . EnableCache )
62+ {
63+ if ( rtCache . GetCacheItemsByKeySearch ( cacheKey ) . Any ( ) )
64+ rtCache . ClearCacheByKeySearch ( cacheKey ) ;
6065
61- // Sanity check; make sure there are no orphan forms around
62- // (forms not contained within any folder). If so, move them to the root folder
63- var orphans = baseTreeNodes . Where ( n => PerplexFolder . Get ( f => f . Forms . Any ( formId => formId == n . Id . ToString ( ) ) ) == null ) . ToList ( ) ;
64- if ( orphans . Count > 0 )
65- {
66- foreach ( var orphan in orphans )
67- {
68- PerplexFolder . GetRootFolder ( ) . Forms . Add ( orphan . Id . ToString ( ) ) ;
66+ rtCache . InsertCacheItem ( cacheKey , ( ) => treeNodeCollection , new TimeSpan ( 0 , _cacheConfig . CacheDurationInMinutes , 0 ) , true ) ;
67+ }
6968 }
7069
71- PerplexFolder . SaveAll ( ) ;
70+ return treeNodeCollection ;
7271 }
7372
74- // Hide all Forms that are not contained within this folder
75- // If this folder itself is disabled (due to the user not having access),
76- // we also hide all its forms
77- baseTreeNodes . RemoveAll ( n =>
78- ! folder . Forms . Contains ( n . Id . ToString ( ) ) ||
79- ( folder . Disabled && folder . Forms . Contains ( n . Id . ToString ( ) ) )
80- ) ;
73+ // This is a folder
74+ var baseTreeNodes = _cacheConfig . EnableCache ? ( TreeNodeCollection ) rtCache . GetCacheItem ( cacheKey ) : ( TreeNodeCollection ) null ;
8175
82- // Sort the forms of this folder in the order as defined by the folder
83- baseTreeNodes . Sort ( ( x , y ) =>
76+ if ( baseTreeNodes == null )
8477 {
85- int idxX , idxY ;
78+ // We require all forms, and apply filtering based on folders later
79+ baseTreeNodes = base . GetTreeNodes ( "-1" , queryStrings ) ;
8680
87- idxX = folder . Forms . IndexOf ( x . Id . ToString ( ) ) ;
88- idxY = folder . Forms . IndexOf ( y . Id . ToString ( ) ) ;
81+ // Sanity check; make sure there are no orphan forms around
82+ // (forms not contained within any folder). If so, move them to the root folder
83+ var orphans = baseTreeNodes . Where ( n => PerplexFolder . Get ( f => f . Forms . Any ( formId => formId == n . Id . ToString ( ) ) ) == null ) . ToList ( ) ;
84+ if ( orphans . Count > 0 )
85+ {
86+ foreach ( var orphan in orphans )
87+ {
88+ PerplexFolder . GetRootFolder ( ) . Forms . Add ( orphan . Id . ToString ( ) ) ;
89+ }
8990
90- return idxX . CompareTo ( idxY ) ;
91- } ) ;
91+ PerplexFolder . SaveAll ( ) ;
92+ }
9293
93- // Add any subfolders of this node
94- // We loop through the list in reverse as we add every folder at the start of the list (before forms)
95- foreach ( var subFolder in folder . Folders . Reverse < PerplexFolder > ( ) )
96- {
97- // If this subfolder is disabled, and it is not on a path towards
98- // a folder that is NOT disabled, it should not be listed at all.
99- // When multiple start nodes are defined, it is possible for a disabled
100- // folder to be displayed in the tree, when one of its descendant folders is enabled.
101- if ( subFolder . Disabled )
94+ // Hide all Forms that are not contained within this folder
95+ // If this folder itself is disabled (due to the user not having access),
96+ // we also hide all its forms
97+ baseTreeNodes . RemoveAll ( n =>
98+ ! folder . Forms . Contains ( n . Id . ToString ( ) ) ||
99+ ( folder . Disabled && folder . Forms . Contains ( n . Id . ToString ( ) ) )
100+ ) ;
101+
102+ // Sort the forms of this folder in the order as defined by the folder
103+ baseTreeNodes . Sort ( ( x , y ) =>
104+ {
105+ int idxX , idxY ;
106+
107+ idxX = folder . Forms . IndexOf ( x . Id . ToString ( ) ) ;
108+ idxY = folder . Forms . IndexOf ( y . Id . ToString ( ) ) ;
109+
110+ return idxX . CompareTo ( idxY ) ;
111+ } ) ;
112+
113+ // Add any subfolders of this node
114+ // We loop through the list in reverse as we add every folder at the start of the list (before forms)
115+ foreach ( var subFolder in folder . Folders . Reverse ( ) )
102116 {
103- var startFolders = PerplexFolder . GetStartFoldersForCurrentUser ( ) ;
117+ // If this subfolder is disabled, and it is not on a path towards
118+ // a folder that is NOT disabled, it should not be listed at all.
119+ // When multiple start nodes are defined, it is possible for a disabled
120+ // folder to be displayed in the tree, when one of its descendant folders is enabled.
121+ if ( subFolder . Disabled )
122+ {
123+ var startFolders = PerplexFolder . GetStartFoldersForCurrentUser ( ) ;
124+
125+ bool isOnPathTowardsStartFolder = startFolders . Any ( sf => sf . Path . Any ( fid => fid == subFolder . Id ) ) ;
126+ if ( ! isOnPathTowardsStartFolder )
127+ {
128+ continue ;
129+ }
130+ }
104131
105- bool isOnPathTowardsStartFolder = startFolders . Any ( sf => sf . Path . Any ( fid => fid == subFolder . Id ) ) ;
106- if ( ! isOnPathTowardsStartFolder )
132+ var treeNode = CreateTreeNode ( subFolder . Id , id , queryStrings , subFolder . Name ) ;
133+
134+ // Clicking this folder will show the folder overview
135+ // By default all nodes go to /forms/form/edit/<GUID>, but this
136+ // is only valid for forms. We direct to our custom folder view
137+ treeNode . RoutePath = "forms/perplexForms/folder/" + treeNode . Id ;
138+ if ( subFolder . Disabled )
107139 {
108- continue ;
140+ treeNode . CssClasses . Add ( "disabled" ) ;
109141 }
110- }
111142
112- var treeNode = CreateTreeNode ( subFolder . Id , id , queryStrings , subFolder . Name ) ;
143+ // Folder has children if it has either forms or folders.
144+ // If it is disabled, this is only true when it has subfolders
145+ // since we do not show its forms.
146+ treeNode . HasChildren = ( subFolder . Disabled && subFolder . Folders . Any ( ) ) || ( ! subFolder . Disabled && ( subFolder . Forms . Any ( ) || subFolder . Folders . Any ( ) ) ) ;
113147
114- // Clicking this folder will show the folder overview
115- // By default all nodes go to /forms/form/edit/<GUID>, but this
116- // is only valid for forms. We direct to our custom folder view
117- treeNode . RoutePath = "forms/perplexForms/folder/" + treeNode . Id ;
118- if ( subFolder . Disabled )
119- {
120- treeNode . CssClasses . Add ( "disabled" ) ;
148+ // Folders are added at the top of the list, before forms
149+ baseTreeNodes . Insert ( 0 , treeNode ) ;
121150 }
122151
123- // Folder has children if it has either forms or folders.
124- // If it is disabled, this is only true when it has subfolders
125- // since we do not show its forms.
126- treeNode . HasChildren = ( subFolder . Disabled && subFolder . Folders . Any ( ) ) || ( ! subFolder . Disabled && ( subFolder . Forms . Any ( ) || subFolder . Folders . Any ( ) ) ) ;
152+ if ( _cacheConfig . EnableCache )
153+ {
154+ if ( rtCache . GetCacheItemsByKeySearch ( cacheKey ) . Any ( ) )
155+ rtCache . ClearCacheByKeySearch ( cacheKey ) ;
127156
128- // Folders are added at the top of the list, before forms
129- baseTreeNodes . Insert ( 0 , treeNode ) ;
157+ rtCache . InsertCacheItem ( cacheKey , ( ) => baseTreeNodes , new TimeSpan ( 0 , _cacheConfig . CacheDurationInMinutes , 0 ) , true ) ;
158+ }
130159 }
131160
132161 return baseTreeNodes ;
@@ -139,7 +168,7 @@ protected override TreeNode CreateRootNode(FormDataCollection queryStrings)
139168
140169 // If none are set, all folders are allowed so we just use default behavior
141170 // Likewise if the common ancestors of all allowed folders is the root.
142- PerplexFolder commonAncestor = PerplexFolder . GetCommonAncestor ( startFolders ) ;
171+ PerplexFolder commonAncestor = PerplexFolder . GetCommonAncestor ( startFolders ) ;
143172
144173 if ( ! startFolders . Any ( ) || commonAncestor == PerplexFolder . GetRootFolder ( ) )
145174 {
@@ -157,11 +186,11 @@ protected override TreeNode CreateRootNode(FormDataCollection queryStrings)
157186 // if this is the common ancestor of this user's start nodes but not
158187 // a start node itself. In that case it should also show as disabled in
159188 // the UI, and we hide its URL.
160- rootNode . RoutePath = "forms/perplexForms/folder/" + commonAncestor . Id ;
161- if ( commonAncestor . Disabled )
189+ rootNode . RoutePath = "forms/perplexForms/folder/" + commonAncestor . Id ;
190+ if ( commonAncestor . Disabled )
162191 {
163192 rootNode . CssClasses . Add ( "disabled" ) ;
164- }
193+ }
165194
166195 // Folder has children if it has either forms or folders
167196 rootNode . HasChildren = commonAncestor . Forms . Any ( ) || commonAncestor . Folders . Any ( ) ;
@@ -197,10 +226,10 @@ protected override MenuItemCollection GetMenuForNode(string id, FormDataCollecti
197226 {
198227 menu . Items . RemoveAll ( m => m . Alias != ActionRefresh . Instance . Alias ) ;
199228 return menu ;
200- }
229+ }
201230
202231 // Create Form (default Umbraco view, hence alias)
203- AddMenuItem ( menu , "Create Form" , alias : "create" , icon : "icon icon-add" ) ;
232+ AddMenuItem ( menu , "Create Form" , alias : "create" , icon : "icon icon-add" ) ;
204233
205234 // Create Folder
206235 AddMenuItem ( menu , "Create Folder" , view : "createFolder" , icon : "icon icon-folder" ) ;
@@ -239,7 +268,7 @@ protected override MenuItemCollection GetMenuForNode(string id, FormDataCollecti
239268 var root = PerplexFolder . GetRootFolder ( ) ;
240269
241270 // If the root folder is disabled, remove all menu actions except Reload
242- if ( root . Disabled )
271+ if ( root . Disabled )
243272 {
244273 menu . Items . RemoveAll ( m => m . Alias != ActionRefresh . Instance . Alias ) ;
245274 return menu ;
0 commit comments