Merge remote-tracking branch 'origin/temp8' into temp8-dashboards-collection
This commit is contained in:
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Will use HttpContext.Current.</para>
|
||||
/// fixme/task: use IHttpContextAccessor NOT HttpContext.Current
|
||||
/// TODO - https://github.com/umbraco/Umbraco-CMS/issues/4239 - use IHttpContextAccessor NOT HttpContext.Current
|
||||
/// </remarks>
|
||||
public HttpRequestAppCache()
|
||||
{ }
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
try
|
||||
{
|
||||
// fixme/task - stop having version in web.config appSettings
|
||||
// TODO - https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
|
||||
var value = ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
|
||||
return value.IsNullOrWhiteSpace() ? null : SemVersion.TryParse(value, out var semver) ? semver : null;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,12 @@ namespace Umbraco.Core
|
||||
/// RadioButton list.
|
||||
/// </summary>
|
||||
public const string RadioButtonList = "Umbraco.RadioButtonList";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Related Links.
|
||||
/// </summary>
|
||||
public const string RelatedLinks = "Umbraco.RelatedLinks";
|
||||
|
||||
/// <summary>
|
||||
/// Slider.
|
||||
/// </summary>
|
||||
|
||||
34
src/Umbraco.Core/Deploy/IDataTypeConfigurationConnector.cs
Normal file
34
src/Umbraco.Core/Deploy/IDataTypeConfigurationConnector.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines methods that can convert a data type configurations to / from an environment-agnostic string.
|
||||
/// </summary>
|
||||
/// <remarks>Configurations may contain values such as content identifiers, that would be local
|
||||
/// to one environment, and need to be converted in order to be deployed.</remarks>
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "This is actual only used by Deploy, but we dont want third parties to have references on deploy, thats why this interface is part of core.")]
|
||||
public interface IDataTypeConfigurationConnector
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the property editor aliases that the value converter supports by default.
|
||||
/// </summary>
|
||||
IEnumerable<string> PropertyEditorAliases { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the environment-agnostic data type configurations corresponding to environment-specific configurations.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The environment-specific configuration.</param>
|
||||
/// <param name="dependencies">The dependencies.</param>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> ConvertToDeploy(IDictionary<string, string> configuration, ICollection<ArtifactDependency> dependencies);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the environment-specific data type configurations corresponding to environment-agnostic configurations.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The environment-agnostic configuration.</param>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> ConvertToLocalEnvironment(IDictionary<string, string> configuration);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines methods that can convert a preValue to / from an environment-agnostic string.
|
||||
/// </summary>
|
||||
/// <remarks>PreValues may contain values such as content identifiers, that would be local
|
||||
/// to one environment, and need to be converted in order to be deployed.</remarks>
|
||||
public interface IPreValueConnector // fixme/task: rename to IDataTypeConfigurationConnector + kill all "preValues" name usage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the property editor aliases that the value converter supports by default.
|
||||
/// </summary>
|
||||
IEnumerable<string> PropertyEditorAliases { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the environment-agnostic preValues corresponding to environment-specific preValues.
|
||||
/// </summary>
|
||||
/// <param name="preValues">The environment-specific preValues.</param>
|
||||
/// <param name="dependencies">The dependencies.</param>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> ConvertToDeploy(IDictionary<string, string> preValues, ICollection<ArtifactDependency> dependencies);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the environment-specific preValues corresponding to environment-agnostic preValues.
|
||||
/// </summary>
|
||||
/// <param name="preValues">The environment-agnostic preValues.</param>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> ConvertToLocalEnvironment(IDictionary<string, string> preValues);
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Multi URL Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Related Links", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
private void CreateLockData()
|
||||
@@ -301,7 +301,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1048, EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1049, EditorAlias = Constants.PropertyEditors.Aliases.MediaPicker, DbType = "Ntext",
|
||||
Configuration = "{\"multiPicker\":1}" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1050, EditorAlias = Constants.PropertyEditors.Aliases.MultiUrlPicker, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1050, EditorAlias = Constants.PropertyEditors.Aliases.RelatedLinks, DbType = "Ntext" });
|
||||
}
|
||||
|
||||
private void CreateRelationTypeData()
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
RenameDataType(Constants.PropertyEditors.Aliases.MediaPicker + "2", Constants.PropertyEditors.Aliases.MediaPicker);
|
||||
RenameDataType(Constants.PropertyEditors.Aliases.MemberPicker + "2", Constants.PropertyEditors.Aliases.MemberPicker);
|
||||
RenameDataType(Constants.PropertyEditors.Aliases.MultiNodeTreePicker + "2", Constants.PropertyEditors.Aliases.MultiNodeTreePicker);
|
||||
RenameDataType(Constants.PropertyEditors.Aliases.RelatedLinks + "2", Constants.PropertyEditors.Aliases.RelatedLinks);
|
||||
RenameDataType("Umbraco.TextboxMultiple", Constants.PropertyEditors.Aliases.TextArea, false);
|
||||
RenameDataType("Umbraco.Textbox", Constants.PropertyEditors.Aliases.TextBox, false);
|
||||
}
|
||||
|
||||
@@ -153,8 +153,12 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// </remarks>
|
||||
bool IsDraft(string culture = null);
|
||||
|
||||
// fixme/task - consider having an IsPublished flag too
|
||||
// so that when IsDraft is true, we can check whether there is a published version?
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content is published.
|
||||
/// </summary>
|
||||
/// <param name="culture"></param>
|
||||
bool IsPublished(string culture = null);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -111,6 +111,10 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsDraft(string culture = null) => _content.IsDraft(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsPublished(string culture = null) => _content.IsPublished(culture);
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tree
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
{
|
||||
private readonly Lazy<PropertyEditorCollection> _editors;
|
||||
|
||||
// fixme/task - get rid of Lazy injection and fix circular dependencies
|
||||
// TODO - https://github.com/umbraco/Umbraco-CMS/issues/4237 - get rid of Lazy injection and fix circular dependencies
|
||||
public DataTypeRepository(IScopeAccessor scopeAccessor, AppCaches cache, Lazy<PropertyEditorCollection> editors, ILogger logger)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
{
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
protected override void PersistNewItem(IContent entity)
|
||||
{
|
||||
// fixme/task - sort out IContent vs Content
|
||||
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4234 - sort out IContent vs Content
|
||||
// however, it's not just so we have access to AddingEntity
|
||||
// there are tons of things at the end of the methods, that can only work with a true Content
|
||||
// and basically, the repository requires a Content, not an IContent
|
||||
|
||||
@@ -315,6 +315,7 @@
|
||||
<Compile Include="Dashboards\AccessRuleType.cs" />
|
||||
<Compile Include="Dashboards\IAccessRule.cs" />
|
||||
<Compile Include="Dashboards\IDashboardSection.cs" />
|
||||
<Compile Include="Deploy\IDataTypeConfigurationConnector.cs" />
|
||||
<Compile Include="DisposableObjectSlim.cs" />
|
||||
<Compile Include="Events\ExportedMemberEventArgs.cs" />
|
||||
<Compile Include="Events\RolesEventArgs.cs" />
|
||||
@@ -548,7 +549,6 @@
|
||||
<Compile Include="Deploy\IImageSourceParser.cs" />
|
||||
<Compile Include="Deploy\ILocalLinkParser.cs" />
|
||||
<Compile Include="Deploy\IMacroParser.cs" />
|
||||
<Compile Include="Deploy\IPreValueConnector.cs" />
|
||||
<Compile Include="Deploy\IServiceConnector.cs" />
|
||||
<Compile Include="Deploy\IUniqueIdentifyingServiceConnector.cs" />
|
||||
<Compile Include="Deploy\IValueConnector.cs" />
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
Guid key, version;
|
||||
string name, urlName, writerName, creatorName, docTypeAlias, path;
|
||||
bool isDraft;
|
||||
bool isPublished;
|
||||
DateTime createDate, updateDate;
|
||||
PublishedContentType publishedContentType;
|
||||
Dictionary<string, IPublishedProperty> properties;
|
||||
@@ -104,7 +105,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
OriginalInitializeNode(_xml10.DocumentElement, false, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out isPublished, out publishedContentType,
|
||||
out properties);
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
OriginalInitializeNode(_xml100.DocumentElement, false, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out isPublished, out publishedContentType,
|
||||
out properties);
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
OriginalInitializeNode(_xml1000.DocumentElement, false, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out isPublished, out publishedContentType,
|
||||
out properties);
|
||||
}
|
||||
|
||||
@@ -134,7 +135,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
OriginalInitializeNode(_xml10000.DocumentElement, false, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out version, out createDate, out updateDate, out level, out isDraft, out isPublished, out publishedContentType,
|
||||
out properties);
|
||||
}
|
||||
|
||||
@@ -144,7 +145,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
XmlPublishedContent.InitializeNode(null, _xml10.DocumentElement, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out createDate, out updateDate, out level, out isDraft, out isPublished, out publishedContentType,
|
||||
out properties, GetPublishedContentType);
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
XmlPublishedContent.InitializeNode(null, _xml100.DocumentElement, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out createDate, out updateDate, out level, out isDraft, out isPublished,out publishedContentType,
|
||||
out properties, GetPublishedContentType);
|
||||
}
|
||||
|
||||
@@ -164,7 +165,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
XmlPublishedContent.InitializeNode(null, _xml1000.DocumentElement, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out createDate, out updateDate, out level, out isDraft, out isPublished,out publishedContentType,
|
||||
out properties, GetPublishedContentType);
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
XmlPublishedContent.InitializeNode(null, _xml10000.DocumentElement, false,
|
||||
out id, out key, out template, out sortOrder, out name, out writerName, out urlName,
|
||||
out creatorName, out creatorId, out writerId, out docTypeAlias, out nodeType, out path,
|
||||
out createDate, out updateDate, out level, out isDraft, out publishedContentType,
|
||||
out createDate, out updateDate, out level, out isDraft, out isPublished,out publishedContentType,
|
||||
out properties, GetPublishedContentType);
|
||||
}
|
||||
|
||||
@@ -182,7 +183,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
internal static void OriginalInitializeNode(XmlNode xmlNode, bool legacy, bool isPreviewing,
|
||||
out int id, out Guid key, out int template, out int sortOrder, out string name, out string writerName, out string urlName,
|
||||
out string creatorName, out int creatorId, out int writerId, out string docTypeAlias, out int docTypeId, out string path,
|
||||
out Guid version, out DateTime createDate, out DateTime updateDate, out int level, out bool isDraft,
|
||||
out Guid version, out DateTime createDate, out DateTime updateDate, out int level, out bool isDraft, out bool isPublished,
|
||||
out PublishedContentType contentType, out Dictionary<string, IPublishedProperty> properties)
|
||||
{
|
||||
//initialize the out params with defaults:
|
||||
@@ -193,6 +194,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
name = writerName = urlName = creatorName = docTypeAlias = path = null;
|
||||
createDate = updateDate = default(DateTime);
|
||||
isDraft = false;
|
||||
isPublished = true;
|
||||
contentType = null;
|
||||
properties = null;
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ AnotherContentFinder
|
||||
public void GetDataEditors()
|
||||
{
|
||||
var types = _typeLoader.GetDataEditors();
|
||||
Assert.AreEqual(39, types.Count());
|
||||
Assert.AreEqual(40, types.Count());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -262,6 +262,7 @@ namespace Umbraco.Tests.Published
|
||||
// ReSharper disable UnassignedGetOnlyAutoProperty
|
||||
public override PublishedItemType ItemType { get; }
|
||||
public override bool IsDraft(string culture = null) => false;
|
||||
public override bool IsPublished(string culture = null) => true;
|
||||
public override IPublishedContent Parent { get; }
|
||||
public override IEnumerable<IPublishedContent> Children { get; }
|
||||
public override PublishedContentType ContentType { get; }
|
||||
|
||||
@@ -217,6 +217,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
public Guid Version { get; set; }
|
||||
public int Level { get; set; }
|
||||
public bool IsDraft(string culture = null) => false;
|
||||
public bool IsPublished(string culture = null) => true;
|
||||
|
||||
public IEnumerable<IPublishedProperty> Properties { get; set; }
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
|
||||
public PublishedItemType ItemType { get { return PublishedItemType.Content; } }
|
||||
public bool IsDraft(string culture = null) => false;
|
||||
public bool IsPublished(string culture = null) => true;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -2215,7 +2215,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(sut.GetValue<Udi>("contentPicker"), Is.EqualTo(Udi.Create(Constants.UdiEntityType.Document, new Guid("74ECA1D4-934E-436A-A7C7-36CC16D4095C"))));
|
||||
Assert.That(sut.GetValue<Udi>("mediaPicker"), Is.EqualTo(Udi.Create(Constants.UdiEntityType.Media, new Guid("44CB39C8-01E5-45EB-9CF8-E70AAF2D1691"))));
|
||||
Assert.That(sut.GetValue<Udi>("memberPicker"), Is.EqualTo(Udi.Create(Constants.UdiEntityType.Member, new Guid("9A50A448-59C0-4D42-8F93-4F1D55B0F47D"))));
|
||||
Assert.That(sut.GetValue<string>("multiUrlPicker"), Is.EqualTo("[{\"name\":\"https://test.com\",\"url\":\"https://test.com\"}]"));
|
||||
Assert.That(sut.GetValue<string>("relatedLinks"), Is.EqualTo("<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>"));
|
||||
Assert.That(sut.GetValue<string>("tags"), Is.EqualTo("this,is,tags"));
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
content.SetValue("contentPicker", Udi.Create(Constants.UdiEntityType.Document, new Guid("74ECA1D4-934E-436A-A7C7-36CC16D4095C")).ToString());
|
||||
content.SetValue("mediaPicker", Udi.Create(Constants.UdiEntityType.Media, new Guid("44CB39C8-01E5-45EB-9CF8-E70AAF2D1691")).ToString());
|
||||
content.SetValue("memberPicker", Udi.Create(Constants.UdiEntityType.Member, new Guid("9A50A448-59C0-4D42-8F93-4F1D55B0F47D")).ToString());
|
||||
content.SetValue("multiUrlPicker", "[{\"name\":\"https://test.com\",\"url\":\"https://test.com\"}]");
|
||||
content.SetValue("relatedLinks", "<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>");
|
||||
content.SetValue("tags", "this,is,tags");
|
||||
|
||||
return content;
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ContentPicker, ValueStorageType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeId = 1046 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.MediaPicker, ValueStorageType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeId = 1048 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.MemberPicker, ValueStorageType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeId = 1047 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.MultiUrlPicker, ValueStorageType.Nvarchar) { Alias = "multiUrlPicker", Name = "Multi URL Picker", Mandatory = false, SortOrder = 21, DataTypeId = 1050 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.RelatedLinks, ValueStorageType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeId = 1050 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Tags, ValueStorageType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeId = 1041 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Umbraco.Tests.TestHelpers.Stubs
|
||||
public string GetUrl(string culture = null) => throw new NotSupportedException();
|
||||
public PublishedItemType ItemType => ContentType.ItemType;
|
||||
public bool IsDraft(string culture = null) => false;
|
||||
public bool IsPublished(string culture = null) => true;
|
||||
public IPublishedContent Parent { get; set; }
|
||||
public IEnumerable<IPublishedContent> Children { get; set; }
|
||||
|
||||
|
||||
@@ -29,5 +29,30 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"});
|
||||
Assert.AreEqual("<div style=\"color:red;\" onclick=\"void();\">hello world</div>", output.ToHtmlString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRelatedLinkHtml_Simple()
|
||||
{
|
||||
var relatedLink = new Umbraco.Web.Models.RelatedLink {
|
||||
Caption = "Link Caption",
|
||||
NewWindow = true,
|
||||
Link = "https://www.google.com/"
|
||||
};
|
||||
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink);
|
||||
Assert.AreEqual("<a href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetRelatedLinkHtml_HtmlAttributes()
|
||||
{
|
||||
var relatedLink = new Umbraco.Web.Models.RelatedLink
|
||||
{
|
||||
Caption = "Link Caption",
|
||||
NewWindow = true,
|
||||
Link = "https://www.google.com/"
|
||||
};
|
||||
var output = _htmlHelper.GetRelatedLinkHtml(relatedLink, new { @class = "test-class"});
|
||||
Assert.AreEqual("<a class=\"test-class\" href=\"https://www.google.com/\" target=\"_blank\">Link Caption</a>", output.ToHtmlString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
cursor: pointer;
|
||||
justify-content: space-between;
|
||||
color: @black;
|
||||
|
||||
&:hover .umb-expansion-panel__expand {
|
||||
color: @gray-6;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-expansion-panel__expand {
|
||||
@@ -22,4 +26,4 @@
|
||||
.umb-expansion-panel__content {
|
||||
padding: 20px;
|
||||
border-top: 1px solid @gray-9;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
// fixme/task - deal with this
|
||||
// this is not authenticated, and therefore public, and therefore reveals we
|
||||
// are running Umbraco - but, all requests should come from localhost really,
|
||||
// so there should be a way to 404 when the request comes from the outside.
|
||||
|
||||
public class KeepAliveController : UmbracoApiController
|
||||
{
|
||||
[OnlyLocalRequests]
|
||||
[HttpGet]
|
||||
public KeepAlivePingResult Ping()
|
||||
{
|
||||
|
||||
@@ -830,5 +830,39 @@ namespace Umbraco.Web
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region RelatedLink
|
||||
|
||||
/// <summary>
|
||||
/// Renders an anchor element for a RelatedLink instance.
|
||||
/// Format: <a href="relatedLink.Link" target="_blank/_self">relatedLink.Caption</a>
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
|
||||
/// <param name="relatedLink">The RelatedLink instance</param>
|
||||
/// <returns>An anchor element </returns>
|
||||
public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink)
|
||||
{
|
||||
return htmlHelper.GetRelatedLinkHtml(relatedLink, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders an anchor element for a RelatedLink instance, accepting htmlAttributes.
|
||||
/// Format: <a href="relatedLink.Link" target="_blank/_self" htmlAttributes>relatedLink.Caption</a>
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
|
||||
/// <param name="relatedLink">The RelatedLink instance</param>
|
||||
/// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.</param>
|
||||
/// <returns></returns>
|
||||
public static MvcHtmlString GetRelatedLinkHtml(this HtmlHelper htmlHelper, RelatedLink relatedLink, object htmlAttributes)
|
||||
{
|
||||
var tagBuilder = new TagBuilder("a");
|
||||
tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
|
||||
tagBuilder.MergeAttribute("href", relatedLink.Link);
|
||||
tagBuilder.MergeAttribute("target", relatedLink.NewWindow ? "_blank" : "_self");
|
||||
tagBuilder.InnerHtml = HttpUtility.HtmlEncode(relatedLink.Caption);
|
||||
return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,8 @@ namespace Umbraco.Web.Models
|
||||
/// <inheritdoc />
|
||||
public abstract bool IsDraft(string culture = null);
|
||||
|
||||
public abstract bool IsPublished(string culture = null);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tree
|
||||
|
||||
11
src/Umbraco.Web/Models/RelatedLink.cs
Normal file
11
src/Umbraco.Web/Models/RelatedLink.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
public class RelatedLink : RelatedLinkBase
|
||||
{
|
||||
public int? Id { get; internal set; }
|
||||
internal bool IsDeleted { get; set; }
|
||||
public IPublishedContent Content { get; set; }
|
||||
}
|
||||
}
|
||||
18
src/Umbraco.Web/Models/RelatedLinkBase.cs
Normal file
18
src/Umbraco.Web/Models/RelatedLinkBase.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
public abstract class RelatedLinkBase
|
||||
{
|
||||
[JsonProperty("caption")]
|
||||
public string Caption { get; set; }
|
||||
[JsonProperty("link")]
|
||||
public string Link { get; set; }
|
||||
[JsonProperty("newWindow")]
|
||||
public bool NewWindow { get; set; }
|
||||
[JsonProperty("isInternal")]
|
||||
public bool IsInternal { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public RelatedLinkType Type { get; set; }
|
||||
}
|
||||
}
|
||||
27
src/Umbraco.Web/Models/RelatedLinkType.cs
Normal file
27
src/Umbraco.Web/Models/RelatedLinkType.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="RelatedLinkType.cs" company="Umbraco">
|
||||
// Umbraco
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Defines the RelatedLinkType type.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The related link type.
|
||||
/// </summary>
|
||||
public enum RelatedLinkType
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal link type
|
||||
/// </summary>
|
||||
Internal,
|
||||
|
||||
/// <summary>
|
||||
/// External link type
|
||||
/// </summary>
|
||||
External
|
||||
}
|
||||
}
|
||||
42
src/Umbraco.Web/Models/RelatedLinks.cs
Normal file
42
src/Umbraco.Web/Models/RelatedLinks.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Web.Models
|
||||
{
|
||||
[TypeConverter(typeof(RelatedLinksTypeConverter))]
|
||||
public class RelatedLinks : IEnumerable<RelatedLink>
|
||||
{
|
||||
private readonly string _propertyData;
|
||||
|
||||
private readonly IEnumerable<RelatedLink> _relatedLinks;
|
||||
|
||||
public RelatedLinks(IEnumerable<RelatedLink> relatedLinks, string propertyData)
|
||||
{
|
||||
_relatedLinks = relatedLinks;
|
||||
_propertyData = propertyData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property data.
|
||||
/// </summary>
|
||||
internal string PropertyData
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._propertyData;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<RelatedLink> GetEnumerator()
|
||||
{
|
||||
return _relatedLinks.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/Umbraco.Web/Mvc/OnlyLocalRequestsAttribute.cs
Normal file
20
src/Umbraco.Web/Mvc/OnlyLocalRequestsAttribute.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Filters;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
public class OnlyLocalRequestsAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuting(HttpActionContext actionContext)
|
||||
{
|
||||
if (!actionContext.Request.IsLocal())
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/Umbraco.Web/PropertyEditors/RelatedLinksConfiguration.cs
Normal file
13
src/Umbraco.Web/PropertyEditors/RelatedLinksConfiguration.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration for the related links value editor.
|
||||
/// </summary>
|
||||
public class RelatedLinksConfiguration
|
||||
{
|
||||
[ConfigurationField("max", "Maximum number of links", "number", Description = "Enter the maximum amount of links to be added, enter 0 for unlimited")]
|
||||
public int Maximum { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration editor for the related links value editor.
|
||||
/// </summary>
|
||||
public class RelatedLinksConfigurationEditor : ConfigurationEditor
|
||||
{
|
||||
public override IDictionary<string, object> ToValueEditor(object configuration)
|
||||
{
|
||||
var d = base.ToValueEditor(configuration);
|
||||
d["idType"] = "udi";
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[DataEditor(Constants.PropertyEditors.Aliases.RelatedLinks, "Related links", "relatedlinks", ValueType = ValueTypes.Json, Icon = "icon-thumbnail-list", Group = "pickers")]
|
||||
public class RelatedLinksPropertyEditor : DataEditor
|
||||
{
|
||||
public RelatedLinksPropertyEditor(ILogger logger)
|
||||
: base(logger)
|
||||
{ }
|
||||
|
||||
protected override IConfigurationEditor CreateConfigurationEditor() => new RelatedLinksConfigurationEditor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter(typeof(JsonValueConverter))] //this shadows the JsonValueConverter
|
||||
public class RelatedLinksLegacyValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private static readonly string[] MatchingEditors = {
|
||||
Constants.PropertyEditors.Aliases.RelatedLinks
|
||||
};
|
||||
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ServiceContext _services;
|
||||
|
||||
public RelatedLinksLegacyValueConverter(IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, ILogger logger)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> MatchingEditors.Contains(propertyType.EditorAlias);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (JArray);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null) return null;
|
||||
var sourceString = source.ToString();
|
||||
|
||||
if (sourceString.DetectIsJson())
|
||||
{
|
||||
try
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<JArray>(sourceString);
|
||||
//update the internal links if we have a context
|
||||
if (UmbracoContext.Current != null)
|
||||
{
|
||||
var helper = new UmbracoHelper(_umbracoContextAccessor.UmbracoContext, _services);
|
||||
foreach (var a in obj)
|
||||
{
|
||||
var type = a.Value<string>("type");
|
||||
if (type.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
if (type == "internal")
|
||||
{
|
||||
switch (propertyType.EditorAlias)
|
||||
{
|
||||
case Constants.PropertyEditors.Aliases.RelatedLinks:
|
||||
var strLinkId = a.Value<string>("link");
|
||||
var udiAttempt = strLinkId.TryConvertTo<Udi>();
|
||||
if (udiAttempt)
|
||||
{
|
||||
var content = helper.PublishedContent(udiAttempt.Result);
|
||||
if (content == null) break;
|
||||
a["link"] = helper.Url(content.Id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<RelatedLinksLegacyValueConverter>(ex, "Could not parse the string '{Json}' to a json object", sourceString);
|
||||
}
|
||||
}
|
||||
|
||||
//it's not json, just return the string
|
||||
return sourceString;
|
||||
}
|
||||
|
||||
public override object ConvertIntermediateToXPath(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object source, bool preview)
|
||||
{
|
||||
if (source == null) return null;
|
||||
var sourceString = source.ToString();
|
||||
|
||||
if (sourceString.DetectIsJson())
|
||||
{
|
||||
try
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<Array>(sourceString);
|
||||
|
||||
var d = new XmlDocument();
|
||||
var e = d.CreateElement("links");
|
||||
d.AppendChild(e);
|
||||
|
||||
foreach (dynamic link in obj)
|
||||
{
|
||||
var ee = d.CreateElement("link");
|
||||
ee.SetAttribute("title", link.title);
|
||||
ee.SetAttribute("link", link.link);
|
||||
ee.SetAttribute("type", link.type);
|
||||
ee.SetAttribute("newwindow", link.newWindow);
|
||||
|
||||
e.AppendChild(ee);
|
||||
}
|
||||
|
||||
return d.CreateNavigator();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<RelatedLinksLegacyValueConverter>(ex, "Could not parse the string '{Json}' to a json object", sourceString);
|
||||
}
|
||||
}
|
||||
|
||||
//it's not json, just return the string
|
||||
return sourceString;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// The related links property value converter.
|
||||
/// </summary>
|
||||
[DefaultPropertyValueConverter(typeof(RelatedLinksLegacyValueConverter), typeof(JsonValueConverter))]
|
||||
public class RelatedLinksValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public RelatedLinksValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IUmbracoContextAccessor umbracoContextAccessor, ILogger logger)
|
||||
{
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this converter can convert the property editor and registers if it can.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">
|
||||
/// The property type.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="bool"/>.
|
||||
/// </returns>
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
=> propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.RelatedLinks);
|
||||
|
||||
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
=> typeof (JArray);
|
||||
|
||||
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
|
||||
=> PropertyCacheLevel.Element;
|
||||
|
||||
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null) return null;
|
||||
var sourceString = source.ToString();
|
||||
|
||||
var relatedLinksData = JsonConvert.DeserializeObject<IEnumerable<RelatedLink>>(sourceString);
|
||||
var relatedLinks = new List<RelatedLink>();
|
||||
|
||||
foreach (var linkData in relatedLinksData)
|
||||
{
|
||||
var relatedLink = new RelatedLink
|
||||
{
|
||||
Caption = linkData.Caption,
|
||||
NewWindow = linkData.NewWindow,
|
||||
IsInternal = linkData.IsInternal,
|
||||
Type = linkData.Type,
|
||||
Link = linkData.Link
|
||||
};
|
||||
|
||||
int contentId;
|
||||
if (int.TryParse(relatedLink.Link, out contentId))
|
||||
{
|
||||
relatedLink.Id = contentId;
|
||||
relatedLink = CreateLink(relatedLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
var strLinkId = linkData.Link;
|
||||
var udiAttempt = strLinkId.TryConvertTo<GuidUdi>();
|
||||
if (udiAttempt.Success && udiAttempt.Result != null)
|
||||
{
|
||||
var content = _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(udiAttempt.Result.Guid);
|
||||
if (content != null)
|
||||
{
|
||||
relatedLink.Id = content.Id;
|
||||
relatedLink = CreateLink(relatedLink);
|
||||
relatedLink.Content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relatedLink.IsDeleted == false)
|
||||
{
|
||||
relatedLinks.Add(relatedLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn<RelatedLinksValueConverter>("Related Links value converter skipped a link as the node has been unpublished/deleted (Internal Link NodeId: {RelatedLinkNodeId}, Link Caption: '{RelatedLinkCaption}')", relatedLink.Link, relatedLink.Caption);
|
||||
}
|
||||
}
|
||||
|
||||
return new RelatedLinks(relatedLinks, sourceString);
|
||||
}
|
||||
|
||||
private RelatedLink CreateLink(RelatedLink link)
|
||||
{
|
||||
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
|
||||
|
||||
if (link.IsInternal && link.Id != null)
|
||||
{
|
||||
if (umbracoContext == null)
|
||||
return null;
|
||||
|
||||
var urlProvider = umbracoContext.UrlProvider;
|
||||
|
||||
link.Link = urlProvider.GetUrl((int)link.Id);
|
||||
if (link.Link.Equals("#"))
|
||||
{
|
||||
link.IsDeleted = true;
|
||||
link.Link = link.Id.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
link.IsDeleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public override object ConvertIntermediateToXPath(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
|
||||
{
|
||||
if (inter == null) return null;
|
||||
var sourceString = inter.ToString();
|
||||
|
||||
if (sourceString.DetectIsJson())
|
||||
{
|
||||
try
|
||||
{
|
||||
var obj = JsonConvert.DeserializeObject<Array>(sourceString);
|
||||
|
||||
var d = new XmlDocument();
|
||||
var e = d.CreateElement("links");
|
||||
d.AppendChild(e);
|
||||
|
||||
foreach (dynamic link in obj)
|
||||
{
|
||||
var ee = d.CreateElement("link");
|
||||
ee.SetAttribute("title", link.title);
|
||||
ee.SetAttribute("link", link.link);
|
||||
ee.SetAttribute("type", link.type);
|
||||
ee.SetAttribute("newwindow", link.newWindow);
|
||||
|
||||
e.AppendChild(ee);
|
||||
}
|
||||
|
||||
return d.CreateNavigator();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<RelatedLinksValueConverter>(ex, "Could not parse the string {Json} to a json object", sourceString);
|
||||
}
|
||||
}
|
||||
|
||||
//it's not json, just return the string
|
||||
return sourceString;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,6 +293,23 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return _contentData.CultureInfos.TryGetValue(culture, out var cvar) && cvar.IsDraft;
|
||||
}
|
||||
|
||||
public override bool IsPublished(string culture = null)
|
||||
{
|
||||
if (!ContentType.VariesByCulture())
|
||||
{
|
||||
return _contentData.Published;
|
||||
}
|
||||
|
||||
// handle context culture
|
||||
if (culture == null)
|
||||
{
|
||||
culture = VariationContextAccessor?.VariationContext?.Culture ?? "";
|
||||
}
|
||||
|
||||
//If the current culture is not a draft, it must be the published version
|
||||
return _contentData.CultureInfos.TryGetValue(culture, out var cvar) && !cvar.IsDraft;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tree
|
||||
|
||||
@@ -78,6 +78,8 @@ namespace Umbraco.Web.PublishedCache
|
||||
|
||||
public override bool IsDraft(string culture = null) => false;
|
||||
|
||||
public override bool IsPublished(string culture = null) => true;
|
||||
|
||||
public override IPublishedContent Parent => null;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children => Enumerable.Empty<IPublishedContent>();
|
||||
|
||||
@@ -179,6 +179,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
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;
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
private int _sortOrder;
|
||||
private int _level;
|
||||
private bool _isDraft;
|
||||
private bool _isPublished;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children
|
||||
{
|
||||
@@ -228,6 +229,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
return _isDraft; // bah
|
||||
}
|
||||
|
||||
public override bool IsPublished(string culture = null)
|
||||
{
|
||||
EnsureNodeInitialized();
|
||||
return _isPublished;
|
||||
}
|
||||
|
||||
public override IEnumerable<IPublishedProperty> Properties
|
||||
{
|
||||
get
|
||||
@@ -280,7 +287,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
InitializeNode(this, _xmlNode, _isPreviewing,
|
||||
out _id, out _key, out _template, out _sortOrder, out _name, out _writerName,
|
||||
out _urlName, out _creatorName, out _creatorId, out _writerId, out _docTypeAlias, out _docTypeId, out _path,
|
||||
out _createDate, out _updateDate, out _level, out _isDraft, out _contentType, out _properties,
|
||||
out _createDate, out _updateDate, out _level, out _isDraft, out _isPublished, out _contentType, out _properties,
|
||||
_contentTypeCache.Get);
|
||||
|
||||
_nodeInitialized = true;
|
||||
@@ -290,7 +297,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
internal static void InitializeNode(XmlPublishedContent node, XmlNode xmlNode, bool isPreviewing,
|
||||
out int id, out Guid key, out int template, out int sortOrder, out string name, out string writerName, out string urlName,
|
||||
out string creatorName, out int creatorId, out int writerId, out string docTypeAlias, out int docTypeId, out string path,
|
||||
out DateTime createDate, out DateTime updateDate, out int level, out bool isDraft,
|
||||
out DateTime createDate, out DateTime updateDate, out int level, out bool isDraft,out bool isPublished,
|
||||
out PublishedContentType contentType, out Dictionary<string, IPublishedProperty> properties,
|
||||
Func<PublishedItemType, string, PublishedContentType> getPublishedContentType)
|
||||
{
|
||||
@@ -302,6 +309,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
name = writerName = urlName = creatorName = docTypeAlias = path = null;
|
||||
createDate = updateDate = default(DateTime);
|
||||
isDraft = false;
|
||||
isPublished = false;
|
||||
contentType = null;
|
||||
properties = null;
|
||||
|
||||
|
||||
@@ -799,7 +799,7 @@ namespace Umbraco.Web
|
||||
return content.DescendantsOrSelf(false, p => p.Level >= level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, string contentTypeAlias, string culture)
|
||||
{
|
||||
return content.DescendantsOrSelf(false, p => p.ContentType.Alias == contentTypeAlias, culture);
|
||||
}
|
||||
@@ -826,7 +826,7 @@ namespace Umbraco.Web
|
||||
return content.DescendantsOrSelf(true, p => p.Level >= level, culture);
|
||||
}
|
||||
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
public static IEnumerable<IPublishedContent> DescendantsOrSelf(this IPublishedContent content, string contentTypeAlias, string culture)
|
||||
{
|
||||
return content.DescendantsOrSelf(true, p => p.ContentType.Alias == contentTypeAlias, culture);
|
||||
}
|
||||
@@ -853,7 +853,7 @@ namespace Umbraco.Web
|
||||
return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, string contentTypeAlias, string culture)
|
||||
{
|
||||
return content.EnumerateDescendants(false, culture).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias);
|
||||
}
|
||||
@@ -880,7 +880,7 @@ namespace Umbraco.Web
|
||||
return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string contentTypeAlias, string culture = null)
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, string contentTypeAlias, string culture)
|
||||
{
|
||||
return content.EnumerateDescendants(true, culture).FirstOrDefault(x => x.ContentType.Alias == contentTypeAlias);
|
||||
}
|
||||
@@ -954,14 +954,7 @@ namespace Umbraco.Web
|
||||
/// </remarks>
|
||||
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, string culture = null)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content)); // fixme/task wtf is this?
|
||||
|
||||
return content.Children.Where(x =>
|
||||
{
|
||||
if (!x.ContentType.VariesByCulture()) return true; // invariant = always ok
|
||||
return x.HasCulture(culture);
|
||||
return false;
|
||||
});
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
|
||||
return content.Children.WhereIsInvariantOrHasCulture(culture);
|
||||
}
|
||||
@@ -1017,7 +1010,7 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Gets the first child of the content, of a given content type.
|
||||
/// </summary>
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, string alias, string culture = null) // fixme/task oops
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, string alias, string culture)
|
||||
{
|
||||
return content.Children(culture,alias).FirstOrDefault();
|
||||
}
|
||||
|
||||
98
src/Umbraco.Web/RelatedLinksTypeConverter.cs
Normal file
98
src/Umbraco.Web/RelatedLinksTypeConverter.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
public class RelatedLinksTypeConverter : TypeConverter
|
||||
{
|
||||
private readonly UmbracoHelper _umbracoHelper;
|
||||
|
||||
public RelatedLinksTypeConverter(UmbracoHelper umbracoHelper)
|
||||
{
|
||||
_umbracoHelper = umbracoHelper;
|
||||
}
|
||||
|
||||
public RelatedLinksTypeConverter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static readonly Type[] ConvertableTypes = new[]
|
||||
{
|
||||
typeof(JArray)
|
||||
};
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
return ConvertableTypes.Any(x => TypeHelper.IsTypeAssignableFrom(x, destinationType))
|
||||
|| base.CanConvertFrom(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertTo(
|
||||
ITypeDescriptorContext context,
|
||||
CultureInfo culture,
|
||||
object value,
|
||||
Type destinationType)
|
||||
{
|
||||
var relatedLinks = value as RelatedLinks;
|
||||
if (relatedLinks == null)
|
||||
return null;
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<JArray>(destinationType))
|
||||
{
|
||||
// Conversion to JArray taken from old value converter
|
||||
|
||||
var obj = JsonConvert.DeserializeObject<JArray>(relatedLinks.PropertyData);
|
||||
|
||||
var umbracoHelper = GetUmbracoHelper();
|
||||
|
||||
//update the internal links if we have a context
|
||||
if (umbracoHelper != null)
|
||||
{
|
||||
foreach (var a in obj)
|
||||
{
|
||||
var type = a.Value<string>("type");
|
||||
if (type.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
if (type == "internal")
|
||||
{
|
||||
var linkId = a.Value<int>("link");
|
||||
var link = umbracoHelper.Url(linkId);
|
||||
a["link"] = link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
|
||||
private UmbracoHelper GetUmbracoHelper()
|
||||
{
|
||||
if (_umbracoHelper != null)
|
||||
return _umbracoHelper;
|
||||
|
||||
if (UmbracoContext.Current == null)
|
||||
{
|
||||
Current.Logger.Warn<RelatedLinksTypeConverter>("Cannot create an UmbracoHelper the UmbracoContext is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
//DO NOT assign to _umbracoHelper variable, this is a singleton class and we cannot assign this based on an UmbracoHelper which is request based
|
||||
return new UmbracoHelper(UmbracoContext.Current, Current.Services);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,6 +186,7 @@
|
||||
<Compile Include="Services\IDashboardService.cs" />
|
||||
<Compile Include="Models\Link.cs" />
|
||||
<Compile Include="Models\LinkType.cs" />
|
||||
<Compile Include="Mvc\OnlyLocalRequestsAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerConfiguration.cs" />
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerConfigurationEditor.cs" />
|
||||
<Compile Include="PropertyEditors\MultiUrlPickerPropertyEditor.cs" />
|
||||
@@ -417,6 +418,10 @@
|
||||
<Compile Include="Models\Mapping\ContentItemDisplayVariationResolver.cs" />
|
||||
<Compile Include="Models\PublishedContent\HttpContextVariationContextAccessor.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedValueFallback.cs" />
|
||||
<Compile Include="Models\RelatedLink.cs" />
|
||||
<Compile Include="Models\RelatedLinkBase.cs" />
|
||||
<Compile Include="Models\RelatedLinks.cs" />
|
||||
<Compile Include="Models\RelatedLinkType.cs" />
|
||||
<Compile Include="Models\SendCodeViewModel.cs" />
|
||||
<Compile Include="Models\Trees\ExportMember.cs" />
|
||||
<Compile Include="Models\UserTourStatus.cs" />
|
||||
@@ -462,6 +467,9 @@
|
||||
<Compile Include="PropertyEditors\NestedContentPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\ParameterEditors\MultipleContentPickerParameterEditor.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditorsComponent.cs" />
|
||||
<Compile Include="PropertyEditors\RelatedLinksPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\RelatedLinksConfiguration.cs" />
|
||||
<Compile Include="PropertyEditors\RelatedLinksConfigurationEditor.cs" />
|
||||
<Compile Include="PropertyEditors\RichTextConfiguration.cs" />
|
||||
<Compile Include="PropertyEditors\SliderConfigurationEditor.cs" />
|
||||
<Compile Include="PropertyEditors\TagConfigurationEditor.cs" />
|
||||
@@ -477,6 +485,7 @@
|
||||
<Compile Include="PropertyEditors\ValueConverters\NestedContentManyValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\NestedContentValueConverterBase.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\NestedContentSingleValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\RelatedLinksLegacyValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MediaPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MemberPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MultiNodeTreePickerValueConverter.cs" />
|
||||
@@ -540,6 +549,7 @@
|
||||
<Compile Include="PublishedCache\XmlPublishedCache\XmlStoreFilePersister.cs" />
|
||||
<Compile Include="PublishedElementExtensions.cs" />
|
||||
<Compile Include="PublishedModels\DummyClassSoThatPublishedModelsNamespaceExists.cs" />
|
||||
<Compile Include="RelatedLinksTypeConverter.cs" />
|
||||
<Compile Include="Routing\ContentFinderByUrl.cs" />
|
||||
<Compile Include="Routing\ContentFinderByUrlAndTemplate.cs" />
|
||||
<Compile Include="Routing\ContentFinderCollection.cs" />
|
||||
@@ -862,6 +872,7 @@
|
||||
<Compile Include="PropertyEditors\TagsPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\UploadFileTypeValidator.cs" />
|
||||
<Compile Include="PropertyEditors\UserPickerPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\RelatedLinksValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueListConfigurationEditor.cs" />
|
||||
<Compile Include="PublishedContentQuery.cs" />
|
||||
<Compile Include="ImageCropperTemplateExtensions.cs" />
|
||||
|
||||
@@ -469,6 +469,11 @@ namespace umbraco
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsPublished(string culture = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPublishedContent Parent
|
||||
{
|
||||
get { return _parent; }
|
||||
|
||||
Reference in New Issue
Block a user