diff --git a/.hgignore b/.hgignore index a6ddc03595..980273f4f7 100644 --- a/.hgignore +++ b/.hgignore @@ -47,5 +47,6 @@ src/Umbraco.Tests/config/trees.config src/Umbraco.Web.UI/web.config *.orig src/Umbraco.Tests/config/404handlers.config -src/Umbraco.Web.UI/Views/* +src/Umbraco.Web.UI/Views/*.cshtml +src/Umbraco.Web.UI/Views/*.vbhtml src/Umbraco.Tests/config/umbracoSettings.config diff --git a/build/Build.bat b/build/Build.bat index 76cf1b11fe..aca687fdcc 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,2 +1,9 @@ +@ECHO OFF %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" -REM pause \ No newline at end of file + +if ERRORLEVEL 1 goto :showerror + +goto :EOF + +:showerror +pause \ No newline at end of file diff --git a/src/Umbraco.Core/ActivatorHelper.cs b/src/Umbraco.Core/ActivatorHelper.cs new file mode 100644 index 0000000000..88ec01ae35 --- /dev/null +++ b/src/Umbraco.Core/ActivatorHelper.cs @@ -0,0 +1,20 @@ +using System; + +namespace Umbraco.Core +{ + /// + /// Helper methods for Activation + /// + internal static class ActivatorHelper + { + /// + /// Creates an instance of a type using that type's default constructor. + /// + /// + /// + public static T CreateInstance() where T : class, new() + { + return Activator.CreateInstance(typeof(T)) as T; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index f330049fb7..424e7b2f24 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -115,7 +115,7 @@ namespace Umbraco.Core.Configuration /// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin /// we will convert the '/' to '-' and use that as the path. its a bit lame but will work. /// - internal static string MvcArea + internal static string UmbracoMvcArea { get { diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings.cs b/src/Umbraco.Core/Configuration/UmbracoSettings.cs index 2c7e2a00d3..8de810f588 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings.cs @@ -1145,6 +1145,71 @@ namespace Umbraco.Core.Configuration } } + /// + /// Enables MVC, and at the same time disable webform masterpage templates. + /// This ensure views are automaticly created instead of masterpages. + /// Views are display in the tree instead of masterpages and a MVC template editor + /// is used instead of the masterpages editor + /// + /// true if umbraco defaults to using MVC views for templating, otherwise false. + + private static bool? _enableMvc; + public static bool EnableMvcSupport + { + get + { + if (_enableMvc == null) + { + try + { + bool enableMvc = false; + string value = GetKey("/settings/templates/enableMvcSupport"); + if (value != null) + if (bool.TryParse(value, out enableMvc)) + _enableMvc = enableMvc; + } + catch (Exception ex) + { + Trace.WriteLine("Could not load /settings/templates/enableMvcSupport from umbracosettings.config:\r\n {0}", + ex.Message); + + _enableMvc = false; + } + } + return _enableMvc == true; + } + } + + private static string[] _mvcViewExtensions; + public static string[] MvcViewExtensions + { + get + { + string[] defaultValue = "cshtml".Split(','); + + if (_mvcViewExtensions == null) + { + try + { + string value = GetKey("/settings/templates/mvcViewExtensions"); + if (!string.IsNullOrEmpty(value)) + _mvcViewExtensions = value.Split(','); + else + _mvcViewExtensions = defaultValue; + } + catch (Exception ex) + { + Trace.WriteLine("Could not load /settings/templates/mvcViewExtensions from umbracosettings.config:\r\n {0}", + ex.Message); + + _mvcViewExtensions = defaultValue; + } + } + + return _mvcViewExtensions; + } + } + /// /// Configuration regarding webservices /// diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index 8a3a0688d5..f718483d0f 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -165,6 +165,23 @@ namespace Umbraco.Core.IO return true; } + public static bool ValidateEditPath(string filePath, string[] validDirs) + { + foreach (var dir in validDirs) + { + var validDir = dir; + if (!filePath.StartsWith(MapPath(SystemDirectories.Root))) + filePath = MapPath(filePath); + if (!validDir.StartsWith(MapPath(SystemDirectories.Root))) + validDir = MapPath(validDir); + + if (filePath.StartsWith(validDir)) + return true; + } + + throw new FileSecurityException(String.Format("The filepath '{0}' is not within an allowed directory for this type of files", filePath.Replace(MapPath(SystemDirectories.Root), ""))); + } + public static bool ValidateFileExtension(string filePath, List validFileExtensions) { if (!filePath.StartsWith(MapPath(SystemDirectories.Root))) diff --git a/src/Umbraco.Core/IThumbnailProvider.cs b/src/Umbraco.Core/IThumbnailProvider.cs index 0948f1d8eb..c05f50bb62 100644 --- a/src/Umbraco.Core/IThumbnailProvider.cs +++ b/src/Umbraco.Core/IThumbnailProvider.cs @@ -7,7 +7,6 @@ namespace Umbraco.Core { public interface IThumbnailProvider { - int Priority { get; } bool CanProvideThumbnail(string fileUrl); string GetThumbnailUrl(string fileUrl); } diff --git a/src/Umbraco.Core/Mandate.cs b/src/Umbraco.Core/Mandate.cs new file mode 100644 index 0000000000..54d589b90a --- /dev/null +++ b/src/Umbraco.Core/Mandate.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Umbraco.Core +{ + /// + /// Helper class for mandating values, for example on method parameters. + /// + internal static class Mandate + { + /// + /// Mandates that the specified parameter is not null. + /// + /// The value. + /// Name of the param. + /// If is null. + public static void ParameterNotNull(T value, string paramName) where T : class + { + That(value != null, () => new ArgumentNullException(paramName)); + } + + + /// + /// Mandates that the specified parameter is not null. + /// + /// The value. + /// Name of the param. + /// If is null or whitespace. + public static void ParameterNotNullOrEmpty(string value, string paramName) + { + That(!string.IsNullOrWhiteSpace(value), () => new ArgumentNullException(paramName)); + } + + /// + /// Mandates that the specified sequence is not null and has at least one element. + /// + /// + /// The sequence. + /// Name of the param. + public static void ParameterNotNullOrEmpty(IEnumerable sequence, string paramName) + { + ParameterNotNull(sequence, paramName); + ParameterCondition(sequence.Any(), paramName); + } + + + /// + /// Mandates that the specified parameter matches the condition. + /// + /// The condition to check. + /// Name of the param. + /// If the condition is false. + public static void ParameterCondition(bool condition, string paramName) + { + ParameterCondition(condition, paramName, (string)null); + } + + /// + /// Mandates that the specified parameter matches the condition. + /// + /// The condition to check. + /// Name of the param. + /// The message. + /// If the condition is false. + public static void ParameterCondition(bool condition, string paramName, string message) + { + // Warning: don't make this method have an optional message parameter (removing the other ParameterCondition overload) as it will + // make binaries compiled against previous Framework libs incompatible unneccesarily + message = message ?? "A parameter passed into a method was not a valid value"; + That(condition, () => new ArgumentException(message, paramName)); + } + + /// + /// Mandates that the specified condition is true, otherwise throws an exception specified in . + /// + /// The type of the exception. + /// if set to true, throws exception . + /// An exception of type is raised if the condition is false. + public static void That(bool condition) where TException : Exception, new() + { + if (!condition) + throw ActivatorHelper.CreateInstance(); + } + + /// + /// Mandates that the specified condition is true, otherwise throws an exception specified in . + /// + /// The type of the exception. + /// if set to true, throws exception . + /// Deffered expression to call if the exception should be raised. + /// An exception of type is raised if the condition is false. + public static void That(bool condition, Func defer) where TException : Exception, new() + { + if (!condition) + { + throw defer.Invoke(); + } + + // Here is an example of how this method is actually called + //object myParam = null; + //Mandate.That(myParam != null, + // textManager => new ArgumentNullException(textManager.Get("blah", new {User = "blah"}))); + } + } +} diff --git a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs index bab284c7f4..2b8d1c43c7 100644 --- a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs +++ b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Web; namespace Umbraco.Core.ObjectResolution { + internal abstract class ManyObjectsResolverBase : ResolverBase where TResolved : class where TResolver : class @@ -94,6 +96,40 @@ namespace Umbraco.Core.ObjectResolution /// protected ObjectLifetimeScope LifetimeScope { get; private set; } + private int _defaultPluginWeight = 10; + + /// + /// Used in conjunction with GetSortedValues and WeightedPluginAttribute, if any of the objects + /// being resolved do not contain the WeightedPluginAttribute then this will be the default weight applied + /// to the object. + /// + protected virtual int DefaultPluginWeight + { + get { return _defaultPluginWeight; } + set { _defaultPluginWeight = value; } + } + + /// + /// If a resolver requries that objects are resolved with a specific order using the WeightedPluginAttribute + /// then this method should be used instead of the Values property. + /// + /// + protected IEnumerable GetSortedValues() + { + var vals = Values.ToList(); + //ensure they are sorted + vals.Sort((f1, f2) => + { + Func getWeight = o => + { + var weightAttribute = f1.GetType().GetCustomAttribute(true); + return weightAttribute != null ? weightAttribute.Weight : DefaultPluginWeight; + }; + return getWeight(f1).CompareTo(getWeight(f2)); + }); + return vals; + } + /// /// Returns the list of new object instances. /// diff --git a/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs b/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs new file mode 100644 index 0000000000..9ea4fec101 --- /dev/null +++ b/src/Umbraco.Core/ObjectResolution/WeightedPluginAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Umbraco.Core.ObjectResolution +{ + /// + /// Some many object resolvers require that the objects that they resolve have weights applied to them so that + /// the objects are returned in a sorted order, this attribute is used in these scenarios. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + internal class WeightedPluginAttribute : Attribute + { + public WeightedPluginAttribute(int weight) + { + Weight = weight; + } + + public int Weight { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 20bd19baf1..59142f2652 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -49,6 +49,7 @@ Properties\SolutionInfo.cs + @@ -89,7 +90,9 @@ + + diff --git a/src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs b/src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs new file mode 100644 index 0000000000..5efabd891e --- /dev/null +++ b/src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs @@ -0,0 +1,33 @@ +using System.Web.Mvc; +using NUnit.Framework; +using Umbraco.Web; + +namespace Umbraco.Tests +{ + [TestFixture] + public class HtmlHelperExtensionMethodsTests + { + [SetUp] + public virtual void Initialize() + { + //create an empty htmlHelper + _htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage()); + } + + private HtmlHelper _htmlHelper; + + [Test] + public void Wrap_Simple() + { + var output = _htmlHelper.Wrap("div", "hello world"); + Assert.AreEqual("
hello world
", output.ToHtmlString()); + } + + [Test] + public void Wrap_Object_Attributes() + { + var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"}); + Assert.AreEqual("
hello world
", output.ToHtmlString()); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/StringExtensionsTests.cs b/src/Umbraco.Tests/StringExtensionsTests.cs index 73e828ac73..49f8f830d7 100644 --- a/src/Umbraco.Tests/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/StringExtensionsTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Security; using System.Text; -using System.Web.Mvc; using NUnit.Framework; using Umbraco.Core; diff --git a/src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs b/src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs new file mode 100644 index 0000000000..ce0895e98f --- /dev/null +++ b/src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Tests.TestHelpers; +using Umbraco.Web; +using Umbraco.Web.Mvc; + +namespace Umbraco.Tests.Surface +{ + [TestFixture] + public class PluginControllerAreaTests : BaseWebTest + { + protected override bool RequiresDbSetup + { + get { return false; } + } + + [Test] + public void Ensure_Same_Area1() + { + Assert.Throws(() => + new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Controller1)), + PluginController.GetMetadata(typeof(Controller2)), + PluginController.GetMetadata(typeof(Controller3)) //not same area + })); + } + + [Test] + public void Ensure_Same_Area3() + { + Assert.Throws(() => + new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Controller1)), + PluginController.GetMetadata(typeof(Controller2)), + PluginController.GetMetadata(typeof(Controller4)) //no area assigned + })); + } + + [Test] + public void Ensure_Same_Area2() + { + var area = new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Controller1)), + PluginController.GetMetadata(typeof(Controller2)) + }); + Assert.Pass(); + } + + #region Test classes + + [PluginController("Area1")] + public class Controller1 : PluginController + { + public Controller1(UmbracoContext umbracoContext) : base(umbracoContext) + { + } + } + + [PluginController("Area1")] + public class Controller2 : PluginController + { + public Controller2(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + [PluginController("Area2")] + public class Controller3 : PluginController + { + public Controller3(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + public class Controller4 : PluginController + { + public Controller4(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + #endregion + + } +} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index a4a7b46302..b924753e6c 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -55,6 +55,7 @@ + @@ -70,6 +71,7 @@ + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index d9b73a2890..88426ad6d1 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -172,6 +172,7 @@ False ..\..\lib\WebPages\System.Web.Helpers.dll + False ..\..\lib\WebPages\System.Web.Razor.dll @@ -322,6 +323,7 @@ Dashboard.config + UI.xml @@ -354,6 +356,7 @@ + @@ -1668,6 +1671,7 @@ + Web.Template.config Designer @@ -2203,7 +2207,6 @@ - diff --git a/src/Umbraco.Web.UI/Views/Web.config b/src/Umbraco.Web.UI/Views/Web.config new file mode 100644 index 0000000000..6685adb973 --- /dev/null +++ b/src/Umbraco.Web.UI/Views/Web.config @@ -0,0 +1,59 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI/Web.config b/src/Umbraco.Web.UI/Web.config index b7b1e137c2..3422403616 100644 --- a/src/Umbraco.Web.UI/Web.config +++ b/src/Umbraco.Web.UI/Web.config @@ -35,12 +35,12 @@ - + - - + + diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config index 5f649fac98..057945415a 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.Release.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.Release.config @@ -130,6 +130,7 @@ true + false diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index dcb71c0538..f614615947 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -89,7 +89,6 @@ false - @@ -113,9 +112,11 @@ aa + true true + true diff --git a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml index b988bb864a..eaa028c34b 100644 --- a/src/Umbraco.Web.UI/umbraco/config/create/UI.xml +++ b/src/Umbraco.Web.UI/umbraco/config/create/UI.xml @@ -303,6 +303,7 @@ +
Package
/create/simple.ascx diff --git a/src/Umbraco.Web.UI/umbraco/developer/Xslt/editXslt.aspx b/src/Umbraco.Web.UI/umbraco/developer/Xslt/editXslt.aspx index 451a3d294d..4e96930591 100644 --- a/src/Umbraco.Web.UI/umbraco/developer/Xslt/editXslt.aspx +++ b/src/Umbraco.Web.UI/umbraco/developer/Xslt/editXslt.aspx @@ -57,7 +57,7 @@ xsltSnippet = UmbEditor.IsSimpleEditor ? jQuery("#<%= editorSource.ClientID %>").getSelection().text - : UmbEditor._editor.getSelection(); + : UmbEditor._editor.selection(); if (xsltSnippet == '') { xsltSnippet = UmbEditor.IsSimpleEditor diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/umbracoField.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/umbracoField.aspx index 9f3bda9703..39144f52b0 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/umbracoField.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/umbracoField.aspx @@ -9,7 +9,8 @@ { margin-top: 0px !important; padding-top: 0px !important; - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/views/editView.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/views/editView.aspx.cs new file mode 100644 index 0000000000..3b7d4b024e --- /dev/null +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/views/editView.aspx.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco.BasePages; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic.skinning; +using umbraco.cms.businesslogic.template; +using umbraco.cms.presentation.Trees; +using umbraco.DataLayer; +using umbraco.IO; +using umbraco.uicontrols; + +namespace umbraco.cms.presentation.settings.views +{ + public partial class editView : BasePages.UmbracoEnsuredPage + { + private Template _template; + + protected global::ClientDependency.Core.Controls.CssInclude CssInclude1; + protected global::ClientDependency.Core.Controls.JsInclude JsInclude; + + protected global::umbraco.uicontrols.UmbracoPanel Panel1; + protected global::umbraco.uicontrols.Pane Pane7; + protected global::umbraco.uicontrols.PropertyPanel pp_name; + protected global::System.Web.UI.WebControls.TextBox NameTxt; + protected global::umbraco.uicontrols.PropertyPanel pp_alias; + protected global::System.Web.UI.WebControls.TextBox AliasTxt; + protected global::umbraco.uicontrols.PropertyPanel pp_masterTemplate; + protected global::System.Web.UI.WebControls.DropDownList MasterTemplate; + protected global::umbraco.uicontrols.PropertyPanel pp_source; + protected global::umbraco.uicontrols.CodeArea editorSource; + protected global::System.Web.UI.WebControls.Repeater rpt_codeTemplates; + protected global::System.Web.UI.WebControls.Repeater rpt_macros; + + + public editView() + { + CurrentApp = BusinessLogic.DefaultApps.settings.ToString(); + } + + protected void Page_Load(object sender, EventArgs e) + { + MasterTemplate.Attributes.Add("onchange", "changeMasterPageFile()"); + + if (!IsPostBack) + { + MasterTemplate.Items.Add(new ListItem(ui.Text("none"), "0")); + + foreach (Template t in Template.GetAllAsList()) + { + if (t.Id != _template.Id) + { + var li = new ListItem(t.Text, t.Id.ToString()); + + li.Attributes.Add("id", t.Alias.Replace(" ", "")); + + if (t.Id == _template.MasterTemplate) + { + try + { + li.Selected = true; + } + catch + { + } + } + MasterTemplate.Items.Add(li); + } + } + + NameTxt.Text = _template.GetRawText(); + AliasTxt.Text = _template.Alias; + editorSource.Text = _template.Design; + + + ClientTools + .SetActiveTreeType(TreeDefinitionCollection.Instance.FindTree().Tree.Alias) + .SyncTree("-1,init," + _template.Path.Replace("-1,", ""), false); + } + } + + + + #region Web Form Designer generated code + protected override void OnInit(EventArgs e) + { + _template = new Template(int.Parse(Request.QueryString["templateID"])); + // + // CODEGEN: This call is required by the ASP.NET Web Form Designer. + // + InitializeComponent(); + base.OnInit(e); + Panel1.hasMenu = true; + + MenuIconI save = Panel1.Menu.NewIcon(); + save.ImageURL = SystemDirectories.Umbraco + "/images/editor/save.gif"; + save.OnClickCommand = "doSubmit()"; + save.AltText = ui.Text("save"); + save.ID = "save"; + + Panel1.Text = ui.Text("edittemplate"); + pp_name.Text = ui.Text("name", base.getUser()); + pp_alias.Text = ui.Text("alias", base.getUser()); + pp_masterTemplate.Text = ui.Text("mastertemplate", base.getUser()); + + // Editing buttons + Panel1.Menu.InsertSplitter(); + MenuIconI umbField = Panel1.Menu.NewIcon(); + umbField.ImageURL = UmbracoPath + "/images/editor/insField.gif"; + umbField.OnClickCommand = + ClientTools.Scripts.OpenModalWindow( + IOHelper.ResolveUrl(SystemDirectories.Umbraco) + "/dialogs/umbracoField.aspx?objectId=" + + editorSource.ClientID + "&tagName=UMBRACOGETDATA", ui.Text("template", "insertPageField"), 640, 550); + umbField.AltText = ui.Text("template", "insertPageField"); + + + // TODO: Update icon + MenuIconI umbDictionary = Panel1.Menu.NewIcon(); + umbDictionary.ImageURL = GlobalSettings.Path + "/images/editor/dictionaryItem.gif"; + umbDictionary.OnClickCommand = + ClientTools.Scripts.OpenModalWindow( + IOHelper.ResolveUrl(SystemDirectories.Umbraco) + "/dialogs/umbracoField.aspx?objectId=" + + editorSource.ClientID + "&tagName=UMBRACOGETDICTIONARY", ui.Text("template", "insertDictionaryItem"), + 640, 550); + umbDictionary.AltText = "Insert umbraco dictionary item"; + + //uicontrols.MenuIconI umbMacro = Panel1.Menu.NewIcon(); + //umbMacro.ImageURL = UmbracoPath + "/images/editor/insMacro.gif"; + //umbMacro.AltText = ui.Text("template", "insertMacro"); + //umbMacro.OnClickCommand = umbraco.BasePages.ClientTools.Scripts.OpenModalWindow(umbraco.IO.IOHelper.ResolveUrl(umbraco.IO.SystemDirectories.Umbraco) + "/dialogs/editMacro.aspx?objectId=" + editorSource.ClientID, ui.Text("template", "insertMacro"), 470, 530); + + Panel1.Menu.NewElement("div", "splitButtonMacroPlaceHolder", "sbPlaceHolder", 40); + + if (UmbracoSettings.UseAspNetMasterPages) + { + Panel1.Menu.InsertSplitter(); + + MenuIconI umbContainer = Panel1.Menu.NewIcon(); + umbContainer.ImageURL = UmbracoPath + "/images/editor/masterpagePlaceHolder.gif"; + umbContainer.AltText = ui.Text("template", "insertContentAreaPlaceHolder"); + umbContainer.OnClickCommand = + ClientTools.Scripts.OpenModalWindow( + IOHelper.ResolveUrl(SystemDirectories.Umbraco) + + "/dialogs/insertMasterpagePlaceholder.aspx?&id=" + _template.Id, + ui.Text("template", "insertContentAreaPlaceHolder"), 470, 320); + + MenuIconI umbContent = Panel1.Menu.NewIcon(); + umbContent.ImageURL = UmbracoPath + "/images/editor/masterpageContent.gif"; + umbContent.AltText = ui.Text("template", "insertContentArea"); + umbContent.OnClickCommand = + ClientTools.Scripts.OpenModalWindow( + IOHelper.ResolveUrl(SystemDirectories.Umbraco) + "/dialogs/insertMasterpageContent.aspx?id=" + + _template.Id, ui.Text("template", "insertContentArea"), 470, 300); + } + + + //Spit button + Panel1.Menu.InsertSplitter(); + Panel1.Menu.NewElement("div", "splitButtonPlaceHolder", "sbPlaceHolder", 40); + + // Help + Panel1.Menu.InsertSplitter(); + + MenuIconI helpIcon = Panel1.Menu.NewIcon(); + helpIcon.OnClickCommand = + ClientTools.Scripts.OpenModalWindow( + IOHelper.ResolveUrl(SystemDirectories.Umbraco) + "/settings/modals/showumbracotags.aspx?alias=" + + _template.Alias, ui.Text("template", "quickGuide"), 600, 580); + helpIcon.ImageURL = UmbracoPath + "/images/editor/help.png"; + helpIcon.AltText = ui.Text("template", "quickGuide"); + } + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + + } + + + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/codeEditorSave.asmx")); + ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx")); + } + #endregion + + } +} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/ContentExtensions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/ContentExtensions.cs index 0b1eba0cbc..0ff0dba254 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/ContentExtensions.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/ContentExtensions.cs @@ -37,7 +37,7 @@ namespace umbraco public static T GetProperty(this Content item, string propertyAlias) { // check to see if return object handles it's own object hydration - if (typeof(T).GetInterface(typeof(uQuery.IGetProperty).Name) != null) + if (typeof(uQuery.IGetProperty).IsAssignableFrom(typeof(T))) { // create new instance of T with empty constructor uQuery.IGetProperty t = (uQuery.IGetProperty)Activator.CreateInstance(); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/NodeExtensions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/NodeExtensions.cs index 2bebaf2fd6..7ba77ac082 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/NodeExtensions.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/NodeExtensions.cs @@ -271,7 +271,7 @@ namespace umbraco public static T GetProperty(this Node node, string propertyAlias) { // check to see if return object handles it's own object hydration - if (typeof(T).GetInterface(typeof(uQuery.IGetProperty).Name) != null) + if (typeof(uQuery.IGetProperty).IsAssignableFrom(typeof(T))) { // create new instance of T with empty constructor uQuery.IGetProperty t = (uQuery.IGetProperty)Activator.CreateInstance(); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/codeEditorSave.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/codeEditorSave.asmx.cs index db232b9e04..722abb3d18 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/codeEditorSave.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/codeEditorSave.asmx.cs @@ -402,7 +402,7 @@ namespace umbraco.presentation.webservices } return "false"; } - + [WebMethod] public string SaveTemplate(string templateName, string templateAlias, string templateContents, int templateID, int masterTemplateID) { @@ -417,6 +417,7 @@ namespace umbraco.presentation.webservices _template.Alias = templateAlias; _template.MasterTemplate = masterTemplateID; _template.Design = templateContents; + _template.Save(); retVal = "true"; diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs index 7ea5cc9928..e30d8c5dca 100644 --- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs +++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Web; using System.Web.Compilation; using System.Web.WebPages; +using Umbraco.Core; using umbraco.cms.businesslogic.macro; using umbraco.interfaces; using umbraco.IO; @@ -24,14 +25,7 @@ namespace umbraco.MacroEngines } public string GetMd5(string text) { - var x = new System.Security.Cryptography.MD5CryptoServiceProvider(); - var bs = System.Text.Encoding.UTF8.GetBytes(text); - bs = x.ComputeHash(bs); - var s = new System.Text.StringBuilder(); - foreach (var b in bs) { - s.Append(b.ToString("x2").ToLower()); - } - return s.ToString(); + return text.ToMd5(); } /// diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs b/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs index 6c59eb4244..7239330fb9 100644 --- a/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs +++ b/src/umbraco.MacroEngines/RazorDynamicNode/RazorLibraryCore.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Web.Mvc; using Umbraco.Core.Dynamics; using Umbraco.Web; using umbraco.interfaces; @@ -17,6 +18,12 @@ namespace umbraco.MacroEngines.Library { private readonly INode _node; private readonly UmbracoHelper _umbracoHelper; + + /// + /// An empty HtmlHelper with a blank ViewContext, used only to access some htmlHelper extension methods + /// + private readonly HtmlHelper _htmlHelper; + public INode Node { get { return _node; } @@ -25,6 +32,7 @@ namespace umbraco.MacroEngines.Library { this._node = node; _umbracoHelper = new UmbracoHelper(UmbracoContext.Current); + _htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage()); } public dynamic NodeById(int Id) @@ -194,24 +202,24 @@ namespace umbraco.MacroEngines.Library } public Umbraco.Web.Mvc.HtmlTagWrapper Wrap(string tag, string innerText, params Umbraco.Web.Mvc.IHtmlTagWrapper[] children) - { - return _umbracoHelper.Wrap(tag, innerText, children); + { + return _htmlHelper.Wrap(tag, innerText, children); } public Umbraco.Web.Mvc.HtmlTagWrapper Wrap(string tag, object inner, object anonymousAttributes, params Umbraco.Web.Mvc.IHtmlTagWrapper[] children) { - return _umbracoHelper.Wrap(tag, inner, anonymousAttributes, children); + return _htmlHelper.Wrap(tag, inner, anonymousAttributes, children); } public Umbraco.Web.Mvc.HtmlTagWrapper Wrap(string tag, object inner) { - return _umbracoHelper.Wrap(tag, inner); + return _htmlHelper.Wrap(tag, inner); } public Umbraco.Web.Mvc.HtmlTagWrapper Wrap(string tag, string innerText, object anonymousAttributes, params Umbraco.Web.Mvc.IHtmlTagWrapper[] children) { - return _umbracoHelper.Wrap(tag, innerText, anonymousAttributes, children); + return _htmlHelper.Wrap(tag, innerText, anonymousAttributes, children); } public Umbraco.Web.Mvc.HtmlTagWrapper Wrap(bool visible, string tag, string innerText, object anonymousAttributes, params Umbraco.Web.Mvc.IHtmlTagWrapper[] children) { - return _umbracoHelper.Wrap(visible, tag, innerText, anonymousAttributes, children); + return _htmlHelper.Wrap(visible, tag, innerText, anonymousAttributes, children); } public IHtmlString Truncate(IHtmlString html, int length) diff --git a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj index 58786d2ce8..38b25e1993 100644 --- a/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj +++ b/src/umbraco.MacroEngines/umbraco.MacroEngines.csproj @@ -54,6 +54,7 @@ + False ..\..\lib\WebPages\System.Web.Razor.dll diff --git a/src/umbraco.businesslogic/IO/IOHelper.cs b/src/umbraco.businesslogic/IO/IOHelper.cs index 8bd27eab9c..8bc3f886b2 100644 --- a/src/umbraco.businesslogic/IO/IOHelper.cs +++ b/src/umbraco.businesslogic/IO/IOHelper.cs @@ -77,7 +77,12 @@ namespace umbraco.IO return Umbraco.Core.IO.IOHelper.ValidateEditPath(filePath, validDir); } - public static bool ValidateFileExtension(string filePath, List validFileExtensions) + public static bool ValidateEditPath(string filePath, string[] validDirs) + { + return Umbraco.Core.IO.IOHelper.ValidateEditPath(filePath, validDirs); + } + + public static bool ValidateFileExtension(string filePath, List validFileExtensions) { return Umbraco.Core.IO.IOHelper.ValidateFileExtension(filePath, validFileExtensions); } diff --git a/src/umbraco.businesslogic/UmbracoSettings.cs b/src/umbraco.businesslogic/UmbracoSettings.cs index 6e30200699..bd070fb659 100644 --- a/src/umbraco.businesslogic/UmbracoSettings.cs +++ b/src/umbraco.businesslogic/UmbracoSettings.cs @@ -546,6 +546,19 @@ namespace umbraco get { return Umbraco.Core.Configuration.UmbracoSettings.ResolveUrlsFromTextString; } } + + /// + /// Enables MVC, and at the same time disable webform masterpage templates. + /// This ensure views are automaticly created instead of masterpages. + /// Views are display in the tree instead of masterpages and a MVC template editor + /// is used instead of the masterpages editor + /// + /// true if umbraco defaults to using MVC views for templating, otherwise false. + public static bool EnableMvcSupport + { + get { return Umbraco.Core.Configuration.UmbracoSettings.EnableMvcSupport; } + } + /// /// Configuration regarding webservices /// diff --git a/src/umbraco.cms/businesslogic/template/MasterpageHelper.cs b/src/umbraco.cms/businesslogic/template/MasterpageHelper.cs new file mode 100644 index 0000000000..8f3866472a --- /dev/null +++ b/src/umbraco.cms/businesslogic/template/MasterpageHelper.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Umbraco.Core.IO; + +namespace umbraco.cms.businesslogic.template +{ + internal class MasterpageHelper + { + internal static readonly string DefaultMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master"; + internal static string CreateMasterpageFile(Template t, bool overWrite = false) + { + string masterpageContent = ""; + + if (!File.Exists(t.MasterPageFile) || overWrite) + masterpageContent = saveTemplateToFile(t, t.Alias); + else + { + System.IO.TextReader tr = new StreamReader(t.MasterPageFile); + masterpageContent = tr.ReadToEnd(); + tr.Close(); + } + + return masterpageContent; + } + + internal static string GetMasterpageFile(Template t) + { + string masterpageContent = ""; + if (File.Exists(t.MasterPageFile)){ + System.IO.TextReader tr = new StreamReader(t.MasterPageFile); + masterpageContent = tr.ReadToEnd(); + tr.Close(); + } + + return masterpageContent; + } + + internal static string UpdateMasterpageFile(Template t, string currentAlias) + { + return saveTemplateToFile(t, currentAlias); + } + + internal static string saveTemplateToFile(Template template, string currentAlias) + { + var masterPageContent = template.Design; + if (!isMasterPageSyntax(masterPageContent)) + masterPageContent = ConvertToMasterPageSyntax(template); + + // Add header to master page if it doesn't exist + if (!masterPageContent.TrimStart().StartsWith("<%@")) + { + masterPageContent = getMasterPageHeader(template) + "\n" + masterPageContent; + } + else + { + // verify that the masterpage attribute is the same as the masterpage + string masterHeader = + masterPageContent.Substring(0, masterPageContent.IndexOf("%>") + 2).Trim( + Environment.NewLine.ToCharArray()); + + // find the masterpagefile attribute + MatchCollection m = Regex.Matches(masterHeader, "(?\\S*)=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + foreach (Match attributeSet in m) + { + if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile") + { + // validate the masterpagefile + string currentMasterPageFile = attributeSet.Groups["attributeValue"].Value; + string currentMasterTemplateFile = parentTemplatePath(template); + + if (currentMasterPageFile != currentMasterTemplateFile) + { + masterPageContent = + masterPageContent.Replace( + attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"", + attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile + + "\""); + + } + } + } + + } + + //we have a Old Alias if the alias and therefor the masterpage file name has changed... + //so before we save the new masterfile, we'll clear the old one, so we don't up with + //Unused masterpage files + if (!string.IsNullOrEmpty(currentAlias) && currentAlias != template.Alias) + { + + //Ensure that child templates have the right master masterpage file name + if (template.HasChildren) + { + //store children array here because iterating over an Array property object is very inneficient. + var c = template.Children; + foreach (CMSNode cmn in c) + UpdateMasterpageFile(new Template(cmn.Id), null); + } + + //then kill the old file.. + string _oldFile = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + currentAlias.Replace(" ", "") + ".master"); + if (System.IO.File.Exists(_oldFile)) + System.IO.File.Delete(_oldFile); + } + + // save the file in UTF-8 + System.IO.File.WriteAllText(template.MasterPageFile, masterPageContent, System.Text.Encoding.UTF8); + + return masterPageContent; + } + + internal static string ConvertToMasterPageSyntax(Template template) + { + string masterPageContent = GetMasterContentElement(template) + "\n"; + + masterPageContent += template.Design; + + // Parse the design for getitems + masterPageContent = EnsureMasterPageSyntax(template.Alias, masterPageContent); + + // append ending asp:content element + masterPageContent += "\n" + Environment.NewLine; + + return masterPageContent; + } + + private static bool isMasterPageSyntax(string code) + { + return code.Contains("<%@ Master") || code.Contains("", parentTemplatePath(template)) + Environment.NewLine; + } + + private static string parentTemplatePath(Template template) + { + var masterTemplate = DefaultMasterTemplate; + if (template.MasterTemplate != 0) + masterTemplate = SystemDirectories.Masterpages + "/" + new Template(template.MasterTemplate).Alias.Replace(" ", "") + ".master"; + + return masterTemplate; + } + + private static string GetMasterContentElement(Template template) + { + if (template.MasterTemplate != 0) + { + string masterAlias = new Template(template.MasterTemplate).Alias.Replace(" ", ""); + return + String.Format("", + template.Alias.Replace(" ", ""), masterAlias); + } + else + return + String.Format("", + template.Alias.Replace(" ", "")); + + } + + internal static string EnsureMasterPageSyntax(string templateAlias, string masterPageContent) + { + replaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", true); + replaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", false); + + // Parse the design for macros + replaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", true); + replaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", false); + + // Parse the design for load childs + masterPageContent = masterPageContent.Replace("", createDefaultPlaceHolder(templateAlias)) + .Replace("", createDefaultPlaceHolder(templateAlias)); + // Parse the design for aspnet forms + getAspNetMasterPageForm(ref masterPageContent, templateAlias); + masterPageContent = masterPageContent.Replace("", ""); + // Parse the design for aspnet heads + masterPageContent = masterPageContent.Replace("", String.Format("", templateAlias.Replace(" ", ""))); + masterPageContent = masterPageContent.Replace("", ""); + return masterPageContent; + } + + + private static void getAspNetMasterPageForm(ref string design, string templateAlias) + { + Match formElement = Regex.Match(design, getElementRegExp("?ASPNET_FORM", false), RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + if (formElement != null && formElement.Value != "") + { + string formReplace = String.Format("
", templateAlias.Replace(" ", "")); + if (formElement.Groups.Count == 0) + { + formReplace += ""; + } + design = design.Replace(formElement.Value, formReplace); + } + } + + private static string createDefaultPlaceHolder(string templateAlias) + { + return String.Format("", templateAlias.Replace(" ", "")); + } + + private static void replaceElement(ref string design, string elementName, string newElementName, bool checkForQuotes) + { + MatchCollection m = + Regex.Matches(design, getElementRegExp(elementName, checkForQuotes), + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + foreach (Match match in m) + { + GroupCollection groups = match.Groups; + + // generate new element (compensate for a closing trail on single elements ("/")) + string elementAttributes = groups[1].Value; + // test for macro alias + if (elementName == "?UMBRACO_MACRO") + { + Hashtable tags = helpers.xhtml.ReturnAttributes(match.Value); + if (tags["macroAlias"] != null) + elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroAlias"].ToString()) + elementAttributes; + else if (tags["macroalias"] != null) + elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroalias"].ToString()) + elementAttributes; + } + string newElement = "<" + newElementName + " runat=\"server\" " + elementAttributes.Trim() + ">"; + if (elementAttributes.EndsWith("/")) + { + elementAttributes = elementAttributes.Substring(0, elementAttributes.Length - 1); + } + else if (groups[0].Value.StartsWith(""; + + if (checkForQuotes) + { + // if it's inside quotes, we'll change element attribute quotes to single quotes + newElement = newElement.Replace("\"", "'"); + newElement = String.Format("\"{0}\"", newElement); + } + design = design.Replace(match.Value, newElement); + } + } + + private static string getElementRegExp(string elementName, bool checkForQuotes) + { + if (checkForQuotes) + return String.Format("\"<[^>\\s]*\\b{0}(\\b[^>]*)>\"", elementName); + else + return String.Format("<[^>\\s]*\\b{0}(\\b[^>]*)>", elementName); + + } + + } +} diff --git a/src/umbraco.cms/businesslogic/template/Template.cs b/src/umbraco.cms/businesslogic/template/Template.cs index a87488768c..f8a00f842e 100644 --- a/src/umbraco.cms/businesslogic/template/Template.cs +++ b/src/umbraco.cms/businesslogic/template/Template.cs @@ -132,12 +132,12 @@ namespace umbraco.cms.businesslogic.template _mastertemplate = dr.IsNull("master") ? 0 : dr.GetInt("master"); } dr.Close(); + + if (UmbracoSettings.EnableMvcSupport && Template.HasView(this)) + _design = ViewHelper.GetViewFile(this); + else + _design = MasterpageHelper.GetMasterpageFile(this); - // test for masterpages - if (UmbracoSettings.UseAspNetMasterPages) - { - _design = getMasterPageContent(); - } } private bool isMasterPageSyntax(string code) @@ -145,18 +145,6 @@ namespace umbraco.cms.businesslogic.template return code.Contains("<%@ Master") || code.Contains("") + 3).Trim(Environment.NewLine.ToCharArray()); - if (UmbracoSettings.UseAspNetMasterPages && isMasterPageSyntax(_design)) - { - SaveMasterPageFile(_design); - SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", - SqlHelper.CreateParameter("@design", value), - SqlHelper.CreateParameter("@id", Id)); + //we only switch to MVC View editing if the template has a view file, and MVC editing is enabled + if (UmbracoSettings.EnableMvcSupport && !isMasterPageSyntax(_design)) + _design = ViewHelper.UpdateViewFile(this); + else if (UmbracoSettings.UseAspNetMasterPages) + _design = MasterpageHelper.UpdateMasterpageFile(this, _oldAlias); + - } - else - SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", - SqlHelper.CreateParameter("@design", value), + SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", + SqlHelper.CreateParameter("@design", _design), SqlHelper.CreateParameter("@id", Id)); } } @@ -331,11 +318,17 @@ namespace umbraco.cms.businesslogic.template public static Template MakeNew(string Name, BusinessLogic.User u, Template master) { - Template t = MakeNew(Name, u); t.MasterTemplate = master.Id; - t.Design = ""; + if (UmbracoSettings.EnableMvcSupport) + ViewHelper.CreateViewFile(t, true); + else + MasterpageHelper.CreateMasterpageFile(t, true); + + + + /* if (UmbracoSettings.UseAspNetMasterPages) { string design = t.getMasterPageHeader() + "\n"; @@ -346,7 +339,7 @@ namespace umbraco.cms.businesslogic.template } t.Design = design; - } + }*/ t.Save(); return t; @@ -367,6 +360,8 @@ namespace umbraco.cms.businesslogic.template if (name.Length > 100) name = name.Substring(0, 95) + "..."; + + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)", SqlHelper.CreateParameter("@nodeId", n.Id), @@ -378,6 +373,12 @@ namespace umbraco.cms.businesslogic.template NewEventArgs e = new NewEventArgs(); t.OnNew(e); + if (UmbracoSettings.EnableMvcSupport) + t._design = ViewHelper.CreateViewFile(t); + else + t._design = MasterpageHelper.CreateMasterpageFile(t); + + return t; } @@ -504,13 +505,17 @@ namespace umbraco.cms.businesslogic.template if (System.IO.File.Exists(MasterPageFile)) System.IO.File.Delete(MasterPageFile); + if (System.IO.File.Exists(Umbraco.Core.IO.IOHelper.MapPath(ViewHelper.ViewPath(this)))) + System.IO.File.Delete(Umbraco.Core.IO.IOHelper.MapPath(ViewHelper.ViewPath(this))); + FireAfterDelete(e); } } - public void SaveAsMasterPage() + [Obsolete("This method, doesnt actually do anything, as the file is created when the design is set", false)] + public void _SaveAsMasterPage() { - SaveMasterPageFile(ConvertToMasterPageSyntax(Design)); + //SaveMasterPageFile(ConvertToMasterPageSyntax(Design)); } public string GetMasterContentElement(int masterTemplateId) @@ -526,7 +531,6 @@ namespace umbraco.cms.businesslogic.template return String.Format("", Alias.Replace(" ", "")); - } public List contentPlaceholderIds() @@ -591,8 +595,13 @@ namespace umbraco.cms.businesslogic.template return masterPageContent; } + + public void ImportDesign(string design) { + Design = design; + + /* if (!isMasterPageSyntax(design)) { Design = ConvertToMasterPageSyntax(design); @@ -600,26 +609,17 @@ namespace umbraco.cms.businesslogic.template else { Design = design; - } + }*/ } - private string getMasterPageHeader() - { - return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>", - currentMasterTemplateFileName()) + Environment.NewLine; - } - - private string currentMasterTemplateFileName() - { - if (MasterTemplate != 0) - return SystemDirectories.Masterpages + "/" + new Template(MasterTemplate).Alias.Replace(" ", "") + ".master"; - else - return UmbracoMasterTemplate; - } - public void SaveMasterPageFile(string masterPageContent) { + //this will trigger the helper and store everything + this.Design = masterPageContent; + + /* + // Add header to master page if it doesn't exist if (!masterPageContent.StartsWith("<%@")) { @@ -681,6 +681,21 @@ namespace umbraco.cms.businesslogic.template // save the file in UTF-8 File.WriteAllText(MasterPageFile, masterPageContent, System.Text.Encoding.UTF8); + * */ + } + + private string getMasterPageHeader() + { + return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>", + currentMasterTemplateFileName()) + Environment.NewLine; + } + + private string currentMasterTemplateFileName() + { + if (MasterTemplate != 0) + return SystemDirectories.Masterpages + "/" + new Template(MasterTemplate).Alias.Replace(" ", "") + ".master"; + else + return UmbracoMasterTemplate; } private void getAspNetMasterPageForm(ref string design) @@ -802,12 +817,18 @@ namespace umbraco.cms.businesslogic.template } t.Alias = alias; - t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design"))); return t; } + public static bool HasView(Template t) + { + var path = Umbraco.Core.IO.SystemDirectories.MvcViews + "/" + t.Alias.Replace(" ", "") + ".cshtml"; + return System.IO.File.Exists(Umbraco.Core.IO.IOHelper.MapPath(path)); + } + + #region Events //EVENTS /// diff --git a/src/umbraco.cms/businesslogic/template/ViewHelper.cs b/src/umbraco.cms/businesslogic/template/ViewHelper.cs new file mode 100644 index 0000000000..c3e9306b5e --- /dev/null +++ b/src/umbraco.cms/businesslogic/template/ViewHelper.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Umbraco.Core.IO; + +namespace umbraco.cms.businesslogic.template +{ + class ViewHelper + { + internal static string GetViewFile(Template t) + { + string viewContent = ""; + string path = IOHelper.MapPath(ViewPath(t)); + + if (File.Exists(path)) + { + System.IO.TextReader tr = new StreamReader(path); + viewContent = tr.ReadToEnd(); + tr.Close(); + } + + return viewContent; + } + + internal static string CreateViewFile(Template t, bool overWrite = false) + { + string viewContent = ""; + string path = IOHelper.MapPath(ViewPath(t)); + + if (!File.Exists(path) || overWrite) + viewContent = saveTemplateToFile(t, t.Alias); + else + { + System.IO.TextReader tr = new StreamReader(path); + viewContent = tr.ReadToEnd(); + tr.Close(); + } + + return viewContent; + } + + internal static string saveTemplateToFile(Template template, string currentAlias) + { + var design = EnsureInheritedLayout(template); + System.IO.File.WriteAllText(IOHelper.MapPath(ViewPath(template)), design, Encoding.UTF8); + + return template.Design; + } + + internal static string UpdateViewFile(Template t) + { + var path = IOHelper.MapPath(ViewPath(t)); + System.IO.File.WriteAllText(path, t.Design, Encoding.UTF8); + return t.Design; + } + + public static string ViewPath(Template t) + { + return Umbraco.Core.IO.SystemDirectories.MvcViews + "/" + t.Alias.Replace(" ", "") + ".cshtml"; + } + + + + private static string EnsureInheritedLayout(Template template) + { + string design = template.Design; + + if (string.IsNullOrEmpty(design)) + { + design = @"@inherits Umbraco.Web.Mvc.RenderViewPage +@{ + Layout = null; +}"; + + if (template.MasterTemplate > 0) + design = design.Replace("null", "\"" + new Template(template.MasterTemplate).Alias.Replace(" ", "") + "\""); + + } + + return design; + } + } +} diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj index e293cc1585..1db1c56de3 100644 --- a/src/umbraco.cms/umbraco.cms.csproj +++ b/src/umbraco.cms/umbraco.cms.csproj @@ -261,6 +261,8 @@ + + diff --git a/src/umbraco.editorControls/XPathCheckBoxList/XPathCheckBoxList.cs b/src/umbraco.editorControls/XPathCheckBoxList/XPathCheckBoxList.cs new file mode 100644 index 0000000000..b15a91eb71 --- /dev/null +++ b/src/umbraco.editorControls/XPathCheckBoxList/XPathCheckBoxList.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using umbraco.NodeFactory; + +namespace umbraco.editorControls.XPathCheckBoxList +{ + public class XPathCheckBoxList : uQuery.IGetProperty + { + public XPathCheckBoxList() + { + } + + void uQuery.IGetProperty.LoadPropertyValue(string value) + { + this.SelectedNodes = uQuery.GetNodesByXml(value); + } + + public IEnumerable SelectedNodes + { + get; + private set; + } + } +} diff --git a/src/umbraco.editorControls/umbraco.editorControls.csproj b/src/umbraco.editorControls/umbraco.editorControls.csproj index 6fd470981f..67ce867795 100644 --- a/src/umbraco.editorControls/umbraco.editorControls.csproj +++ b/src/umbraco.editorControls/umbraco.editorControls.csproj @@ -415,6 +415,7 @@ +