Refactors how macros are stored in the DB

This commit is contained in:
Shannon
2018-05-01 12:12:26 +10:00
parent 1bdf064437
commit 459479a7b8
31 changed files with 592 additions and 653 deletions

View File

@@ -19,7 +19,7 @@ namespace Umbraco.Core.Events
/// <summary>
/// Filename, file path, fully qualified class name, or other key used by the macro engine to do it's processing of the faulting macro.
/// </summary>
public string ItemKey { get; set; }
public string MacroSource { get; set; }
/// <summary>
/// Exception raised.

View File

@@ -118,9 +118,10 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}");
Chain<AddVariationTables1A>("{66B6821A-0DE3-4DF8-A6A4-65ABD211EDDE}");
Chain<AddVariationTables2>("{49506BAE-CEBB-4431-A1A6-24AD6EBBBC57}");
Chain<RefactorMacroColumns>("{083A9894-903D-41B7-B6B3-9EAF2D4CCED0}");
// must chain to v8 final state (see at end of file)
Chain("{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
Chain("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
// UPGRADE FROM 7, MORE RECENT
@@ -209,10 +210,12 @@ namespace Umbraco.Core.Migrations.Upgrade
// however, need to take care of ppl in post-AddVariationTables1 state
Add<AddVariationTables1A>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}", "{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
Chain<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
// FINAL STATE - MUST MATCH LAST ONE ABOVE !
// whenever this changes, update all references in this file!
Add(string.Empty, "{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}");
Add(string.Empty, "{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
}
}
}

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
//now we need to update the new column with some values because this column doesn't allow NULL values
Update.Table(ContentVersionCultureVariationDto.TableName).Set(new {date = DateTime.Now}).AllRows().Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls) Database.Execute(sql);
foreach (var sql in sqls) Execute.Sql(sql).Do();
// name, languageId are now non-nullable
AlterColumn<ContentVersionCultureVariationDto>(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation, "name");

View File

@@ -0,0 +1,43 @@
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class RefactorMacroColumns : MigrationBase
{
public RefactorMacroColumns(IMigrationContext context)
: base(context)
{ }
public override void Migrate()
{
if (ColumnExists(Constants.DatabaseSchema.Tables.Macro, "macroXSLT"))
{
//special trick to add the column without constraints and return the sql to add them later
AddColumn<MacroDto>("macroType", out var sqls1);
//now we need to update the new column with some values because this column doesn't allow NULL values
Update.Table(Constants.DatabaseSchema.Tables.Macro).Set(new { macroType = (int)MacroTypes.Unknown}).AllRows().Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls1) Execute.Sql(sql).Do();
//special trick to add the column without constraints and return the sql to add them later
AddColumn<MacroDto>("macroSource", out var sqls2);
//populate the new macroSource column with legacy data
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroXSLT, macroType = {(int)MacroTypes.Unknown} WHERE macroXSLT IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroScriptAssembly, macroType = {(int)MacroTypes.Unknown} WHERE macroScriptAssembly IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroScriptType, macroType = {(int)MacroTypes.UserControl} WHERE macroScriptType IS NOT NULL").Do();
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.Macro} SET macroSource = macroPython, macroType = {(int)MacroTypes.PartialView} WHERE macroPython IS NOT NULL").Do();
//now apply constraints (NOT NULL) to new table
foreach (var sql in sqls2) Execute.Sql(sql).Do();
//now remove these old columns
Delete.Column("macroXSLT").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroScriptAssembly").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroScriptType").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
Delete.Column("macroPython").FromTable(Constants.DatabaseSchema.Tables.Macro).Do();
}
}
}
}

View File

@@ -51,20 +51,19 @@ namespace Umbraco.Core.Models
/// </summary>
[DataMember]
bool DontRender { get; set; }
/// <summary>
/// Gets or sets the path to user control or the Control Type to render
/// Gets or set the path to the macro source to render
/// </summary>
[DataMember]
string ControlType { get; set; }
string MacroSource { get; set; }
/// <summary>
/// Gets or set the path to the Python file in use
/// Gets or set the macro type
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
string ScriptPath { get; set; }
MacroTypes MacroType { get; set; }
/// <summary>
/// Gets or sets a list of Macro Properties
/// </summary>

View File

@@ -34,12 +34,11 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param>
/// <param name="dontRender"></param>
/// <param name="scriptPath"></param>
public Macro(int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, string controlType, bool cacheByPage, bool cacheByMember, bool dontRender, string scriptPath)
/// <param name="macroSource"></param>
public Macro(int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, bool cacheByPage, bool cacheByMember, bool dontRender, string macroSource, MacroTypes macroType)
: this()
{
Id = id;
@@ -48,11 +47,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
MacroSource = macroSource;
MacroType = macroType;
}
/// <summary>
@@ -62,14 +61,13 @@ namespace Umbraco.Core.Models
/// <param name="cacheDuration"></param>
/// <param name="alias"></param>
/// <param name="name"></param>
/// <param name="controlType"></param>
/// <param name="cacheByPage"></param>
/// <param name="cacheByMember"></param>
/// <param name="dontRender"></param>
/// <param name="scriptPath"></param>
/// <param name="macroSource"></param>
public Macro(string @alias, string name,
string controlType = "",
string scriptPath = "",
string macroSource,
MacroTypes macroType,
bool cacheByPage = false,
bool cacheByMember = false,
bool dontRender = true,
@@ -81,11 +79,11 @@ namespace Umbraco.Core.Models
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
MacroSource = macroSource;
MacroType = macroType;
}
private string _alias;
@@ -95,8 +93,8 @@ namespace Umbraco.Core.Models
private bool _cacheByPage;
private bool _cacheByMember;
private bool _dontRender;
private string _scriptFile;
private string _scriptPath;
private string _macroSource;
private MacroTypes _macroType = MacroTypes.Unknown;
private MacroPropertyCollection _properties;
private List<string> _addedProperties;
private List<string> _removedProperties;
@@ -112,8 +110,8 @@ namespace Umbraco.Core.Models
public readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByPage);
public readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember);
public readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.DontRender);
public readonly PropertyInfo ControlPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlType);
public readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ScriptPath);
public readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.MacroSource);
public readonly PropertyInfo MacroTypeSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroTypes>(x => x.MacroType);
public readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties);
}
@@ -258,24 +256,23 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets or sets the path to user control or the Control Type to render
/// Gets or set the path to the Partial View to render
/// </summary>
[DataMember]
public string ControlType
public string MacroSource
{
get { return _scriptFile; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptFile, Ps.Value.ControlPathSelector); }
}
get { return _macroSource; }
set { SetPropertyValueAndDetectChanges(value, ref _macroSource, Ps.Value.ScriptPathSelector); }
}
/// <summary>
/// Gets or set the path to the Python file in use
/// Gets or set the path to the Partial View to render
/// </summary>
/// <remarks>Optional: Can only be one of three Script, Python or Xslt</remarks>
[DataMember]
public string ScriptPath
public MacroTypes MacroType
{
get { return _scriptPath; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptPath, Ps.Value.ScriptPathSelector); }
get { return _macroType; }
set { SetPropertyValueAndDetectChanges(value, ref _macroType, Ps.Value.MacroTypeSelector); }
}
/// <summary>

