diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs index 54979990b7bb..070885d6211e 100644 --- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs +++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs @@ -1,21 +1,14 @@ using System; using System.IO; -using System.Linq; -using System.Net.Http.Formatting; -using umbraco.BusinessLogic.Actions; -using Umbraco.Core; using Umbraco.Core.IO; -using Umbraco.Core.Services; using Umbraco.Web.Models.Trees; -using System.Web; namespace Umbraco.Web.Trees { public abstract class FileSystemTreeController : TreeController { - protected abstract IFileSystem2 FileSystem { get; } - protected abstract string[] Extensions { get; } - protected abstract string FileIcon { get; } + protected abstract string FilePath { get; } + protected abstract string FileSearchPattern { get; } /// /// Inheritors can override this method to modify the file node that is created. @@ -29,100 +22,68 @@ public abstract class FileSystemTreeController : TreeController /// protected virtual void OnRenderFolderNode(ref TreeNode treeNode) { } - protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + protected override TreeNodeCollection GetTreeNodes(string id, System.Net.Http.Formatting.FormDataCollection queryStrings) { - var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString() - ? HttpUtility.UrlDecode(id).TrimStart("/") - : ""; - - var directories = FileSystem.GetDirectories(path); - - var nodes = new TreeNodeCollection(); - foreach (var directory in directories) + var orgPath = ""; + string path; + if (string.IsNullOrEmpty(id) == false && id != "-1") { - var hasChildren = FileSystem.GetFiles(directory).Any() || FileSystem.GetDirectories(directory).Any(); - - var name = Path.GetFileName(directory); - var node = CreateTreeNode(HttpUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren); - OnRenderFolderNode(ref node); - if(node != null) - nodes.Add(node); + orgPath = id; + path = IOHelper.MapPath(FilePath + "/" + orgPath); + orgPath += "/"; } - - //this is a hack to enable file system tree to support multiple file extension look-up - //so the pattern both support *.* *.xml and xml,js,vb for lookups - var files = FileSystem.GetFiles(path).Where(x => + else { - var extension = Path.GetExtension(x); - return extension != null && Extensions.Contains(extension.Trim('.'), StringComparer.InvariantCultureIgnoreCase); - }); + path = IOHelper.MapPath(FilePath); + } + + var dirInfo = new DirectoryInfo(path); + var dirInfos = dirInfo.GetDirectories(); - foreach (var file in files) - { - var withoutExt = Path.GetFileNameWithoutExtension(file); - if (withoutExt.IsNullOrWhiteSpace() == false) + var nodes = new TreeNodeCollection(); + foreach (var dir in dirInfos) + { + if ((dir.Attributes & FileAttributes.Hidden) == 0) { - var name = Path.GetFileName(file); - var node = CreateTreeNode(HttpUtility.UrlEncode(file), path, queryStrings, name, FileIcon, false); - OnRenderFileNode(ref node); + var hasChildren = dir.GetFiles().Length > 0 || dir.GetDirectories().Length > 0; + var node = CreateTreeNode(orgPath + dir.Name, orgPath, queryStrings, dir.Name, "icon-folder", hasChildren); + + OnRenderFolderNode(ref node); if (node != null) nodes.Add(node); } } - return nodes; - } - - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) - { - var menu = new MenuItemCollection(); + //this is a hack to enable file system tree to support multiple file extension look-up + //so the pattern both support *.* *.xml and xml,js,vb for lookups + var allowedExtensions = new string[0]; + var filterByMultipleExtensions = FileSearchPattern.Contains(","); + FileInfo[] fileInfo; - //if root node no need to visit the filesystem so lets just create the menu and return it - if (id == Constants.System.Root.ToInvariantString()) + if (filterByMultipleExtensions) { - //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; - //create action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); - //refresh action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); - - return menu; + fileInfo = dirInfo.GetFiles(); + allowedExtensions = FileSearchPattern.ToLower().Split(','); } + else + fileInfo = dirInfo.GetFiles(FileSearchPattern); - var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString() - ? System.Web.HttpUtility.UrlDecode(id).TrimStart("/") - : ""; - - var isFile = FileSystem.FileExists(path); - var isDirectory = FileSystem.DirectoryExists(path); - - if (isDirectory) + foreach (var file in fileInfo) { - //set the default to create - menu.DefaultMenuAlias = ActionNew.Instance.Alias; - //create action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + if ((file.Attributes & FileAttributes.Hidden) == 0) + { + if (filterByMultipleExtensions && Array.IndexOf(allowedExtensions, file.Extension.ToLower().Trim('.')) < 0) + continue; - var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); + var node = CreateTreeNode(orgPath + file.Name, orgPath, queryStrings, file.Name, "icon-file", false); - //We can only delete folders if it doesn't have any children (folders or files) - if (hasChildren == false) - { - //delete action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); - } + OnRenderFileNode(ref node); - //refresh action - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); - } - else if (isFile) - { - //if it's not a directory then we only allow to delete the item - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); + if (node != null) + nodes.Add(node); + } } - - return menu; + return nodes; } } } diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController2.cs b/src/Umbraco.Web/Trees/FileSystemTreeController2.cs new file mode 100644 index 000000000000..79735e7e68e5 --- /dev/null +++ b/src/Umbraco.Web/Trees/FileSystemTreeController2.cs @@ -0,0 +1,128 @@ +using System; +using System.IO; +using System.Linq; +using System.Net.Http.Formatting; +using umbraco.BusinessLogic.Actions; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.Services; +using Umbraco.Web.Models.Trees; +using System.Web; + +namespace Umbraco.Web.Trees +{ + public abstract class FileSystemTreeController2 : TreeController + { + protected abstract IFileSystem2 FileSystem { get; } + protected abstract string[] Extensions { get; } + protected abstract string FileIcon { get; } + + /// + /// Inheritors can override this method to modify the file node that is created. + /// + /// + protected virtual void OnRenderFileNode(ref TreeNode treeNode) { } + + /// + /// Inheritors can override this method to modify the folder node that is created. + /// + /// + protected virtual void OnRenderFolderNode(ref TreeNode treeNode) { } + + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString() + ? HttpUtility.UrlDecode(id).TrimStart("/") + : ""; + + var directories = FileSystem.GetDirectories(path); + + var nodes = new TreeNodeCollection(); + foreach (var directory in directories) + { + var hasChildren = FileSystem.GetFiles(directory).Any() || FileSystem.GetDirectories(directory).Any(); + + var name = Path.GetFileName(directory); + var node = CreateTreeNode(HttpUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren); + OnRenderFolderNode(ref node); + if(node != null) + nodes.Add(node); + } + + //this is a hack to enable file system tree to support multiple file extension look-up + //so the pattern both support *.* *.xml and xml,js,vb for lookups + var files = FileSystem.GetFiles(path).Where(x => + { + var extension = Path.GetExtension(x); + return extension != null && Extensions.Contains(extension.Trim('.'), StringComparer.InvariantCultureIgnoreCase); + }); + + foreach (var file in files) + { + var withoutExt = Path.GetFileNameWithoutExtension(file); + if (withoutExt.IsNullOrWhiteSpace() == false) + { + var name = Path.GetFileName(file); + var node = CreateTreeNode(HttpUtility.UrlEncode(file), path, queryStrings, name, FileIcon, false); + OnRenderFileNode(ref node); + if (node != null) + nodes.Add(node); + } + } + + return nodes; + } + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + + //if root node no need to visit the filesystem so lets just create the menu and return it + if (id == Constants.System.Root.ToInvariantString()) + { + //set the default to create + menu.DefaultMenuAlias = ActionNew.Instance.Alias; + //create action + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + //refresh action + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + + return menu; + } + + var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString() + ? HttpUtility.UrlDecode(id).TrimStart("/") + : ""; + + var isFile = FileSystem.FileExists(path); + var isDirectory = FileSystem.DirectoryExists(path); + + if (isDirectory) + { + //set the default to create + menu.DefaultMenuAlias = ActionNew.Instance.Alias; + //create action + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); + + var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); + + //We can only delete folders if it doesn't have any children (folders or files) + if (hasChildren == false) + { + //delete action + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true); + } + + //refresh action + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true); + } + else if (isFile) + { + //if it's not a directory then we only allow to delete the item + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias))); + } + + return menu; + } + } +} diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs index db4f3676e530..ba4724aeadee 100644 --- a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs @@ -8,14 +8,14 @@ namespace Umbraco.Web.Trees /// Tree for displaying partial view macros in the developer app /// [Tree(Constants.Applications.Developer, "partialViewMacros", null, sortOrder: 6)] - public class PartialViewMacrosTreeController : FileSystemTreeController + public class PartialViewMacrosTreeController : FileSystemTreeController2 { protected override IFileSystem2 FileSystem { get { return FileSystemProviderManager.Current.MacroPartialsFileSystem; } } - private static readonly string[] ExtensionsStatic = { "cshtml" }; + private static readonly string[] ExtensionsStatic = {"cshtml"}; protected override string[] Extensions { diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs index 480cb789d8fa..bf4ec65a2eaa 100644 --- a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs @@ -8,14 +8,14 @@ namespace Umbraco.Web.Trees /// Tree for displaying partial views in the settings app /// [Tree(Constants.Applications.Settings, "partialViews", null, sortOrder: 2)] - public class PartialViewsTreeController : FileSystemTreeController + public class PartialViewsTreeController : FileSystemTreeController2 { - protected override IFileSystem2 FileSystem - { - get { return FileSystemProviderManager.Current.PartialViewsFileSystem; } - } + protected override IFileSystem2 FileSystem + { + get { return FileSystemProviderManager.Current.PartialViewsFileSystem; } + } - private static readonly string[] ExtensionsStatic = { "cshtml" }; + private static readonly string[] ExtensionsStatic = {"cshtml"}; protected override string[] Extensions { diff --git a/src/Umbraco.Web/Trees/ScriptTreeController.cs b/src/Umbraco.Web/Trees/ScriptTreeController.cs index 2e4c25c65602..cb9954019b22 100644 --- a/src/Umbraco.Web/Trees/ScriptTreeController.cs +++ b/src/Umbraco.Web/Trees/ScriptTreeController.cs @@ -5,7 +5,7 @@ namespace Umbraco.Web.Trees { [Tree(Constants.Applications.Settings, "scripts", null, sortOrder: 4)] - public class ScriptTreeController : FileSystemTreeController + public class ScriptTreeController : FileSystemTreeController2 { protected override IFileSystem2 FileSystem { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 9aaab32af979..44b3258c84d1 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -435,6 +435,7 @@ + @@ -712,7 +713,7 @@ - +