Skip to content

Commit 380775a

Browse files
committed
Added caching option
1 parent db56937 commit 380775a

File tree

6 files changed

+161
-87
lines changed

6 files changed

+161
-87
lines changed

Perplex.Umbraco.Forms/App_Plugins/PerplexUmbracoForms/PerplexUmbracoForms.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,8 @@
4444
<PerplexRecaptchConfig>
4545
<ErrorMessage />
4646
</PerplexRecaptchConfig>
47+
<PerplexCacheConfig>
48+
<EnableCache>true</EnableCache>
49+
<CacheDurationInMinutes>10</CacheDurationInMinutes>
50+
</PerplexCacheConfig>
4751
</PerplexUmbracoFormsConfig>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Xml.Serialization;
2+
3+
namespace PerplexUmbraco.Forms.Code.Configuration
4+
{
5+
[XmlType("PerplexCacheConfig")]
6+
public class PerplexCacheConfig
7+
{
8+
[XmlElement("CacheDurationInMinutes")]
9+
public int CacheDurationInMinutes { get; set; }
10+
11+
[XmlElement("EnableCache")]
12+
public bool EnableCache { get; set; }
13+
}
14+
}

Perplex.Umbraco.Forms/Code/Configuration/PerplexUmbracoFormsConfig.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4-
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
74
using System.Web.Hosting;
85
using System.Xml.Serialization;
6+
97
using static PerplexUmbraco.Forms.Code.Constants;
108

119
namespace PerplexUmbraco.Forms.Code.Configuration
@@ -73,6 +71,8 @@ public static void CreateIfNotExists()
7371

7472
public PerplexRecaptchaConfig PerplexRecaptchaConfig { get; set; }
7573

74+
public PerplexCacheConfig PerplexCacheConfig { get; set; }
75+
7676
private static string GetFilePath()
7777
{
7878
return HostingEnvironment.MapPath(Constants.CONFIGURATION_FILE_PATH);
@@ -139,6 +139,12 @@ private static string GetFilePath()
139139
PerplexRecaptchaConfig = new PerplexRecaptchaConfig
140140
{
141141
ErrorMessage = ""
142+
},
143+
144+
PerplexCacheConfig = new PerplexCacheConfig
145+
{
146+
EnableCache = false,
147+
CacheDurationInMinutes = 10
142148
}
143149
};
144150
}

Perplex.Umbraco.Forms/Code/UmbracoEvents.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using System.Web;
4+
5+
using PerplexUmbraco.Forms.Code.Configuration;
6+
37
using Umbraco.Core;
48
using Umbraco.Core.Logging;
5-
using PerplexUmbraco.Forms.Code.Configuration;
6-
using Umbraco.Web;
7-
using Umbraco.Forms.Data.Storage;
8-
using System;
99
using Umbraco.Forms.Core;
10+
using Umbraco.Forms.Data.Storage;
11+
using Umbraco.Web;
1012

1113
namespace PerplexUmbraco.Forms.Code
1214
{
@@ -64,6 +66,8 @@ void FormStorage_Created(object sender, FormEventArgs e)
6466

6567
folder.Forms.Add(form.Id.ToString());
6668
PerplexFolder.SaveAll();
69+
70+
ClearFormsCache(folderId.ToString());
6771
}
6872

6973
void FormStorage_Deleted(object sender, FormEventArgs e)
@@ -75,7 +79,23 @@ void FormStorage_Deleted(object sender, FormEventArgs e)
7579
{
7680
folder.Forms.Remove(form.Id.ToString());
7781
PerplexFolder.SaveAll();
82+
83+
ClearFormsCache(folder.Id);
84+
}
85+
}
86+
87+
void ClearFormsCache(string folderId)
88+
{
89+
var cacheConfig = PerplexUmbracoFormsConfig.Get.PerplexCacheConfig;
90+
91+
if (cacheConfig.EnableCache)
92+
{
93+
var cacheKey = $"PerplexFormTreeController_GetTreeNodes_id:{folderId}";
94+
var rtCache = ApplicationContext.Current.ApplicationCache.RuntimeCache;
95+
96+
if (rtCache.GetCacheItemsByKeySearch(cacheKey).Any())
97+
rtCache.ClearCacheByKeySearch(cacheKey);
7898
}
7999
}
80100
}
81-
}
101+
}

Perplex.Umbraco.Forms/Controllers/PerplexFormTreeController.cs

Lines changed: 107 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
1-
using Newtonsoft.Json;
2-
using PerplexUmbraco.Forms.Code;
3-
using System;
4-
using System.Collections.Generic;
5-
using System.IO;
1+
using System;
62
using System.Linq;
73
using System.Net.Http.Formatting;
8-
using System.Text;
9-
using System.Threading.Tasks;
104
using 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;
1411
using Umbraco.Forms.Web.Trees;
12+
using Umbraco.Web;
1513
using Umbraco.Web.Models.Trees;
1614
using Umbraco.Web.Mvc;
1715
using Umbraco.Web.Trees;
18-
using Umbraco.Web;
19-
using umbraco.BusinessLogic.Actions;
20-
using umbraco;
2116

2217
namespace 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;

Perplex.Umbraco.Forms/Perplex.Umbraco.Forms.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
</Reference>
231231
</ItemGroup>
232232
<ItemGroup>
233+
<Compile Include="Code\Configuration\PerplexCacheConfig.cs" />
233234
<Compile Include="Code\Configuration\ExtensionConfig.cs" />
234235
<Compile Include="Code\Configuration\FieldTypeConfig.cs" />
235236
<Compile Include="Code\Configuration\PerplexBaseFileConfig.cs" />

0 commit comments

Comments
 (0)