View File

@@ -34,10 +34,6 @@ namespace Umbraco.Core.Persistence.Dtos
[NullSetting(NullSetting = NullSettings.Null)]
public string Name { get; set; }
[Column("macroScriptType")]
[NullSetting(NullSetting = NullSettings.Null)]
public string ScriptType { get; set; }
[Column("macroCacheByPage")]
[Constraint(Default = "1")]
public bool CacheByPage { get; set; }
@@ -50,10 +46,13 @@ namespace Umbraco.Core.Persistence.Dtos
[Constraint(Default = "0")]
public bool DontRender { get; set; }
//TODO: Rename this column! - actually please revamp all of the macros! :)
[Column("macroPython")]
[NullSetting(NullSetting = NullSettings.Null)]
public string MacroFilePath { get; set; }
[Column("macroSource")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public string MacroSource { get; set; }
[Column("macroType")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public int MacroType { get; set; }
[ResultColumn]
[Reference(ReferenceType.Many, ReferenceMemberName = "Macro")]

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Factories
{
public IMacro BuildEntity(MacroDto dto)
{
var model = new Macro(dto.Id, dto.UniqueId, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.ScriptType, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.MacroFilePath);
var model = new Macro(dto.Id, dto.UniqueId, dto.UseInEditor, dto.RefreshRate, dto.Alias, dto.Name, dto.CacheByPage, dto.CachePersonalized, dto.DontRender, dto.MacroSource, (MacroTypes)dto.MacroType);
try
{
@@ -40,11 +40,11 @@ namespace Umbraco.Core.Persistence.Factories
CachePersonalized = entity.CacheByMember,
DontRender = entity.DontRender,
Name = entity.Name,
MacroFilePath = entity.ScriptPath,
MacroSource = entity.MacroSource,
RefreshRate = entity.CacheDuration,
ScriptType = entity.ControlType,
UseInEditor = entity.UseInEditor,
MacroPropertyDtos = BuildPropertyDtos(entity)
MacroPropertyDtos = BuildPropertyDtos(entity),
MacroType = (int)entity.MacroType
};
if (entity.HasIdentity)

View File

@@ -18,11 +18,11 @@ namespace Umbraco.Core.Persistence.Mappers
CacheMap<Macro, MacroDto>(src => src.Alias, dto => dto.Alias);
CacheMap<Macro, MacroDto>(src => src.CacheByPage, dto => dto.CacheByPage);
CacheMap<Macro, MacroDto>(src => src.CacheByMember, dto => dto.CachePersonalized);
CacheMap<Macro, MacroDto>(src => src.ControlType, dto => dto.ScriptType);
CacheMap<Macro, MacroDto>(src => src.MacroType, dto => dto.MacroType);
CacheMap<Macro, MacroDto>(src => src.DontRender, dto => dto.DontRender);
CacheMap<Macro, MacroDto>(src => src.Name, dto => dto.Name);
CacheMap<Macro, MacroDto>(src => src.CacheDuration, dto => dto.RefreshRate);
CacheMap<Macro, MacroDto>(src => src.ScriptPath, dto => dto.MacroFilePath);
CacheMap<Macro, MacroDto>(src => src.MacroSource, dto => dto.MacroSource);
CacheMap<Macro, MacroDto>(src => src.UseInEditor, dto => dto.UseInEditor);
}
}

View File

@@ -295,8 +295,8 @@ namespace Umbraco.Core.Services
var xml = new XElement("macro");
xml.Add(new XElement("name", macro.Name));
xml.Add(new XElement("alias", macro.Alias));
xml.Add(new XElement("scriptType", macro.ControlType));
xml.Add(new XElement("scriptingFile", macro.ScriptPath));
xml.Add(new XElement("macroType", macro.MacroType));
xml.Add(new XElement("macroSource", macro.MacroSource));
xml.Add(new XElement("useInEditor", macro.UseInEditor.ToString()));
xml.Add(new XElement("dontRender", macro.DontRender.ToString()));
xml.Add(new XElement("refreshRate", macro.CacheDuration.ToString(CultureInfo.InvariantCulture)));

View File

@@ -25,21 +25,6 @@ namespace Umbraco.Core.Services.Implement
_auditRepository = auditRepository;
}
/// <summary>
/// Returns an enum <see cref="MacroTypes"/> based on the properties on the Macro
/// </summary>
/// <returns><see cref="MacroTypes"/></returns>
internal static MacroTypes GetMacroType(IMacro macro)
{
if (string.IsNullOrEmpty(macro.ScriptPath) == false)
return MacroTypes.PartialView;
if (string.IsNullOrEmpty(macro.ControlType) == false && macro.ControlType.InvariantContains(".ascx"))
return MacroTypes.UserControl;
return MacroTypes.Unknown;
}
/// <summary>
/// Gets an <see cref="IMacro"/> object by its alias
/// </summary>

View File

@@ -1270,8 +1270,8 @@ namespace Umbraco.Core.Services.Implement
{
var macroName = macroElement.Element("name").Value;
var macroAlias = macroElement.Element("alias").Value;
var controlType = macroElement.Element("scriptType").Value;
var scriptPath = macroElement.Element("scriptingFile").Value;
var macroType = Enum<MacroTypes>.Parse(macroElement.Element("macroType").Value);
var macroSource = macroElement.Element("macroSource").Value;
//Following xml elements are treated as nullable properties
var useInEditorElement = macroElement.Element("useInEditor");
@@ -1306,7 +1306,7 @@ namespace Umbraco.Core.Services.Implement
}
var existingMacro = _macroService.GetByAlias(macroAlias) as Macro;
var macro = existingMacro ?? new Macro(macroAlias, macroName, controlType, scriptPath,
var macro = existingMacro ?? new Macro(macroAlias, macroName, macroSource, macroType,
cacheByPage, cacheByMember, dontRender, useInEditor, cacheDuration);
var properties = macroElement.Element("properties");

View File

@@ -329,6 +329,7 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypeMigration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\LanguageColumns.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\PropertyEditorsMigration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\RefactorMacroColumns.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\SuperZero.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\TagsMigration.cs" />
<Compile Include="Models\AuditEntry.cs" />

View File

@@ -53,7 +53,7 @@ namespace Umbraco.Tests.Macros
{
Name = "test",
Alias = "test",
ScriptName = "~/usercontrols/menu.ascx"
MacroSource = "~/usercontrols/menu.ascx"
};
macroModel.Properties.Add(new MacroPropertyModel(macroPropName, val));
@@ -77,8 +77,7 @@ namespace Umbraco.Tests.Macros
var model = new MacroModel
{
MacroType = macroType,
ScriptName = "anything",
TypeName = "anything"
MacroSource = "anything"
};
var filename = MacroRenderer.GetMacroFileName(model);
if (expectedNonNull)

View File

@@ -20,7 +20,7 @@ namespace Umbraco.Tests.Models
[Test]
public void Can_Deep_Clone()
{
var macro = new Macro(1, Guid.NewGuid(), true, 3, "test", "Test", "blah", false, true, true, "script");
var macro = new Macro(1, Guid.NewGuid(), true, 3, "test", "Test", false, true, true, "~/script.cshtml", MacroTypes.PartialView);
macro.Properties.Add(new MacroProperty(6, Guid.NewGuid(), "rewq", "REWQ", 1, "asdfasdf"));
var clone = (Macro)macro.DeepClone();

View File

@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
var macro = new Macro("test1", "Test", "~/usercontrol/blah.ascx", "~/views/macropartials/test.cshtml");
var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView);
;
Assert.Throws<SqlCeException>(() => repository.Save(macro));
@@ -94,11 +94,10 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(macro.Alias, Is.EqualTo("test1"));
Assert.That(macro.CacheByPage, Is.EqualTo(false));
Assert.That(macro.CacheByMember, Is.EqualTo(false));
Assert.That(macro.ControlType, Is.EqualTo("~/usercontrol/test1.ascx"));
Assert.That(macro.DontRender, Is.EqualTo(true));
Assert.That(macro.Name, Is.EqualTo("Test1"));
Assert.That(macro.CacheDuration, Is.EqualTo(0));
Assert.That(macro.ScriptPath, Is.EqualTo("~/views/macropartials/test1.cshtml"));
Assert.That(macro.MacroSource, Is.EqualTo("~/views/macropartials/test1.cshtml"));
Assert.That(macro.UseInEditor, Is.EqualTo(false));
}
@@ -169,7 +168,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
// Act
var macro = new Macro("test", "Test", "~/usercontrol/blah.ascx", "~/views/macropartials/test.cshtml");
var macro = new Macro("test", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView);
macro.Properties.Add(new MacroProperty("test", "Test", 0, "test"));
repository.Save(macro);
@@ -195,9 +194,8 @@ namespace Umbraco.Tests.Persistence.Repositories
macro.CacheDuration = 1234;
macro.CacheByPage = true;
macro.CacheByMember = true;
macro.ControlType = "";
macro.DontRender = false;
macro.ScriptPath = "~/newpath.cshtml";
macro.MacroSource = "~/newpath.cshtml";
macro.UseInEditor = true;
repository.Save(macro);
@@ -210,9 +208,8 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.That(macroUpdated.CacheDuration, Is.EqualTo(1234));
Assert.That(macroUpdated.CacheByPage, Is.EqualTo(true));
Assert.That(macroUpdated.CacheByMember, Is.EqualTo(true));
Assert.That(macroUpdated.ControlType, Is.EqualTo(""));
Assert.That(macroUpdated.DontRender, Is.EqualTo(false));
Assert.That(macroUpdated.ScriptPath, Is.EqualTo("~/newpath.cshtml"));
Assert.That(macroUpdated.MacroSource, Is.EqualTo("~/newpath.cshtml"));
Assert.That(macroUpdated.UseInEditor, Is.EqualTo(true));
}
}
@@ -293,7 +290,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "~/views/macropartials/test1.cshtml");
var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView);
macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor"));
repository.Save(macro);
@@ -318,7 +315,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "~/views/macropartials/test1.cshtml");
var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView);
macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor"));
repository.Save(macro);
@@ -342,7 +339,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
var macro = new Macro("newmacro", "A new macro", "~/usercontrol/test1.ascx", "~/views/macropartials/test1.cshtml");
var macro = new Macro("newmacro", "A new macro", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView);
var prop1 = new MacroProperty("blah1", "New1", 4, "test.editor");
var prop2 = new MacroProperty("blah2", "New2", 3, "test.editor");
@@ -428,9 +425,9 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
repository.Save(new Macro("test1", "Test1", "~/usercontrol/test1.ascx", "~/views/macropartials/test1.cshtml"));
repository.Save(new Macro("test2", "Test2", "~/usercontrol/test2.ascx", "~/views/macropartials/test2.cshtml"));
repository.Save(new Macro("test3", "Tet3", "~/usercontrol/test3.ascx", "~/views/macropartials/test3.cshtml"));
repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView));
repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView));
repository.Save(new Macro("test3", "Tet3", "~/views/macropartials/test3.cshtml", MacroTypes.PartialView));
scope.Complete();
}

