Removing the last references to MacroTypes and removing the references to pageElements coming from old legacy (PublishedContentHashtableConverter), which is deleted as well

This commit is contained in:
elitsa
2020-02-25 13:43:08 +01:00
parent 65e719cfa6
commit 0bdf03bda2
2 changed files with 15 additions and 378 deletions

View File

@@ -112,10 +112,6 @@ namespace Umbraco.Web.Macros
}
}
// this is legacy and I'm not sure what exactly it is supposed to do
if (macroContent.Control != null)
macroContent.Control.ID = macroContent.ControlId;
return macroContent;
}
@@ -137,10 +133,6 @@ namespace Umbraco.Web.Macros
if (key == null) return;
}
// this is legacy and I'm not sure what exactly it is supposed to do
if (macroContent.Control != null)
macroContent.ControlId = macroContent.Control.ID;
// remember when we cache the content
macroContent.Date = DateTime.Now;
@@ -155,23 +147,12 @@ namespace Umbraco.Web.Macros
}
// gets the macro source file name
// null if the macro is not file-based
// null if the macro is not file-based, or not supported
internal static string GetMacroFileName(MacroModel model)
{
string filename;
string filename = model.MacroSource; // partial views are saved with their full virtual path
switch (model.MacroType)
{
case MacroTypes.PartialView:
filename = model.MacroSource; // partial views are saved with their full virtual path
break;
default:
// not file-based, or not supported
filename = null;
break;
}
return filename;
return string.IsNullOrEmpty(filename) ? null : filename;
}
// gets the macro source file
@@ -210,24 +191,22 @@ namespace Umbraco.Web.Macros
if (m == null)
throw new InvalidOperationException("No macro found by alias " + macroAlias);
var page = new PublishedContentHashtableConverter(content, _userService);
var macro = new MacroModel(m);
UpdateMacroModelProperties(macro, macroParams);
return Render(macro, content, page.Elements);
return Render(macro, content);
}
private MacroContent Render(MacroModel macro, IPublishedContent content, IDictionary pageElements)
private MacroContent Render(MacroModel macro, IPublishedContent content)
{
if (content == null) throw new ArgumentNullException(nameof(content));
var macroInfo = $"Render Macro: {macro.Name}, type: {macro.MacroType}, cache: {macro.CacheDuration}";
var macroInfo = $"Render Macro: {macro.Name}, cache: {macro.CacheDuration}";
using (_plogger.DebugDuration<MacroRenderer>(macroInfo, "Rendered Macro."))
{
// parse macro parameters ie replace the special [#key], [$key], etc. syntaxes
foreach (var prop in macro.Properties)
prop.Value = ParseAttribute(pageElements, prop.Value);
prop.Value = ParseAttribute(prop.Value);
macro.CacheIdentifier = GetContentCacheIdentifier(macro, content.Id);
@@ -334,22 +313,11 @@ namespace Umbraco.Web.Macros
var textService = _textService;
switch (model.MacroType)
{
case MacroTypes.PartialView:
return ExecuteMacroWithErrorWrapper(model,
$"Executing PartialView: MacroSource=\"{model.MacroSource}\".",
"Executed PartialView.",
() => ExecutePartialView(model, content),
() => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource }));
default:
return ExecuteMacroWithErrorWrapper(model,
$"Execute macro with unsupported type \"{model.MacroType}\".",
"Executed.",
() => { throw new Exception("Unsupported macro type."); },
() => textService.Localize("errors/macroErrorUnsupportedType"));
}
return ExecuteMacroWithErrorWrapper(model,
$"Executing PartialView: MacroSource=\"{model.MacroSource}\".",
"Executed PartialView.",
() => ExecutePartialView(model, content),
() => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource }));
}
@@ -371,12 +339,10 @@ namespace Umbraco.Web.Macros
#region Execution helpers
// parses attribute value looking for [@requestKey], [%sessionKey], [#pageElement], [$recursiveValue]
// parses attribute value looking for [@requestKey], [%sessionKey]
// supports fallbacks eg "[@requestKey],[%sessionKey],1234"
private string ParseAttribute(IDictionary pageElements, string attributeValue)
private string ParseAttribute(string attributeValue)
{
if (pageElements == null) throw new ArgumentNullException(nameof(pageElements));
// check for potential querystring/cookie variables
attributeValue = attributeValue.Trim();
if (attributeValue.StartsWith("[") == false)
@@ -388,7 +354,7 @@ namespace Umbraco.Web.Macros
// like [1,2,3] which we don't want to parse - however the last one can be a literal, so
// don't check on the last one which can be just anything - check all previous tokens
char[] validTypes = { '@', '%', '#', '$' };
char[] validTypes = { '@', '%' };
if (tokens.Take(tokens.Length - 1).Any(x =>
x.Length < 4 // ie "[?x]".Length - too short
|| x[0] != '[' // starts with [
@@ -424,14 +390,6 @@ namespace Umbraco.Web.Macros
if (string.IsNullOrEmpty(attributeValue))
attributeValue = _cookieManager.GetCookieValue(name);
break;
case '#':
attributeValue = pageElements[name]?.ToString();
break;
case '$':
attributeValue = pageElements[name]?.ToString();
if (string.IsNullOrEmpty(attributeValue))
attributeValue = ParseAttributeOnParents(pageElements, name);
break;
}
attributeValue = attributeValue?.Trim();
@@ -442,26 +400,6 @@ namespace Umbraco.Web.Macros
return attributeValue;
}
private string ParseAttributeOnParents(IDictionary pageElements, string name)
{
if (pageElements == null) throw new ArgumentNullException(nameof(pageElements));
// this was, and still is, an ugly piece of nonsense
var value = string.Empty;
var cache = _umbracoContextAccessor.UmbracoContext.Content;
var splitpath = (string[])pageElements["splitpath"];
for (var i = splitpath.Length - 1; i > 0; i--) // at 0 we have root (-1)
{
var content = cache.GetById(int.Parse(splitpath[i]));
if (content == null) continue;
value = content.Value(name)?.ToString();
if (string.IsNullOrEmpty(value) == false) break;
}
return value;
}
#endregion
}

