diff --git a/src/Umbraco.Cms.Api.Management/Services/FileSystem/FileSystemTreeServiceBase.cs b/src/Umbraco.Cms.Api.Management/Services/FileSystem/FileSystemTreeServiceBase.cs index 43816e77b2..894c837dd8 100644 --- a/src/Umbraco.Cms.Api.Management/Services/FileSystem/FileSystemTreeServiceBase.cs +++ b/src/Umbraco.Cms.Api.Management/Services/FileSystem/FileSystemTreeServiceBase.cs @@ -75,9 +75,12 @@ public abstract class FileSystemTreeServiceBase : IFileSystemTreeService public string[] GetFiles(string path) => FileSystem .GetFiles(path) + .Where(FilterFile) .OrderBy(file => file) .ToArray(); + protected virtual bool FilterFile(string file) => true; + public bool DirectoryHasChildren(string path) => FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any(); diff --git a/src/Umbraco.Cms.Api.Management/Services/FileSystem/PartialViewTreeService.cs b/src/Umbraco.Cms.Api.Management/Services/FileSystem/PartialViewTreeService.cs index 3da299008c..7a614e69f3 100644 --- a/src/Umbraco.Cms.Api.Management/Services/FileSystem/PartialViewTreeService.cs +++ b/src/Umbraco.Cms.Api.Management/Services/FileSystem/PartialViewTreeService.cs @@ -11,4 +11,6 @@ public class PartialViewTreeService : FileSystemTreeServiceBase, IPartialViewTre public PartialViewTreeService(FileSystems fileSystems) => _partialViewFileSystem = fileSystems.PartialViewsFileSystem ?? throw new ArgumentException("Missing partial views file system", nameof(fileSystems)); + + protected override bool FilterFile(string file) => file.ToLowerInvariant().EndsWith(".cshtml"); } diff --git a/src/Umbraco.Cms.Api.Management/Services/FileSystem/ScriptTreeService.cs b/src/Umbraco.Cms.Api.Management/Services/FileSystem/ScriptTreeService.cs index ef870406f8..27b1eaf8f5 100644 --- a/src/Umbraco.Cms.Api.Management/Services/FileSystem/ScriptTreeService.cs +++ b/src/Umbraco.Cms.Api.Management/Services/FileSystem/ScriptTreeService.cs @@ -11,4 +11,6 @@ public class ScriptTreeService : FileSystemTreeServiceBase, IScriptTreeService public ScriptTreeService(FileSystems fileSystems) => _scriptFileSystem = fileSystems.ScriptsFileSystem ?? throw new ArgumentException("Missing partial views file system", nameof(fileSystems)); + + protected override bool FilterFile(string file) => file.ToLowerInvariant().EndsWith(".js"); } diff --git a/src/Umbraco.Cms.Api.Management/Services/FileSystem/StyleSheetTreeService.cs b/src/Umbraco.Cms.Api.Management/Services/FileSystem/StyleSheetTreeService.cs index ed14819231..57cdf616ae 100644 --- a/src/Umbraco.Cms.Api.Management/Services/FileSystem/StyleSheetTreeService.cs +++ b/src/Umbraco.Cms.Api.Management/Services/FileSystem/StyleSheetTreeService.cs @@ -10,5 +10,7 @@ public class StyleSheetTreeService : FileSystemTreeServiceBase, IStyleSheetTreeS public StyleSheetTreeService(FileSystems fileSystems) => _scriptFileSystem = fileSystems.StylesheetsFileSystem ?? - throw new ArgumentException("Missing partial views file system", nameof(fileSystems)); + throw new ArgumentException("Missing stylesheets file system", nameof(fileSystems)); + + protected override bool FilterFile(string file) => file.ToLowerInvariant().EndsWith(".css"); } diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/FileSystemTreeServiceTestsBase.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/FileSystemTreeServiceTestsBase.cs index e328b90d41..0ae45feb11 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/FileSystemTreeServiceTestsBase.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/FileSystemTreeServiceTestsBase.cs @@ -16,12 +16,14 @@ public abstract class FileSystemTreeServiceTestsBase : UmbracoIntegrationTest protected IFileSystem TestFileSystem { get; private set; } + protected abstract string FileExtension { get; set; } + protected abstract string FileSystemPath { get; } protected IHostingEnvironment HostingEnvironment => GetRequiredService(); [SetUp] - public void SetUpFileSystem() + public virtual void SetUpFileSystem() { TestFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, LoggerFactory.CreateLogger(), HostingEnvironment.MapPathWebRoot(FileSystemPath), HostingEnvironment.ToAbsolute(FileSystemPath)); @@ -37,11 +39,11 @@ public abstract class FileSystemTreeServiceTestsBase : UmbracoIntegrationTest for (int i = 0; i < 10; i++) { using var stream = CreateStream(Path.Join("tests")); - TestFileSystem.AddFile($"file{i}", stream); + TestFileSystem.AddFile($"file{i}{FileExtension}", stream); } } - private static Stream CreateStream(string contents = null) + protected static Stream CreateStream(string contents = null) { if (string.IsNullOrEmpty(contents)) { @@ -59,7 +61,7 @@ public abstract class FileSystemTreeServiceTestsBase : UmbracoIntegrationTest protected virtual IFileSystem? GetScriptsFileSystem() => null; [TearDown] - public void TearDownFileSystem() + public virtual void TearDownFileSystem() { Purge(TestFileSystem, string.Empty); FileSystems = null; diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/PartialViewTreeServiceTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/PartialViewTreeServiceTests.cs index 0dbe9f39a3..f2068a4b70 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/PartialViewTreeServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/PartialViewTreeServiceTests.cs @@ -8,6 +8,8 @@ namespace Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees; public class PartialViewTreeServiceTests : FileSystemTreeServiceTestsBase { + protected override string FileExtension { get; set; } = ".cshtml"; + protected override string FileSystemPath => Constants.SystemDirectories.PartialViews; protected override IFileSystem? GetPartialViewsFileSystem() => TestFileSystem; @@ -17,12 +19,12 @@ public class PartialViewTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new PartialViewTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels("file5", 1, 1, out long before, out var after); - int index = Array.FindIndex(treeModel, item => item.Name == "file5"); + FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels($"file5{FileExtension}", 1, 1, out long before, out var after); + int index = Array.FindIndex(treeModel, item => item.Name == $"file5{FileExtension}"); - Assert.AreEqual(treeModel[index].Name, "file5"); - Assert.AreEqual(treeModel[index - 1].Name, "file4"); - Assert.AreEqual(treeModel[index + 1].Name, "file6"); + Assert.AreEqual(treeModel[index].Name, $"file5{FileExtension}"); + Assert.AreEqual(treeModel[index - 1].Name, $"file4{FileExtension}"); + Assert.AreEqual(treeModel[index + 1].Name, $"file6{FileExtension}"); Assert.That(treeModel.Length == 3); Assert.AreEqual(after, 3); Assert.AreEqual(before, 4); @@ -33,7 +35,7 @@ public class PartialViewTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new PartialViewTreeService(FileSystems); - var path = Path.Join("tests", "file5"); + var path = Path.Join("tests", $"file5{FileExtension}"); FileSystemTreeItemPresentationModel[] treeModel = service.GetAncestorModels(path, true); Assert.IsNotEmpty(treeModel); @@ -46,9 +48,25 @@ public class PartialViewTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new PartialViewTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, Int32.MaxValue, out var totalItems); + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); Assert.IsNotEmpty(treeModels); Assert.AreEqual(treeModels.Length, totalItems); } + + [Test] + public void Will_Hide_Unsupported_File_Extensions() + { + var service = new PartialViewTreeService(FileSystems); + for (int i = 0; i < 2; i++) + { + using var stream = CreateStream(Path.Join("tests")); + TestFileSystem.AddFile($"file{i}.invalid", stream); + } + + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); + + Assert.IsEmpty(treeModels.Where(file => file.Name.Contains(".invalid"))); + Assert.AreEqual(treeModels.Length, totalItems); + } } diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/ScriptTreeServiceTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/ScriptTreeServiceTests.cs index 481fbd609b..874d59fd15 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/ScriptTreeServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/ScriptTreeServiceTests.cs @@ -7,6 +7,7 @@ namespace Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees; public class ScriptTreeServiceTests : FileSystemTreeServiceTestsBase { + protected override string FileExtension { get; set; } = ".js"; protected override string FileSystemPath => GlobalSettings.UmbracoScriptsPath; protected override IFileSystem? GetScriptsFileSystem() => TestFileSystem; @@ -16,12 +17,12 @@ public class ScriptTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new ScriptTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels("file5", 1, 1, out long before, out var after); - int index = Array.FindIndex(treeModel, item => item.Name == "file5"); + FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels($"file5{FileExtension}", 1, 1, out long before, out var after); + int index = Array.FindIndex(treeModel, item => item.Name == $"file5{FileExtension}"); - Assert.AreEqual(treeModel[index].Name, "file5"); - Assert.AreEqual(treeModel[index - 1].Name, "file4"); - Assert.AreEqual(treeModel[index + 1].Name, "file6"); + Assert.AreEqual(treeModel[index].Name, $"file5{FileExtension}"); + Assert.AreEqual(treeModel[index - 1].Name, $"file4{FileExtension}"); + Assert.AreEqual(treeModel[index + 1].Name, $"file6{FileExtension}"); Assert.That(treeModel.Length == 3); Assert.AreEqual(after, 3); Assert.AreEqual(before, 4); @@ -32,7 +33,7 @@ public class ScriptTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new ScriptTreeService(FileSystems); - var path = Path.Join("tests", "file5"); + var path = Path.Join("tests", $"file5{FileExtension}"); FileSystemTreeItemPresentationModel[] treeModel = service.GetAncestorModels(path, true); Assert.IsNotEmpty(treeModel); @@ -45,9 +46,25 @@ public class ScriptTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new ScriptTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, Int32.MaxValue, out var totalItems); + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); Assert.IsNotEmpty(treeModels); Assert.AreEqual(treeModels.Length, totalItems); } + + [Test] + public void Will_Hide_Unsupported_File_Extensions() + { + var service = new ScriptTreeService(FileSystems); + for (int i = 0; i < 2; i++) + { + using var stream = CreateStream(Path.Join("tests")); + TestFileSystem.AddFile($"file{i}.invalid", stream); + } + + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); + + Assert.IsEmpty(treeModels.Where(file => file.Name.Contains(".invalid"))); + Assert.AreEqual(treeModels.Length, totalItems); + } } diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/StyleSheetTreeServiceTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/StyleSheetTreeServiceTests.cs index 2fe15f27ea..c3300bcbb8 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/StyleSheetTreeServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Services/Trees/StyleSheetTreeServiceTests.cs @@ -7,6 +7,8 @@ namespace Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees; public class StyleSheetTreeServiceTests : FileSystemTreeServiceTestsBase { + protected override string FileExtension { get; set; } = ".css"; + protected override string FileSystemPath => GlobalSettings.UmbracoCssPath; protected override IFileSystem? GetStylesheetsFileSystem() => TestFileSystem; @@ -16,12 +18,12 @@ public class StyleSheetTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new StyleSheetTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels("file5", 1, 1, out long before, out var after); - int index = Array.FindIndex(treeModel, item => item.Name == "file5"); + FileSystemTreeItemPresentationModel[] treeModel = service.GetSiblingsViewModels($"file5{FileExtension}", 1, 1, out long before, out var after); + int index = Array.FindIndex(treeModel, item => item.Name == $"file5{FileExtension}"); - Assert.AreEqual(treeModel[index].Name, "file5"); - Assert.AreEqual(treeModel[index - 1].Name, "file4"); - Assert.AreEqual(treeModel[index + 1].Name, "file6"); + Assert.AreEqual(treeModel[index].Name, $"file5{FileExtension}"); + Assert.AreEqual(treeModel[index - 1].Name, $"file4{FileExtension}"); + Assert.AreEqual(treeModel[index + 1].Name, $"file6{FileExtension}"); Assert.That(treeModel.Length == 3); Assert.AreEqual(after, 3); Assert.AreEqual(before, 4); @@ -32,7 +34,7 @@ public class StyleSheetTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new StyleSheetTreeService(FileSystems); - var path = Path.Join("tests", "file5"); + var path = Path.Join("tests", $"file5{FileExtension}"); FileSystemTreeItemPresentationModel[] treeModel = service.GetAncestorModels(path, true); Assert.IsNotEmpty(treeModel); @@ -45,9 +47,25 @@ public class StyleSheetTreeServiceTests : FileSystemTreeServiceTestsBase { var service = new StyleSheetTreeService(FileSystems); - FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, Int32.MaxValue, out var totalItems); + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); Assert.IsNotEmpty(treeModels); Assert.AreEqual(treeModels.Length, totalItems); } + + [Test] + public void Will_Hide_Unsupported_File_Extensions() + { + var service = new StyleSheetTreeService(FileSystems); + for (int i = 0; i < 2; i++) + { + using var stream = CreateStream(Path.Join("tests")); + TestFileSystem.AddFile($"file{i}.invalid", stream); + } + + FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems); + + Assert.IsEmpty(treeModels.Where(file => file.Name.Contains(".invalid"))); + Assert.AreEqual(treeModels.Length, totalItems); + } }