View File

@@ -28,9 +28,9 @@ namespace Umbraco.Tests.Services
{
var repository = new MacroRepository((IScopeAccessor) provider, CacheHelper.CreateDisabledCacheHelper(), Mock.Of<ILogger>());
repository.Save(new Macro("test1", "Test1", "~/usercontrol/test1.ascx", "~/views/macropartials/test1.cshtml"));
repository.Save(new Macro("test2", "Test2", "~/usercontrol/test2.ascx", "~/views/macropartials/test2.cshtml"));
repository.Save(new Macro("test3", "Tet3", "~/usercontrol/test3.ascx", "~/views/macropartials/test3.cshtml"));
repository.Save(new Macro("test1", "Test1", "~/views/macropartials/test1.cshtml", MacroTypes.PartialView));
repository.Save(new Macro("test2", "Test2", "~/views/macropartials/test2.cshtml", MacroTypes.PartialView));
repository.Save(new Macro("test3", "Tet3", "~/views/macropartials/test3.cshtml", MacroTypes.PartialView));
scope.Complete();
}
}
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Services
var macroService = ServiceContext.MacroService;
// Act
var macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
var macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
macroService.Save(macro);
//assert
@@ -85,13 +85,13 @@ namespace Umbraco.Tests.Services
var result = macroService.GetById(macro.Id);
Assert.AreEqual("test", result.Alias);
Assert.AreEqual("Test", result.Name);
Assert.AreEqual("~/Views/MacroPartials/Test.cshtml", result.ScriptPath);
Assert.AreEqual("~/Views/MacroPartials/Test.cshtml", result.MacroSource);
Assert.AreEqual(1234, result.CacheDuration);
result = macroService.GetById(macro.Key);
Assert.AreEqual("test", result.Alias);
Assert.AreEqual("Test", result.Name);
Assert.AreEqual("~/Views/MacroPartials/Test.cshtml", result.ScriptPath);
Assert.AreEqual("~/Views/MacroPartials/Test.cshtml", result.MacroSource);
Assert.AreEqual(1234, result.CacheDuration);
}
@@ -100,7 +100,7 @@ namespace Umbraco.Tests.Services
{
// Arrange
var macroService = ServiceContext.MacroService;
var macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
var macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
macroService.Save(macro);
// Act
@@ -119,7 +119,7 @@ namespace Umbraco.Tests.Services
{
// Arrange
var macroService = ServiceContext.MacroService;
IMacro macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
IMacro macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
macroService.Save(macro);
// Act
@@ -143,7 +143,7 @@ namespace Umbraco.Tests.Services
{
// Arrange
var macroService = ServiceContext.MacroService;
IMacro macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
IMacro macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
macro.Properties.Add(new MacroProperty("blah", "Blah", 0, "blah"));
macroService.Save(macro);
@@ -174,7 +174,7 @@ namespace Umbraco.Tests.Services
{
// Arrange
var macroService = ServiceContext.MacroService;
IMacro macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
IMacro macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
macro.Properties.Add(new MacroProperty("blah1", "Blah1", 0, "blah1"));
macro.Properties.Add(new MacroProperty("blah2", "Blah2", 1, "blah2"));
macro.Properties.Add(new MacroProperty("blah3", "Blah3", 2, "blah3"));
@@ -218,7 +218,7 @@ namespace Umbraco.Tests.Services
public void Can_Add_And_Remove_Properties()
{
var macroService = ServiceContext.MacroService;
var macro = new Macro("test", "Test", scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
var macro = new Macro("test", "Test", "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
//adds some properties
macro.Properties.Add(new MacroProperty("blah1", "Blah1", 0, "blah1"));
@@ -253,7 +253,7 @@ namespace Umbraco.Tests.Services
{
// Arrange
var macroService = ServiceContext.MacroService;
var macro = new Macro("test", string.Empty, scriptPath: "~/Views/MacroPartials/Test.cshtml", cacheDuration: 1234);
var macro = new Macro("test", string.Empty, "~/Views/MacroPartials/Test.cshtml", MacroTypes.PartialView, cacheDuration: 1234);
// Act & Assert
Assert.Throws<ArgumentException>(() => macroService.Save(macro));

View File

@@ -23,7 +23,7 @@ namespace Umbraco.Tests.Services
public void PackagingService_Can_Export_Macro()
{
// Arrange
var macro = new Macro("test1", "Test", "~/usercontrol/blah.ascx", "~/views/macropartials/test.cshtml");
var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView);
ServiceContext.MacroService.Save(macro);
// Act

View File

@@ -1,63 +1,287 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Umbraco.Core.IO;
using System.Web.UI.HtmlControls;
using System.IO;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using umbraco.cms.presentation.Trees;
using System.Linq;
using Umbraco.Web.UI;
using Umbraco.Web.UI.Pages;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.Composing;
using Umbraco.Web._Legacy.Controls;
namespace Umbraco.Web.UI.Umbraco.Developer.Macros
{
public partial class EditMacro : global::umbraco.cms.presentation.developer.editMacro
{
public partial class EditMacro : UmbracoEnsuredPage
{
public EditMacro()
{
CurrentApp = Constants.Applications.Developer.ToString();
}
protected PlaceHolder Buttons;
protected Table MacroElements;
public TabPage InfoTabPage;
public TabPage Parameters;
private IMacro _macro;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
base.OnLoad(e);
_macro = Services.MacroService.GetById(Convert.ToInt32(Request.QueryString["macroID"]));
PopulatePartialViewFiles();
}
/// <summary>
/// This ensures that the SelectedPartialView txt box value is set correctly when the m_macro object's
/// ScriptingFile property contains a full virtual path beginning with the MacroPartials path
/// </summary>
/// <param name="macro"> </param>
/// <param name="macroAssemblyValue"></param>
/// <param name="macroTypeValue"></param>
protected override void PopulateFieldsOnLoad(IMacro macro, string macroTypeValue)
{
base.PopulateFieldsOnLoad(macro, macroTypeValue);
//check if the ScriptingFile property contains the MacroPartials path
if (macro.ScriptPath.IsNullOrWhiteSpace() == false &&
(macro.ScriptPath.StartsWith(SystemDirectories.MvcViews + "/MacroPartials/")
|| (Regex.IsMatch(macro.ScriptPath, "~/App_Plugins/.+?/Views/MacroPartials", RegexOptions.Compiled))))
if (IsPostBack == false)
{
SelectedPartialView.Text = macro.ScriptPath;
ClientTools
.SyncTree("-1," + _macro.Id, false);
PopulateFieldsOnLoad(_macro);
// Load elements from macro
MacroPropertyBind();
PopulatePartialViewFiles();
// Load usercontrols
PopulateUserControls(IOHelper.MapPath(SystemDirectories.UserControls));
userControlList.Items.Insert(0, new ListItem("Browse usercontrols on server...", string.Empty));
}
}
/// <summary>
/// This changes the macro type to a PartialViewMacro if the SelectedPartialView txt box has a value.
/// This then also updates the file path saved for the partial view to be the full virtual path, not just the file name.
/// Populates the control (textbox) values on page load
/// </summary>
/// <param name="macro"> </param>
/// <param name="macroCachePeriod"></param>
/// <param name="macroAssemblyValue"></param>
/// <param name="macroTypeValue"></param>
protected override void SetMacroValuesFromPostBack(IMacro macro, int macroCachePeriod, string macroTypeValue)
/// <param name="macro"></param>
protected void PopulateFieldsOnLoad(IMacro macro)
{
base.SetMacroValuesFromPostBack(macro, macroCachePeriod, macroTypeValue);
if (!SelectedPartialView.Text.IsNullOrWhiteSpace())
{
macro.ScriptPath = SelectedPartialView.Text;
}
macroName.Text = macro.Name;
macroAlias.Text = macro.Alias;
macroKey.Text = macro.Key.ToString();
cachePeriod.Text = macro.CacheDuration.ToInvariantString();
macroRenderContent.Checked = macro.DontRender == false;
macroEditor.Checked = macro.UseInEditor;
cacheByPage.Checked = macro.CacheByPage;
cachePersonalized.Checked = macro.CacheByMember;
macroUserControl.Text = macro.MacroType == MacroTypes.UserControl ? macro.MacroSource : null;
SelectedPartialView.Text = macro.MacroType == MacroTypes.PartialView ? macro.MacroSource : null;
}
/// <summary>
/// Sets the values on the Macro object from the values posted back before saving the macro
/// </summary>
protected void SetMacroValuesFromPostBack(IMacro macro, int macroCachePeriod, string userControlValue, string partialViewValue)
{
macro.UseInEditor = macroEditor.Checked;
macro.DontRender = macroRenderContent.Checked == false;
macro.CacheByPage = cacheByPage.Checked;
macro.CacheByMember = cachePersonalized.Checked;
macro.CacheDuration = macroCachePeriod;
macro.Alias = macroAlias.Text;
macro.Name = macroName.Text;
macro.MacroSource = !userControlValue.IsNullOrWhiteSpace() ? userControlValue : partialViewValue;
macro.MacroType = !userControlValue.IsNullOrWhiteSpace() ? MacroTypes.UserControl : !partialViewValue.IsNullOrWhiteSpace() ? MacroTypes.PartialView : MacroTypes.Unknown;
}
public void DeleteMacroProperty(object sender, EventArgs e)
{
var macroPropertyId = (HtmlInputHidden)((Control)sender).Parent.FindControl("macroPropertyID");
var property = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
_macro.Properties.Remove(property);
Services.MacroService.Save(_macro);
MacroPropertyBind();
}
public void MacroPropertyBind()
{
macroProperties.DataSource = _macro.Properties.OrderBy(x => x.SortOrder);
macroProperties.DataBind();
}
public object CheckNull(object test)
{
return Convert.IsDBNull(test) ? 0 : test;
}
protected IEnumerable<IDataEditor> GetMacroParameterEditors()
{
// we need to show the depracated ones for backwards compatibility
// FIXME not managing deprecated here?!
return Current.ParameterEditors;
}
public void macroPropertyCreate(object sender, EventArgs e)
{
//enable add validators
var val1 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator1");
var val2 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator4");
var val3 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator5");
val1.Enabled = true;
val2.Enabled = true;
val3.Enabled = true;
Page.Validate();
if (Page.IsValid == false)
{
return;
}
var macroPropertyAliasNew = (TextBox)((Control)sender).Parent.FindControl("macroPropertyAliasNew");
var macroPropertyNameNew = (TextBox)((Control)sender).Parent.FindControl("macroPropertyNameNew");
var macroPropertyTypeNew = (DropDownList)((Control)sender).Parent.FindControl("macroPropertyTypeNew");
if (macroPropertyAliasNew.Text != Services.TextService.Localize("general/new") + " " + Services.TextService.Localize("general/alias"))
{
if (_macro.Properties.ContainsKey(macroPropertyAliasNew.Text.Trim()))
{
//don't continue
return;
}
_macro.Properties.Add(new MacroProperty(
macroPropertyAliasNew.Text.Trim(),
macroPropertyNameNew.Text.Trim(),
_macro.Properties.Any() ? _macro.Properties.Max(x => x.SortOrder) + 1 : 0,
macroPropertyTypeNew.SelectedValue));
Services.MacroService.Save(_macro);
MacroPropertyBind();
}
}
public bool macroIsVisible(object isChecked)
{
return Convert.ToBoolean(isChecked);
}
public void AddChooseList(object sender, EventArgs e)
{
if (IsPostBack == false)
{
var dropDown = (DropDownList)sender;
dropDown.Items.Insert(0, new ListItem("Choose...", string.Empty));
}
}
private void PopulateUserControls(string path)
{
var directoryInfo = new DirectoryInfo(path);
if (directoryInfo.Exists == false) return;
var rootDir = IOHelper.MapPath(SystemDirectories.UserControls);
foreach (var uc in directoryInfo.GetFiles("*.ascx"))
{
userControlList.Items.Add(
new ListItem(SystemDirectories.UserControls +
uc.FullName.Substring(rootDir.Length).Replace(IOHelper.DirSepChar, '/')));
}
foreach (var dir in directoryInfo.GetDirectories())
PopulateUserControls(dir.FullName);
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
EnsureChildControls();
}
protected override void CreateChildControls()
{
base.CreateChildControls();
// Tab setup
InfoTabPage = TabView1.NewTabPage("Macro Properties");
InfoTabPage.Controls.Add(Pane1);
InfoTabPage.Controls.Add(Pane1_2);
InfoTabPage.Controls.Add(Pane1_3);
InfoTabPage.Controls.Add(Pane1_4);
Parameters = TabView1.NewTabPage("Parameters");
Parameters.Controls.Add(Panel2);
var save = TabView1.Menu.NewButton();
save.ButtonType = MenuButtonType.Primary;
save.Text = Services.TextService.Localize("save");
save.ID = "save";
save.Click += Save_Click;
}
void Save_Click(object sender, EventArgs e)
{
Page.Validate();
ClientTools
.SyncTree("-1," + _macro.Id.ToInvariantString(), true); //true forces the reload
var tempCachePeriod = cachePeriod.Text;
if (tempCachePeriod == string.Empty)
tempCachePeriod = "0";
SetMacroValuesFromPostBack(_macro, Convert.ToInt32(tempCachePeriod), macroUserControl.Text, SelectedPartialView.Text);
// save elements
// this is oh so completely broken
var aliases = new Dictionary<string, string>();
foreach (RepeaterItem item in macroProperties.Items)
{
var macroPropertyId = (HtmlInputHidden)item.FindControl("macroPropertyID");
var macroElementName = (TextBox)item.FindControl("macroPropertyName");
var macroElementAlias = (TextBox)item.FindControl("macroPropertyAlias");
var macroElementSortOrder = (TextBox)item.FindControl("macroPropertySortOrder");
var macroElementType = (DropDownList)item.FindControl("macroPropertyType");
var prop = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
var sortOrder = 0;
int.TryParse(macroElementSortOrder.Text, out sortOrder);
var alias = macroElementAlias.Text.Trim();
if (prop.Alias != alias) // changing the alias
{
// use a temp alias to avoid collision if eg swapping aliases
var tempAlias = Guid.NewGuid().ToString("N").Substring(0, 8);
aliases[tempAlias] = alias;
alias = tempAlias;
}
_macro.Properties.UpdateProperty(
prop.Alias,
macroElementName.Text.Trim(),
sortOrder,
macroElementType.SelectedValue,
alias);
}
// now apply the real aliases, should not collide
foreach (var kvp in aliases)
_macro.Properties.UpdateProperty(kvp.Key, newAlias: kvp.Value);
Services.MacroService.Save(_macro);
ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Save, "Macro saved", "");
MacroPropertyBind();
}
/// <summary>
/// Populate the drop down list for partial view files
/// </summary>

View File

@@ -37,6 +37,186 @@ namespace Umbraco.Web.UI.Umbraco.Developer.Macros {
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.DropDownList PartialViewList;
protected global::System.Web.UI.WebControls.DropDownList PartialViewList;
/// <summary>
/// TabView1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.TabView TabView1;
/// <summary>
/// Pane1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1;
/// <summary>
/// macroPane control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable macroPane;
/// <summary>
/// macroName control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroName;
/// <summary>
/// macroAlias control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroAlias;
/// <summary>
/// macroAlias control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Label macroKey;
/// <summary>
/// Pane1_2 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_2;
/// <summary>
/// macroUserControl control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroUserControl;
/// <summary>
/// userControlList control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.DropDownList userControlList;
/// <summary>
/// Pane1_3 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_3;
/// <summary>
/// Table1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable Table1;
/// <summary>
/// macroEditor control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox macroEditor;
/// <summary>
/// macroRenderContent control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox macroRenderContent;
/// <summary>
/// Pane1_4 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_4;
/// <summary>
/// Table3 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable Table3;
/// <summary>
/// cachePeriod control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox cachePeriod;
/// <summary>
/// cacheByPage control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox cacheByPage;
/// <summary>
/// cachePersonalized control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox cachePersonalized;
/// <summary>
/// Panel2 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Panel2;
/// <summary>
/// macroProperties control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Repeater macroProperties;
}
}

View File

@@ -143,7 +143,7 @@ namespace Umbraco.Web.Editors
{
Alias = macroName.ToSafeAlias(),
Name = macroName,
ScriptPath = model.VirtualPath.EnsureStartsWith("~")
MacroSource = model.VirtualPath.EnsureStartsWith("~")
};
Services.MacroService.Save(macro); // may throw

View File

@@ -19,13 +19,7 @@ namespace Umbraco.Web.Macros
public MacroTypes MacroType { get; set; }
public string TypeName { get; set; }
public string ScriptName { get; set; }
public string ScriptCode { get; set; }
public string ScriptLanguage { get; set; }
public string MacroSource { get; set; }
public int CacheDuration { get; set; }
@@ -49,8 +43,8 @@ namespace Umbraco.Web.Macros
Id = macro.Id;
Name = macro.Name;
Alias = macro.Alias;
TypeName = macro.ControlType;
ScriptName = macro.ScriptPath;
MacroType = macro.MacroType;
MacroSource = macro.MacroSource;
CacheDuration = macro.CacheDuration;
CacheByPage = macro.CacheByPage;
CacheByMember = macro.CacheByMember;
@@ -59,8 +53,7 @@ namespace Umbraco.Web.Macros
foreach (var prop in macro.Properties)
Properties.Add(new MacroPropertyModel(prop.Alias, string.Empty, prop.EditorAlias));
// can convert enums
MacroType = MacroService.GetMacroType(macro);
MacroType = macro.MacroType;
}
}
}

View File

@@ -46,9 +46,7 @@ namespace Umbraco.Web.Macros
{
var id = new StringBuilder();
var alias = string.IsNullOrEmpty(model.ScriptCode)
? model.Alias
: GenerateCacheKeyFromCode(model.ScriptCode);
var alias = model.Alias;
id.AppendFormat("{0}-", alias);
if (model.CacheByPage)
@@ -173,10 +171,8 @@ namespace Umbraco.Web.Macros
switch (model.MacroType)
{
case MacroTypes.PartialView:
filename = model.ScriptName; //partial views are saved with their full virtual path
break;
case MacroTypes.UserControl:
filename = model.TypeName; //user controls are saved with their full virtual path
filename = model.MacroSource; //user controls & partial views are saved with their full virtual path
break;
default:
// not file-based, or not supported
@@ -314,7 +310,7 @@ namespace Umbraco.Web.Macros
{
Name = macro.Name,
Alias = macro.Alias,
ItemKey = macro.ScriptName,
MacroSource = macro.MacroSource,
Exception = e,
Behaviour = UmbracoConfig.For.UmbracoSettings().Content.MacroErrorBehaviour
};
@@ -362,17 +358,17 @@ namespace Umbraco.Web.Macros
{
case MacroTypes.PartialView:
return ExecuteMacroWithErrorWrapper(model,
$"Executing PartialView: TypeName=\"{model.TypeName}\", ScriptName=\"{model.ScriptName}\".",
$"Executing PartialView: MacroSource=\"{model.MacroSource}\".",
"Executed PartialView.",
() => ExecutePartialView(model),
() => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.ScriptName }));
() => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource }));
case MacroTypes.UserControl:
return ExecuteMacroWithErrorWrapper(model,
$"Loading UserControl: TypeName=\"{model.TypeName}\".",
$"Loading UserControl: MacroSource=\"{model.MacroSource}\".",
"Loaded UserControl.",
() => ExecuteUserControl(model),
() => textService.Localize("errors/macroErrorLoadingUsercontrol", new[] { model.TypeName }));
() => textService.Localize("errors/macroErrorLoadingUsercontrol", new[] { model.MacroSource }));
//case MacroTypes.Script:
default:
@@ -418,9 +414,9 @@ namespace Umbraco.Web.Macros
public static MacroContent ExecuteUserControl(MacroModel macro)
{
// add tilde for v4 defined macros
if (string.IsNullOrEmpty(macro.TypeName) == false
&& macro.TypeName.StartsWith("~") == false)
macro.TypeName = "~/" + macro.TypeName;
if (string.IsNullOrEmpty(macro.MacroSource) == false
&& macro.MacroSource.StartsWith("~") == false)
macro.MacroSource = "~/" + macro.MacroSource;
var engine = new UserControlMacroEngine();
return engine.Execute(macro);

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Web.Macros
_macro.Alias,
_macro.Name,
_macro.Properties.ToDictionary(x => x.Key, x => (object)x.Value));
return PartialView(_macro.ScriptName, model);
return PartialView(_macro.MacroSource, model);
}
}
}

