diff --git a/src/Orchard.Tests/Storage/FileSystemStorageProviderTests.cs b/src/Orchard.Tests/Storage/FileSystemStorageProviderTests.cs index f18355963..fb87bbcb2 100644 --- a/src/Orchard.Tests/Storage/FileSystemStorageProviderTests.cs +++ b/src/Orchard.Tests/Storage/FileSystemStorageProviderTests.cs @@ -3,43 +3,170 @@ using System.IO; using System.Linq; using NUnit.Framework; using System; +using Orchard.Environment.Configuration; using Orchard.Storage; namespace Orchard.Tests.Storage { [TestFixture] public class FileSystemStorageProviderTests { - #region Setup/Teardown - [TestFixtureSetUp] - public void InitFixture() { - _folderPath = Directory.CreateDirectory(Path.GetTempPath() + "filesystemstorageprovidertests").FullName; + [SetUp] + public void Init() { + _folderPath = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media"), "Default"); _filePath = _folderPath + "\\testfile.txt"; - FileStream fileStream = File.Create(_filePath); - fileStream.Close(); - _fileSystemStorageProvider = new FileSystemStorageProvider(); + + Directory.CreateDirectory(_folderPath); + File.WriteAllText(_filePath, "testfile contents"); + + var subfolder1 = Path.Combine(_folderPath, "Subfolder1"); + Directory.CreateDirectory(subfolder1); + File.WriteAllText(Path.Combine(subfolder1, "one.txt"), "one contents"); + File.WriteAllText(Path.Combine(subfolder1, "two.txt"), "two contents"); + + var subsubfolder1 = Path.Combine(subfolder1, "SubSubfolder1"); + Directory.CreateDirectory(subsubfolder1); + + _storageProvider = new FileSystemStorageProvider(new ShellSettings { Name = "Default" }); } - [TestFixtureTearDown] - public void TermFixture() { + [TearDown] + public void Term() { Directory.Delete(_folderPath, true); } - #endregion private string _filePath; private string _folderPath; - private FileSystemStorageProvider _fileSystemStorageProvider; + private IStorageProvider _storageProvider; [Test] [ExpectedException(typeof(ArgumentException))] public void GetFileThatDoesNotExistShouldThrow() { - _fileSystemStorageProvider.GetFile("notexisting"); + _storageProvider.GetFile("notexisting"); } [Test] public void ListFilesShouldReturnFilesFromFilesystem() { - IEnumerable files = _fileSystemStorageProvider.ListFiles(_folderPath); + IEnumerable files = _storageProvider.ListFiles(_folderPath); Assert.That(files.Count(), Is.EqualTo(1)); } + + [Test] + public void ExistingFileIsReturnedWithShortPath() { + var file = _storageProvider.GetFile("testfile.txt"); + Assert.That(file, Is.Not.Null); + Assert.That(file.GetPath(), Is.EqualTo("testfile.txt")); + Assert.That(file.GetName(), Is.EqualTo("testfile.txt")); + } + + + [Test] + public void ListFilesReturnsItemsWithShortPathAndEnvironmentSlashes() { + var files = _storageProvider.ListFiles("Subfolder1"); + Assert.That(files, Is.Not.Null); + Assert.That(files.Count(), Is.EqualTo(2)); + var one = files.Single(x => x.GetName() == "one.txt"); + var two = files.Single(x => x.GetName() == "two.txt"); + + Assert.That(one.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt")); + Assert.That(two.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "two.txt")); + } + + + [Test] + public void AnySlashInGetFileBecomesEnvironmentAppropriate() { + var file1 = _storageProvider.GetFile(@"Subfolder1/one.txt"); + var file2 = _storageProvider.GetFile(@"Subfolder1\one.txt"); + Assert.That(file1.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt")); + Assert.That(file2.GetPath(), Is.EqualTo("Subfolder1" + Path.DirectorySeparatorChar + "one.txt")); + } + + [Test] + public void ListFoldersReturnsItemsWithShortPathAndEnvironmentSlashes() { + var folders = _storageProvider.ListFolders(@"Subfolder1"); + Assert.That(folders, Is.Not.Null); + Assert.That(folders.Count(), Is.EqualTo(1)); + Assert.That(folders.Single().GetName(), Is.EqualTo("SubSubfolder1")); + Assert.That(folders.Single().GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1"))); + } + + [Test] + public void ParentFolderPathIsStillShort() { + var subsubfolder = _storageProvider.ListFolders(@"Subfolder1").Single(); + var subfolder = subsubfolder.GetParent(); + Assert.That(subsubfolder.GetName(), Is.EqualTo("SubSubfolder1")); + Assert.That(subsubfolder.GetPath(), Is.EqualTo(Path.Combine("Subfolder1", "SubSubfolder1"))); + Assert.That(subfolder.GetName(), Is.EqualTo("Subfolder1")); + Assert.That(subfolder.GetPath(), Is.EqualTo("Subfolder1")); + } + + [Test] + public void CreateFolderAndDeleteFolderTakesAnySlash() { + Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1)); + _storageProvider.CreateFolder(@"SubFolder1/SubSubFolder2"); + _storageProvider.CreateFolder(@"SubFolder1\SubSubFolder3"); + Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(3)); + _storageProvider.DeleteFolder(@"SubFolder1/SubSubFolder2"); + _storageProvider.DeleteFolder(@"SubFolder1\SubSubFolder3"); + Assert.That(_storageProvider.ListFolders(@"Subfolder1").Count(), Is.EqualTo(1)); + } + + private IStorageFolder GetFolder(string path) { + return _storageProvider.ListFolders(Path.GetDirectoryName(path)) + .SingleOrDefault(x => string.Equals(x.GetName(), Path.GetFileName(path), StringComparison.OrdinalIgnoreCase)); + } + private IStorageFile GetFile(string path) { + try { + return _storageProvider.GetFile(path); + } + catch (ArgumentException) { + return null; + } + } + + [Test] + public void RenameFolderTakesShortPathWithAnyKindOfSlash() { + Assert.That(GetFolder(@"SubFolder1/SubSubFolder1"), Is.Not.Null); + _storageProvider.RenameFolder(@"SubFolder1\SubSubFolder1", @"SubFolder1/SubSubFolder2"); + _storageProvider.RenameFolder(@"SubFolder1\SubSubFolder2", @"SubFolder1\SubSubFolder3"); + _storageProvider.RenameFolder(@"SubFolder1/SubSubFolder3", @"SubFolder1\SubSubFolder4"); + _storageProvider.RenameFolder(@"SubFolder1/SubSubFolder4", @"SubFolder1/SubSubFolder5"); + Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder1")), Is.Null); + Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder2")), Is.Null); + Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder3")), Is.Null); + Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder4")), Is.Null); + Assert.That(GetFolder(Path.Combine("SubFolder1", "SubSubFolder5")), Is.Not.Null); + } + + + [Test] + public void CreateFileAndDeleteFileTakesAnySlash() { + Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2)); + var alpha = _storageProvider.CreateFile(@"SubFolder1/alpha.txt"); + var beta = _storageProvider.CreateFile(@"SubFolder1\beta.txt"); + Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(4)); + Assert.That(alpha.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "alpha.txt"))); + Assert.That(beta.GetPath(), Is.EqualTo(Path.Combine("SubFolder1", "beta.txt"))); + _storageProvider.DeleteFile(@"SubFolder1\alpha.txt"); + _storageProvider.DeleteFile(@"SubFolder1/beta.txt"); + Assert.That(_storageProvider.ListFiles(@"Subfolder1").Count(), Is.EqualTo(2)); + } + + [Test] + public void RenameFileTakesShortPathWithAnyKindOfSlash() { + Assert.That(GetFile(@"Subfolder1/one.txt"), Is.Not.Null); + _storageProvider.RenameFile(@"SubFolder1\one.txt", @"SubFolder1/testfile2.txt"); + _storageProvider.RenameFile(@"SubFolder1\testfile2.txt", @"SubFolder1\testfile3.txt"); + _storageProvider.RenameFile(@"SubFolder1/testfile3.txt", @"SubFolder1\testfile4.txt"); + _storageProvider.RenameFile(@"SubFolder1/testfile4.txt", @"SubFolder1/testfile5.txt"); + Assert.That(GetFile(Path.Combine("SubFolder1", "one.txt")), Is.Null); + Assert.That(GetFile(Path.Combine("SubFolder1", "testfile2.txt")), Is.Null); + Assert.That(GetFile(Path.Combine("SubFolder1", "testfile3.txt")), Is.Null); + Assert.That(GetFile(Path.Combine("SubFolder1", "testfile4.txt")), Is.Null); + Assert.That(GetFile(Path.Combine("SubFolder1", "testfile5.txt")), Is.Not.Null); + } } } + + + diff --git a/src/Orchard.Web/Orchard.Web.csproj b/src/Orchard.Web/Orchard.Web.csproj index fb81981bd..5f74ca391 100644 --- a/src/Orchard.Web/Orchard.Web.csproj +++ b/src/Orchard.Web/Orchard.Web.csproj @@ -102,6 +102,10 @@ {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} Orchard.Framework + + {33B1BC8D-E292-4972-A363-22056B207156} + Orchard + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} Orchard.Core diff --git a/src/Orchard/Storage/FileSystemStorageProvider.cs b/src/Orchard/Storage/FileSystemStorageProvider.cs index f60f63031..bf6f341ac 100644 --- a/src/Orchard/Storage/FileSystemStorageProvider.cs +++ b/src/Orchard/Storage/FileSystemStorageProvider.cs @@ -2,44 +2,68 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Web.Hosting; +using Orchard.Environment.Configuration; namespace Orchard.Storage { public class FileSystemStorageProvider : IStorageProvider { + private readonly ShellSettings _settings; + private string _storagePath; + + public FileSystemStorageProvider(ShellSettings settings) { + _settings = settings; + + var mediaPath = HostingEnvironment.IsHosted + ? HostingEnvironment.MapPath("~/Media/") + : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media"); + _storagePath = Path.Combine(mediaPath, settings.Name); + } + + string Map(string path) { + return Path.Combine(_storagePath, path); + } + + static string Fix(string path) { + return Path.DirectorySeparatorChar != '/' + ? path.Replace('/', Path.DirectorySeparatorChar) + : path; + } + #region Implementation of IStorageProvider public IStorageFile GetFile(string path) { - if (!File.Exists(path)) { + if (!File.Exists(Map(path))) { throw new ArgumentException("File " + path + " does not exist"); } - return new FileSystemStorageFile(new FileInfo(path)); + return new FileSystemStorageFile(Fix(path), new FileInfo(Map(path))); } public IEnumerable ListFiles(string path) { - if (!Directory.Exists(path)) { + if (!Directory.Exists(Map(path))) { throw new ArgumentException("Directory " + path + " does not exist"); } - return new DirectoryInfo(path) + return new DirectoryInfo(Map(path)) .GetFiles() .Where(fi => !IsHidden(fi)) - .Select(fi => new FileSystemStorageFile(fi)) + .Select(fi => new FileSystemStorageFile(Path.Combine(Fix(path), fi.Name), fi)) .ToList(); } public IEnumerable ListFolders(string path) { - if (!Directory.Exists(path)) { + if (!Directory.Exists(Map(path))) { try { - Directory.CreateDirectory(path); - } + Directory.CreateDirectory(Map(path)); + } catch (Exception ex) { - throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}",path,ex)); + throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}", path, ex)); } } - return new DirectoryInfo(path) + return new DirectoryInfo(Map(path)) .GetDirectories() .Where(di => !IsHidden(di)) - .Select(di => new FileSystemStorageFolder(di)) + .Select(di => new FileSystemStorageFolder(Path.Combine(Fix(path), di.Name), di)) .ToList(); } @@ -48,81 +72,80 @@ namespace Orchard.Storage { } public void CreateFolder(string path) { - if (Directory.Exists(path)) { + if (Directory.Exists(Map(path))) { throw new ArgumentException("Directory " + path + " already exists"); } - Directory.CreateDirectory(path); + Directory.CreateDirectory(Map(path)); } public void DeleteFolder(string path) { - if (!Directory.Exists(path)) { + if (!Directory.Exists(Map(path))) { throw new ArgumentException("Directory " + path + " does not exist"); } - Directory.Delete(path, true); + Directory.Delete(Map(path), true); } public void RenameFolder(string path, string newPath) { - if (!Directory.Exists(path)) { + if (!Directory.Exists(Map(path))) { throw new ArgumentException("Directory " + path + "does not exist"); } - if (Directory.Exists(newPath)) { + if (Directory.Exists(Map(newPath))) { throw new ArgumentException("Directory " + newPath + " already exists"); } - Directory.Move(path, newPath); + Directory.Move(Map(path), Map(newPath)); } public IStorageFile CreateFile(string path) { - if (File.Exists(path)) { + if (File.Exists(Map(path))) { throw new ArgumentException("File " + path + " already exists"); } - var fileInfo = new FileInfo(path); - fileInfo.Create(); - return new FileSystemStorageFile(fileInfo); + var fileInfo = new FileInfo(Map(path)); + using (var stream = fileInfo.Create()) { + + } + return new FileSystemStorageFile(Fix(path), fileInfo); } public void DeleteFile(string path) { - if (!File.Exists(path)) { + if (!File.Exists(Map(path))) { throw new ArgumentException("File " + path + " does not exist"); } - File.Delete(path); + File.Delete(Map(path)); } public void RenameFile(string path, string newPath) { - if (!File.Exists(path)) { + if (!File.Exists(Map(path))) { throw new ArgumentException("File " + path + " does not exist"); } - if (File.Exists(newPath)) { + if (File.Exists(Map(newPath))) { throw new ArgumentException("File " + newPath + " already exists"); } - File.Move(path, newPath); - } - - public string Combine(string path1, string path2) - { - return Path.Combine(path1, path2); + File.Move(Map(path), Map(newPath)); } #endregion private class FileSystemStorageFile : IStorageFile { + private readonly string _path; private readonly FileInfo _fileInfo; - public FileSystemStorageFile(FileInfo fileInfo) { + public FileSystemStorageFile(string path, FileInfo fileInfo) { + _path = path; _fileInfo = fileInfo; } #region Implementation of IStorageFile public string GetPath() { - return _fileInfo.FullName; + return _path; } public string GetName() { @@ -141,13 +164,11 @@ namespace Orchard.Storage { return _fileInfo.Extension; } - public Stream OpenRead() - { + public Stream OpenRead() { return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.Read); } - public Stream OpenWrite() - { + public Stream OpenWrite() { return new FileStream(_fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite); } @@ -155,14 +176,20 @@ namespace Orchard.Storage { } private class FileSystemStorageFolder : IStorageFolder { + private readonly string _path; private readonly DirectoryInfo _directoryInfo; - public FileSystemStorageFolder(DirectoryInfo directoryInfo) { + public FileSystemStorageFolder(string path, DirectoryInfo directoryInfo) { + _path = path; _directoryInfo = directoryInfo; } #region Implementation of IStorageFolder + public string GetPath() { + return _path; + } + public string GetName() { return _directoryInfo.Name; } @@ -177,7 +204,7 @@ namespace Orchard.Storage { public IStorageFolder GetParent() { if (_directoryInfo.Parent != null) { - return new FileSystemStorageFolder(_directoryInfo.Parent); + return new FileSystemStorageFolder(Path.GetDirectoryName(_path), _directoryInfo.Parent); } throw new ArgumentException("Directory " + _directoryInfo.Name + " does not have a parent directory"); } diff --git a/src/Orchard/Storage/IStorageFolder.cs b/src/Orchard/Storage/IStorageFolder.cs index c832082de..a31b0a0e9 100644 --- a/src/Orchard/Storage/IStorageFolder.cs +++ b/src/Orchard/Storage/IStorageFolder.cs @@ -2,6 +2,7 @@ namespace Orchard.Storage { public interface IStorageFolder { + string GetPath(); string GetName(); long GetSize(); DateTime GetLastUpdated();