View File

@@ -1,301 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Web.Editors;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Macros
{
/// <summary>
/// Legacy class used by macros which converts a published content item into a hashset of values
/// </summary>
internal class PublishedContentHashtableConverter
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="PublishedContentHashtableConverter"/> class for a published document request.
/// </summary>
/// <param name="frequest">The <see cref="IPublishedRequest"/> pointing to the document.</param>
/// <param name="userService">The <see cref="IUserService"/>.</param>
/// <remarks>
/// The difference between creating the page with PublishedRequest vs an IPublishedContent item is
/// that the PublishedRequest takes into account how a template is assigned during the routing process whereas
/// with an IPublishedContent item, the template id is assigned purely based on the default.
/// </remarks>
internal PublishedContentHashtableConverter(IPublishedRequest frequest, IUserService userService)
{
if (!frequest.HasPublishedContent)
throw new ArgumentException("Document request has no node.", nameof(frequest));
PopulatePageData(frequest.PublishedContent.Id,
frequest.PublishedContent.Name, frequest.PublishedContent.ContentType.Id, frequest.PublishedContent.ContentType.Alias,
frequest.PublishedContent.GetWriterName(userService), frequest.PublishedContent.GetCreatorName(userService), frequest.PublishedContent.CreateDate, frequest.PublishedContent.UpdateDate,
frequest.PublishedContent.Path, frequest.PublishedContent.Parent?.Id ?? -1);
if (frequest.HasTemplate)
{
Elements["template"] = frequest.TemplateModel.Id.ToString();
}
PopulateElementData(frequest.PublishedContent);
}
/// <summary>
/// Initializes a new instance of the page for a published document
/// </summary>
/// <param name="doc"></param>
internal PublishedContentHashtableConverter(IPublishedContent doc, IUserService userService)
{
if (doc == null) throw new ArgumentNullException(nameof(doc));
PopulatePageData(doc.Id,
doc.Name, doc.ContentType.Id, doc.ContentType.Alias,
doc.GetWriterName(userService), doc.GetCreatorName(userService), doc.CreateDate, doc.UpdateDate,
doc.Path, doc.Parent?.Id ?? -1);
if (doc.TemplateId.HasValue)
{
//set the template to whatever is assigned to the doc
Elements["template"] = doc.TemplateId.Value.ToString();
}
PopulateElementData(doc);
}
/// <summary>
/// Initializes a new instance of the page for a content.
/// </summary>
/// <param name="content">The content.</param>
/// <param name="variationContextAccessor"></param>
/// <remarks>This is for <see cref="MacroRenderingController"/> usage only.</remarks>
internal PublishedContentHashtableConverter(IContent content, IVariationContextAccessor variationContextAccessor, IUserService userService, IShortStringHelper shortStringHelper, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IPublishedContentTypeFactory publishedContentTypeFactory, UrlSegmentProviderCollection urlSegmentProviders)
: this(new PagePublishedContent(content, variationContextAccessor, userService, shortStringHelper, contentTypeBaseServiceProvider, publishedContentTypeFactory, urlSegmentProviders), userService)
{ }
#endregion
#region Initialize
private void PopulatePageData(int pageId,
string pageName, int nodeType, string nodeTypeAlias,
string writerName, string creatorName, DateTime createDate, DateTime updateDate,
string path, int parentId)
{
// Update the elements hashtable
Elements.Add("pageID", pageId);
Elements.Add("parentID", parentId);
Elements.Add("pageName", pageName);
Elements.Add("nodeType", nodeType);
Elements.Add("nodeTypeAlias", nodeTypeAlias);
Elements.Add("writerName", writerName);
Elements.Add("creatorName", creatorName);
Elements.Add("createDate", createDate);
Elements.Add("updateDate", updateDate);
Elements.Add("path", path);
Elements.Add("splitpath", path.Split(','));
}
/// <summary>
/// Puts the properties of the node into the elements table
/// </summary>
/// <param name="node"></param>
private void PopulateElementData(IPublishedElement node)
{
foreach (var p in node.Properties)
{
if (Elements.ContainsKey(p.Alias) == false)
{
// note: legacy used the raw value (see populating from an Xml node below)
// so we're doing the same here, using DataValue. If we use Value then every
// value will be converted NOW - including RTEs that may contain macros that
// require that the 'page' is already initialized = catch-22.
// to properly fix this, we'd need to turn the elements collection into some
// sort of collection of lazy values.
Elements[p.Alias] = p.GetSourceValue();
}
}
}
#endregion
/// <summary>
/// Returns a Hashtable of data for a published content item
/// </summary>
public Hashtable Elements { get; } = new Hashtable();
#region PublishedContent
private class PagePublishedProperty : PublishedPropertyBase
{
private readonly object _sourceValue;
private readonly IPublishedContent _content;
public PagePublishedProperty(IPublishedPropertyType propertyType, IPublishedContent content)
: base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored
{
_sourceValue = null;
_content = content;
}
public PagePublishedProperty(IPublishedPropertyType propertyType, IPublishedContent content, IProperty property)
: base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored
{
_sourceValue = property.GetValue();
_content = content;
}
public override bool HasValue(string culture = null, string segment = null)
{
return _sourceValue != null && ((_sourceValue is string) == false || string.IsNullOrWhiteSpace((string)_sourceValue) == false);
}
public override object GetSourceValue(string culture = null, string segment = null)
{
return _sourceValue;
}
public override object GetValue(string culture = null, string segment = null)
{
// isPreviewing is true here since we want to preview anyway...
const bool isPreviewing = true;
var source = PropertyType.ConvertSourceToInter(_content, _sourceValue, isPreviewing);
return PropertyType.ConvertInterToObject(_content, PropertyCacheLevel.Unknown, source, isPreviewing);
}
public override object GetXPathValue(string culture = null, string segment = null)
{
throw new NotImplementedException();
}
}
private class PagePublishedContent : IPublishedContent
{
private readonly IContent _inner;
private readonly IPublishedProperty[] _properties;
private IReadOnlyDictionary<string, PublishedCultureInfo> _cultureInfos;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IShortStringHelper _shortStringHelper;
private readonly UrlSegmentProviderCollection _urlSegmentProviders;
private static readonly IReadOnlyDictionary<string, PublishedCultureInfo> NoCultureInfos = new Dictionary<string, PublishedCultureInfo>();
private PagePublishedContent(int id)
{
Id = id;
}
public PagePublishedContent(IContent inner, IVariationContextAccessor variationContextAccessor, IUserService userService, IShortStringHelper shortStringHelper, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IPublishedContentTypeFactory publishedContentTypeFactory, UrlSegmentProviderCollection urlSegmentProviders)
{
_inner = inner ?? throw new ArgumentNullException(nameof(inner));
_variationContextAccessor = variationContextAccessor;
_shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper));
_urlSegmentProviders = urlSegmentProviders ?? throw new ArgumentNullException(nameof(urlSegmentProviders));
Id = _inner.Id;
Key = _inner.Key;
CreatorName = _inner.GetCreatorProfile(userService)?.Name;
WriterName = _inner.GetWriterProfile(userService)?.Name;
var contentType = contentTypeBaseServiceProvider.GetContentTypeOf(_inner);
ContentType = publishedContentTypeFactory.CreateContentType(contentType);
_properties = ContentType.PropertyTypes
.Select(x =>
{
var p = _inner.Properties.SingleOrDefault(xx => xx.Alias == x.Alias);
return p == null ? new PagePublishedProperty(x, this) : new PagePublishedProperty(x, this, p);
})
.Cast<IPublishedProperty>()
.ToArray();
Parent = new PagePublishedContent(_inner.ParentId);
}
public IPublishedContentType ContentType { get; }
public int Id { get; }
public Guid Key { get; }
public int? TemplateId => _inner.TemplateId;
public int SortOrder => _inner.SortOrder;
public string Name => _inner.Name;
public IReadOnlyDictionary<string, PublishedCultureInfo> Cultures
{
get
{
if (!_inner.ContentType.VariesByCulture())
return NoCultureInfos;
if (_cultureInfos != null)
return _cultureInfos;
return _cultureInfos = _inner.PublishCultureInfos.Values
.ToDictionary(x => x.Culture, x => new PublishedCultureInfo(x.Culture, x.Name, _inner.GetUrlSegment(_shortStringHelper, _urlSegmentProviders, x.Culture), x.Date));
}
}
public string UrlSegment => throw new NotImplementedException();
public string WriterName { get; }
public string CreatorName { get; }
public int WriterId => _inner.WriterId;
public int CreatorId => _inner.CreatorId;
public string Path => _inner.Path;
public DateTime CreateDate => _inner.CreateDate;
public DateTime UpdateDate => _inner.UpdateDate;
public int Level => _inner.Level;
public string Url => throw new NotImplementedException();
public PublishedItemType ItemType => PublishedItemType.Content;
public bool IsDraft(string culture = null)
{
throw new NotImplementedException();
}
public bool IsPublished(string culture = null)
{
throw new NotImplementedException();
}
public IPublishedContent Parent { get; }
public IEnumerable<IPublishedContent> Children => throw new NotImplementedException();
public IEnumerable<IPublishedContent> ChildrenForAllCultures => throw new NotImplementedException();
public IEnumerable<IPublishedProperty> Properties => _properties;
public IPublishedProperty GetProperty(string alias)
{
throw new NotImplementedException();
}
}
#endregion
}
}