View File

@@ -65,7 +65,7 @@ namespace Umbraco.Web.Macros
{
if (macro == null) throw new ArgumentNullException(nameof(macro));
if (content == null) throw new ArgumentNullException(nameof(content));
if (macro.ScriptName.IsNullOrWhiteSpace()) throw new ArgumentException("The ScriptName property of the macro object cannot be null or empty");
if (macro.MacroSource.IsNullOrWhiteSpace()) throw new ArgumentException("The MacroSource property of the macro object cannot be null or empty");
var http = _getHttpContext();
var umbCtx = _getUmbracoContext();

View File

@@ -14,7 +14,7 @@ namespace Umbraco.Web.Macros
{
public MacroContent Execute(MacroModel model)
{
var filename = model.TypeName;
var filename = model.MacroSource;
// ensure the file exists
var path = IOHelper.FindFile(filename);

View File

@@ -1150,9 +1150,6 @@
<Compile Include="umbraco.presentation\umbraco\Default.aspx.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="umbraco.presentation\umbraco\developer\Macros\editMacro.aspx.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="umbraco.presentation\umbraco\dialogs\umbracoField.aspx.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>

View File

@@ -132,13 +132,8 @@ namespace umbraco.cms.businesslogic.packager
if (appendFile)
{
//TODO: Clearly the packager hasn't worked very well for packaging Partial Views to date since there is no logic in here for that
//if (!string.IsNullOrEmpty(mcr.ScriptingFile))
// AppendFileToManifest(IOHelper.ResolveUrl(SystemDirectories.MacroScripts) + "/" + mcr.ScriptingFile, packageDirectory, doc);
if (!string.IsNullOrEmpty(mcr.ControlType))
AppendFileToManifest(mcr.ControlType, packageDirectory, doc);
if (!string.IsNullOrEmpty(mcr.MacroSource))
AppendFileToManifest(mcr.MacroSource, packageDirectory, doc);
}
var serializer = new EntityXmlSerializer();

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Web
var macro = Current.Services.MacroService.GetByAlias(Alias);
if (macro == null)
{
macro = new Macro(Alias, Alias);
macro = new Macro(Alias, Alias, string.Empty, MacroTypes.Unknown);
Current.Services.MacroService.Save(macro);
}
_returnUrl = string.Format("developer/Macros/editMacro.aspx?macroID={0}", macro.Id);

View File

@@ -1,469 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
using Umbraco.Core;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using umbraco.cms.presentation.Trees;
using System.Linq;
using Umbraco.Web.UI;
using Umbraco.Web.UI.Pages;
using Umbraco.Core.Services;
using Umbraco.Web;
using Umbraco.Web.Composing;
using Umbraco.Web._Legacy.Controls;
namespace umbraco.cms.presentation.developer
{
/// <summary>
/// Summary description for editMacro.
/// </summary>
public partial class editMacro : UmbracoEnsuredPage
{
public editMacro()
{
CurrentApp = Constants.Applications.Developer.ToString();
}
protected PlaceHolder Buttons;
protected Table MacroElements;
public TabPage InfoTabPage;
public TabPage Parameters;
private IMacro _macro;
protected void Page_Load(object sender, EventArgs e)
{
_macro = Services.MacroService.GetById(Convert.ToInt32(Request.QueryString["macroID"]));
if (IsPostBack == false)
{
ClientTools
.SyncTree("-1," + _macro.Id, false);
string tempMacroType = _macro.ControlType ?? "";
PopulateFieldsOnLoad(_macro, tempMacroType);
// Load elements from macro
MacroPropertyBind();
// Load usercontrols
PopulateUserControls(IOHelper.MapPath(SystemDirectories.UserControls));
userControlList.Items.Insert(0, new ListItem("Browse usercontrols on server...", string.Empty));
}
}
/// <summary>
/// Populates the control (textbox) values on page load
/// </summary>
/// <param name="macro"></param>
/// <param name="macroAssemblyValue"></param>
/// <param name="macroTypeValue"></param>
protected virtual void PopulateFieldsOnLoad(IMacro macro, string macroTypeValue)
{
macroName.Text = macro.Name;
macroAlias.Text = macro.Alias;
macroKey.Text = macro.Key.ToString();
cachePeriod.Text = macro.CacheDuration.ToInvariantString();
macroRenderContent.Checked = macro.DontRender == false;
macroEditor.Checked = macro.UseInEditor;
cacheByPage.Checked = macro.CacheByPage;
cachePersonalized.Checked = macro.CacheByMember;
macroUserControl.Text = macroTypeValue;
}
/// <summary>
/// Sets the values on the Macro object from the values posted back before saving the macro
/// </summary>
protected virtual void SetMacroValuesFromPostBack(IMacro macro, int macroCachePeriod, string macroTypeValue)
{
macro.UseInEditor = macroEditor.Checked;
macro.DontRender = macroRenderContent.Checked == false;
macro.CacheByPage = cacheByPage.Checked;
macro.CacheByMember = cachePersonalized.Checked;
macro.CacheDuration = macroCachePeriod;
macro.Alias = macroAlias.Text;
macro.Name = macroName.Text;
macro.ControlType = macroTypeValue;
}
public void DeleteMacroProperty(object sender, EventArgs e)
{
var macroPropertyId = (HtmlInputHidden)((Control)sender).Parent.FindControl("macroPropertyID");
var property = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
_macro.Properties.Remove(property);
Services.MacroService.Save(_macro);
MacroPropertyBind();
}
public void MacroPropertyBind()
{
macroProperties.DataSource = _macro.Properties.OrderBy(x => x.SortOrder);
macroProperties.DataBind();
}
public object CheckNull(object test)
{
return Convert.IsDBNull(test) ? 0 : test;
}
protected IEnumerable<IDataEditor> GetMacroParameterEditors()
{
// we need to show the depracated ones for backwards compatibility
// FIXME not managing deprecated here?!
return Current.ParameterEditors;
}
public void macroPropertyCreate(object sender, EventArgs e)
{
//enable add validators
var val1 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator1");
var val2 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator4");
var val3 = (RequiredFieldValidator)((Control)sender).Parent.FindControl("RequiredFieldValidator5");
val1.Enabled = true;
val2.Enabled = true;
val3.Enabled = true;
Page.Validate();
if (Page.IsValid == false)
{
return;
}
var macroPropertyAliasNew = (TextBox)((Control)sender).Parent.FindControl("macroPropertyAliasNew");
var macroPropertyNameNew = (TextBox)((Control)sender).Parent.FindControl("macroPropertyNameNew");
var macroPropertyTypeNew = (DropDownList)((Control)sender).Parent.FindControl("macroPropertyTypeNew");
if (macroPropertyAliasNew.Text != Services.TextService.Localize("general/new") + " " + Services.TextService.Localize("general/alias"))
{
if (_macro.Properties.ContainsKey(macroPropertyAliasNew.Text.Trim()))
{
//don't continue
return;
}
_macro.Properties.Add(new MacroProperty(
macroPropertyAliasNew.Text.Trim(),
macroPropertyNameNew.Text.Trim(),
_macro.Properties.Any() ? _macro.Properties.Max(x => x.SortOrder) + 1 : 0,
macroPropertyTypeNew.SelectedValue));
Services.MacroService.Save(_macro);
MacroPropertyBind();
}
}
public bool macroIsVisible(object isChecked)
{
return Convert.ToBoolean(isChecked);
}
public void AddChooseList(object sender, EventArgs e)
{
if (IsPostBack == false)
{
var dropDown = (DropDownList)sender;
dropDown.Items.Insert(0, new ListItem("Choose...", string.Empty));
}
}
private void PopulateUserControls(string path)
{
var directoryInfo = new DirectoryInfo(path);
if (directoryInfo.Exists == false) return;
var rootDir = IOHelper.MapPath(SystemDirectories.UserControls);
foreach (var uc in directoryInfo.GetFiles("*.ascx"))
{
userControlList.Items.Add(
new ListItem(SystemDirectories.UserControls +
uc.FullName.Substring(rootDir.Length).Replace(IOHelper.DirSepChar, '/')));
}
foreach (var dir in directoryInfo.GetDirectories())
PopulateUserControls(dir.FullName);
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
EnsureChildControls();
}
protected override void CreateChildControls()
{
base.CreateChildControls();
// Tab setup
InfoTabPage = TabView1.NewTabPage("Macro Properties");
InfoTabPage.Controls.Add(Pane1);
InfoTabPage.Controls.Add(Pane1_2);
InfoTabPage.Controls.Add(Pane1_3);
InfoTabPage.Controls.Add(Pane1_4);
Parameters = TabView1.NewTabPage("Parameters");
Parameters.Controls.Add(Panel2);
var save = TabView1.Menu.NewButton();
save.ButtonType = MenuButtonType.Primary;
save.Text = Services.TextService.Localize("save");
save.ID = "save";
save.Click += Save_Click;
}
void Save_Click(object sender, EventArgs e)
{
Page.Validate();
ClientTools
.SyncTree("-1," + _macro.Id.ToInvariantString(), true); //true forces the reload
var tempCachePeriod = cachePeriod.Text;
if (tempCachePeriod == string.Empty)
tempCachePeriod = "0";
var tempMacroType = macroUserControl.Text;
SetMacroValuesFromPostBack(_macro, Convert.ToInt32(tempCachePeriod), tempMacroType);
// save elements
// this is oh so completely broken
var aliases = new Dictionary<string, string>();
foreach (RepeaterItem item in macroProperties.Items)
{
var macroPropertyId = (HtmlInputHidden)item.FindControl("macroPropertyID");
var macroElementName = (TextBox)item.FindControl("macroPropertyName");
var macroElementAlias = (TextBox)item.FindControl("macroPropertyAlias");
var macroElementSortOrder = (TextBox)item.FindControl("macroPropertySortOrder");
var macroElementType = (DropDownList)item.FindControl("macroPropertyType");
var prop = _macro.Properties.Single(x => x.Id == int.Parse(macroPropertyId.Value));
var sortOrder = 0;
int.TryParse(macroElementSortOrder.Text, out sortOrder);
var alias = macroElementAlias.Text.Trim();
if (prop.Alias != alias) // changing the alias
{
// use a temp alias to avoid collision if eg swapping aliases
var tempAlias = Guid.NewGuid().ToString("N").Substring(0, 8);
aliases[tempAlias] = alias;
alias = tempAlias;
}
_macro.Properties.UpdateProperty(
prop.Alias,
macroElementName.Text.Trim(),
sortOrder,
macroElementType.SelectedValue,
alias);
}
// now apply the real aliases, should not collide
foreach (var kvp in aliases)
_macro.Properties.UpdateProperty(kvp.Key, newAlias: kvp.Value);
Services.MacroService.Save(_macro);
ClientTools.ShowSpeechBubble(SpeechBubbleIcon.Save, "Macro saved", "");
MacroPropertyBind();
}
/// <summary>
/// TabView1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.TabView TabView1;
/// <summary>
/// Pane1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1;
/// <summary>
/// macroPane control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable macroPane;
/// <summary>
/// macroName control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroName;
/// <summary>
/// macroAlias control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroAlias;
/// <summary>
/// macroAlias control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Label macroKey;
/// <summary>
/// Pane1_2 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_2;
/// <summary>
/// macroUserControl control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox macroUserControl;
/// <summary>
/// userControlList control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.DropDownList userControlList;
/// <summary>
/// Pane1_3 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_3;
/// <summary>
/// Table1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable Table1;
/// <summary>
/// macroEditor control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox macroEditor;
/// <summary>
/// macroRenderContent control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox macroRenderContent;
/// <summary>
/// Pane1_4 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Pane1_4;
/// <summary>
/// Table3 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlTable Table3;
/// <summary>
/// cachePeriod control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.TextBox cachePeriod;
/// <summary>
/// cacheByPage control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox cacheByPage;
/// <summary>
/// cachePersonalized control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.CheckBox cachePersonalized;
/// <summary>
/// Panel2 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::Umbraco.Web._Legacy.Controls.Pane Panel2;
/// <summary>
/// macroProperties control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Repeater macroProperties;
}
}

View File

@@ -150,7 +150,7 @@ namespace umbraco.presentation.templateControls
if (extension.InvariantEndsWith(".cshtml") == false && extension.InvariantEndsWith(".vbhtml") == false)
throw new NotSupportedException("");
tempMacro.ScriptName = FileLocation;
tempMacro.MacroSource = FileLocation;
tempMacro.MacroType = MacroTypes.PartialView;
if (string.IsNullOrEmpty(Attributes["Cache"]) == false)