From a4de37efb9140cc429cbbaf1e7bfa1d88a4dd5b8 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 20 Oct 2014 11:30:46 +0100 Subject: [PATCH 01/78] Fixes U4-5658 - Dictionary tree JS: 'openDictionary' defined in Languages tree --- .../umbraco.presentation/umbraco/Trees/loadDictionary.cs | 8 +++++--- .../umbraco.presentation/umbraco/Trees/loadLanguages.cs | 4 ---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs index ad7a41b51c..78f44a1e9b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadDictionary.cs @@ -53,11 +53,13 @@ namespace umbraco public override void RenderJS(ref StringBuilder Javascript) { Javascript.Append( - @" + @" + function openDictionary() { + UmbClientMgr.contentFrame('settings/DictionaryItemList.aspx'); + } function openDictionaryItem(id) { UmbClientMgr.contentFrame('settings/editDictionaryItem.aspx?id=' + id); - } - "); + }"); } public override void Render(ref XmlTree tree) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs index 7dd10e3755..c43edff371 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs @@ -46,10 +46,6 @@ namespace umbraco @" function openLanguage(id) { UmbClientMgr.contentFrame('settings/editLanguage.aspx?id=' + id); -} - -function openDictionary() { - UmbClientMgr.contentFrame('settings/DictionaryItemList.aspx'); }"); } From f32a46c546ece87136d2c08c31a8cf587dd4628e Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 20 Nov 2014 13:41:34 +1100 Subject: [PATCH 02/78] Working on U4-1979 - language service --- src/Umbraco.Core/Cache/CacheKeys.cs | 1 + .../Repositories/LanguageRepository.cs | 9 +- .../Cache/LanguageCacheRefresher.cs | 2 - .../businesslogic/language/Item.cs | 1 + .../businesslogic/language/Language.cs | 158 ++++++------------ 5 files changed, 61 insertions(+), 110 deletions(-) diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index c1f82b0d89..7f448bba81 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -45,6 +45,7 @@ namespace Umbraco.Core.Cache public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache"; + [Obsolete("This is no longer used and will be removed from the codebase in the future")] public const string LanguageCacheKey = "UmbracoLanguageCache"; public const string DomainCacheKey = "UmbracoDomainList"; diff --git a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs index affe05e805..014ad03afd 100644 --- a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs @@ -47,6 +47,8 @@ namespace Umbraco.Core.Persistence.Repositories return entity; } + //TODO: Fix this up so there is no N+1 + protected override IEnumerable PerformGetAll(params int[] ids) { if (ids.Any()) @@ -66,6 +68,8 @@ namespace Umbraco.Core.Persistence.Repositories } } + //TODO: Fix this up so there is no N+1 + protected override IEnumerable PerformGetByQuery(IQuery query) { var sqlClause = GetBaseQuery(false); @@ -99,9 +103,12 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable GetDeleteClauses() { - //NOTE: There is no constraint between the Language and cmsDictionary/cmsLanguageText tables (?) + var list = new List { + //NOTE: There is no constraint between the Language and cmsDictionary/cmsLanguageText tables (?) + // but we still need to remove them + "DELETE FROM cmsLanguageText WHERE languageId = @Id", "DELETE FROM umbracoLanguage WHERE id = @Id" }; return list; diff --git a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs index 1dbd5a84a6..fac08fdf5c 100644 --- a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs @@ -29,14 +29,12 @@ namespace Umbraco.Web.Cache public override void Refresh(int id) { RuntimeCacheProvider.Current.Clear(typeof(ILanguage)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.LanguageCacheKey); base.Refresh(id); } public override void Remove(int id) { RuntimeCacheProvider.Current.Clear(typeof(ILanguage)); - ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.LanguageCacheKey); //when a language is removed we must also clear the text cache! global::umbraco.cms.businesslogic.language.Item.ClearCache(); base.Remove(id); diff --git a/src/umbraco.cms/businesslogic/language/Item.cs b/src/umbraco.cms/businesslogic/language/Item.cs index b0f2dcbb66..6d5146b0a3 100644 --- a/src/umbraco.cms/businesslogic/language/Item.cs +++ b/src/umbraco.cms/businesslogic/language/Item.cs @@ -175,6 +175,7 @@ namespace umbraco.cms.businesslogic.language /// Primary used when deleting a language from Umbraco. /// /// + [Obsolete("This is no longer used and will be removed from the codebase in future versions")] public static void RemoveByLanguage(int languageId) { // remove from database diff --git a/src/umbraco.cms/businesslogic/language/Language.cs b/src/umbraco.cms/businesslogic/language/Language.cs index 61cd99e2f2..5e2e3ebeed 100644 --- a/src/umbraco.cms/businesslogic/language/Language.cs +++ b/src/umbraco.cms/businesslogic/language/Language.cs @@ -7,7 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; - +using Umbraco.Core.Services; using umbraco.DataLayer; using umbraco.BusinessLogic; using System.Linq; @@ -23,14 +23,12 @@ namespace umbraco.cms.businesslogic.language /// Besides by using the built in Dictionary you are able to store language specific bits and pieces of translated text /// for use in templates. /// + [Obsolete("Use the LocalizationService instead")] public class Language { #region Private members - private int _id; - private string _name = ""; - private string _friendlyName; - private string _cultureAlias; - private static readonly object Locker = new object(); + + private Umbraco.Core.Models.ILanguage _lang; #endregion #region Constants and static members @@ -56,15 +54,11 @@ namespace umbraco.cms.businesslogic.language /// The id. public Language(int id) { - var lang = GetAllAsList().SingleOrDefault(x => x.id == id); - if (lang == null) + _lang = ApplicationContext.Current.Services.LocalizationService.GetLanguageById(id); + if (_lang == null) { throw new ArgumentException("No language found with the specified id"); } - - _id = lang.id; - _cultureAlias = lang.CultureAlias; - _friendlyName = lang.FriendlyName; } /// @@ -82,18 +76,14 @@ namespace umbraco.cms.businesslogic.language /// Culturecode of the language public static void MakeNew(string cultureCode) { - lock (Locker) + var culture = GetCulture(cultureCode); + if (culture != null) { - var culture = GetCulture(cultureCode); - if (culture != null) - { - //insert it - var newId = ApplicationContext.Current.DatabaseContext.Database.Insert(new LanguageDto { IsoCode = cultureCode }); - var ct = new Language { _id = Convert.ToInt32(newId), _cultureAlias = cultureCode }; - ct.UpdateNames(); - ct.OnNew(new NewEventArgs()); - - } + //insert it + var lang = new Umbraco.Core.Models.Language(cultureCode); + ApplicationContext.Current.Services.LocalizationService.Save(lang); + var ct = new Language { _lang = lang }; + ct.OnNew(new NewEventArgs()); } } @@ -118,23 +108,12 @@ namespace umbraco.cms.businesslogic.language /// public static IEnumerable GetAllAsList() { - return ApplicationContext.Current.ApplicationCache.GetCacheItem>( - CacheKeys.LanguageCacheKey, - TimeSpan.FromMinutes(60), - () => - { - var languages = new List(); - var dtos = ApplicationContext.Current.DatabaseContext.Database.Fetch(""); - foreach (var dto in dtos) - { - var ct = new Language {_id = dto.Id, _cultureAlias = dto.IsoCode}; - ct.UpdateNames(); - languages.Add(ct); - } - return languages; - }); + var all = ApplicationContext.Current.Services.LocalizationService.GetAllLanguages().Select(x => new Language + { + _lang = x + }).ToArray(); + return all; } - /// @@ -144,7 +123,13 @@ namespace umbraco.cms.businesslogic.language /// public static Language GetByCultureCode(string cultureCode) { - return GetAllAsList().SingleOrDefault(x => x.CultureAlias == cultureCode); + var found = ApplicationContext.Current.Services.LocalizationService.GetLanguageByIsoCode(cultureCode); + if (found == null) return null; + var lang = new Language + { + _lang = found + }; + return lang; } private static CultureInfo GetCulture(string cultureCode) @@ -166,6 +151,7 @@ namespace umbraco.cms.businesslogic.language /// /// The XML data. /// + [Obsolete("This is no longer used and will be removed in future versions")] public static Language Import(XmlNode xmlData) { var cA = xmlData.Attributes["CultureAlias"].Value; @@ -185,7 +171,7 @@ namespace umbraco.cms.businesslogic.language /// public int id { - get { return _id; } + get { return _lang.Id; } } /// @@ -193,16 +179,10 @@ namespace umbraco.cms.businesslogic.language /// public string CultureAlias { - get { return _cultureAlias; } + get { return _lang.IsoCode; } set { - _cultureAlias = value; - ApplicationContext.Current.DatabaseContext.Database.Update( - "set languageISOCode = @cultureAlias where id = @id", - new { cultureAlias = _cultureAlias,id=id} - ); - - UpdateNames(); + _lang.IsoCode = value; } } @@ -211,7 +191,7 @@ namespace umbraco.cms.businesslogic.language /// public string FriendlyName { - get { return _friendlyName; } + get { return _lang.CultureInfo.DisplayName; } } #endregion @@ -242,13 +222,16 @@ namespace umbraco.cms.businesslogic.language } /// - /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// Used to persist object changes to the database /// public virtual void Save() { var e = new SaveEventArgs(); FireBeforeSave(e); + //Do the update! + ApplicationContext.Current.Services.LocalizationService.Save(_lang); + if (!e.Cancel) { FireAfterSave(e); @@ -264,32 +247,25 @@ namespace umbraco.cms.businesslogic.language /// You cannot delete the default language: en-US, this is installed by default and is required. /// public void Delete() - { - lock (Locker) + { + if (ApplicationContext.Current.DatabaseContext.Database.ExecuteScalar("SELECT count(id) FROM umbracoDomains where domainDefaultLanguage = @id", new { id = id }) == 0) { + var e = new DeleteEventArgs(); + FireBeforeDelete(e); - if (ApplicationContext.Current.DatabaseContext.Database.ExecuteScalar("SELECT count(id) FROM umbracoDomains where domainDefaultLanguage = @id", new { id = id }) == 0) + if (!e.Cancel) { - var e = new DeleteEventArgs(); - FireBeforeDelete(e); + ApplicationContext.Current.Services.LocalizationService.Delete(_lang); - if (!e.Cancel) - { - //remove the dictionary entries first - Item.RemoveByLanguage(id); - - ApplicationContext.Current.DatabaseContext.Database.Delete("where id = @id", - new {id = id}); - FireAfterDelete(e); - } + FireAfterDelete(e); } - else - { - var e = new DataException("Cannot remove language " + _friendlyName + " because it's attached to a domain on a node"); - LogHelper.Error("Cannot remove language " + _friendlyName + " because it's attached to a domain on a node", e); - throw e; - } - } + } + else + { + var e = new DataException("Cannot remove language " + _lang.CultureInfo.DisplayName + " because it's attached to a domain on a node"); + LogHelper.Error("Cannot remove language " + _lang.CultureInfo.DisplayName + " because it's attached to a domain on a node", e); + throw e; + } } /// @@ -299,44 +275,12 @@ namespace umbraco.cms.businesslogic.language /// public XmlNode ToXml(XmlDocument xd) { - var language = xd.CreateElement("Language"); - language.Attributes.Append(XmlHelper.AddAttribute(xd, "Id", id.ToString())); - language.Attributes.Append(XmlHelper.AddAttribute(xd, "CultureAlias", CultureAlias)); - language.Attributes.Append(XmlHelper.AddAttribute(xd, "FriendlyName", FriendlyName)); - - return language; + var serializer = new EntityXmlSerializer(); + var xml = serializer.Serialize(_lang); + return xml.GetXmlNode(xd); } #endregion - #region Protected methods - - protected void PopulateFromReader(IRecordsReader dr) - { - _id = Convert.ToInt32(dr.GetShort("id")); - _cultureAlias = dr.GetString("languageISOCode"); - - UpdateNames(); - } - - #endregion - - #region Private methods - - private void UpdateNames() - { - try - { - var ci = new CultureInfo(_cultureAlias); - _friendlyName = ci.DisplayName; - } - catch - { - _friendlyName = _name + "(unknown Culture)"; - } - } - - #endregion - #region Events /// From e6d1eb0ba0286fb9e9ead4d0e28a11584613d32d Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 20 Nov 2014 16:28:50 +1100 Subject: [PATCH 03/78] Converts languages tree to new structure --- .../config/trees.Release.config | 2 +- src/Umbraco.Web.UI/config/trees.config | 6 +- .../Trees/LanguageTreeController.cs | 80 +++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 3 +- .../umbraco/Trees/loadLanguages.cs | 3 +- .../umbraco/settings/editLanguage.aspx.cs | 3 +- 6 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 src/Umbraco.Web/Trees/LanguageTreeController.cs diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config index 2124c72560..f58a051a2a 100644 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ b/src/Umbraco.Web.UI/config/trees.Release.config @@ -13,7 +13,7 @@ - + diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 2124c72560..2f7ca1acf0 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -8,12 +8,12 @@ - + - + @@ -37,5 +37,5 @@ + iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="10" />--> \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs new file mode 100644 index 0000000000..39fd1ebee5 --- /dev/null +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -0,0 +1,80 @@ +using System; +using System.Globalization; +using System.Net.Http.Formatting; +using umbraco; +using umbraco.BusinessLogic.Actions; +using Umbraco.Core; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Languages)] + [LegacyBaseTree(typeof(loadLanguages))] + [Tree(Constants.Applications.Settings, Constants.Trees.Languages, "Languages")] + [PluginController("UmbracoTrees")] + [CoreTree] + public class LanguageTreeController : TreeController + { + /// + /// The method called to render the contents of the tree structure + /// + /// + /// + /// All of the query string parameters passed from jsTree + /// + /// + /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end + /// to the back end to be used in the query for model data. + /// + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + var languages = Services.LocalizationService.GetAllLanguages(); + foreach (var language in languages) + { + nodes.Add( + CreateTreeNode( + language.Id.ToString(CultureInfo.InvariantCulture), "-1", queryStrings, language.CultureInfo.DisplayName, "icon-flag-alt", false, + //TODO: Rebuild the language editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) + "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/settings/editLanguage.aspx?id=" + language.Id))); + } + } + return nodes; + } + + /// + /// Returns the menu structure for the node + /// + /// + /// + /// + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + //Create the normal create action + var createMenuItem = menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)); + createMenuItem.LaunchDialogUrl("/umbraco/create.aspx?nodeId=init&nodeType=initlanguages&nodeName=Languages", ui.GetText("general", "create")); + + //refresh action + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); + + return menu; + } + + //add delete option for all languages + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)); + + return menu; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c197ae6852..d871aced4e 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -506,6 +506,7 @@ + @@ -2160,4 +2161,4 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs index 7dd10e3755..8bd6d33ebf 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadLanguages.cs @@ -29,7 +29,8 @@ using Umbraco.Core; namespace umbraco { - [Tree(Constants.Applications.Settings, "languages", "Languages", sortOrder: 4)] + [Obsolete("This is no longer used and will be removed from the codebase in the future")] + //[Tree(Constants.Applications.Settings, "languages", "Languages", sortOrder: 4)] public class loadLanguages : BaseTree { public loadLanguages(string application) : base(application) { } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editLanguage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editLanguage.aspx.cs index 9bc4beefe7..bcb1a5f8db 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editLanguage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editLanguage.aspx.cs @@ -11,6 +11,7 @@ using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using umbraco.cms.presentation.Trees; using Umbraco.Core; +using Umbraco.Web.Trees; namespace umbraco.settings { @@ -42,7 +43,7 @@ namespace umbraco.settings updateCultureList(); ClientTools - .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SetActiveTreeType(Constants.Trees.Languages) .SyncTree(helper.Request("id"), false); } From e558918432913f8364c35a9253c7ed5e4a058668 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 20 Nov 2014 17:54:30 +1100 Subject: [PATCH 04/78] Completes migrating the lang tree to the new format, a good starting place to convert the other ones even with having the legacy dialogs in place. --- src/Umbraco.Web/Models/Trees/MenuItem.cs | 2 +- .../Trees/LanguageTreeController.cs | 27 +++++++++++++++---- src/Umbraco.Web/Trees/TreeControllerBase.cs | 7 ++++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index ae4f8d519c..1717ecb1b6 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -190,7 +190,7 @@ namespace Umbraco.Web.Models.Trees .OnFailure(() => LegacyTreeDataConverter.GetLegacyConfirmView(Action, currentSection), view => LaunchDialogView( view, - ui.GetText("defaultdialogs", "confirmdelete") + " '" + item.Name + "' ?")); + ui.GetText("defaultdialogs", "confirmdelete") + " '" + (item == null ? "" : item.Name) + "' ?")); } #endregion diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs index 39fd1ebee5..52318fe346 100644 --- a/src/Umbraco.Web/Trees/LanguageTreeController.cs +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -1,9 +1,12 @@ using System; using System.Globalization; using System.Net.Http.Formatting; +using System.Web.Services.Description; using umbraco; using umbraco.BusinessLogic.Actions; using Umbraco.Core; +using Umbraco.Core.Models; +using umbraco.presentation.actions; using Umbraco.Web.Models.Trees; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi.Filters; @@ -46,6 +49,7 @@ namespace Umbraco.Web.Trees Uri.EscapeDataString("/umbraco/settings/editLanguage.aspx?id=" + language.Id))); } } + return nodes; } @@ -58,21 +62,34 @@ namespace Umbraco.Web.Trees protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); - + if (id == Constants.System.Root.ToInvariantString()) { //Create the normal create action - var createMenuItem = menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)); - createMenuItem.LaunchDialogUrl("/umbraco/create.aspx?nodeId=init&nodeType=initlanguages&nodeName=Languages", ui.GetText("general", "create")); - + menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "initlanguages", queryStrings.GetValue("application")); + //refresh action menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); return menu; } + var lang = Services.LocalizationService.GetLanguageById(int.Parse(id)); + //add delete option for all languages - menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)); + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(new UmbracoEntity + { + Id = lang.Id, + Level = 1, + ParentId = -1, + Name = lang.CultureInfo.DisplayName + }, "language", queryStrings.GetValue("application")); return menu; } diff --git a/src/Umbraco.Web/Trees/TreeControllerBase.cs b/src/Umbraco.Web/Trees/TreeControllerBase.cs index ebf4275c1f..74b2ffc670 100644 --- a/src/Umbraco.Web/Trees/TreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/TreeControllerBase.cs @@ -190,7 +190,12 @@ namespace Umbraco.Web.Trees { var jsonUrl = Url.GetTreeUrl(GetType(), id, queryStrings); var menuUrl = Url.GetMenuUrl(GetType(), id, queryStrings); - var node = new TreeNode(id, parentId, jsonUrl, menuUrl) { Name = title, Icon = icon }; + var node = new TreeNode(id, parentId, jsonUrl, menuUrl) + { + Name = title, + Icon = icon, + NodeType = TreeAlias + }; return node; } From df3d427c0b1cf7fb95f20183118814862da45527 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 20 Nov 2014 19:51:42 +1100 Subject: [PATCH 05/78] WIP - Updates templates service and repo with some extra methods, creates new template tree, updates template model with some more properties, still need to finish the template tree, it's missing some menu actions. --- .../UmbracoSettings/ITemplatesSection.cs | 5 +- .../UmbracoSettings/TemplatesElement.cs | 5 +- src/Umbraco.Core/Models/ITemplate.cs | 15 ++- src/Umbraco.Core/Models/Template.cs | 80 +++--------- .../Persistence/Factories/ContentFactory.cs | 2 +- .../Factories/ContentTypeFactory.cs | 2 +- .../Factories/DataTypeDefinitionFactory.cs | 2 +- .../Factories/DictionaryItemFactory.cs | 2 +- .../Factories/DictionaryTranslationFactory.cs | 2 +- .../Persistence/Factories/IEntityFactory.cs | 13 -- .../Persistence/Factories/LanguageFactory.cs | 2 +- .../Persistence/Factories/MacroFactory.cs | 2 +- .../Persistence/Factories/MediaFactory.cs | 2 +- .../Persistence/Factories/MediaTypeFactory.cs | 2 +- .../Persistence/Factories/MemberFactory.cs | 2 +- .../Factories/MemberGroupFactory.cs | 2 +- .../Factories/MemberTypeFactory.cs | 2 +- .../Factories/MemberTypeReadOnlyFactory.cs | 2 +- .../Factories/PropertyGroupFactory.cs | 2 +- .../Persistence/Factories/RelationFactory.cs | 2 +- .../Factories/RelationTypeFactory.cs | 2 +- .../Factories/ServerRegistrationFactory.cs | 2 +- .../Persistence/Factories/TagFactory.cs | 2 +- .../Persistence/Factories/TemplateFactory.cs | 31 ++--- .../Factories/UmbracoEntityFactory.cs | 2 +- .../Persistence/Factories/UserFactory.cs | 2 +- .../Factories/UserSectionFactory.cs | 2 +- .../Persistence/Factories/UserTypeFactory.cs | 2 +- .../Interfaces/ITemplateRepository.cs | 3 + .../Repositories/TemplateRepository.cs | 118 +++++++++++++----- src/Umbraco.Core/Services/FileService.cs | 13 ++ src/Umbraco.Core/Services/IFileService.cs | 6 + src/Umbraco.Core/Umbraco.Core.csproj | 1 - .../ContentTypeDefinitionFactory.cs | 2 +- src/Umbraco.Tests/Models/TemplateTests.cs | 13 +- .../Trees/LanguageTreeController.cs | 4 +- .../Trees/TemplatesTreeController.cs | 115 +++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + .../umbraco/Trees/loadTemplates.cs | 3 +- 39 files changed, 309 insertions(+), 163 deletions(-) delete mode 100644 src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs create mode 100644 src/Umbraco.Web/Trees/TemplatesTreeController.cs diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs index f6d104d291..a80fc6d2c7 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ITemplatesSection.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.Configuration.UmbracoSettings +using System; + +namespace Umbraco.Core.Configuration.UmbracoSettings { public interface ITemplatesSection : IUmbracoConfigurationSection { @@ -8,6 +10,7 @@ RenderingEngine DefaultRenderingEngine { get; } + [Obsolete("This has no affect and will be removed in future versions")] bool EnableTemplateFolders { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs index 31c374ce6c..c7eb659766 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/TemplatesElement.cs @@ -1,4 +1,5 @@ -using System.Configuration; +using System; +using System.Configuration; namespace Umbraco.Core.Configuration.UmbracoSettings { @@ -40,6 +41,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings } } + [Obsolete("This has no affect and will be removed in future versions")] [ConfigurationProperty("enableTemplateFolders")] internal InnerTextConfigurationElement EnableTemplateFolders { @@ -67,6 +69,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return DefaultRenderingEngine; } } + [Obsolete("This has no affect and will be removed in future versions")] bool ITemplatesSection.EnableTemplateFolders { get { return EnableTemplateFolders; } diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs index 33c80338b2..c6b016ea83 100644 --- a/src/Umbraco.Core/Models/ITemplate.cs +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Models.EntityBase; +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models { @@ -7,6 +9,17 @@ namespace Umbraco.Core.Models /// public interface ITemplate : IFile, IRememberBeingDirty, ICanBeDirty { + + /// + /// Returns true if the template is used as a layout for other templates (i.e. it has 'children') + /// + bool IsMasterTemplate { get; } + + /// + /// returns the master template alias + /// + string MasterTemplateAlias { get; } + /// /// Returns the that corresponds to the template file /// diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index fc10c818ef..294207f69e 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -18,88 +18,36 @@ namespace Umbraco.Core.Models { private string _alias; private string _name; - private int _creatorId; - private int _level; - private int _sortOrder; - private int _parentId; private string _masterTemplateAlias; + private Lazy _masterTemplateId; + - private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId); - private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level); - private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder); - private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId); private static readonly PropertyInfo MasterTemplateAliasSelector = ExpressionHelper.GetPropertyInfo(x => x.MasterTemplateAlias); + private static readonly PropertyInfo MasterTemplateIdSelector = ExpressionHelper.GetPropertyInfo>(x => x.MasterTemplateId); public Template(string path, string name, string alias) : base(path) { base.Path = path; - ParentId = -1; - _name = name; //.Replace("/", ".").Replace("\\", ""); // why? that's just the name! + _name = name; _alias = alias.ToCleanString(CleanStringType.UnderscoreAlias); } [DataMember] - internal int CreatorId + public Lazy MasterTemplateId { - get { return _creatorId; } + get { return _masterTemplateId; } set { SetPropertyValueAndDetectChanges(o => { - _creatorId = value; - return _creatorId; - }, _creatorId, CreatorIdSelector); + _masterTemplateId = value; + return _masterTemplateId; + }, _masterTemplateId, MasterTemplateIdSelector); } } - [DataMember] - internal int Level - { - get { return _level; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _level = value; - return _level; - }, _level, LevelSelector); - } - } - - [DataMember] - internal int SortOrder - { - get { return _sortOrder; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _sortOrder = value; - return _sortOrder; - }, _sortOrder, SortOrderSelector); - } - } - - [DataMember] - internal int ParentId - { - get { return _parentId; } - set - { - SetPropertyValueAndDetectChanges(o => - { - _parentId = value; - return _parentId; - }, _parentId, ParentIdSelector); - } - } - - [DataMember] - internal Lazy MasterTemplateId { get; set; } - - [DataMember] - internal string MasterTemplateAlias + public string MasterTemplateAlias { get { return _masterTemplateAlias; } set @@ -108,7 +56,7 @@ namespace Umbraco.Core.Models { _masterTemplateAlias = value; return _masterTemplateAlias; - }, _masterTemplateAlias, MasterTemplateAliasSelector); + }, _masterTemplateAlias, MasterTemplateAliasSelector); } } @@ -130,6 +78,12 @@ namespace Umbraco.Core.Models } } + + /// + /// Returns true if the template is used as a layout for other templates (i.e. it has 'children') + /// + public bool IsMasterTemplate { get; internal set; } + /// /// Returns the that corresponds to the template file /// diff --git a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs index d5f89e762c..3e2477594d 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ContentFactory : IEntityFactory + internal class ContentFactory { private readonly IContentType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index cc9ab387f8..23c9270906 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ContentTypeFactory : IEntityFactory + internal class ContentTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs index 13a7ecad35..7b57800277 100644 --- a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DataTypeDefinitionFactory : IEntityFactory + internal class DataTypeDefinitionFactory { private readonly Guid _nodeObjectTypeId; private int _primaryKey; diff --git a/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs b/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs index 4b8e0a74ee..14dca6b366 100644 --- a/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DictionaryItemFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DictionaryItemFactory : IEntityFactory + internal class DictionaryItemFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs b/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs index ee2c8659d2..8dca2494d0 100644 --- a/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DictionaryTranslationFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class DictionaryTranslationFactory : IEntityFactory + internal class DictionaryTranslationFactory { private readonly Guid _uniqueId; private ILanguage _language; diff --git a/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs deleted file mode 100644 index d413e30308..0000000000 --- a/src/Umbraco.Core/Persistence/Factories/IEntityFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Umbraco.Core.Persistence.Factories -{ - //TODO: Not sure why we need this interface as it's never referenced in code. - //TODO: Delete this - - internal interface IEntityFactory - where TEntity : class - where TDto : class - { - TEntity BuildEntity(TDto dto); - TDto BuildDto(TEntity entity); - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs index a2fd9892cd..0287a58b78 100644 --- a/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/LanguageFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class LanguageFactory : IEntityFactory + internal class LanguageFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs index 0f6788a33e..66b493ea4d 100644 --- a/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MacroFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MacroFactory : IEntityFactory + internal class MacroFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index 1ce8a7b37d..cf285cbf66 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MediaFactory : IEntityFactory + internal class MediaFactory { private readonly IMediaType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs index ee2709a79e..b63512e1b6 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MediaTypeFactory : IEntityFactory + internal class MediaTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs index 3a5786d554..42e09b2f9c 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberFactory : IEntityFactory + internal class MemberFactory { private readonly IMemberType _contentType; private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs index 207eea83b3..17dbba3001 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberGroupFactory : IEntityFactory + internal class MemberGroupFactory { private readonly Guid _nodeObjectTypeId; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs index 49feb5f8c8..5879016fa6 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberTypeFactory : IEntityFactory + internal class MemberTypeFactory { private readonly Guid _nodeObjectType; diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs index 2a59f564e2..3db2fd8ba1 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Persistence.Factories { - internal class MemberTypeReadOnlyFactory : IEntityFactory + internal class MemberTypeReadOnlyFactory { public IMemberType BuildEntity(MemberTypeReadOnlyDto dto) { diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs index a7afd2bafc..4764f41544 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class PropertyGroupFactory : IEntityFactory, IEnumerable> + internal class PropertyGroupFactory { private readonly int _id; private readonly DateTime _createDate; diff --git a/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs b/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs index f8fa4bed16..5d614fb6d3 100644 --- a/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/RelationFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class RelationFactory : IEntityFactory + internal class RelationFactory { private readonly IRelationType _relationType; diff --git a/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs index 08a80397ea..358b652d0b 100644 --- a/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/RelationTypeFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class RelationTypeFactory : IEntityFactory + internal class RelationTypeFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs index 5f93bf56d3..e13b24e1e1 100644 --- a/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ServerRegistrationFactory.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class ServerRegistrationFactory : IEntityFactory + internal class ServerRegistrationFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Factories/TagFactory.cs b/src/Umbraco.Core/Persistence/Factories/TagFactory.cs index 7cebe5f65e..0aa60733de 100644 --- a/src/Umbraco.Core/Persistence/Factories/TagFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TagFactory.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class TagFactory : IEntityFactory + internal class TagFactory { public ITag BuildEntity(TagDto dto) { diff --git a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs index a62e9d3c00..281c271fe8 100644 --- a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs @@ -1,11 +1,14 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using Umbraco.Core.Models; +using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class TemplateFactory : IEntityFactory + internal class TemplateFactory { private readonly int _primaryKey; private readonly Guid _nodeObjectTypeId; @@ -25,21 +28,23 @@ namespace Umbraco.Core.Persistence.Factories } #region Implementation of IEntityFactory - - public Template BuildEntity(TemplateDto dto) + + public Template BuildEntity(TemplateDto dto, IEnumerable childDefinitions) { var template = new Template(string.Empty, dto.NodeDto.Text, dto.Alias) { CreateDate = dto.NodeDto.CreateDate, Id = dto.NodeId, - Key = dto.NodeDto.UniqueId.Value, - CreatorId = dto.NodeDto.UserId.Value, - Level = dto.NodeDto.Level, - ParentId = dto.NodeDto.ParentId, - SortOrder = dto.NodeDto.SortOrder, + Key = dto.NodeDto.UniqueId.Value, Path = dto.NodeDto.Path }; - + + if (childDefinitions.Any(x => x.ParentId == dto.NodeId)) + { + template.IsMasterTemplate = true; + } + + //TODO: Change this to ParentId: http://issues.umbraco.org/issue/U4-5846 if(dto.Master.HasValue) template.MasterTemplateId = new Lazy(() => dto.Master.Value); @@ -80,15 +85,13 @@ namespace Umbraco.Core.Persistence.Factories { CreateDate = entity.CreateDate, NodeId = entity.Id, - Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)), + Level = 1, NodeObjectType = _nodeObjectTypeId, - ParentId = entity.ParentId, + ParentId = entity.MasterTemplateId.Value, Path = entity.Path, - SortOrder = entity.SortOrder, Text = entity.Name, Trashed = false, - UniqueId = entity.Key, - UserId = entity.CreatorId + UniqueId = entity.Key }; return nodeDto; diff --git a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs index f33ae1af2f..056d554d17 100644 --- a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Persistence.Factories { - internal class UmbracoEntityFactory : IEntityFactory + internal class UmbracoEntityFactory { internal void AddAdditionalData(UmbracoEntity entity, IDictionary originalEntityProperties) { diff --git a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs index 305c630a71..f13f4e94b4 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs @@ -6,7 +6,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserFactory : IEntityFactory + internal class UserFactory { private readonly IUserType _userType; diff --git a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs index e8c7d2e7c1..0e6a17594f 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserSectionFactory : IEntityFactory, IEnumerable> + internal class UserSectionFactory { private readonly IUser _user; diff --git a/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs index ad81d2b584..b5718b7c3b 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserTypeFactory.cs @@ -5,7 +5,7 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class UserTypeFactory : IEntityFactory + internal class UserTypeFactory { #region Implementation of IEntityFactory diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs index 318b840819..cea457edfb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITemplateRepository.cs @@ -6,8 +6,11 @@ namespace Umbraco.Core.Persistence.Repositories public interface ITemplateRepository : IRepositoryQueryable { ITemplate Get(string alias); + IEnumerable GetAll(params string[] aliases); + IEnumerable GetChildren(int masterTemplateId); + /// /// Returns a template as a template node which can be traversed (parent, children) /// diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index c529a236c3..61f0ea175d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Sync; @@ -71,7 +72,21 @@ namespace Umbraco.Core.Persistence.Repositories var dtos = Database.Fetch(sql); - return dtos.Select(MapFromDto); + //look up the simple template definitions that have a master template assigned, this is used + // later to populate the template item's properties + var childIdsSql = new Sql() + .Select("nodeId,alias," + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("master")) + .From() + .Where(t => t.Master > 0); + var childIds = Database.Fetch(childIdsSql) + .Select(x => new UmbracoEntity + { + Id = x.nodeId, + ParentId = x.master, + Name = x.alias + }); + + return dtos.Select(d => MapFromDto(d, childIds)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -82,7 +97,21 @@ namespace Umbraco.Core.Persistence.Repositories var dtos = Database.Fetch(sql); - return dtos.Select(MapFromDto); + //look up the simple template definitions that have a master template assigned, this is used + // later to populate the template item's properties + var childIdsSql = new Sql() + .Select("nodeId,alias," + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("master")) + .From() + .Where(t => t.Master > 0); + var childIds = Database.Fetch(childIdsSql) + .Select(x => new UmbracoEntity + { + Id = x.nodeId, + ParentId = x.master, + Name = x.alias + }); + + return dtos.Select(d => MapFromDto(d, childIds)); } #endregion @@ -150,23 +179,26 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new TemplateFactory(NodeObjectTypeId); var dto = factory.BuildDto(template); - //NOTE Should the logic below have some kind of fallback for empty parent ids ? - //Logic for setting Path, Level and SortOrder - var parent = Database.First("WHERE id = @ParentId", new { ParentId = template.ParentId }); - int level = parent.Level + 1; - int sortOrder = - Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = template.ParentId, NodeObjectType = NodeObjectTypeId }); + //NOTE: There is no reason for sort order, path or level with templates, also the ParentId column is NOT used, need to fix: + // http://issues.umbraco.org/issue/U4-5846 + //var parent = Database.First("WHERE id = @ParentId", new { ParentId = template.ParentId }); + //int level = parent.Level + 1; + //int sortOrder = + // Database.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE parentID = @ParentId AND nodeObjectType = @NodeObjectType", + // new { ParentId = template.ParentId, NodeObjectType = NodeObjectTypeId }); //Create the (base) node data - umbracoNode var nodeDto = dto.NodeDto; - nodeDto.Path = parent.Path; - nodeDto.Level = short.Parse(level.ToString(CultureInfo.InvariantCulture)); - nodeDto.SortOrder = sortOrder; + nodeDto.Path = "-1," + dto.NodeDto.NodeId; + nodeDto.Level = 1; + nodeDto.SortOrder = 0; var o = Database.IsNew(nodeDto) ? Convert.ToInt32(Database.Insert(nodeDto)) : Database.Update(nodeDto); + //NOTE: Templates don't have paths, but they could i suppose if we wanted, once the ParentId thing is fixed we could + // do it, but we haven't had that since the beginning of time so don't think it's necessary at all. //Update with new correct path - nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); + //nodeDto.Path = string.Concat(parent.Path, ",", nodeDto.NodeId); + Database.Update(nodeDto); //Insert template dto @@ -176,9 +208,7 @@ namespace Umbraco.Core.Persistence.Repositories //Update entity with correct values template.Id = nodeDto.NodeId; //Set Id on entity to ensure an Id is set template.Path = nodeDto.Path; - template.SortOrder = sortOrder; - template.Level = level; - + template.ResetDirtyProperties(); } @@ -198,18 +228,20 @@ namespace Umbraco.Core.Persistence.Repositories } } - //Look up parent to get and set the correct Path if ParentId has changed - if (entity.IsPropertyDirty("ParentId")) - { - var parent = Database.First("WHERE id = @ParentId", new { ParentId = ((Template)entity).ParentId }); - entity.Path = string.Concat(parent.Path, ",", entity.Id); - ((Template)entity).Level = parent.Level + 1; - var maxSortOrder = - Database.ExecuteScalar( - "SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType", - new { ParentId = ((Template)entity).ParentId, NodeObjectType = NodeObjectTypeId }); - ((Template)entity).SortOrder = maxSortOrder + 1; - } + //NOTE: There is no reason for sort order, path or level with templates, also the ParentId column is NOT used, need to fix: + // http://issues.umbraco.org/issue/U4-5846 + ////Look up parent to get and set the correct Path if ParentId has changed + //if (entity.IsPropertyDirty("ParentId")) + //{ + // var parent = Database.First("WHERE id = @ParentId", new { ParentId = ((Template)entity).ParentId }); + // entity.Path = string.Concat(parent.Path, ",", entity.Id); + // ((Template)entity).Level = parent.Level + 1; + // var maxSortOrder = + // Database.ExecuteScalar( + // "SELECT coalesce(max(sortOrder),0) FROM umbracoNode WHERE parentid = @ParentId AND nodeObjectType = @NodeObjectType", + // new { ParentId = ((Template)entity).ParentId, NodeObjectType = NodeObjectTypeId }); + // ((Template)entity).SortOrder = maxSortOrder + 1; + //} //Get TemplateDto from db to get the Primary key of the entity var templateDto = Database.SingleOrDefault("WHERE nodeId = @Id", new { Id = entity.Id }); @@ -278,14 +310,14 @@ namespace Umbraco.Core.Persistence.Repositories #endregion - private ITemplate MapFromDto(TemplateDto dto) + private ITemplate MapFromDto(TemplateDto dto, IEnumerable childDefinitions) { string csViewName = string.Concat(dto.Alias, ".cshtml"); string vbViewName = string.Concat(dto.Alias, ".vbhtml"); string masterpageName = string.Concat(dto.Alias, ".master"); var factory = new TemplateFactory(); - var template = factory.BuildEntity(dto); + var template = factory.BuildEntity(dto, childDefinitions); if (dto.Master.HasValue) { @@ -430,6 +462,28 @@ namespace Umbraco.Core.Persistence.Repositories } + public IEnumerable GetChildren(int masterTemplateId) + { + //TODO: Fix this N+1! + + List found; + if (masterTemplateId == -1) + { + var sql = GetBaseQuery(false).Where(x => x.Master == null); + found = Database.Fetch(sql); + } + else + { + var sql = GetBaseQuery(false).Where(x => x.Master == masterTemplateId); + found = Database.Fetch(sql); + } + + foreach (var templateDto in found) + { + yield return Get(templateDto.NodeId); + } + } + /// /// Returns a template as a template node which can be traversed (parent, children) /// @@ -437,8 +491,8 @@ namespace Umbraco.Core.Persistence.Repositories /// public TemplateNode GetTemplateNode(string alias) { - //in order to do this we need to get all of the templates and then organize, unfortunately - // our db structure does not use the path correctly for templates so we cannot just look + //in order to do this we need to get all of the templates and then organize, + // TODO: unfortunately our db structure does not use the path correctly for templates so we cannot just look // up a template tree easily. //first get all template objects diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 68b695ac1f..9709448cc3 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -12,6 +12,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; @@ -250,6 +251,18 @@ namespace Umbraco.Core.Services } } + /// + /// Gets a list of all objects + /// + /// An enumerable list of objects + public IEnumerable GetTemplates(int masterTemplateId) + { + using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork())) + { + return repository.GetChildren(masterTemplateId); + } + } + /// /// Gets a object by its alias /// diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 9bcce63373..74b16b984b 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -95,6 +95,12 @@ namespace Umbraco.Core.Services /// An enumerable list of objects IEnumerable GetTemplates(params string[] aliases); + /// + /// Gets a list of all objects + /// + /// An enumerable list of objects + IEnumerable GetTemplates(int masterTemplateId); + /// /// Gets a object by its alias /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index c760c4ddb7..bd1a5ceaf3 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -611,7 +611,6 @@ - diff --git a/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs b/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs index f1b98c53e6..b740dd91f9 100644 --- a/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs +++ b/src/Umbraco.Tests/CodeFirst/Definitions/ContentTypeDefinitionFactory.cs @@ -325,7 +325,7 @@ namespace Umbraco.Tests.CodeFirst.Definitions ? string.Concat(@alias, ".cshtml") : string.Concat(@alias, ".masterpage"); - template = new Template(string.Empty, name, @alias) { CreatorId = 0, Content = string.Empty}; + template = new Template(string.Empty, name, @alias) { Content = string.Empty}; ApplicationContext.Current.Services.FileService.SaveTemplate(template); } templates.Add(template); diff --git a/src/Umbraco.Tests/Models/TemplateTests.cs b/src/Umbraco.Tests/Models/TemplateTests.cs index bf63387d61..6d933792a3 100644 --- a/src/Umbraco.Tests/Models/TemplateTests.cs +++ b/src/Umbraco.Tests/Models/TemplateTests.cs @@ -18,10 +18,7 @@ namespace Umbraco.Tests.Models Key = Guid.NewGuid(), UpdateDate = DateTime.Now, Content = "blah", - CreatorId = 66, - Level = 55, - ParentId = 2, - SortOrder = 99, + MasterTemplateAlias = "master", MasterTemplateId = new Lazy(() => 88) }; @@ -32,15 +29,11 @@ namespace Umbraco.Tests.Models Assert.AreEqual(clone, item); Assert.AreEqual(clone.CreateDate, item.CreateDate); Assert.AreEqual(clone.Alias, item.Alias); - Assert.AreEqual(clone.CreatorId, item.CreatorId); Assert.AreEqual(clone.Id, item.Id); Assert.AreEqual(clone.Key, item.Key); - Assert.AreEqual(clone.Level, item.Level); Assert.AreEqual(clone.MasterTemplateAlias, item.MasterTemplateAlias); Assert.AreEqual(clone.MasterTemplateId.Value, item.MasterTemplateId.Value); Assert.AreEqual(clone.Name, item.Name); - Assert.AreEqual(clone.ParentId, item.ParentId); - Assert.AreEqual(clone.SortOrder, item.SortOrder); Assert.AreEqual(clone.UpdateDate, item.UpdateDate); //This double verifies by reflection @@ -63,10 +56,6 @@ namespace Umbraco.Tests.Models Key = Guid.NewGuid(), UpdateDate = DateTime.Now, Content = "blah", - CreatorId = 66, - Level = 55, - ParentId = 2, - SortOrder = 99, MasterTemplateAlias = "master", MasterTemplateId = new Lazy(() => 88) }; diff --git a/src/Umbraco.Web/Trees/LanguageTreeController.cs b/src/Umbraco.Web/Trees/LanguageTreeController.cs index 52318fe346..fefbf82307 100644 --- a/src/Umbraco.Web/Trees/LanguageTreeController.cs +++ b/src/Umbraco.Web/Trees/LanguageTreeController.cs @@ -1,4 +1,5 @@ using System; +using System.Data.SqlClient; using System.Globalization; using System.Net.Http.Formatting; using System.Web.Services.Description; @@ -16,7 +17,7 @@ namespace Umbraco.Web.Trees { [UmbracoTreeAuthorize(Constants.Trees.Languages)] [LegacyBaseTree(typeof(loadLanguages))] - [Tree(Constants.Applications.Settings, Constants.Trees.Languages, "Languages")] + [Tree(Constants.Applications.Settings, Constants.Trees.Languages, "Languages", sortOrder: 4)] [PluginController("UmbracoTrees")] [CoreTree] public class LanguageTreeController : TreeController @@ -78,6 +79,7 @@ namespace Umbraco.Web.Trees } var lang = Services.LocalizationService.GetLanguageById(int.Parse(id)); + if (lang == null) return new MenuItemCollection(); //add delete option for all languages menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)) diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs new file mode 100644 index 0000000000..f8cd861f6e --- /dev/null +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net.Http.Formatting; +using System.Web.Services.Description; +using umbraco; +using umbraco.BusinessLogic.Actions; +using umbraco.cms.businesslogic.template; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models; +using Umbraco.Web.Models.Trees; +using Umbraco.Web.Mvc; +using Umbraco.Web.WebApi.Filters; +using Constants = Umbraco.Core.Constants; + +namespace Umbraco.Web.Trees +{ + [UmbracoTreeAuthorize(Constants.Trees.Templates)] + [LegacyBaseTree(typeof (loadTemplates))] + [Tree(Constants.Applications.Settings, Constants.Trees.Templates, "Templates", sortOrder:1)] + [PluginController("UmbracoTrees")] + [CoreTree] + public class TemplatesTreeController : TreeController + { + /// + /// The method called to render the contents of the tree structure + /// + /// + /// + /// All of the query string parameters passed from jsTree + /// + /// + /// We are allowing an arbitrary number of query strings to be pased in so that developers are able to persist custom data from the front-end + /// to the back end to be used in the query for model data. + /// + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + var nodes = new TreeNodeCollection(); + + var found = id == Constants.System.Root.ToInvariantString() + ? Services.FileService.GetTemplates(-1) + : Services.FileService.GetTemplates(int.Parse(id)); + + nodes.AddRange(found.Select(template => CreateTreeNode( + template.Id.ToString(CultureInfo.InvariantCulture), + //TODO: Fix parent ID stuff for templates + "-1", + queryStrings, + template.Name, + template.IsMasterTemplate ? "icon-newspaper" : "icon-newspaper-alt", + template.IsMasterTemplate, + GetEditorPath(template, queryStrings)))); + + return nodes; + } + + /// + /// Returns the menu structure for the node + /// + /// + /// + /// + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + + if (id == Constants.System.Root.ToInvariantString()) + { + //Create the normal create action + menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "initlanguages", queryStrings.GetValue("application")); + + //refresh action + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); + + return menu; + } + + var template = Services.FileService.GetTemplate(int.Parse(id)); + if (template == null) return new MenuItemCollection(); + + if (template.IsMasterTemplate == false) + { + //add delete option if it doesn't have children + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)) + //Since we haven't implemented anything for languages in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(null, "templates", queryStrings.GetValue("application")); + } + + + + return menu; + } + + private string GetEditorPath(ITemplate template, FormDataCollection queryStrings) + { + //UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && ViewHelper.ViewExists(template) + + //TODO: Rebuild the language editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) + + return Path.GetExtension(template.Path).InvariantEquals(".master") + ? "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/settings/editTemplate.aspx?id=" + template.Id) + : "/" + queryStrings.GetValue("application") + "/framed/" + + Uri.EscapeDataString("/umbraco/settings/Views/EditView.aspx?treeType=" + Constants.Trees.Templates + "&templateID=" + template.Id); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index d871aced4e..0c2a2034b8 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -512,6 +512,7 @@ + diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs index 4b44883d21..f251e2499d 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/loadTemplates.cs @@ -32,7 +32,8 @@ using umbraco.BusinessLogic.Actions; namespace umbraco { - [Tree(Constants.Applications.Settings, "templates", "Templates", sortOrder: 1)] + [Obsolete("This is no longer used and will be removed from the codebase in the future")] + //[Tree(Constants.Applications.Settings, "templates", "Templates", sortOrder: 1)] public class loadTemplates : BaseTree { public loadTemplates(string application) : base(application) {} From 7f78aef05f103cfbea78527f99c4f7fb17640584 Mon Sep 17 00:00:00 2001 From: Anthony Dang Date: Thu, 20 Nov 2014 16:11:04 +0000 Subject: [PATCH 06/78] Issue U4-5231 - Created an interface based on the LogHelper, and created a service, exposed through Application.Services. --- src/Umbraco.Core/Logging/LogHelper.cs | 1 + src/Umbraco.Core/Services/ILoggingService.cs | 40 +++ src/Umbraco.Core/Services/LoggingService.cs | 267 +++++++++++++++++++ src/Umbraco.Core/Services/ServiceContext.cs | 20 +- src/Umbraco.Core/Umbraco.Core.csproj | 6 +- src/Umbraco.Tests/MockTests.cs | 5 +- 6 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 src/Umbraco.Core/Services/ILoggingService.cs create mode 100644 src/Umbraco.Core/Services/LoggingService.cs diff --git a/src/Umbraco.Core/Logging/LogHelper.cs b/src/Umbraco.Core/Logging/LogHelper.cs index 9291ffec1d..0513699f4e 100644 --- a/src/Umbraco.Core/Logging/LogHelper.cs +++ b/src/Umbraco.Core/Logging/LogHelper.cs @@ -9,6 +9,7 @@ namespace Umbraco.Core.Logging /// /// Used for logging /// + [Obsolete("Use UmbracoContext.Current.Application.Services.LoggingService instead")] public static class LogHelper { /// diff --git a/src/Umbraco.Core/Services/ILoggingService.cs b/src/Umbraco.Core/Services/ILoggingService.cs new file mode 100644 index 0000000000..1094428c5e --- /dev/null +++ b/src/Umbraco.Core/Services/ILoggingService.cs @@ -0,0 +1,40 @@ +using System; + +namespace Umbraco.Core.Services +{ + /// + /// Interface for logging service. + /// + public interface ILoggingService + { + void Error(string message, Exception exception); + void Error(Type callingType, string message, Exception exception); + void Warn(Type callingType, string message, params Func[] formatItems); + void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems); + void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems); + void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func[] formatItems); + + void Warn(string message, params Func[] formatItems); + void Warn(string message, bool showHttpTrace, params Func[] formatItems); + void WarnWithException(string message, Exception e, params Func[] formatItems); + void WarnWithException(string message, bool showHttpTrace, Exception e, params Func[] formatItems); + + void Info(Func generateMessage); + + void Info(Type callingType, Func generateMessage); + + void Info(Type type, string generateMessageFormat, params Func[] formatItems); + + void Info(string generateMessageFormat, params Func[] formatItems); + + void Debug(Func generateMessage); + + void Debug(Type callingType, Func generateMessage); + + void Debug(Type type, string generateMessageFormat, params Func[] formatItems); + + void Debug(string generateMessageFormat, params Func[] formatItems); + + void Debug(string generateMessageFormat, bool showHttpTrace, params Func[] formatItems); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/LoggingService.cs b/src/Umbraco.Core/Services/LoggingService.cs new file mode 100644 index 0000000000..7c6bbc8958 --- /dev/null +++ b/src/Umbraco.Core/Services/LoggingService.cs @@ -0,0 +1,267 @@ +using System; +using System.Linq; +using System.Threading; +using System.Web; +using log4net; + +namespace Umbraco.Core.Services +{ + /// + /// Used for logging + /// + public class LoggingService : ILoggingService + { + /// + /// Returns a logger for the type specified + /// + /// + /// + internal ILog LoggerFor() + { + return LogManager.GetLogger(typeof(T)); + } + + /// + /// Returns a logger for the object's type + /// + /// + /// + internal ILog LoggerFor(object getTypeFromInstance) + { + if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance"); + + return LogManager.GetLogger(getTypeFromInstance.GetType()); + } + + /// + /// Useful if the logger itself is running on another thread + /// + /// + /// + private string PrefixThreadId(string generateMessageFormat) + { + return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat; + } + + #region Error + /// + /// Adds an error log + /// + /// + /// + /// + public void Error(string message, Exception exception) + { + Error(typeof (T), message, exception); + } + + public void Error(Type callingType, string message, Exception exception) + { + var logger = LogManager.GetLogger(callingType); + if (logger != null) + logger.Error(PrefixThreadId(message), exception); + } + + #endregion + + #region Warn + + public void Warn(Type callingType, string message, params Func[] formatItems) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + } + + public void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems) + { + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray())); + } + + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray()); + + } + + public void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems) + { + WarnWithException(callingType, message, false, e, formatItems); + } + + public void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func[] formatItems) + { + Mandate.ParameterNotNull(e, "e"); + Mandate.ParameterNotNull(callingType, "callingType"); + Mandate.ParameterNotNullOrEmpty(message, "message"); + + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Warn( + callingType.Name, + string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()), + e); + } + + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsWarnEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams); + } + + /// + /// Adds a warn log + /// + /// + /// + /// + public void Warn(string message, params Func[] formatItems) + { + Warn(typeof(T), message, formatItems); + } + + public void Warn(string message, bool showHttpTrace, params Func[] formatItems) + { + Warn(typeof(T), message, showHttpTrace, formatItems); + } + + public void WarnWithException(string message, Exception e, params Func[] formatItems) + { + WarnWithException(typeof(T), message, e, formatItems); + } + public void WarnWithException(string message, bool showHttpTrace, Exception e, params Func[] formatItems) + { + WarnWithException(typeof(T), message, showHttpTrace, e, formatItems); + } + + #endregion + + #region Info + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The delegate to generate a message. + /// + public void Info(Func generateMessage) + { + Info(typeof(T), generateMessage); + } + + /// + /// Traces if tracing is enabled. + /// + /// + /// + public void Info(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsInfoEnabled) return; + logger.Info(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Traces if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Info(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || !logger.IsInfoEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + /// + /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The generate message format. + /// The format items. + /// + public void Info(string generateMessageFormat, params Func[] formatItems) + { + Info(typeof(T), generateMessageFormat, formatItems); + } + #endregion + + #region Debug + /// + /// Debugs a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The delegate to generate a message. + /// + public void Debug(Func generateMessage) + { + Debug(typeof(T), generateMessage); + } + + /// + /// Debugs if tracing is enabled. + /// + /// + /// + public void Debug(Type callingType, Func generateMessage) + { + var logger = LogManager.GetLogger(callingType); + if (logger == null || !logger.IsDebugEnabled) return; + logger.Debug(PrefixThreadId(generateMessage.Invoke())); + } + + /// + /// Debugs if tracing is enabled. + /// + /// The type for the logging namespace. + /// The message format. + /// The format items. + public void Debug(Type type, string generateMessageFormat, params Func[] formatItems) + { + var logger = LogManager.GetLogger(type); + if (logger == null || !logger.IsDebugEnabled) return; + var executedParams = formatItems.Select(x => x.Invoke()).ToArray(); + logger.DebugFormat(PrefixThreadId(generateMessageFormat), executedParams); + } + + /// + /// Debugs a message, only generating the message if debug is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. + /// + /// + /// The generate message format. + /// The format items. + /// + public void Debug(string generateMessageFormat, params Func[] formatItems) + { + Debug(typeof(T), generateMessageFormat, formatItems); + } + + /// + /// Debugs a message and also writes to the TraceContext specified, useful for when you would like the debug + /// output also displayed in the Http trace output. + /// + /// + /// + /// + /// + public void Debug(string generateMessageFormat, bool showHttpTrace, params Func[] formatItems) + { + if (showHttpTrace && HttpContext.Current != null) + { + HttpContext.Current.Trace.Write( + typeof(T).Name, + string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray())); + } + Debug(typeof(T), generateMessageFormat, formatItems); + } + + #endregion + + } +} diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index a6e74b00d0..9de61bf7f0 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; @@ -12,6 +13,7 @@ namespace Umbraco.Core.Services /// public class ServiceContext { + private Lazy _loggingService; private Lazy _tagService; private Lazy _contentService; private Lazy _userService; @@ -52,6 +54,7 @@ namespace Umbraco.Core.Services /// /// /// + /// public ServiceContext( IContentService contentService, IMediaService mediaService, @@ -69,7 +72,7 @@ namespace Umbraco.Core.Services ISectionService sectionService, IApplicationTreeService treeService, ITagService tagService, - INotificationService notificationService) + INotificationService notificationService, ILoggingService loggingService) { _tagService = new Lazy(() => tagService); _contentService = new Lazy(() => contentService); @@ -88,7 +91,7 @@ namespace Umbraco.Core.Services _memberService = new Lazy(() => memberService); _userService = new Lazy(() => userService); _notificationService = new Lazy(() => notificationService); - + _loggingService = new Lazy(() => loggingService); } /// @@ -174,6 +177,10 @@ namespace Umbraco.Core.Services _tagService = new Lazy(() => new TagService(provider, repositoryFactory.Value)); if (_memberGroupService == null) _memberGroupService = new Lazy(() => new MemberGroupService(provider, repositoryFactory.Value)); + + + if (_loggingService== null) + _loggingService = new Lazy(() => new LoggingService()); } @@ -328,6 +335,13 @@ namespace Umbraco.Core.Services { get { return _memberGroupService.Value; } } - + + /// + /// Gets the LoggingService + /// + public ILoggingService LoggingService + { + get { return _loggingService.Value; } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5d72a83243..089969ba3f 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -1,4 +1,4 @@ - + Debug @@ -106,7 +106,7 @@ True ..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll - + False @@ -315,6 +315,8 @@ + + diff --git a/src/Umbraco.Tests/MockTests.cs b/src/Umbraco.Tests/MockTests.cs index f8810fe67f..5e895ae9d1 100644 --- a/src/Umbraco.Tests/MockTests.cs +++ b/src/Umbraco.Tests/MockTests.cs @@ -5,6 +5,7 @@ using System.Text; using System.Web; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; @@ -56,7 +57,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new Mock().Object); + new Mock().Object, new Mock().Object); Assert.Pass(); } @@ -101,7 +102,7 @@ namespace Umbraco.Tests new Mock().Object, new Mock().Object, new Mock().Object, - new Mock().Object), + new Mock().Object, new Mock().Object), CacheHelper.CreateDisabledCacheHelper()); Assert.Pass(); From 79990b6a6ccbee0bdcb3cac63635d994b6990e92 Mon Sep 17 00:00:00 2001 From: Anthony Dang Date: Fri, 21 Nov 2014 12:38:27 +0000 Subject: [PATCH 07/78] Cleaned up interface as per Shannons comments https://github.com/umbraco/Umbraco-CMS/pull/559/files#r20683448 --- src/Umbraco.Core/Services/ILoggingService.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Services/ILoggingService.cs b/src/Umbraco.Core/Services/ILoggingService.cs index 1094428c5e..6348e2495c 100644 --- a/src/Umbraco.Core/Services/ILoggingService.cs +++ b/src/Umbraco.Core/Services/ILoggingService.cs @@ -7,34 +7,17 @@ namespace Umbraco.Core.Services /// public interface ILoggingService { - void Error(string message, Exception exception); void Error(Type callingType, string message, Exception exception); void Warn(Type callingType, string message, params Func[] formatItems); - void Warn(Type callingType, string message, bool showHttpTrace, params Func[] formatItems); + void WarnWithException(Type callingType, string message, Exception e, params Func[] formatItems); - void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func[] formatItems); - - void Warn(string message, params Func[] formatItems); - void Warn(string message, bool showHttpTrace, params Func[] formatItems); - void WarnWithException(string message, Exception e, params Func[] formatItems); - void WarnWithException(string message, bool showHttpTrace, Exception e, params Func[] formatItems); - - void Info(Func generateMessage); void Info(Type callingType, Func generateMessage); void Info(Type type, string generateMessageFormat, params Func[] formatItems); - void Info(string generateMessageFormat, params Func[] formatItems); - - void Debug(Func generateMessage); - void Debug(Type callingType, Func generateMessage); void Debug(Type type, string generateMessageFormat, params Func[] formatItems); - - void Debug(string generateMessageFormat, params Func[] formatItems); - - void Debug(string generateMessageFormat, bool showHttpTrace, params Func[] formatItems); } } \ No newline at end of file From e03988dd813027215b9971b421443dbdfa22b4a4 Mon Sep 17 00:00:00 2001 From: Anthony Dang Date: Fri, 21 Nov 2014 12:38:56 +0000 Subject: [PATCH 08/78] Removed regions from LoggingService to expose code. --- src/Umbraco.Core/Services/LoggingService.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Services/LoggingService.cs b/src/Umbraco.Core/Services/LoggingService.cs index 7c6bbc8958..43cd5b0cba 100644 --- a/src/Umbraco.Core/Services/LoggingService.cs +++ b/src/Umbraco.Core/Services/LoggingService.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Services return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat; } - #region Error + /// /// Adds an error log /// @@ -62,9 +62,7 @@ namespace Umbraco.Core.Services logger.Error(PrefixThreadId(message), exception); } - #endregion - #region Warn public void Warn(Type callingType, string message, params Func[] formatItems) { @@ -139,9 +137,9 @@ namespace Umbraco.Core.Services WarnWithException(typeof(T), message, showHttpTrace, e, formatItems); } - #endregion + + - #region Info /// /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. /// @@ -190,9 +188,10 @@ namespace Umbraco.Core.Services { Info(typeof(T), generateMessageFormat, formatItems); } - #endregion + + + - #region Debug /// /// Debugs a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled. /// @@ -261,7 +260,5 @@ namespace Umbraco.Core.Services Debug(typeof(T), generateMessageFormat, formatItems); } - #endregion - } } From 5af67facad11ef656b6c450fbc84cd87550dfefd Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 25 Nov 2014 17:36:02 +1100 Subject: [PATCH 09/78] Removes non-completed/tested/used code for templates which was during a WIP of the grid some time ago. --- .../src/common/resources/template.resource.js | 82 ------------ .../Editors/BackOfficeController.cs | 5 - src/Umbraco.Web/Editors/TemplateController.cs | 117 ------------------ .../Models/ContentEditing/TemplateDisplay.cs | 16 --- .../Trees/TemplatesTreeController.cs | 38 +++++- src/Umbraco.Web/Umbraco.Web.csproj | 2 - 6 files changed, 32 insertions(+), 228 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js delete mode 100644 src/Umbraco.Web/Editors/TemplateController.cs delete mode 100644 src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js deleted file mode 100644 index d6fec8640f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/resources/template.resource.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @ngdoc service - * @name umbraco.resources.stylesheetResource - * @description service to retrieve available stylesheets - * - * - **/ -function templateResource($q, $http, umbRequestHelper) { - - //the factory object returned - return { - - /** - * @ngdoc method - * @name umbraco.resources.stylesheetResource#getAll - * @methodOf umbraco.resources.stylesheetResource - * - * @description - * Gets all registered stylesheets - * - * ##usage - *
-         * stylesheetResource.getAll()
-         *    .then(function(stylesheets) {
-         *        alert('its here!');
-         *    });
-         * 
- * - * @returns {Promise} resourcePromise object containing the stylesheets. - * - */ - getAll: function () { - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "templateApiBaseUrl", - "GetAll")), - 'Failed to retrieve stylesheets '); - }, - - /** - * @ngdoc method - * @name umbraco.resources.stylesheetResource#getRulesByName - * @methodOf umbraco.resources.stylesheetResource - * - * @description - * Returns all defined child rules for a stylesheet with a given name - * - * ##usage - *
-         * stylesheetResource.getRulesByName("ie7stylesheet")
-         *    .then(function(rules) {
-         *        alert('its here!');
-         *    });
-         * 
- * - * @returns {Promise} resourcePromise object containing the rules. - * - */ - getById: function (id) { - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "templateApiBaseUrl", - "GetById", - [{ id: id }])), - 'Failed to retreive template '); - }, - - saveAndRender: function(html, templateId, pageId){ - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "templateApiBaseUrl", - "PostSaveAndRender"), - {templateId: templateId, pageId: pageId, html: html }), - 'Failed to retreive template '); - } - }; -} - -angular.module('umbraco.resources').factory('templateResource', templateResource); diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 0e7d48d3d9..91c26c603a 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -196,11 +196,6 @@ namespace Umbraco.Web.Editors "stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetAll()) }, - - { - "templateApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( - controller => controller.GetById(0)) - }, { "memberTypeApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetAllTypes()) diff --git a/src/Umbraco.Web/Editors/TemplateController.cs b/src/Umbraco.Web/Editors/TemplateController.cs deleted file mode 100644 index 3799be7e23..0000000000 --- a/src/Umbraco.Web/Editors/TemplateController.cs +++ /dev/null @@ -1,117 +0,0 @@ -using AutoMapper; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web.Http; -using Umbraco.Core.Models; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; -using Umbraco.Web.WebApi.Filters; - -namespace Umbraco.Web.Editors -{ - [PluginController("UmbracoApi")] - [UmbracoTreeAuthorize(Core.Constants.Trees.Templates)] - public class TemplateController : UmbracoAuthorizedJsonController - { - /// - /// Gets the content json for the content id - /// - /// - /// - public TemplateDisplay GetById(int id) - { - var template = Services.FileService.GetTemplate(id); - if (template == null) - { - throw new HttpResponseException(HttpStatusCode.NotFound); - } - - TemplateDisplay t = new TemplateDisplay(); - t.Alias = template.Alias; - t.Content = template.Content; - t.Id = template.Id; - t.Name = template.Name; - - return t; - } - - /// - /// Deletes a data type wth a given ID - /// - /// - /// - [HttpDelete] - [HttpPost] - public HttpResponseMessage DeleteById(int id) - { - var foundTemplate = Services.FileService.GetTemplate(id); - if (foundTemplate == null) - { - throw new HttpResponseException(HttpStatusCode.NotFound); - } - Services.FileService.DeleteTemplate(foundTemplate.Alias); - return Request.CreateResponse(HttpStatusCode.OK); - } - - [HttpPost] - public HttpResponseMessage PostSaveAndRender(dynamic model) - { - var foundTemplate = Services.FileService.GetTemplate((int)model.templateId); - if (foundTemplate == null) - { - throw new HttpResponseException(HttpStatusCode.NotFound); - } - foundTemplate.Content = model.html; - Services.FileService.SaveTemplate(foundTemplate); - - string result = string.Empty; - try - { - var url = "http://" + Request.RequestUri.Host + "/" + model.pageId + ".aspx?altTemplate=" + foundTemplate.Alias; - result = url; - - WebClient wc = new WebClient(); - result = wc.DownloadString(new Uri(url)); - } - catch (WebException exception) - { - if (exception.Response != null) - { - var responseStream = exception.Response.GetResponseStream(); - - if (responseStream != null) - { - using (var reader = new StreamReader(responseStream)) - { - result = reader.ReadToEnd(); - } - } - } - } - catch (Exception ex) - { - result += ex.ToString(); - } - - - return new HttpResponseMessage() - { - Content = new StringContent( - result, - Encoding.UTF8, - "text/html" - ) - }; - } - - - - } -} diff --git a/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs deleted file mode 100644 index 5291b9cca3..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/TemplateDisplay.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Web.Models.ContentEditing -{ - [DataContract(Name = "template", Namespace = "")] - public class TemplateDisplay : EntityBasic - { - [DataMember(Name = "content")] - public string Content { get; set; } - } -} diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index f8cd861f6e..5e88691591 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -55,6 +55,8 @@ namespace Umbraco.Web.Trees template.IsMasterTemplate, GetEditorPath(template, queryStrings)))); + nodes.ForEach(x => x.NodeType = "tempaltes"); + return nodes; } @@ -72,9 +74,9 @@ namespace Umbraco.Web.Trees { //Create the normal create action menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)) - //Since we haven't implemented anything for languages in angular, this needs to be converted to + //Since we haven't implemented anything for templates in angular, this needs to be converted to //use the legacy format - .ConvertLegacyMenuItem(null, "initlanguages", queryStrings.GetValue("application")); + .ConvertLegacyMenuItem(null, "inittemplates", queryStrings.GetValue("application")); //refresh action menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); @@ -84,25 +86,49 @@ namespace Umbraco.Web.Trees var template = Services.FileService.GetTemplate(int.Parse(id)); if (template == null) return new MenuItemCollection(); + var entity = FromTemplate(template); + //Create the create action for creating sub layouts + menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)) + //Since we haven't implemented anything for templates in angular, this needs to be converted to + //use the legacy format + .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); + + //don't allow delete if it has child layouts if (template.IsMasterTemplate == false) { //add delete option if it doesn't have children - menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias)) + menu.Items.Add(ui.Text("actions", ActionDelete.Instance.Alias), true) //Since we haven't implemented anything for languages in angular, this needs to be converted to //use the legacy format - .ConvertLegacyMenuItem(null, "templates", queryStrings.GetValue("application")); + .ConvertLegacyMenuItem(entity, "templates", queryStrings.GetValue("application")); } + //add refresh + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); return menu; } + private UmbracoEntity FromTemplate(ITemplate template) + { + return new UmbracoEntity + { + CreateDate = template.CreateDate, + Id = template.Id, + Key = template.Key, + Name = template.Name, + NodeObjectTypeId = new Guid(Constants.ObjectTypes.Template), + //TODO: Fix parent/paths on templates + ParentId = -1, + Path = template.Path, + UpdateDate = template.UpdateDate + }; + } + private string GetEditorPath(ITemplate template, FormDataCollection queryStrings) { - //UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && ViewHelper.ViewExists(template) - //TODO: Rebuild the language editor in angular, then we dont need to have this at all (which is just a path to the legacy editor) return Path.GetExtension(template.Path).InvariantEquals(".master") diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 0c2a2034b8..b0620994ec 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -308,7 +308,6 @@ - @@ -329,7 +328,6 @@ - From 8328f09d6bf23a97dda6674020bdd8383168e5f6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 25 Nov 2014 17:59:59 +1100 Subject: [PATCH 10/78] Works on U4-2866 - converted template tree to new tree structure. --- src/Umbraco.Core/Constants-Applications.cs | 7 ++++--- src/Umbraco.Web.UI/config/trees.Release.config | 2 +- src/Umbraco.Web.UI/config/trees.config | 6 +++--- src/Umbraco.Web/Trees/TemplatesTreeController.cs | 2 -- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Constants-Applications.cs b/src/Umbraco.Core/Constants-Applications.cs index c32dba0ca3..c33bebe41b 100644 --- a/src/Umbraco.Core/Constants-Applications.cs +++ b/src/Umbraco.Core/Constants-Applications.cs @@ -78,12 +78,12 @@ /// public const string Dictionary = "dictionary"; - //TODO: Fill in the rest! + /// - /// alias for the media tree. + /// alias for the template tree. /// - public const string Templates = "template"; + public const string Templates = "templates"; public const string RelationTypes = "relationTypes"; @@ -91,6 +91,7 @@ public const string Languages = "languages"; + //TODO: Fill in the rest! } } diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config index f58a051a2a..bb60356cd4 100644 --- a/src/Umbraco.Web.UI/config/trees.Release.config +++ b/src/Umbraco.Web.UI/config/trees.Release.config @@ -9,7 +9,7 @@ - + diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 2f7ca1acf0..8a85f26788 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -8,8 +8,8 @@ - - + + @@ -37,5 +37,5 @@ + iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="10" />--> \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/TemplatesTreeController.cs b/src/Umbraco.Web/Trees/TemplatesTreeController.cs index 5e88691591..8c19749d27 100644 --- a/src/Umbraco.Web/Trees/TemplatesTreeController.cs +++ b/src/Umbraco.Web/Trees/TemplatesTreeController.cs @@ -55,8 +55,6 @@ namespace Umbraco.Web.Trees template.IsMasterTemplate, GetEditorPath(template, queryStrings)))); - nodes.ForEach(x => x.NodeType = "tempaltes"); - return nodes; } From 787e10bbe1ee199376df9ba31161d27837f65656 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 25 Nov 2014 18:02:17 +1100 Subject: [PATCH 11/78] ensures the templates are sorted by name --- src/Umbraco.Core/Services/FileService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 9709448cc3..48fbefa1ab 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -247,7 +247,7 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork())) { - return repository.GetAll(aliases); + return repository.GetAll(aliases).OrderBy(x => x.Name); } } @@ -259,7 +259,7 @@ namespace Umbraco.Core.Services { using (var repository = _repositoryFactory.CreateTemplateRepository(_dataUowProvider.GetUnitOfWork())) { - return repository.GetChildren(masterTemplateId); + return repository.GetChildren(masterTemplateId).OrderBy(x => x.Name); } } From 7cfcab4011a5849da1f2c18ab6929caec8effb75 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 25 Nov 2014 18:48:19 +1100 Subject: [PATCH 12/78] WIP working on getting the template services up to par and wrapping the new ones from old ones. --- src/Umbraco.Core/Models/ITemplate.cs | 9 + src/Umbraco.Core/Models/Template.cs | 32 +- .../Repositories/TemplateRepository.cs | 4 +- src/Umbraco.Core/Services/FileService.cs | 18 + src/Umbraco.Core/Services/IFileService.cs | 2 + .../businesslogic/template/Template.cs | 498 +++++++++--------- 6 files changed, 308 insertions(+), 255 deletions(-) diff --git a/src/Umbraco.Core/Models/ITemplate.cs b/src/Umbraco.Core/Models/ITemplate.cs index c6b016ea83..ae73b9f5ee 100644 --- a/src/Umbraco.Core/Models/ITemplate.cs +++ b/src/Umbraco.Core/Models/ITemplate.cs @@ -9,6 +9,15 @@ namespace Umbraco.Core.Models /// public interface ITemplate : IFile, IRememberBeingDirty, ICanBeDirty { + /// + /// Gets the Name of the File including extension + /// + new string Name { get; set; } + + /// + /// Gets the Alias of the File, which is the name without the extension + /// + new string Alias { get; set; } /// /// Returns true if the template is used as a layout for other templates (i.e. it has 'children') diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index 294207f69e..4659595049 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -21,10 +21,16 @@ namespace Umbraco.Core.Models private string _masterTemplateAlias; private Lazy _masterTemplateId; - private static readonly PropertyInfo MasterTemplateAliasSelector = ExpressionHelper.GetPropertyInfo(x => x.MasterTemplateAlias); private static readonly PropertyInfo MasterTemplateIdSelector = ExpressionHelper.GetPropertyInfo>(x => x.MasterTemplateId); - + + public Template(string name, string alias) + : base(string.Empty) + { + _name = name; + _alias = alias.ToCleanString(CleanStringType.UnderscoreAlias); + } + public Template(string path, string name, string alias) : base(path) { @@ -61,21 +67,19 @@ namespace Umbraco.Core.Models } [DataMember] - public override string Alias - { - get - { - return _alias; - } - } + string ITemplate.Name { get; set; } [DataMember] + string ITemplate.Alias { get; set; } + + public override string Alias + { + get { return ((ITemplate)this).Alias; } + } + public override string Name { - get - { - return _name; - } + get { return ((ITemplate)this).Name; } } @@ -156,5 +160,7 @@ namespace Umbraco.Core.Models return clone; } + + } } diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index 61f0ea175d..ec8c5ded76 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -170,7 +170,9 @@ namespace Umbraco.Core.Persistence.Repositories } } - //TODO Possibly ensure unique alias here (as is done in the legacy Template class)? + //TODO ensure unique alias here (as is done in the legacy Template class)! + //TODO: The legacy one also checked for length, so do that too! + //TODO: Integrate the ViewHelper, MasterPageHelper stuff for when saving the template content //Save to db var template = entity as Template; diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 48fbefa1ab..a5685756c4 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -239,6 +239,21 @@ namespace Umbraco.Core.Services #region Templates + + public ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0) + { + var template = new Template(name, name) + { + Content = content + }; + if (masterTemplate != null) + { + template.SetMasterTemplate(masterTemplate); + } + SaveTemplate(template, userId); + return template; + } + /// /// Gets a list of all objects /// @@ -807,5 +822,8 @@ namespace Umbraco.Core.Services #endregion + + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 74b16b984b..0a3be1aa88 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -137,6 +137,8 @@ namespace Umbraco.Core.Services /// Optional id of the user saving the template void SaveTemplate(ITemplate template, int userId = 0); + ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0); + /// /// Deletes a template by its alias /// diff --git a/src/umbraco.cms/businesslogic/template/Template.cs b/src/umbraco.cms/businesslogic/template/Template.cs index 12b59d7138..60f008d084 100644 --- a/src/umbraco.cms/businesslogic/template/Template.cs +++ b/src/umbraco.cms/businesslogic/template/Template.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Models; using Umbraco.Core.Strings; using umbraco.DataLayer; using System.Text.RegularExpressions; @@ -21,19 +22,20 @@ namespace umbraco.cms.businesslogic.template /// /// Summary description for Template. /// - //[Obsolete("Obsolete, This class will eventually be phased out - Use Umbraco.Core.Models.Template", false)] + [Obsolete("Obsolete, Use IFileService and ITemplate to work with templates instead")] public class Template : CMSNode { #region Private members - private string _OutputContentType; - private string _design; - private string _alias; - private string _oldAlias; - private int _mastertemplate; - private bool _hasChildrenInitialized = false; - private bool _hasChildren; + private ITemplate _template; + //private string _OutputContentType; + //private string _design; + //private string _alias; + //private string _oldAlias; + private int? _mastertemplate; + //private bool _hasChildrenInitialized = false; + //private bool _hasChildren; #endregion @@ -41,10 +43,10 @@ namespace umbraco.cms.businesslogic.template public static readonly string UmbracoMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master"; private static Hashtable _templateAliases = new Hashtable(); - private static volatile bool _templateAliasesInitialized = false; - private static readonly object TemplateLoaderLocker = new object(); - private static readonly Guid ObjectType = new Guid(Constants.ObjectTypes.Template); - private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray(); + //private static volatile bool _templateAliasesInitialized = false; + //private static readonly object TemplateLoaderLocker = new object(); + //private static readonly Guid ObjectType = new Guid(Constants.ObjectTypes.Template); + //private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray(); #endregion @@ -61,6 +63,8 @@ namespace umbraco.cms.businesslogic.template { get { + return _template.Path; + switch (DetermineRenderingEngine(this)) { case RenderingEngine.Mvc: @@ -73,6 +77,7 @@ namespace umbraco.cms.businesslogic.template } } + [Obsolete("This is not used at all, do not use this")] public static Hashtable TemplateAliases { get { return _templateAliases; } @@ -80,9 +85,16 @@ namespace umbraco.cms.businesslogic.template } #region Constructors + + internal Template(ITemplate template) + { + _template = template; + } + public Template(int id) : base(id) { } public Template(Guid id) : base(id) { } + #endregion /// @@ -95,21 +107,25 @@ namespace umbraco.cms.businesslogic.template if (!e.Cancel) { - base.Save(); + ApplicationContext.Current.Services.FileService.SaveTemplate(_template); + //base.Save(); FireAfterSave(e); } } public string GetRawText() { - return base.Text; + return _template.Content; + //return base.Text; } + //TODO: This is the name of the template, which can apparenlty be localized using the umbraco dictionary, so we need to cater for this! public override string Text { get { - string tempText = base.Text; + var tempText = _template.Name; + //string tempText = base.Text; if (!tempText.StartsWith("#")) return tempText; else @@ -135,31 +151,34 @@ namespace umbraco.cms.businesslogic.template } } - public string OutputContentType - { - get { return _OutputContentType; } - set { _OutputContentType = value; } - } + [Obsolete("This is not used whatsoever")] + public string OutputContentType { get; set; } protected override void setupNode() { - base.setupNode(); - - IRecordsReader dr = SqlHelper.ExecuteReader("Select alias,design,master from cmsTemplate where nodeId = " + this.Id); - bool hasRows = dr.Read(); - if (hasRows) + _template = ApplicationContext.Current.Services.FileService.GetTemplate(Id); + if (_template == null) { - _alias = dr.GetString("alias"); - _design = dr.GetString("design"); - //set the master template to zero if it's null - _mastertemplate = dr.IsNull("master") ? 0 : dr.GetInt("master"); + throw new ArgumentException(string.Format("No node exists with id '{0}'", Id)); } - dr.Close(); - if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && ViewHelper.ViewExists(this)) - _design = ViewHelper.GetFileContents(this); - else - _design = MasterPageHelper.GetFileContents(this); + //base.setupNode(); + + //IRecordsReader dr = SqlHelper.ExecuteReader("Select alias,design,master from cmsTemplate where nodeId = " + this.Id); + //bool hasRows = dr.Read(); + //if (hasRows) + //{ + // _alias = dr.GetString("alias"); + // _design = dr.GetString("design"); + // //set the master template to zero if it's null + // _mastertemplate = dr.IsNull("master") ? 0 : dr.GetInt("master"); + //} + //dr.Close(); + + //if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && ViewHelper.ViewExists(this)) + // _design = ViewHelper.GetFileContents(this); + //else + // _design = MasterPageHelper.GetFileContents(this); } @@ -167,52 +186,46 @@ namespace umbraco.cms.businesslogic.template { get { - List path = new List(); - Template working = this; - while (working != null) - { - path.Add(working.Id); - try - { - if (working.MasterTemplate != 0) - { - working = new Template(working.MasterTemplate); - } - else - { - working = null; - } - } - catch (ArgumentException) - { - working = null; - } - } - path.Add(-1); - path.Reverse(); - string sPath = string.Join(",", path.ConvertAll(item => item.ToString()).ToArray()); - return sPath; + return _template.Path; + + //TODO: Fix the path on templates! + + //List path = new List(); + //Template working = this; + //while (working != null) + //{ + // path.Add(working.Id); + // try + // { + // if (working.MasterTemplate != 0) + // { + // working = new Template(working.MasterTemplate); + // } + // else + // { + // working = null; + // } + // } + // catch (ArgumentException) + // { + // working = null; + // } + //} + //path.Add(-1); + //path.Reverse(); + //string sPath = string.Join(",", path.ConvertAll(item => item.ToString()).ToArray()); + //return sPath; } set { - base.Path = value; + _template.Path = value; } } public string Alias { - get { return _alias; } - set - { - FlushCache(); - _oldAlias = _alias; - _alias = value.ToCleanString(CleanStringType.UnderscoreAlias); - - SqlHelper.ExecuteNonQuery("Update cmsTemplate set alias = @alias where NodeId = " + this.Id, SqlHelper.CreateParameter("@alias", _alias)); - _templateAliasesInitialized = false; - - InitTemplateAliases(); - } + get { return _template.Alias; } + set { _template.Alias = value; } } @@ -224,66 +237,82 @@ namespace umbraco.cms.businesslogic.template public override bool HasChildren { - get - { - if (!_hasChildrenInitialized) - { - _hasChildren = SqlHelper.ExecuteScalar("select count(NodeId) as tmp from cmsTemplate where master = " + Id) > 0; - } - return _hasChildren; - } + get { return _template.IsMasterTemplate; } set { - _hasChildrenInitialized = true; - _hasChildren = value; + //Do nothing! } } public int MasterTemplate { - get { return _mastertemplate; } + get + { + if (_mastertemplate.HasValue == false) + { + var master = ApplicationContext.Current.Services.FileService.GetTemplate(_template.MasterTemplateAlias); + if (master != null) + { + _mastertemplate = master.Id; + } + else + { + _mastertemplate = -1; + } + } + return _mastertemplate.Value; + } set { - FlushCache(); - _mastertemplate = value; - - //set to null if it's zero - object masterVal = value; - if (value == 0) masterVal = DBNull.Value; - - SqlHelper.ExecuteNonQuery("Update cmsTemplate set master = @master where NodeId = @nodeId", - SqlHelper.CreateParameter("@master", masterVal), - SqlHelper.CreateParameter("@nodeId", this.Id)); + //set to null if it's zero + if (value == 0) + { + _template.SetMasterTemplate(null); + } + else + { + var found = ApplicationContext.Current.Services.FileService.GetTemplate(value); + if (found != null) + { + _template.SetMasterTemplate(found); + _mastertemplate = found.Id; + } + } } } public string Design { - get { return _design; } + get + { + return _template.Content; + } set { - FlushCache(); + _template.Content = value; - _design = value.Trim(NewLineChars); + //FlushCache(); - //we only switch to MVC View editing if the template has a view file, and MVC editing is enabled - if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && !MasterPageHelper.IsMasterPageSyntax(_design)) - { - MasterPageHelper.RemoveMasterPageFile(this.Alias); - MasterPageHelper.RemoveMasterPageFile(_oldAlias); - _design = ViewHelper.UpdateViewFile(this, _oldAlias); - } - else if (UmbracoConfig.For.UmbracoSettings().Templates.UseAspNetMasterPages) - { - ViewHelper.RemoveViewFile(this.Alias); - ViewHelper.RemoveViewFile(_oldAlias); - _design = MasterPageHelper.UpdateMasterPageFile(this, _oldAlias); - } - + //_design = value.Trim(NewLineChars); - SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", - SqlHelper.CreateParameter("@design", _design), - SqlHelper.CreateParameter("@id", Id)); + ////we only switch to MVC View editing if the template has a view file, and MVC editing is enabled + //if (UmbracoConfig.For.UmbracoSettings().Templates.DefaultRenderingEngine == RenderingEngine.Mvc && !MasterPageHelper.IsMasterPageSyntax(_design)) + //{ + // MasterPageHelper.RemoveMasterPageFile(this.Alias); + // MasterPageHelper.RemoveMasterPageFile(_oldAlias); + // _design = ViewHelper.UpdateViewFile(this, _oldAlias); + //} + //else if (UmbracoConfig.For.UmbracoSettings().Templates.UseAspNetMasterPages) + //{ + // ViewHelper.RemoveViewFile(this.Alias); + // ViewHelper.RemoveViewFile(_oldAlias); + // _design = MasterPageHelper.UpdateMasterPageFile(this, _oldAlias); + //} + + + //SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", + // SqlHelper.CreateParameter("@design", _design), + // SqlHelper.CreateParameter("@id", Id)); } } @@ -331,6 +360,7 @@ namespace umbraco.cms.businesslogic.template } } + [Obsolete("This method should have never existed here")] public IEnumerable GetDocumentTypes() { return DocumentType.GetAllAsList().Where(x => x.allowedTemplates.Select(t => t.Id).Contains(this.Id)); @@ -383,100 +413,93 @@ namespace umbraco.cms.businesslogic.template return engine; } - public static Template MakeNew(string Name, BusinessLogic.User u, Template master) + public static Template MakeNew(string Name, User u, Template master) { return MakeNew(Name, u, master, null); } - private static Template MakeNew(string name, BusinessLogic.User u, string design) + private static Template MakeNew(string name, User u, string design) { return MakeNew(name, u, null, design); } - public static Template MakeNew(string name, BusinessLogic.User u) + public static Template MakeNew(string name, User u) { return MakeNew(name, u, design: null); } - private static Template MakeNew(string name, BusinessLogic.User u, Template master, string design) + private static Template MakeNew(string name, User u, Template master, string design) { - // CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) - var node = MakeNew(-1, ObjectType, u.Id, 1, name, Guid.NewGuid()); + var foundMaster = ApplicationContext.Current.Services.FileService.GetTemplate(master.Id); + var template = ApplicationContext.Current.Services.FileService.CreateTemplateWithIdentity(name, design, foundMaster, u.Id); - //ensure unique alias - name = name.ToCleanString(CleanStringType.UnderscoreAlias); - if (GetByAlias(name) != null) - name = EnsureUniqueAlias(name, 1); - //name = name.Replace("/", ".").Replace("\\", ""); //why? ToSafeAlias() already removes those chars + var legacyTemplate = new Template(template); - if (name.Length > 100) - name = name.Substring(0, 95); // + "..."; // no, these are invalid alias chars + //// CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) + //var node = MakeNew(-1, ObjectType, u.Id, 1, name, Guid.NewGuid()); + + ////ensure unique alias + //name = name.ToCleanString(CleanStringType.UnderscoreAlias); + //if (GetByAlias(name) != null) + // name = EnsureUniqueAlias(name, 1); + ////name = name.Replace("/", ".").Replace("\\", ""); //why? ToSafeAlias() already removes those chars + + //if (name.Length > 100) + // name = name.Substring(0, 95); // + "..."; // no, these are invalid alias chars - SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)", - SqlHelper.CreateParameter("@nodeId", node.Id), - SqlHelper.CreateParameter("@alias", name), - SqlHelper.CreateParameter("@design", ' '), - SqlHelper.CreateParameter("@master", DBNull.Value)); + //SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)", + // SqlHelper.CreateParameter("@nodeId", node.Id), + // SqlHelper.CreateParameter("@alias", name), + // SqlHelper.CreateParameter("@design", ' '), + // SqlHelper.CreateParameter("@master", DBNull.Value)); - var template = new Template(node.Id); - if (master != null) - template.MasterTemplate = master.Id; + //var template = new Template(node.Id); + //if (master != null) + // template.MasterTemplate = master.Id; - switch (DetermineRenderingEngine(template, design)) - { - case RenderingEngine.Mvc: - ViewHelper.CreateViewFile(template); - break; - case RenderingEngine.WebForms: - MasterPageHelper.CreateMasterPage(template); - break; - } + //switch (DetermineRenderingEngine(template, design)) + //{ + // case RenderingEngine.Mvc: + // ViewHelper.CreateViewFile(template); + // break; + // case RenderingEngine.WebForms: + // MasterPageHelper.CreateMasterPage(template); + // break; + //} - //if a design is supplied ensure it is updated. - if (design.IsNullOrWhiteSpace() == false) - { - template.ImportDesign(design); - } + ////if a design is supplied ensure it is updated. + //if (design.IsNullOrWhiteSpace() == false) + //{ + // template.ImportDesign(design); + //} var e = new NewEventArgs(); - template.OnNew(e); + legacyTemplate.OnNew(e); - return template; + return legacyTemplate; } - private static string EnsureUniqueAlias(string alias, int attempts) - { - if (GetByAlias(alias + attempts.ToString()) == null) - return alias + attempts.ToString(); - else - { - attempts++; - return EnsureUniqueAlias(alias, attempts); - } - } + //private static string EnsureUniqueAlias(string alias, int attempts) + //{ + // if (GetByAlias(alias + attempts.ToString()) == null) + // return alias + attempts.ToString(); + // else + // { + // attempts++; + // return EnsureUniqueAlias(alias, attempts); + // } + //} public static Template GetByAlias(string Alias) { return GetByAlias(Alias, false); } + [Obsolete("this overload is the same as the other one, the useCache has no affect")] public static Template GetByAlias(string Alias, bool useCache) { - if (!useCache) - { - try - { - return new Template(SqlHelper.ExecuteScalar("select nodeId from cmsTemplate where alias = @alias", SqlHelper.CreateParameter("@alias", Alias))); - } - catch - { - return null; - } - } - - //return from cache instead - var id = GetTemplateIdFromAlias(Alias); - return id == 0 ? null : GetTemplate(id); + var found = ApplicationContext.Current.Services.FileService.GetTemplate(Alias); + return found == null ? null : new Template(found); } [Obsolete("Obsolete, please use GetAllAsList() method instead", true)] @@ -487,46 +510,34 @@ namespace umbraco.cms.businesslogic.template public static List