diff --git a/src/Umbraco.Core/IO/FileSystemExtensions.cs b/src/Umbraco.Core/IO/FileSystemExtensions.cs index 78f39466f8..a4a40d37ba 100644 --- a/src/Umbraco.Core/IO/FileSystemExtensions.cs +++ b/src/Umbraco.Core/IO/FileSystemExtensions.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using Umbraco.Core.CodeAnnotations; namespace Umbraco.Core.IO @@ -30,5 +31,17 @@ namespace Umbraco.Core.IO { return Path.GetFileName(fs.GetFullPath(path)); } + + //TODO: Currently this is the only way to do this + internal static void CreateFolder(this IFileSystem fs, string folderPath) + { + var path = fs.GetRelativePath(folderPath); + var tempFile = Path.Combine(path, Guid.NewGuid().ToString("N") + ".tmp"); + using (var s = new MemoryStream()) + { + fs.AddFile(tempFile, s); + } + fs.DeleteFile(tempFile); + } } } diff --git a/src/Umbraco.Core/IO/IFileSystem.cs b/src/Umbraco.Core/IO/IFileSystem.cs index 8e1753da6d..113f63565c 100644 --- a/src/Umbraco.Core/IO/IFileSystem.cs +++ b/src/Umbraco.Core/IO/IFileSystem.cs @@ -5,6 +5,8 @@ using Umbraco.Core.CodeAnnotations; namespace Umbraco.Core.IO { + //TODO: There is no way to create a directory here without creating a file in a directory and then deleting it + public interface IFileSystem { IEnumerable GetDirectories(string path); diff --git a/src/Umbraco.Core/Models/File.cs b/src/Umbraco.Core/Models/File.cs index 978e54390f..f520b63210 100644 --- a/src/Umbraco.Core/Models/File.cs +++ b/src/Umbraco.Core/Models/File.cs @@ -6,6 +6,16 @@ using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { + internal sealed class Folder : Entity + { + public Folder(string folderPath) + { + Path = folderPath; + } + + public string Path { get; set; } + } + /// /// Represents an abstract file which provides basic functionality for a File with an Alias and Name /// @@ -23,6 +33,8 @@ namespace Umbraco.Core.Models private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo(x => x.Content); private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path); + private string _alias; + private string _name; /// /// Gets or sets the Name of the File including extension @@ -32,7 +44,11 @@ namespace Umbraco.Core.Models { get { - return new FileInfo(Path).Name; + if (_name == null) + { + _name = System.IO.Path.GetFileName(Path); + } + return _name; } } @@ -44,10 +60,14 @@ namespace Umbraco.Core.Models { get { - var fileInfo = new FileInfo(Path); - var name = fileInfo.Name; - int lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase); - return name.Substring(0, lastIndexOf); + if (_alias == null) + { + var name = System.IO.Path.GetFileName(Path); + if (name == null) return string.Empty; + var lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase); + _alias = name.Substring(0, lastIndexOf); + } + return _alias; } } @@ -60,6 +80,10 @@ namespace Umbraco.Core.Models get { return _path; } set { + //reset + _alias = null; + _name = null; + SetPropertyValueAndDetectChanges(o => { _path = value; diff --git a/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs b/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs index d70aa9510c..cd36f75369 100644 --- a/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/FileRepository.cs @@ -33,6 +33,16 @@ namespace Umbraco.Core.Persistence.Repositories get { return _fileSystem; } } + internal virtual void AddFolder(string folderPath) + { + _work.RegisterAdded(new Folder(folderPath), this); + } + + internal virtual void DeleteFolder(string folderPath) + { + _work.RegisterRemoved(new Folder(folderPath), this); + } + #region Implementation of IRepository public virtual void AddOrUpdate(TEntity entity) @@ -68,7 +78,16 @@ namespace Umbraco.Core.Persistence.Repositories public void PersistNewItem(IEntity entity) { - PersistNewItem((TEntity)entity); + //special case for folder + var folder = entity as Folder; + if (folder != null) + { + PersistNewFolder(folder); + } + else + { + PersistNewItem((TEntity)entity); + } } public void PersistUpdatedItem(IEntity entity) @@ -78,23 +97,46 @@ namespace Umbraco.Core.Persistence.Repositories public void PersistDeletedItem(IEntity entity) { - PersistDeletedItem((TEntity)entity); + //special case for folder + var folder = entity as Folder; + if (folder != null) + { + PersistDeletedFolder(folder); + } + else + { + PersistDeletedItem((TEntity)entity); + } } #endregion - #region Abstract IUnitOfWorkRepository Methods + internal virtual void PersistNewFolder(Folder entity) + { + _fileSystem.CreateFolder(entity.Path); + } + internal virtual void PersistDeletedFolder(Folder entity) + { + _fileSystem.DeleteDirectory(entity.Path); + } + + #region Abstract IUnitOfWorkRepository Methods + protected virtual void PersistNewItem(TEntity entity) { - var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)); - FileSystem.AddFile(entity.Name, stream, true); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content))) + { + FileSystem.AddFile(entity.Path, stream, true); + } } protected virtual void PersistUpdatedItem(TEntity entity) { - var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)); - FileSystem.AddFile(entity.Name, stream, true); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content))) + { + FileSystem.AddFile(entity.Path, stream, true); + } } protected virtual void PersistDeletedItem(TEntity entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs index 45bde95b3f..8c675a7d3a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IScriptRepository.cs @@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories { public interface IScriptRepository : IRepository { - + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs index de7dd50223..f6af195b94 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ScriptRepository.cs @@ -28,9 +28,10 @@ namespace Umbraco.Core.Persistence.Repositories public override Script Get(string id) { - if(!FileSystem.FileExists(id)) + if(FileSystem.FileExists(id) == false) { - throw new Exception(string.Format("The file {0} was not found", id)); + return null; + //throw new Exception(string.Format("The file {0} was not found", id)); } string content = string.Empty; diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs index 34d2ff616b..9fe69a4ca9 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxContext.cs @@ -23,24 +23,4 @@ namespace Umbraco.Core.Persistence.SqlSyntax set { _sqlSyntaxProvider = value; } } } - - internal static class SqlSyntaxProviderExtensions - { - /// - /// This is used to generate a delete query that uses a sub-query to select the data, it is required because there's a very particular syntax that - /// needs to be used to work for all servers: MySql, SQLCE and MSSQL - /// - /// - /// - /// See: http://issues.umbraco.org/issue/U4-3876 - /// - public static string GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery) - { - return string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)", - sqlProvider.GetQuotedTableName(tableName), - sqlProvider.GetQuotedColumnName(columnName), - subQuery.SQL); - } - - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs new file mode 100644 index 0000000000..8bcc965af7 --- /dev/null +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs @@ -0,0 +1,22 @@ +namespace Umbraco.Core.Persistence.SqlSyntax +{ + internal static class SqlSyntaxProviderExtensions + { + /// + /// This is used to generate a delete query that uses a sub-query to select the data, it is required because there's a very particular syntax that + /// needs to be used to work for all servers: MySql, SQLCE and MSSQL + /// + /// + /// + /// See: http://issues.umbraco.org/issue/U4-3876 + /// + public static string GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery) + { + return string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)", + sqlProvider.GetQuotedTableName(tableName), + sqlProvider.GetQuotedColumnName(columnName), + subQuery.SQL); + } + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 5d4f2b1da8..848097f6f0 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -4,6 +4,7 @@ using Umbraco.Core.Auditing; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services @@ -195,6 +196,26 @@ namespace Umbraco.Core.Services return script.IsValid(); } + public void CreateScriptFolder(string folderPath) + { + var uow = _fileUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateScriptRepository(uow)) + { + ((ScriptRepository)repository).AddFolder(folderPath); + uow.Commit(); + } + } + + public void DeleteScriptFolder(string folderPath) + { + var uow = _fileUowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateScriptRepository(uow)) + { + ((ScriptRepository)repository).DeleteFolder(folderPath); + uow.Commit(); + } + } + /// /// Gets a list of all objects /// diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 2e1e2eef49..c59f80b2ff 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -76,6 +76,19 @@ namespace Umbraco.Core.Services /// True if Script is valid, otherwise false bool ValidateScript(Script script); + /// + /// Creates a folder for scripts + /// + /// + /// + void CreateScriptFolder(string folderPath); + + /// + /// Deletes a folder for scripts + /// + /// + void DeleteScriptFolder(string folderPath); + /// /// Gets a list of all objects /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b0d3da50ed..38068e7082 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -209,6 +209,7 @@ + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 5003cf090f..f993e4fce4 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -101,9 +101,9 @@ {07fbc26b-2927-4a22-8d96-d644c667fecc} UmbracoExamine - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll False diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 1a8a9cf48a..1e28adb56a 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index cd2c67c8c8..99328aa539 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -93,9 +93,9 @@ {07fbc26b-2927-4a22-8d96-d644c667fecc} UmbracoExamine - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll False diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index eec795bd35..49d2f513ab 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/ScriptTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/ScriptTasks.cs index ea2e08128c..dfcc4b9aa0 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/ScriptTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/ScriptTasks.cs @@ -1,7 +1,9 @@ using System; using System.Data; using System.Web.Security; +using Umbraco.Core; using Umbraco.Core.Logging; +using Umbraco.Core.Models; using umbraco.BusinessLogic; using umbraco.DataLayer; using umbraco.BasePages; @@ -42,48 +44,43 @@ namespace umbraco public bool Save() { - string[] scriptFileAr = _alias.Split('\u00A4'); + var scriptFileAr = _alias.Split('\u00A4'); + var relPath = scriptFileAr[0]; + var fileName = scriptFileAr[1]; + var fileType = scriptFileAr[2]; + var createFolder = ParentID; - string relPath = scriptFileAr[0]; - string fileName = scriptFileAr[1]; - string fileType = scriptFileAr[2]; + if (createFolder == 1) + { + ApplicationContext.Current.Services.FileService.CreateScriptFolder(relPath + fileName); + return true; + } - int createFolder = ParentID; - - string basePath = IOHelper.MapPath(SystemDirectories.Scripts + "/" + relPath + fileName); - if (System.IO.File.Exists(basePath)) + var found = ApplicationContext.Current.Services.FileService.GetScriptByName(relPath + fileName + "." + fileType); + if (found != null) { m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName, fileType); return true; } - else - { - if (createFolder == 1) - { - System.IO.Directory.CreateDirectory(basePath); - } - else - { - System.IO.File.Create(basePath + "." + fileType).Close(); - m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName, - fileType); - } - } + + ApplicationContext.Current.Services.FileService.SaveScript(new Script(relPath + fileName + "." + fileType)); + m_returnUrl = string.Format("settings/scripts/editScript.aspx?file={0}{1}.{2}", relPath, fileName, fileType); return true; } public bool Delete() { - string path = IOHelper.MapPath(SystemDirectories.Scripts + "/" + _alias.TrimStart('/')); - - if (System.IO.File.Exists(path)) - System.IO.File.Delete(path); - else if (System.IO.Directory.Exists(path)) - System.IO.Directory.Delete(path, true); - - LogHelper.Info(string.Format("{0} Deleted by user {1}", _alias, UmbracoEnsuredPage.CurrentUser.Id)); + if (_alias.Contains(".") == false) + { + //there is no extension so we'll assume it's a folder + ApplicationContext.Current.Services.FileService.DeleteScriptFolder(_alias.TrimStart('/')); + } + else + { + ApplicationContext.Current.Services.FileService.DeleteScript(_alias.TrimStart('/')); + } return true; } diff --git a/src/umbraco.cms/packages.config b/src/umbraco.cms/packages.config index fb0f66ebab..4be7142dcc 100644 --- a/src/umbraco.cms/packages.config +++ b/src/umbraco.cms/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj index 22b89f894f..25809f1444 100644 --- a/src/umbraco.cms/umbraco.cms.csproj +++ b/src/umbraco.cms/umbraco.cms.csproj @@ -104,9 +104,9 @@ AllRules.ruleset - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll False diff --git a/src/umbraco.controls/packages.config b/src/umbraco.controls/packages.config index a432c3897a..6471b6a3c4 100644 --- a/src/umbraco.controls/packages.config +++ b/src/umbraco.controls/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/umbraco.controls/umbraco.controls.csproj b/src/umbraco.controls/umbraco.controls.csproj index 0bf53c57d0..e529af0372 100644 --- a/src/umbraco.controls/umbraco.controls.csproj +++ b/src/umbraco.controls/umbraco.controls.csproj @@ -66,9 +66,9 @@ AllRules.ruleset - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll diff --git a/src/umbraco.editorControls/packages.config b/src/umbraco.editorControls/packages.config index a432c3897a..6471b6a3c4 100644 --- a/src/umbraco.editorControls/packages.config +++ b/src/umbraco.editorControls/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index b3b07340cd..26e1553c0a 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -112,9 +112,9 @@ {651E1350-91B6-44B7-BD60-7207006D7003} Umbraco.Web - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll System diff --git a/src/umbraco.macroRenderings/packages.config b/src/umbraco.macroRenderings/packages.config index 38a750a6ff..2d70f501ed 100644 --- a/src/umbraco.macroRenderings/packages.config +++ b/src/umbraco.macroRenderings/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/umbraco.macroRenderings/umbraco.macroRenderings.csproj b/src/umbraco.macroRenderings/umbraco.macroRenderings.csproj index 74f7adb80d..1b2ae2867b 100644 --- a/src/umbraco.macroRenderings/umbraco.macroRenderings.csproj +++ b/src/umbraco.macroRenderings/umbraco.macroRenderings.csproj @@ -104,9 +104,9 @@ AllRules.ruleset - + False - ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll + ..\packages\ClientDependency.1.7.1.1\lib\ClientDependency.Core.dll False