* Update gitignore * Move csproj * Update project references * Update solutions * Update build scripts * Tests used to share editorconfig with projects in src * Fix broken tests. * Stop copying around .editorconfig merged root one with linting * csharp_style_expression_bodied -> suggestion * Move StyleCop rulesets to matching directories and update shared build properties * Remove legacy build files, update NuGet.cofig and solution files * Restore myget source * Clean up .gitignore * Update .gitignore * Move new test classes to tests after merge * Gitignore + nuget config * Move new test Co-authored-by: Ronald Barendse <ronald@barend.se>
222 lines
10 KiB
C#
222 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Xml.XPath;
|
|
using Examine;
|
|
using Microsoft.Extensions.Logging;
|
|
using Umbraco.Cms.Core.Cache;
|
|
using Umbraco.Cms.Core.Models.PublishedContent;
|
|
using Umbraco.Cms.Core.PublishedCache;
|
|
using Umbraco.Extensions;
|
|
using Umbraco.Web.Composing;
|
|
|
|
namespace Umbraco.Tests.LegacyXmlPublishedCache
|
|
{
|
|
/// <summary>
|
|
/// An IPublishedContent that is represented all by a dictionary.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This is a helper class and definitely not intended for public use, it expects that all of the values required
|
|
/// to create an IPublishedContent exist in the dictionary by specific aliases.
|
|
/// </remarks>
|
|
internal class DictionaryPublishedContent : PublishedContentBase
|
|
{
|
|
// note: I'm not sure this class fully complies with IPublishedContent rules especially
|
|
// I'm not sure that _properties contains all properties including those without a value,
|
|
// neither that GetProperty will return a property without a value vs. null... @zpqrtbnk
|
|
|
|
// List of properties that will appear in the XML and do not match
|
|
// anything in the ContentType, so they must be ignored.
|
|
private static readonly string[] IgnoredKeys = { "version", "isDoc" };
|
|
|
|
public DictionaryPublishedContent(
|
|
IReadOnlyDictionary<string, string> valueDictionary,
|
|
Func<int, IPublishedContent> getParent,
|
|
Func<int, XPathNavigator, IEnumerable<IPublishedContent>> getChildren,
|
|
Func<DictionaryPublishedContent, string, IPublishedProperty> getProperty,
|
|
IAppCache appCache,
|
|
IVariationContextAccessor variationContextAccessor,
|
|
PublishedContentTypeCache contentTypeCache,
|
|
XPathNavigator nav,
|
|
bool fromExamine):base(variationContextAccessor)
|
|
{
|
|
if (valueDictionary == null) throw new ArgumentNullException(nameof(valueDictionary));
|
|
if (getParent == null) throw new ArgumentNullException(nameof(getParent));
|
|
if (getProperty == null) throw new ArgumentNullException(nameof(getProperty));
|
|
|
|
_getParent = new Lazy<IPublishedContent>(() => getParent(ParentId));
|
|
_getChildren = new Lazy<IEnumerable<IPublishedContent>>(() => getChildren(Id, nav));
|
|
_getProperty = getProperty;
|
|
_appCache = appCache;
|
|
|
|
LoadedFromExamine = fromExamine;
|
|
|
|
ValidateAndSetProperty(valueDictionary, val => _id = Int32.Parse(val), "id", "nodeId", "__NodeId"); //should validate the int!
|
|
ValidateAndSetProperty(valueDictionary, val => _key = Guid.Parse(val), "key", "__key", "__Key");
|
|
//ValidateAndSetProperty(valueDictionary, val => _templateId = int.Parse(val), "template", "templateId");
|
|
ValidateAndSetProperty(valueDictionary, val => _sortOrder = Int32.Parse(val), "sortOrder");
|
|
ValidateAndSetProperty(valueDictionary, val => _name = val, "nodeName");
|
|
ValidateAndSetProperty(valueDictionary, val => _urlName = val, "urlName");
|
|
ValidateAndSetProperty(valueDictionary, val => _documentTypeAlias = val, "nodeTypeAlias", ExamineFieldNames.ItemTypeFieldName);
|
|
ValidateAndSetProperty(valueDictionary, val => _documentTypeId = Int32.Parse(val), "nodeType");
|
|
//ValidateAndSetProperty(valueDictionary, val => _writerId = int.Parse(val), "writerID");
|
|
ValidateAndSetProperty(valueDictionary, val => _creatorId = Int32.Parse(val), "creatorID", "writerID"); //this is a bit of a hack fix for: U4-1132
|
|
ValidateAndSetProperty(valueDictionary, val => _path = val, "path", "__Path");
|
|
ValidateAndSetProperty(valueDictionary, val => _createDate = ParseDateTimeValue(val), "createDate");
|
|
ValidateAndSetProperty(valueDictionary, val => _updateDate = ParseDateTimeValue(val), "updateDate");
|
|
ValidateAndSetProperty(valueDictionary, val => _level = Int32.Parse(val), "level");
|
|
ValidateAndSetProperty(valueDictionary, val =>
|
|
{
|
|
int pId;
|
|
ParentId = -1;
|
|
if (Int32.TryParse(val, out pId))
|
|
{
|
|
ParentId = pId;
|
|
}
|
|
}, "parentID");
|
|
|
|
_contentType = contentTypeCache.Get(PublishedItemType.Media, _documentTypeAlias);
|
|
_properties = new Collection<IPublishedProperty>();
|
|
|
|
//handle content type properties
|
|
//make sure we create them even if there's no value
|
|
foreach (var propertyType in _contentType.PropertyTypes)
|
|
{
|
|
var alias = propertyType.Alias;
|
|
_keysAdded.Add(alias);
|
|
string value;
|
|
const bool isPreviewing = false; // false :: never preview a media
|
|
var property = valueDictionary.TryGetValue(alias, out value) == false || value == null
|
|
? new XmlPublishedProperty(propertyType, this, isPreviewing)
|
|
: new XmlPublishedProperty(propertyType, this, isPreviewing, value);
|
|
_properties.Add(property);
|
|
}
|
|
|
|
//loop through remaining values that haven't been applied
|
|
foreach (var i in valueDictionary.Where(x =>
|
|
_keysAdded.Contains(x.Key) == false // not already processed
|
|
&& IgnoredKeys.Contains(x.Key) == false)) // not ignorable
|
|
{
|
|
if (i.Key.InvariantStartsWith("__"))
|
|
{
|
|
// no type for that one, dunno how to convert, drop it
|
|
//IPublishedProperty property = new PropertyResult(i.Key, i.Value, PropertyResultType.CustomProperty);
|
|
//_properties.Add(property);
|
|
}
|
|
else
|
|
{
|
|
// this is a property that does not correspond to anything, ignore and log
|
|
Current.Logger.LogWarning("Dropping property '{PropertyKey}' because it does not belong to the content type.", i.Key);
|
|
}
|
|
}
|
|
}
|
|
|
|
private DateTime ParseDateTimeValue(string val)
|
|
{
|
|
if (LoadedFromExamine == false)
|
|
return DateTime.Parse(val);
|
|
|
|
//we need to parse the date time using Lucene converters
|
|
var ticks = Int64.Parse(val);
|
|
return new DateTime(ticks);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flag to get/set if this was loaded from examine cache
|
|
/// </summary>
|
|
internal bool LoadedFromExamine { get; }
|
|
|
|
//private readonly Func<DictionaryPublishedContent, IPublishedContent> _getParent;
|
|
private readonly Lazy<IPublishedContent> _getParent;
|
|
//private readonly Func<DictionaryPublishedContent, IEnumerable<IPublishedContent>> _getChildren;
|
|
private readonly Lazy<IEnumerable<IPublishedContent>> _getChildren;
|
|
private readonly Func<DictionaryPublishedContent, string, IPublishedProperty> _getProperty;
|
|
private readonly IAppCache _appCache;
|
|
|
|
/// <summary>
|
|
/// Returns 'Media' as the item type
|
|
/// </summary>
|
|
public override PublishedItemType ItemType => PublishedItemType.Media;
|
|
|
|
public override IPublishedContent Parent => _getParent.Value;
|
|
|
|
public int ParentId { get; private set; }
|
|
|
|
public override int Id => _id;
|
|
|
|
public override Guid Key => _key;
|
|
|
|
public override int? TemplateId => null;
|
|
|
|
public override int SortOrder => _sortOrder;
|
|
|
|
public override string Name => _name;
|
|
|
|
private static readonly Lazy<Dictionary<string, PublishedCultureInfo>> NoCultures = new Lazy<Dictionary<string, PublishedCultureInfo>>(() => new Dictionary<string, PublishedCultureInfo>());
|
|
public override IReadOnlyDictionary<string, PublishedCultureInfo> Cultures => NoCultures.Value;
|
|
|
|
public override string UrlSegment => _urlName;
|
|
|
|
public override int WriterId => _creatorId;
|
|
|
|
public override int CreatorId => _creatorId;
|
|
|
|
public override string Path => _path;
|
|
|
|
public override DateTime CreateDate => _createDate;
|
|
|
|
public override DateTime UpdateDate => _updateDate;
|
|
|
|
public override int Level => _level;
|
|
|
|
public override bool IsDraft(string culture = null) => false;
|
|
|
|
public override bool IsPublished(string culture = null) => true;
|
|
|
|
public override IEnumerable<IPublishedProperty> Properties => _properties;
|
|
|
|
public override IEnumerable<IPublishedContent> Children => _getChildren.Value;
|
|
|
|
public override IEnumerable<IPublishedContent> ChildrenForAllCultures => Children;
|
|
|
|
public override IPublishedProperty GetProperty(string alias)
|
|
{
|
|
return _getProperty(this, alias);
|
|
}
|
|
|
|
public override IPublishedContentType ContentType => _contentType;
|
|
|
|
private readonly List<string> _keysAdded = new List<string>();
|
|
private int _id;
|
|
private Guid _key;
|
|
//private int _templateId;
|
|
private int _sortOrder;
|
|
private string _name;
|
|
private string _urlName;
|
|
private string _documentTypeAlias;
|
|
private int _documentTypeId;
|
|
//private int _writerId;
|
|
private int _creatorId;
|
|
private string _path;
|
|
private DateTime _createDate;
|
|
private DateTime _updateDate;
|
|
//private Guid _version;
|
|
private int _level;
|
|
private readonly ICollection<IPublishedProperty> _properties;
|
|
private readonly IPublishedContentType _contentType;
|
|
|
|
private void ValidateAndSetProperty(IReadOnlyDictionary<string, string> valueDictionary, Action<string> setProperty, params string[] potentialKeys)
|
|
{
|
|
var key = potentialKeys.FirstOrDefault(x => valueDictionary.ContainsKey(x) && valueDictionary[x] != null);
|
|
if (key == null)
|
|
{
|
|
throw new FormatException("The valueDictionary is not formatted correctly and is missing any of the '" + String.Join(",", potentialKeys) + "' elements");
|
|
}
|
|
|
|
setProperty(valueDictionary[key]);
|
|
_keysAdded.Add(key);
|
|
}
|
|
}
|
|
}
|