Merge branch 'temp8' into temp8-injection-ihttpcontextaccessor-instead-of-controller

# Conflicts:
#	src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
#	src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
This commit is contained in:
Bjarke Berg
2019-02-18 09:10:47 +01:00
59 changed files with 850 additions and 659 deletions

View File

@@ -219,7 +219,7 @@ namespace Umbraco.Core
},
{
FailedPasswordAttempts,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Integer, true, FailedPasswordAttempts)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, FailedPasswordAttempts)
{
Name = FailedPasswordAttemptsLabel
}
@@ -240,35 +240,35 @@ namespace Umbraco.Core
},
{
LastLockoutDate,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, true, LastLockoutDate)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLockoutDate)
{
Name = LastLockoutDateLabel
}
},
{
LastLoginDate,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, true, LastLoginDate)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLoginDate)
{
Name = LastLoginDateLabel
}
},
{
LastPasswordChangeDate,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, true, LastPasswordChangeDate)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastPasswordChangeDate)
{
Name = LastPasswordChangeDateLabel
}
},
{
PasswordAnswer,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar, true, PasswordAnswer)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordAnswer)
{
Name = PasswordAnswerLabel
}
},
{
PasswordQuestion,
new PropertyType(PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar, true, PasswordQuestion)
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordQuestion)
{
Name = PasswordQuestionLabel
}

View File

@@ -105,9 +105,9 @@ namespace Umbraco.Core
public const string MultipleTextstring = "Umbraco.MultipleTextstring";
/// <summary>
/// NoEdit.
/// Label.
/// </summary>
public const string NoEdit = "Umbraco.NoEdit";
public const string Label = "Umbraco.Label";
/// <summary>
/// Picker Relations.
@@ -142,7 +142,7 @@ namespace Umbraco.Core
/// <summary>
/// TinyMCE
/// </summary>
public const string TinyMce = "Umbraco.TinyMCEv3";
public const string TinyMce = "Umbraco.TinyMCE";
/// <summary>
/// Boolean.

View File

@@ -271,12 +271,12 @@ namespace Umbraco.Core.Migrations.Install
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -88, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -89, EditorAlias = Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -90, EditorAlias = Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" });
InsertDataTypeDto(Constants.DataTypes.LabelString, Constants.PropertyEditors.Aliases.NoEdit, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}");
InsertDataTypeDto(Constants.DataTypes.LabelInt, Constants.PropertyEditors.Aliases.NoEdit, "Integer", "{\"umbracoDataValueType\":\"INT\"}");
InsertDataTypeDto(Constants.DataTypes.LabelBigint, Constants.PropertyEditors.Aliases.NoEdit, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}");
InsertDataTypeDto(Constants.DataTypes.LabelDateTime, Constants.PropertyEditors.Aliases.NoEdit, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}");
InsertDataTypeDto(Constants.DataTypes.LabelDecimal, Constants.PropertyEditors.Aliases.NoEdit, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}");
InsertDataTypeDto(Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.NoEdit, "Date", "{\"umbracoDataValueType\":\"TIME\"}");
InsertDataTypeDto(Constants.DataTypes.LabelString, Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}");
InsertDataTypeDto(Constants.DataTypes.LabelInt, Constants.PropertyEditors.Aliases.Label, "Integer", "{\"umbracoDataValueType\":\"INT\"}");
InsertDataTypeDto(Constants.DataTypes.LabelBigint, Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}");
InsertDataTypeDto(Constants.DataTypes.LabelDateTime, Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}");
InsertDataTypeDto(Constants.DataTypes.LabelDecimal, Constants.PropertyEditors.Aliases.Label, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}");
InsertDataTypeDto(Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"TIME\"}");
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -36, EditorAlias = Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" });
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -37, EditorAlias = Constants.PropertyEditors.Aliases.ColorPicker, DbType = "Nvarchar" });
InsertDataTypeDto(Constants.DataTypes.DropDownSingle, Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":false}");

View File

@@ -135,6 +135,8 @@ namespace Umbraco.Core.Migrations.Upgrade
.To<RadioAndCheckboxAndDropdownPropertyEditorsMigration>("{940FD19A-00A8-4D5C-B8FF-939143585726}")
.As("{0576E786-5C30-4000-B969-302B61E90CA3}");
To<RenameLabelAndRichTextPropertyEditorAliases>("{E0CBE54D-A84F-4A8F-9B13-900945FD7ED9}");
//FINAL

View File

@@ -53,7 +53,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
var dataTypeDto = new DataTypeDto
{
NodeId = id,
EditorAlias = Constants.PropertyEditors.Aliases.NoEdit,
EditorAlias = Constants.PropertyEditors.Aliases.Label,
DbType = dbType
};

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class RenameLabelAndRichTextPropertyEditorAliases : MigrationBase
{
public RenameLabelAndRichTextPropertyEditorAliases(IMigrationContext context)
: base(context)
{
}
public override void Migrate()
{
MigratePropertyEditorAlias("Umbraco.TinyMCEv3", Constants.PropertyEditors.Aliases.TinyMce);
MigratePropertyEditorAlias("Umbraco.NoEdit", Constants.PropertyEditors.Aliases.Label);
}
private void MigratePropertyEditorAlias(string oldAlias, string newAlias)
{
var dataTypes = GetDataTypes(oldAlias);
foreach (var dataType in dataTypes)
{
dataType.EditorAlias = newAlias;
Database.Update(dataType);
}
}
private List<DataTypeDto> GetDataTypes(string editorAlias)
{
var dataTypes = Database.Fetch<DataTypeDto>(Sql()
.Select<DataTypeDto>()
.From<DataTypeDto>()
.Where<DataTypeDto>(x => x.EditorAlias == editorAlias));
return dataTypes;
}
}
}

View File

@@ -735,7 +735,7 @@ namespace Umbraco.Core.Packaging
property.Element("Name").Value, dataTypeDefinitionId, property.Element("Type").Value.Trim());
//convert to a label!
dataTypeDefinition = _dataTypeService.GetByEditorAlias(Constants.PropertyEditors.Aliases.NoEdit).FirstOrDefault();
dataTypeDefinition = _dataTypeService.GetByEditorAlias(Constants.PropertyEditors.Aliases.Label).FirstOrDefault();
//if for some odd reason this isn't there then ignore
if (dataTypeDefinition == null) continue;
}

View File

@@ -5,7 +5,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Represents a property editor for label properties.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.NoEdit, "Label", "readonlyvalue", Icon = "icon-readonly")]
[DataEditor(Constants.PropertyEditors.Aliases.Label, "Label", "readonlyvalue", Icon = "icon-readonly")]
public class LabelPropertyEditor : DataEditor
{
/// <summary>

View File

@@ -17,7 +17,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public class LabelValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
=> Constants.PropertyEditors.Aliases.NoEdit.Equals(propertyType.EditorAlias);
=> Constants.PropertyEditors.Aliases.Label.Equals(propertyType.EditorAlias);
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
{

View File

@@ -1212,21 +1212,21 @@ namespace Umbraco.Core.Services.Implement
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, Constants.Conventions.Member.LastLockoutDate)
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, Constants.Conventions.Member.LastLockoutDate)
{
Name = Constants.Conventions.Member.LastLockoutDateLabel,
SortOrder = 5,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, Constants.Conventions.Member.LastLoginDate)
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, Constants.Conventions.Member.LastLoginDate)
{
Name = Constants.Conventions.Member.LastLoginDateLabel,
SortOrder = 6,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Date, Constants.Conventions.Member.LastPasswordChangeDate)
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Date, Constants.Conventions.Member.LastPasswordChangeDate)
{
Name = Constants.Conventions.Member.LastPasswordChangeDateLabel,
SortOrder = 7,

View File

@@ -205,6 +205,7 @@
<Compile Include="Composing\TypeFinder.cs" />
<Compile Include="Composing\TypeHelper.cs" />
<Compile Include="Composing\TypeLoader.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameLabelAndRichTextPropertyEditorAliases.cs" />
<Compile Include="TypeLoaderExtensions.cs" />
<Compile Include="Composing\WeightAttribute.cs" />
<Compile Include="Composing\WeightedCollectionBuilderBase.cs" />

View File

@@ -70,7 +70,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
/// <param name="appCache"></param>
/// <param name="contentTypeCache"></param>
/// <param name="entitySerializer"></param>
internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, IAppCache appCache, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer)
internal PublishedMediaCache(IMediaService mediaService, IUserService userService, ISearcher searchProvider, IAppCache appCache, PublishedContentTypeCache contentTypeCache, IEntityXmlSerializer entitySerializer, IUmbracoContextAccessor umbracoContextAccessor)
: base(false)
{
_mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService));
@@ -79,6 +79,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
_appCache = appCache;
_contentTypeCache = contentTypeCache;
_entitySerializer = entitySerializer;
_umbracoContextAccessor = umbracoContextAccessor;
}
static PublishedMediaCache()

View File

@@ -344,7 +344,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Assert
Assert.That(definitionUpdated, Is.Not.Null);
Assert.That(definitionUpdated.Name, Is.EqualTo("AgeDataType Updated"));
Assert.That(definitionUpdated.EditorAlias, Is.EqualTo(Constants.PropertyEditors.Aliases.NoEdit));
Assert.That(definitionUpdated.EditorAlias, Is.EqualTo(Constants.PropertyEditors.Aliases.Label));
}
}

View File

@@ -23,6 +23,7 @@ using Umbraco.Core.Models.Membership;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Tests.LegacyXmlPublishedCache;
using Umbraco.Tests.Testing.Objects.Accessors;
namespace Umbraco.Tests.PublishedContent
{
@@ -44,6 +45,8 @@ namespace Umbraco.Tests.PublishedContent
Composition.WithCollectionBuilder<UrlSegmentProviderCollectionBuilder>()
.Clear()
.Append<DefaultUrlSegmentProvider>();
Composition.RegisterUnique<IUmbracoContextAccessor, TestUmbracoContextAccessor>();
}
private IMediaType MakeNewMediaType(IUser user, string text, int parentId = -1)
@@ -126,7 +129,7 @@ namespace Umbraco.Tests.PublishedContent
var searcher = indexer.GetSearcher();
var ctx = GetUmbracoContext("/test");
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -156,7 +159,7 @@ namespace Umbraco.Tests.PublishedContent
var searcher = indexer.GetSearcher();
var ctx = GetUmbracoContext("/test");
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//ensure it is found
var publishedMedia = cache.GetById(3113);
@@ -203,7 +206,7 @@ namespace Umbraco.Tests.PublishedContent
var searcher = indexer.GetSearcher();
var ctx = GetUmbracoContext("/test");
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -231,7 +234,7 @@ namespace Umbraco.Tests.PublishedContent
var searcher = indexer.GetSearcher();
var ctx = GetUmbracoContext("/test");
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -259,7 +262,7 @@ namespace Umbraco.Tests.PublishedContent
var searcher = indexer.GetSearcher();
var ctx = GetUmbracoContext("/test");
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(1111);
@@ -288,7 +291,7 @@ namespace Umbraco.Tests.PublishedContent
var ctx = GetUmbracoContext("/test");
var searcher = indexer.GetSearcher();
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(3113);
@@ -314,7 +317,7 @@ namespace Umbraco.Tests.PublishedContent
var ctx = GetUmbracoContext("/test");
var searcher = indexer.GetSearcher();
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>());
var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance<IEntityXmlSerializer>(), Factory.GetInstance<IUmbracoContextAccessor>());
//we are using the media.xml media to test the examine results implementation, see the media.xml file in the ExamineHelpers namespace
var publishedMedia = cache.GetById(3113);

View File

@@ -25,6 +25,7 @@ using Umbraco.Core.Services;
using Umbraco.Tests.PublishedContent;
using Umbraco.Tests.Testing;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Runtime;
using Umbraco.Web.Security;
using Current = Umbraco.Web.Composing.Current;
@@ -144,13 +145,14 @@ namespace Umbraco.Tests.Routing
var handler = new RenderRouteHandler(umbracoContext, new TestControllerFactory(umbracoContextAccessor, Mock.Of<ILogger>(), context =>
{
var membershipHelper = new MembershipHelper(umbracoContextAccessor, Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var membershipHelper = new MembershipHelper(
umbracoContext.HttpContext, Mock.Of<IPublishedMemberCache>(), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
return new CustomDocumentController(Factory.GetInstance<IGlobalSettings>(),
umbracoContextAccessor,
Factory.GetInstance<ServiceContext>(),
Factory.GetInstance<AppCaches>(),
Factory.GetInstance<IProfilingLogger>(),
new UmbracoHelper(umbracoContext, Mock.Of<ITagQuery>(), Mock.Of<ICultureDictionaryFactory>(), Mock.Of<IUmbracoComponentRenderer>(), Mock.Of<IPublishedContentQuery>(), membershipHelper));
new UmbracoHelper(Mock.Of<IPublishedContent>(), Mock.Of<ITagQuery>(), Mock.Of<ICultureDictionaryFactory>(), Mock.Of<IUmbracoComponentRenderer>(), Mock.Of<IPublishedContentQuery>(), membershipHelper));
}));
handler.GetHandlerForRoute(umbracoContext.HttpContext.Request.RequestContext, frequest);

View File

@@ -71,7 +71,7 @@
<GenericProperty>
<Name>Content</Name>
<Alias>content</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Type>Umbraco.TinyMCE</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>

View File

@@ -324,7 +324,7 @@
<GenericProperty>
<Name>AboutText</Name>
<Alias>aboutText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Type>Umbraco.TinyMCE</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>About</Tab>
<Mandatory>False</Mandatory>
@@ -472,7 +472,7 @@
<GenericProperty>
<Name>Content</Name>
<Alias>bodyText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Type>Umbraco.TinyMCE</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>
@@ -593,7 +593,7 @@
<GenericProperty>
<Name>Content</Name>
<Alias>bodyText</Alias>
<Type>Umbraco.TinyMCEv3</Type>
<Type>Umbraco.TinyMCE</Type>
<Definition>ca90c950-0aff-4e72-b976-a30b1ac57dad</Definition>
<Tab>Content</Tab>
<Mandatory>False</Mandatory>

View File

@@ -9,7 +9,6 @@ using System.Web.Http.Dispatcher;
using System.Web.Security;
using Moq;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Models.Membership;
@@ -150,9 +149,9 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
urlHelper.Setup(provider => provider.GetUrl(It.IsAny<UmbracoContext>(), It.IsAny<IPublishedContent>(), It.IsAny<UrlProviderMode>(), It.IsAny<string>(), It.IsAny<Uri>()))
.Returns(UrlInfo.Url("/hello/world/1234"));
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var membershipHelper = new MembershipHelper(umbCtx.HttpContext, Mock.Of<IPublishedMemberCache>(), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var umbHelper = new UmbracoHelper(umbCtx,
var umbHelper = new UmbracoHelper(Mock.Of<IPublishedContent>(),
Mock.Of<ITagQuery>(),
Mock.Of<ICultureDictionaryFactory>(),
Mock.Of<IUmbracoComponentRenderer>(),

View File

@@ -359,7 +359,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Nvarchar) { Alias = "singleLineText", Name = "Text String", Mandatory = false, SortOrder = 4, DataTypeId = -88 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.TextArea, ValueStorageType.Ntext) { Alias = "multilineText", Name = "Multiple Text Strings", Mandatory = false, SortOrder = 5, DataTypeId = -89 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.UploadField, ValueStorageType.Nvarchar) { Alias = "upload", Name = "Upload Field", Mandatory = false, SortOrder = 6, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeId = -92 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeId = -92 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DateTime, ValueStorageType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeId = -36 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ColorPicker, ValueStorageType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeId = -37 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListFlexible, ValueStorageType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeId = -39 });
@@ -420,10 +420,10 @@ namespace Umbraco.Tests.TestHelpers.Entities
var contentCollection = new PropertyTypeCollection(false);
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.UploadField, ValueStorageType.Nvarchar) { Alias = Constants.Conventions.Media.File, Name = "File", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Width, Name = "Width", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Height, Name = "Height", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Bytes, Name = "Bytes", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar) { Alias = Constants.Conventions.Media.Extension, Name = "File Extension", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Width, Name = "Width", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Height, Name = "Height", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Integer) { Alias = Constants.Conventions.Media.Bytes, Name = "Bytes", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar) { Alias = Constants.Conventions.Media.Extension, Name = "File Extension", Description = "", Mandatory = false, SortOrder = 2, DataTypeId = -90 });
mediaType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Media", SortOrder = 1 });

View File

@@ -16,6 +16,7 @@ using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Current = Umbraco.Web.Composing.Current;
@@ -60,12 +61,12 @@ namespace Umbraco.Tests.Testing.TestingTests
Composition.Register<ServiceContext>();
// ReSharper disable once UnusedVariable
var helper = new UmbracoHelper(umbracoContext,
var helper = new UmbracoHelper(Mock.Of<IPublishedContent>(),
Mock.Of<ITagQuery>(),
Mock.Of<ICultureDictionaryFactory>(),
Mock.Of<IUmbracoComponentRenderer>(),
Mock.Of<IPublishedContentQuery>(),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
new MembershipHelper(umbracoContext.HttpContext, Mock.Of<IPublishedMemberCache>(), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
Assert.Pass();
}

View File

@@ -262,7 +262,7 @@
<Compile Include="StringNewlineExtensions.cs" />
<Compile Include="Strings\StylesheetHelperTests.cs" />
<Compile Include="Strings\StringValidationTests.cs" />
<Compile Include="FrontEnd\UmbracoHelperTests.cs" />
<Compile Include="Web\UmbracoHelperTests.cs" />
<Compile Include="Membership\MembershipProviderBaseTests.cs" />
<Compile Include="Membership\UmbracoServiceMembershipProviderTests.cs" />
<Compile Include="Migrations\Stubs\FiveZeroMigration.cs" />
@@ -491,6 +491,7 @@
<Compile Include="Routing\UmbracoModuleTests.cs" />
<Compile Include="CoreThings\VersionExtensionTests.cs" />
<Compile Include="Web\TemplateUtilitiesTests.cs" />
<Compile Include="Web\UrlHelperExtensionTests.cs" />
<Compile Include="Web\WebExtensionMethodTests.cs" />
<Compile Include="CoreThings\XmlExtensionsTests.cs" />
<Compile Include="Misc\XmlHelperTests.cs" />

View File

@@ -7,6 +7,9 @@ namespace Umbraco.Tests.Web.Mvc
[TestFixture]
public class HtmlHelperExtensionMethodsTests
{
private const string SampleWithAnchorElement = "Hello world, this is some text <a href='blah'>with a link</a>";
private const string SampleWithBoldAndAnchorElements = "Hello world, <b>this</b> is some text <a href='blah'>with a link</a>";
[SetUp]
public virtual void Initialize()
{
@@ -29,5 +32,99 @@ 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 static void Truncate_Simple()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.Truncate(SampleWithAnchorElement, 25).ToString();
Assert.AreEqual("Hello world, this is some&hellip;", result);
}
[Test]
public static void When_Truncating_A_String_Ends_With_A_Space_We_Should_Trim_The_Space_Before_Appending_The_Ellipsis()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.Truncate(SampleWithAnchorElement, 26).ToString();
Assert.AreEqual("Hello world, this is some&hellip;", result);
}
[Test]
public static void Truncate_Inside_Word()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.Truncate(SampleWithAnchorElement, 24).ToString();
Assert.AreEqual("Hello world, this is som&hellip;", result);
}
[Test]
public static void Truncate_With_Tag()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.Truncate(SampleWithAnchorElement, 35).ToString();
Assert.AreEqual("Hello world, this is some text <a href='blah'>with&hellip;</a>", result);
}
[Test]
public static void Truncate_By_Words()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.TruncateByWords(SampleWithAnchorElement, 4).ToString();
Assert.AreEqual("Hello world, this is&hellip;", result);
}
[Test]
public static void Truncate_By_Words_With_Tag()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.TruncateByWords(SampleWithBoldAndAnchorElements, 4).ToString();
Assert.AreEqual("Hello world, <b>this</b> is&hellip;", result);
}
[Test]
public static void Truncate_By_Words_Mid_Tag()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.TruncateByWords(SampleWithAnchorElement, 7).ToString();
Assert.AreEqual("Hello world, this is some text <a href='blah'>with&hellip;</a>", result);
}
[Test]
public static void Strip_All_Html()
{
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.StripHtml(SampleWithBoldAndAnchorElements, null).ToString();
Assert.AreEqual("Hello world, this is some text with a link", result);
}
[Test]
public static void Strip_Specific_Html()
{
string[] tags = { "b" };
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.StripHtml(SampleWithBoldAndAnchorElements, tags).ToString();
Assert.AreEqual(SampleWithAnchorElement, result);
}
[Test]
public static void Strip_Invalid_Html()
{
const string text = "Hello world, <bthis</b> is some text <a href='blah'>with a link</a>";
var helper = new HtmlHelper(new ViewContext(), new ViewPage());
var result = helper.StripHtml(text).ToString();
Assert.AreEqual("Hello world, is some text with a link", result);
}
}
}

View File

@@ -7,14 +7,12 @@ using System.Web.Security;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web;
@@ -114,12 +112,12 @@ namespace Umbraco.Tests.Web.Mvc
var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext);
var helper = new UmbracoHelper(
umbracoContext,
content.Object,
Mock.Of<ITagQuery>(),
Mock.Of<ICultureDictionaryFactory>(),
Mock.Of<IUmbracoComponentRenderer>(),
Mock.Of<IPublishedContentQuery>(query => query.Content(2) == content.Object),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
new MembershipHelper(umbracoContext.HttpContext, Mock.Of<IPublishedMemberCache>(), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
var ctrl = new TestSurfaceController(umbracoContextAccessor, helper);
var result = ctrl.GetContent(2) as PublishedContentResult;

View File

@@ -1,183 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Tests.TestHelpers;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
namespace Umbraco.Tests.FrontEnd
namespace Umbraco.Tests.Web
{
[TestFixture]
public class UmbracoHelperTests
{
private const string SampleWithAnchorElement = "Hello world, this is some text <a href='blah'>with a link</a>";
private const string SampleWithBoldAndAnchorElements = "Hello world, <b>this</b> is some text <a href='blah'>with a link</a>";
[TearDown]
public void TearDown()
{
Current.Reset();
}
[Test]
public static void Truncate_Simple()
{
var helper = new UmbracoHelper();
var result = helper.Truncate(SampleWithAnchorElement, 25).ToString();
Assert.AreEqual("Hello world, this is some&hellip;", result);
}
[Test]
public static void When_Truncating_A_String_Ends_With_A_Space_We_Should_Trim_The_Space_Before_Appending_The_Ellipsis()
{
var helper = new UmbracoHelper();
var result = helper.Truncate(SampleWithAnchorElement, 26).ToString();
Assert.AreEqual("Hello world, this is some&hellip;", result);
}
[Test]
public static void Truncate_Inside_Word()
{
var helper = new UmbracoHelper();
var result = helper.Truncate(SampleWithAnchorElement, 24).ToString();
Assert.AreEqual("Hello world, this is som&hellip;", result);
}
[Test]
public static void Truncate_With_Tag()
{
var helper = new UmbracoHelper();
var result = helper.Truncate(SampleWithAnchorElement, 35).ToString();
Assert.AreEqual("Hello world, this is some text <a href='blah'>with&hellip;</a>", result);
}
[Test]
public static void Create_Encrypted_RouteString_From_Anonymous_Object()
{
var additionalRouteValues = new
{
key1 = "value1",
key2 = "value2",
Key3 = "Value3",
keY4 = "valuE4"
};
var encryptedRouteString = UmbracoHelper.CreateEncryptedRouteString(
"FormController",
"FormAction",
"",
additionalRouteValues
);
var result = encryptedRouteString.DecryptWithMachineKey();
const string expectedResult = "c=FormController&a=FormAction&ar=&key1=value1&key2=value2&Key3=Value3&keY4=valuE4";
Assert.AreEqual(expectedResult, result);
}
[Test]
public static void Create_Encrypted_RouteString_From_Dictionary()
{
var additionalRouteValues = new Dictionary<string, object>()
{
{"key1", "value1"},
{"key2", "value2"},
{"Key3", "Value3"},
{"keY4", "valuE4"}
};
var encryptedRouteString = UmbracoHelper.CreateEncryptedRouteString(
"FormController",
"FormAction",
"",
additionalRouteValues
);
var result = encryptedRouteString.DecryptWithMachineKey();
const string expectedResult = "c=FormController&a=FormAction&ar=&key1=value1&key2=value2&Key3=Value3&keY4=valuE4";
Assert.AreEqual(expectedResult, result);
}
[Test]
public static void Truncate_By_Words()
{
var helper = new UmbracoHelper();
var result = helper.TruncateByWords(SampleWithAnchorElement, 4).ToString();
Assert.AreEqual("Hello world, this is&hellip;", result);
}
[Test]
public static void Truncate_By_Words_With_Tag()
{
var helper = new UmbracoHelper();
var result = helper.TruncateByWords(SampleWithBoldAndAnchorElements, 4).ToString();
Assert.AreEqual("Hello world, <b>this</b> is&hellip;", result);
}
[Test]
public static void Truncate_By_Words_Mid_Tag()
{
var helper = new UmbracoHelper();
var result = helper.TruncateByWords(SampleWithAnchorElement, 7).ToString();
Assert.AreEqual("Hello world, this is some text <a href='blah'>with&hellip;</a>", result);
}
[Test]
public static void Strip_All_Html()
{
var helper = new UmbracoHelper();
var result = helper.StripHtml(SampleWithBoldAndAnchorElements, null).ToString();
Assert.AreEqual("Hello world, this is some text with a link", result);
}
[Test]
public static void Strip_Specific_Html()
{
string[] tags = { "b" };
var helper = new UmbracoHelper();
var result = helper.StripHtml(SampleWithBoldAndAnchorElements, tags).ToString();
Assert.AreEqual(SampleWithAnchorElement, result);
}
[Test]
public static void Strip_Invalid_Html()
{
const string text = "Hello world, <bthis</b> is some text <a href='blah'>with a link</a>";
var helper = new UmbracoHelper();
var result = helper.StripHtml(text).ToString();
Assert.AreEqual("Hello world, is some text with a link", result);
}
// ------- Int32 conversion tests
[Test]

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Web;
namespace Umbraco.Tests.Web
{
[TestFixture]
public class UrlHelperExtensionTests
{
[Test]
public static void Create_Encrypted_RouteString_From_Anonymous_Object()
{
var additionalRouteValues = new
{
key1 = "value1",
key2 = "value2",
Key3 = "Value3",
keY4 = "valuE4"
};
var encryptedRouteString = UrlHelperRenderExtensions.CreateEncryptedRouteString(
"FormController",
"FormAction",
"",
additionalRouteValues
);
var result = encryptedRouteString.DecryptWithMachineKey();
const string expectedResult = "c=FormController&a=FormAction&ar=&key1=value1&key2=value2&Key3=Value3&keY4=valuE4";
Assert.AreEqual(expectedResult, result);
}
[Test]
public static void Create_Encrypted_RouteString_From_Dictionary()
{
var additionalRouteValues = new Dictionary<string, object>()
{
{"key1", "value1"},
{"key2", "value2"},
{"Key3", "Value3"},
{"keY4", "valuE4"}
};
var encryptedRouteString = UrlHelperRenderExtensions.CreateEncryptedRouteString(
"FormController",
"FormAction",
"",
additionalRouteValues
);
var result = encryptedRouteString.DecryptWithMachineKey();
const string expectedResult = "c=FormController&a=FormAction&ar=&key1=value1&key2=value2&Key3=Value3&keY4=valuE4";
Assert.AreEqual(expectedResult, result);
}
}
}

View File

@@ -4,7 +4,7 @@
function ContentEditController($rootScope, $scope, $routeParams, $q, $window,
appState, contentResource, entityResource, navigationService, notificationsService,
serverValidationManager, contentEditingHelper, treeService, formHelper, umbRequestHelper,
editorState, $http, eventsService, relationResource, overlayService) {
editorState, $http, eventsService, relationResource, overlayService, $location) {
var evts = [];
var infiniteMode = $scope.infiniteModel && $scope.infiniteModel.infiniteMode;
@@ -22,7 +22,7 @@
$scope.page.isNew = $scope.isNew ? true : false;
$scope.page.buttonGroupState = "init";
$scope.page.hideActionsMenu = infiniteMode ? true : false;
$scope.page.hideChangeVariant = infiniteMode ? true : false;
$scope.page.hideChangeVariant = false;
$scope.allowOpen = true;
$scope.app = null;
@@ -214,23 +214,6 @@
}
// create infinite editing buttons
function createInfiniteModeButtons(content) {
$scope.page.allowInfinitePublishAndClose = false;
$scope.page.allowInfiniteSaveAndClose = false;
// check for publish rights
if (_.contains(content.allowedActions, "U")) {
$scope.page.allowInfinitePublishAndClose = true;
// check for save rights
} else if (_.contains(content.allowedActions, "A")) {
$scope.page.allowInfiniteSaveAndClose = true;
}
}
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
function syncTreeNode(content, path, initialLoad) {
@@ -874,11 +857,8 @@
$scope.$broadcast("editors.apps.appChanged", { app: app });
if (infiniteMode) {
createInfiniteModeButtons($scope.content);
} else {
createButtons($scope.content);
}
};
/**
@@ -897,6 +877,18 @@
}
};
/**
* Call back when user click the back-icon
*/
$scope.onBack = function() {
if ($scope.infiniteModel && $scope.infiniteModel.close) {
$scope.infiniteModel.close($scope.infiniteModel);
} else {
// navigate backwards if content has a parent.
$location.path('/' + $routeParams.section + '/' + $routeParams.tree + '/' + $routeParams.method + '/' + $scope.content.parentId);
}
};
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {

View File

@@ -17,7 +17,9 @@
onSelectVariant: "&",
onOpenSplitView: "&",
onSelectApp: "&",
onSelectAppAnchor: "&"
onSelectAppAnchor: "&",
onBack: "&?",
showBack: "<?"
},
controllerAs: 'vm',
controller: umbVariantContentController
@@ -37,6 +39,7 @@
vm.openSplitView = openSplitView;
vm.selectApp = selectApp;
vm.selectAppAnchor = selectAppAnchor;
vm.showBackButton = showBackButton;
function onInit() {
// disable the name field if the active content app is not "Content"
@@ -48,6 +51,10 @@
});
}
function showBackButton() {
return vm.page.listViewPath !== null && vm.showBack;
}
/** Called when the component has linked all elements, this is when the form controller is available */
function postLink() {
//set the content to dirty if the header changes

View File

@@ -11,7 +11,9 @@
content: "<", // TODO: Not sure if this should be = since we are changing the 'active' property of a variant
culture: "<",
onSelectApp: "&?",
onSelectAppAnchor: "&?"
onSelectAppAnchor: "&?",
onBack: "&?",
showBack: "<?"
},
controllerAs: 'vm',
controller: umbVariantContentEditorsController

View File

@@ -1,7 +1,7 @@
(function () {
'use strict';
function EditorContentHeader($location, $routeParams) {
function EditorContentHeader() {
function link(scope, el, attr, ctrl) {
@@ -37,7 +37,9 @@
}
scope.goBack = function () {
$location.path('/' + $routeParams.section + '/' + $routeParams.tree + '/' + $routeParams.method + '/' + scope.menu.currentNode.parentId);
if (scope.onBack) {
scope.onBack();
}
};
scope.selectVariant = function (event, variant) {
@@ -113,13 +115,14 @@
name: "=",
nameDisabled: "<?",
menu: "=",
hideMenu: "<?",
hideActionsMenu: "<?",
content: "=",
openVariants: "<",
hideChangeVariant: "<?",
onSelectNavigationItem: "&?",
onSelectAnchorItem: "&?",
showBackButton: "<?",
onBack: "&?",
splitViewOpen: "=?",
onOpenInSplitView: "&?",
onCloseSplitView: "&?",

View File

@@ -258,7 +258,7 @@ Use this directive to construct a header inside the main editor window.
name: "=",
nameLocked: "=",
menu: "=",
hideMenu: "<?",
hideActionsMenu: "<?",
icon: "=",
hideIcon: "@",
alias: "=",

View File

@@ -11,7 +11,10 @@
content="content"
culture="culture"
on-select-app="appChanged(app)"
on-select-app-anchor="appAnchorChanged(app, anchor)">
on-select-app-anchor="appAnchorChanged(app, anchor)"
on-back="onBack()"
show-back="!(infiniteModel && infiniteModel.infiniteMode)"
>
</umb-variant-content-editors>
<umb-editor-footer>
@@ -59,7 +62,7 @@
</umb-button>
<umb-button-group
ng-if="defaultButton && !content.trashed && !content.isElement && !infiniteModel.infiniteMode"
ng-if="defaultButton && !content.trashed && !content.isElement"
button-style="success"
default-button="defaultButton"
sub-buttons="subButtons"

View File

@@ -14,7 +14,9 @@
on-close-split-view="vm.closeSplitView($index)"
on-select-variant="vm.selectVariant(variant, $index)"
on-select-app="vm.selectApp(app)"
on-select-app-anchor="vm.selectAppAnchor(app, anchor)">
on-select-app-anchor="vm.selectAppAnchor(app, anchor)"
on-back="vm.onBack()"
show-back="vm.showBack">
</umb-variant-content>
</div>

View File

@@ -16,7 +16,8 @@
on-select-anchor-item="vm.selectAppAnchor(item, anchor)"
open-variants="vm.openVariants"
hide-change-variant="vm.page.hideChangeVariant"
show-back-button="vm.page.listViewPath !== null"
show-back-button="vm.showBackButton()"
on-back="vm.onBack()"
split-view-open="vm.editorCount > 1"
on-open-in-split-view="vm.openSplitView(variant)"
on-close-split-view="vm.onCloseSplitView()"

View File

@@ -69,7 +69,7 @@
</umb-editor-navigation>
</div>
<div ng-if="menu.currentNode && splitViewOpen !== true && hideMenu !== true">
<div ng-if="menu.currentNode && splitViewOpen !== true && hideActionsMenu !== true">
<umb-editor-menu
data-element="editor-actions"
current-node="menu.currentNode"

View File

@@ -77,7 +77,7 @@
</umb-editor-navigation>
</div>
<div ng-if="menu.currentNode && splitViewOpen !== true && hideMenu !== true">
<div ng-if="menu.currentNode && splitViewOpen !== true && hideActionsMenu !== true">
<umb-editor-menu
data-element="editor-actions"
current-node="menu.currentNode"

View File

@@ -14,23 +14,26 @@
if (packageInstallData) {
localStorageService.remove("packageInstallData");
if (packageInstallData.postInstallationPath) {
//navigate to the custom installer screen if set
$location.path(packageInstallData.postInstallationPath).search("packageId", packageInstallData.id);
return;
}
if (packageInstallData && packageInstallData !== "installed" && packageInstallData.postInstallationPath) {
//navigate to the custom installer screen, if it is just "installed" it means there is no custom installer screen
$location.path(packageInstallData.postInstallationPath).search("packageId", packageInstallData.id);
//if it is "installed" then set the uri/path to that
if (packageInstallData === "installed") {
packageUri = "installed";
}
else {
}
var vm = this;
vm.page = {};
vm.page.labels = {};
vm.page.name = "";
vm.page.navigation = [];
packageUri = packageInstallData ? packageInstallData : packageUri; //use the path stored in storage over the one in the current path
onInit();
}
function onInit() {

View File

@@ -9,7 +9,8 @@
(function () {
"use strict";
function ListViewGridLayoutController($scope, $routeParams, mediaHelper, mediaResource, $location, listViewHelper, mediaTypeHelper) {
function ListViewGridLayoutController($scope, $routeParams, mediaHelper, mediaResource,
listViewHelper, mediaTypeHelper, editorService) {
var vm = this;
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
@@ -116,8 +117,29 @@
listViewHelper.selectHandler(folder, $index, $scope.folders, $scope.selection, $event);
}
function goToItem(item, $event, $index) {
$location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + item.id);
function goToItem(node, $event, $index) {
$event.stopPropagation();
var contentEditor = {
id: node.id,
submit: function (model) {
// update the node
node.name = model.contentNode.name;
// TODO: node.description = model.contentNode.description;
node.published = model.contentNode.hasPublishedVersion;
if (entityType !== "Member") {
entityResource.getUrl(model.contentNode.id, entityType).then(function (data) {
node.url = data;
});
}
editorService.close();
},
close: function () {
editorService.close();
}
};
editorService.contentEditor(contentEditor);
}
activate();

View File

@@ -1,7 +1,7 @@
(function () {
"use strict";
function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper, mediaTypeHelper) {
function ListViewListLayoutController($scope, listViewHelper, mediaHelper, mediaTypeHelper, editorService) {
var vm = this;
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
@@ -52,10 +52,30 @@
listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event);
}
function clickItem(item) {
// if item.id is 2147483647 (int.MaxValue) use item.key
$location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + (item.id === 2147483647 ? item.key : item.id));
function clickItem(node) {
var contentEditor = {
id: node.id,
submit: function (model) {
// update the node
node.name = model.contentNode.name;
// TODO: node.description = model.contentNode.description;
node.published = model.contentNode.hasPublishedVersion;
if (entityType !== "Member") {
entityResource.getUrl(model.contentNode.id, entityType).then(function (data) {
node.url = data;
});
}
editorService.close();
},
close: function () {
editorService.close();
}
};
editorService.contentEditor(contentEditor);
}
function isSortDirection(col, direction) {
return listViewHelper.setSortingDirection(col, direction, $scope.options);

View File

@@ -396,7 +396,7 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
public HttpResponseMessage GetNiceUrl(int id)
{
var url = Umbraco.Url(id);
var url = UmbracoContext.Url(id);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(url, Encoding.UTF8, "text/plain");
return response;
@@ -409,7 +409,7 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
public HttpResponseMessage GetNiceUrl(Guid id)
{
var url = Umbraco.UrlProvider.GetUrl(id);
var url = UmbracoContext.Url(id);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(url, Encoding.UTF8, "text/plain");
return response;

View File

@@ -94,7 +94,7 @@ namespace Umbraco.Web.Editors
public DataTypeDisplay GetEmpty(int parentId)
{
// cannot create an "empty" data type, so use something by default.
var editor = _propertyEditors[Constants.PropertyEditors.Aliases.NoEdit];
var editor = _propertyEditors[Constants.PropertyEditors.Aliases.Label];
var dt = new DataType(editor, parentId);
return Mapper.Map<IDataType, DataTypeDisplay>(dt);
}

View File

@@ -213,7 +213,7 @@ namespace Umbraco.Web.Editors
if (type == UmbracoEntityTypes.Document)
{
var foundUrl = Umbraco.Url(id);
var foundUrl = UmbracoContext.Url(id);
if (string.IsNullOrEmpty(foundUrl) == false && foundUrl != "#")
{
returnUrl = foundUrl;

View File

@@ -222,7 +222,7 @@ namespace Umbraco.Web
_viewContext = viewContext;
_method = method;
_controllerName = controllerName;
_encryptedString = UmbracoHelper.CreateEncryptedRouteString(controllerName, controllerAction, area, additionalRouteVals);
_encryptedString = UrlHelperRenderExtensions.CreateEncryptedRouteString(controllerName, controllerAction, area, additionalRouteVals);
}
private readonly ViewContext _viewContext;
@@ -830,5 +830,186 @@ namespace Umbraco.Web
}
#endregion
#region If
/// <summary>
/// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned.
/// </summary>
public static IHtmlString If(this HtmlHelper html, bool test, string valueIfTrue, string valueIfFalse)
{
return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse);
}
/// <summary>
/// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned.
/// </summary>
public static IHtmlString If(this HtmlHelper html, bool test, string valueIfTrue)
{
return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty);
}
#endregion
#region Strings
private static readonly HtmlStringUtilities StringUtilities = new HtmlStringUtilities();
/// <summary>
/// Replaces text line breaks with HTML line breaks
/// </summary>
/// <param name="helper"></param>
/// <param name="text">The text.</param>
/// <returns>The text with text line breaks replaced with HTML line breaks (<br/>)</returns>
public static IHtmlString ReplaceLineBreaksForHtml(this HtmlHelper helper, string text)
{
return StringUtilities.ReplaceLineBreaksForHtml(text);
}
/// <summary>
/// Generates a hash based on the text string passed in. This method will detect the
/// security requirements (is FIPS enabled) and return an appropriate hash.
/// </summary>
/// <param name="helper"></param>
/// <param name="text">The text to create a hash from</param>
/// <returns>Hash of the text string</returns>
public static string CreateHash(this HtmlHelper helper, string text)
{
return text.GenerateHash();
}
/// <summary>
/// Strips all HTML tags from a given string, all contents of the tags will remain.
/// </summary>
public static IHtmlString StripHtml(this HtmlHelper helper, IHtmlString html, params string[] tags)
{
return helper.StripHtml(html.ToHtmlString(), tags);
}
/// <summary>
/// Strips all HTML tags from a given string, all contents of the tags will remain.
/// </summary>
public static IHtmlString StripHtml(this HtmlHelper helper, string html, params string[] tags)
{
return StringUtilities.StripHtmlTags(html, tags);
}
/// <summary>
/// Will take the first non-null value in the collection and return the value of it.
/// </summary>
public static string Coalesce(this HtmlHelper helper, params object[] args)
{
return StringUtilities.Coalesce(args);
}
/// <summary>
/// Joins any number of int/string/objects into one string
/// </summary>
public static string Concatenate(this HtmlHelper helper, params object[] args)
{
return StringUtilities.Concatenate(args);
}
/// <summary>
/// Joins any number of int/string/objects into one string and separates them with the string separator parameter.
/// </summary>
public static string Join(this HtmlHelper helper, string separator, params object[] args)
{
return StringUtilities.Join(separator, args);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length)
{
return helper.Truncate(html.ToHtmlString(), length, true, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length, bool addElipsis)
{
return helper.Truncate(html.ToHtmlString(), length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent)
{
return helper.Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, string html, int length)
{
return helper.Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, string html, int length, bool addElipsis)
{
return helper.Truncate(html, length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString Truncate(this HtmlHelper helper, string html, int length, bool addElipsis, bool treatTagsAsContent)
{
return StringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent);
}
#region Truncate by Words
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString TruncateByWords(this HtmlHelper helper, string html, int words)
{
int length = StringUtilities.WordsToLength(html, words);
return helper.Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString TruncateByWords(this HtmlHelper helper, string html, int words, bool addElipsis)
{
int length = StringUtilities.WordsToLength(html, words);
return helper.Truncate(html, length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString TruncateByWords(this HtmlHelper helper, IHtmlString html, int words)
{
int length = StringUtilities.WordsToLength(html.ToHtmlString(), words);
return helper.Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public static IHtmlString TruncateByWords(this HtmlHelper helper, IHtmlString html, int words, bool addElipsis)
{
int length = StringUtilities.WordsToLength(html.ToHtmlString(), words);
return helper.Truncate(html, length, addElipsis, false);
}
#endregion
#endregion
}
}

View File

@@ -4,7 +4,16 @@ using Umbraco.Core;
namespace Umbraco.Web
{
internal abstract class HybridAccessorBase<T>
/// <summary>
/// Provides a base class for hybrid accessors.
/// </summary>
/// <typeparam name="T">The type of the accessed object.</typeparam>
/// <remarks>
/// <para>Hybrid accessors store the accessed object in HttpContext if they can,
/// otherwise they rely on the logical call context, to maintain an ambient
/// object that flows with async.</para>
/// </remarks>
public abstract class HybridAccessorBase<T>
where T : class
{
// ReSharper disable StaticMemberInGenericType
@@ -33,7 +42,7 @@ namespace Umbraco.Web
// yes! flows with async!
private T NonContextValue
{
get { return (T) CallContext.LogicalGetData(ItemKey); }
get => (T) CallContext.LogicalGetData(ItemKey);
set
{
if (value == null) CallContext.FreeNamedDataSlot(ItemKey);
@@ -43,8 +52,7 @@ namespace Umbraco.Web
protected HybridAccessorBase(IHttpContextAccessor httpContextAccessor)
{
if (httpContextAccessor == null) throw new ArgumentNullException(nameof(httpContextAccessor));
_httpContextAccessor = httpContextAccessor;
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
lock (Locker)
{

View File

@@ -1,17 +1,27 @@
namespace Umbraco.Web
{
/// <summary>
/// Implements a hybrid <see cref="IUmbracoContextAccessor"/>.
/// </summary>
internal class HybridUmbracoContextAccessor : HybridAccessorBase<UmbracoContext>, IUmbracoContextAccessor
{
/// <summary>
/// Initializes a new instance of the <see cref="HybridUmbracoContextAccessor"/> class.
/// </summary>
public HybridUmbracoContextAccessor(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
{ }
/// <inheritdoc />
protected override string ItemKey => "Umbraco.Web.HybridUmbracoContextAccessor";
/// <summary>
/// Gets or sets the <see cref="UmbracoContext"/> object.
/// </summary>
public UmbracoContext UmbracoContext
{
get { return Value; }
set { Value = value; }
get => Value;
set => Value = value;
}
}
}

View File

@@ -44,7 +44,7 @@ namespace Umbraco.Web.Models.Mapping
"No property editor '{PropertyEditorAlias}' found, converting to a Label",
property.PropertyType.PropertyEditorAlias);
editor = _propertyEditors[Constants.PropertyEditors.Aliases.NoEdit];
editor = _propertyEditors[Constants.PropertyEditors.Aliases.Label];
}
var result = new TDestination

View File

@@ -124,7 +124,7 @@ namespace Umbraco.Web.Models.Mapping
Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype",
Label = _localizedTextService.Localize("content/membertype"),
Value = _localizedTextService.UmbracoDictionaryTranslate(member.ContentType.Name),
View = Current.PropertyEditors[Constants.PropertyEditors.Aliases.NoEdit].GetValueEditor().View
View = Current.PropertyEditors[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View
},
GetLoginProperty(_memberService, member, _localizedTextService),
new ContentPropertyDisplay

View File

@@ -210,7 +210,7 @@ namespace Umbraco.Web.Models.Mapping
{
_logger.Error(GetType(),
"No property editor could be resolved with the alias: {PropertyEditorAlias}, defaulting to label", p.PropertyEditorAlias);
propertyEditorAlias = Constants.PropertyEditors.Aliases.NoEdit;
propertyEditorAlias = Constants.PropertyEditors.Aliases.Label;
propertyEditor = _propertyEditors[propertyEditorAlias];
}

View File

@@ -0,0 +1,26 @@
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Web.Models.PublishedContent
{
/// <summary>
/// Implements a hybrid <see cref="IVariationContextAccessor"/>.
/// </summary>
internal class HybridVariationContextAccessor : HybridAccessorBase<VariationContext>, IVariationContextAccessor
{
public HybridVariationContextAccessor(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
{ }
/// <inheritdoc />
protected override string ItemKey => "Umbraco.Web.HybridVariationContextAccessor";
/// <summary>
/// Gets or sets the <see cref="VariationContext"/> object.
/// </summary>
public VariationContext VariationContext
{
get => Value;
set => Value = value;
}
}
}

View File

@@ -15,13 +15,13 @@ namespace Umbraco.Web.Models
[DebuggerDisplay("Content Id: {Id}, Name: {Name}")]
public abstract class PublishedContentBase : IPublishedContent
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
protected PublishedContentBase(IUmbracoContextAccessor umbracoContextAccessor)
{
_umbracoContextAccessor = umbracoContextAccessor;
UmbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
}
protected IUmbracoContextAccessor UmbracoContextAccessor { get; }
#region ContentType
public abstract PublishedContentType ContentType { get; }
@@ -86,14 +86,16 @@ namespace Umbraco.Web.Models
/// </remarks>
public virtual string GetUrl(string culture = null) // TODO: consider .GetCulture("fr-FR").Url
{
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
switch (ItemType)
{
case PublishedItemType.Content:
var umbracoContext = UmbracoContextAccessor.UmbracoContext;
if (umbracoContext == null)
throw new InvalidOperationException("Cannot compute Url for a content item when UmbracoContext is null.");
if (umbracoContext.UrlProvider == null)
throw new InvalidOperationException("Cannot compute Url for a content item when UmbracoContext.UrlProvider is null.");
return umbracoContext.UrlProvider.GetUrl(this, culture);
case PublishedItemType.Media:
@@ -112,8 +114,8 @@ namespace Umbraco.Web.Models
switch (propType.EditorAlias)
{
case Constants.PropertyEditors.Aliases.UploadField:
return prop.GetValue().ToString();
break;
case Constants.PropertyEditors.Aliases.ImageCropper:
//get the url from the json format

View File

@@ -13,7 +13,6 @@ namespace Umbraco.Web.PublishedCache.NuCache
internal class PublishedContent : PublishedContentBase
{
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ContentNode _contentNode;
private readonly string _urlSegment;
@@ -24,13 +23,13 @@ namespace Umbraco.Web.PublishedCache.NuCache
ContentData contentData,
IPublishedSnapshotAccessor publishedSnapshotAccessor,
IVariationContextAccessor variationContextAccessor,
IUmbracoContextAccessor umbracoContextAccessor) :base(umbracoContextAccessor)
IUmbracoContextAccessor umbracoContextAccessor)
: base(umbracoContextAccessor)
{
_contentNode = contentNode;
ContentData = contentData;
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_umbracoContextAccessor = umbracoContextAccessor;
VariationContextAccessor = variationContextAccessor;
_contentNode = contentNode ?? throw new ArgumentNullException(nameof(contentNode));
ContentData = contentData ?? throw new ArgumentNullException(nameof(contentData));
_publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor));
VariationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_urlSegment = ContentData.Name.ToUrlSegment();
IsPreviewing = ContentData.Published == false;
@@ -72,7 +71,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
public PublishedContent(
ContentNode contentNode,
PublishedContent origin,
IUmbracoContextAccessor umbracoContextAccessor) :base(umbracoContextAccessor)
IUmbracoContextAccessor umbracoContextAccessor)
: base(umbracoContextAccessor)
{
_contentNode = contentNode;
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
@@ -91,7 +91,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
// clone for previewing as draft a published content that is published and has no draft
private PublishedContent(
PublishedContent origin,
IUmbracoContextAccessor umbracoContextAccessor) :base(umbracoContextAccessor)
IUmbracoContextAccessor umbracoContextAccessor)
: base(umbracoContextAccessor)
{
_publishedSnapshotAccessor = origin._publishedSnapshotAccessor;
VariationContextAccessor = origin.VariationContextAccessor;
@@ -468,8 +469,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
return this;
var cache = GetAppropriateCache();
if (cache == null) return new PublishedContent(this, _umbracoContextAccessor).CreateModel();
return (IPublishedContent)cache.Get(AsPreviewingCacheKey, () => new PublishedContent(this, _umbracoContextAccessor).CreateModel());
if (cache == null) return new PublishedContent(this, UmbracoContextAccessor).CreateModel();
return (IPublishedContent)cache.Get(AsPreviewingCacheKey, () => new PublishedContent(this, UmbracoContextAccessor).CreateModel());
}
// used by Navigable.Source,...

View File

@@ -246,7 +246,7 @@ namespace Umbraco.Web.Routing
/// </remarks>
public IEnumerable<UrlInfo> GetOtherUrls(int id, Uri current)
{
return _urlProviders.SelectMany(provider => provider.GetOtherUrls(_umbracoContext, id, current));
return _urlProviders.SelectMany(provider => provider.GetOtherUrls(_umbracoContext, id, current) ?? Enumerable.Empty<UrlInfo>());
}
#endregion

View File

@@ -72,8 +72,12 @@ namespace Umbraco.Web.Runtime
// setup mvc and webapi services
SetupMvcAndWebApi();
// client dependency
// When using a non-web runtime and this component is loaded ClientDependency explodes because it'll
// want to access HttpContext.Current, which doesn't exist
if (IOHelper.IsHosted)
{
ConfigureClientDependency(_globalSettings);
}
// Disable the X-AspNetMvc-Version HTTP Header
MvcHandler.DisableMvcResponseHeader = true;
@@ -255,9 +259,6 @@ namespace Umbraco.Web.Runtime
{ "compositeFileHandlerPath", ClientDependencySettings.Instance.CompositeFileHandlerPath }
});
// When using a non-web runtime and this component is loaded ClientDependency explodes because it'll
// want to access HttpContext.Current, which doesn't exist
if (IOHelper.IsHosted)
ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer);
}
}

View File

@@ -64,11 +64,12 @@ namespace Umbraco.Web.Runtime
// register membership stuff
composition.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider());
composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance<IMemberService>()));
composition.Register<MembershipHelper>();
composition.Register<MembershipHelper>(Lifetime.Request);
composition.Register<IPublishedMemberCache>(factory => factory.GetInstance<UmbracoContext>().PublishedSnapshot.Members);
// register accessors for cultures
composition.RegisterUnique<IDefaultCultureAccessor, DefaultCultureAccessor>();
composition.RegisterUnique<IVariationContextAccessor, HttpContextVariationContextAccessor>();
composition.RegisterUnique<IVariationContextAccessor, HybridVariationContextAccessor>();
// register the http context and umbraco context accessors
// we *should* use the HttpContextUmbracoContextAccessor, however there are cases when
@@ -107,7 +108,14 @@ namespace Umbraco.Web.Runtime
// also, if not level.Run, we cannot really use the helper (during upgrade...)
// so inject a "void" helper (not exactly pretty but...)
if (composition.RuntimeState.Level == RuntimeLevel.Run)
composition.Register<UmbracoHelper>();
composition.Register<UmbracoHelper>(factory =>
{
var umbCtx = factory.GetInstance<UmbracoContext>();
return new UmbracoHelper(umbCtx.IsFrontEndUmbracoRequest ? umbCtx.PublishedRequest?.PublishedContent : null,
factory.GetInstance<ITagQuery>(), factory.GetInstance<ICultureDictionaryFactory>(),
factory.GetInstance<IUmbracoComponentRenderer>(), factory.GetInstance<IPublishedContentQuery>(),
factory.GetInstance<MembershipHelper>());
});
else
composition.Register(_ => new UmbracoHelper());

View File

@@ -419,11 +419,11 @@ namespace Umbraco.Web.Search
//if it varies by culture, return the default language URL
if (result.Values.TryGetValue(UmbracoContentIndex.VariesByCultureFieldName, out var varies) && varies == "y")
{
entity.AdditionalData["Url"] = _umbracoHelper.Url(intId.Result, defaultLang);
entity.AdditionalData["Url"] = _umbracoContext.Url(intId.Result, defaultLang);
}
else
{
entity.AdditionalData["Url"] = _umbracoHelper.Url(intId.Result);
entity.AdditionalData["Url"] = _umbracoContext.Url(intId.Result);
}
}

View File

@@ -15,7 +15,6 @@ using Umbraco.Core.Composing;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web.Editors;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Security
{
@@ -24,7 +23,6 @@ namespace Umbraco.Web.Security
/// </summary>
public class MembershipHelper
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly MembershipProvider _membershipProvider;
private readonly RoleProvider _roleProvider;
private readonly IMemberService _memberService;
@@ -38,7 +36,8 @@ namespace Umbraco.Web.Security
public MembershipHelper
(
IUmbracoContextAccessor accessor,
HttpContextBase httpContext,
IPublishedMemberCache memberCache,
MembershipProvider membershipProvider,
RoleProvider roleProvider,
IMemberService memberService,
@@ -49,8 +48,8 @@ namespace Umbraco.Web.Security
ILogger logger
)
{
_umbracoContextAccessor = accessor ?? throw new ArgumentNullException(nameof(accessor));
HttpContext = httpContext;
MemberCache = memberCache;
_memberService = memberService;
_memberTypeService = memberTypeService;
_userService = userService;
@@ -64,9 +63,8 @@ namespace Umbraco.Web.Security
#endregion
protected UmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext ?? throw new InvalidOperationException("No UmbracoContext.");
protected HttpContextBase HttpContext => UmbracoContext.HttpContext ?? throw new InvalidOperationException("No UmbracoContext.HttpContext.");
protected IPublishedMemberCache MemberCache => UmbracoContext.PublishedSnapshot.Members ?? throw new InvalidOperationException("No UmbracoContext.PUblishedSnapshot.Members.");
protected HttpContextBase HttpContext { get; }
protected IPublishedMemberCache MemberCache { get; }
/// <summary>
/// Check if a document object is protected by the "Protect Pages" functionality in umbraco
@@ -103,17 +101,9 @@ namespace Umbraco.Web.Security
/// <param name="path"></param>
/// <param name="roleProvider"></param>
/// <returns></returns>
/// <remarks>
/// This is essentially the same as the PublicAccessServiceExtensions.HasAccess however this will use the PCR cache
/// of the already looked up roles for the member so this doesn't need to happen more than once.
/// This does a safety check in case of things like unit tests where there is no PCR and if that is the case it will use
/// lookup the roles directly.
/// </remarks>
private bool HasAccess(string path, RoleProvider roleProvider)
{
return UmbracoContext.PublishedRequest == null
? _publicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser)
: _publicAccessService.HasAccess(path, CurrentUserName, GetUserRoles);
return _publicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser);
}
/// <summary>
@@ -703,7 +693,7 @@ namespace Umbraco.Web.Security
/// <returns></returns>
public virtual Attempt<PasswordChangedModel> ChangePassword(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider)
{
var passwordChanger = new PasswordChanger(_logger, _userService, UmbracoContext.HttpContext);
var passwordChanger = new PasswordChanger(_logger, _userService, HttpContext);
return passwordChanger.ChangePasswordWithMembershipProvider(username, passwordModel, membershipProvider);
}

View File

@@ -202,6 +202,7 @@
<Compile Include="Models\ContentEditing\LinkDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroParameterDisplay.cs" />
<Compile Include="Models\PublishedContent\HybridVariationContextAccessor.cs" />
<Compile Include="Models\TemplateQuery\QueryConditionExtensions.cs" />
<Compile Include="Routing\IPublishedRouter.cs" />
<Compile Include="Services\DashboardService.cs" />

View File

@@ -189,6 +189,78 @@ namespace Umbraco.Web
private set => _previewing = value;
}
#region Urls
/// <summary>
/// Gets the url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
public string Url(int contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, culture);
}
/// <summary>
/// Gets the url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
public string Url(Guid contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, culture);
}
/// <summary>
/// Gets the url of a content identified by its identifier, in a specified mode.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="mode">The mode.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
public string Url(int contentId, UrlProviderMode mode, string culture = null)
{
return UrlProvider.GetUrl(contentId, mode, culture);
}
/// <summary>
/// Gets the url of a content identified by its identifier, in a specified mode.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="mode">The mode.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
public string Url(Guid contentId, UrlProviderMode mode, string culture = null)
{
return UrlProvider.GetUrl(contentId, mode, culture);
}
/// <summary>
/// Gets the absolute url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The absolute url for the content.</returns>
public string UrlAbsolute(int contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, true, culture);
}
/// <summary>
/// Gets the absolute url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The absolute url for the content.</returns>
public string UrlAbsolute(Guid contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, true, culture);
}
#endregion
private string PreviewToken
{
get

View File

@@ -22,14 +22,11 @@ namespace Umbraco.Web
/// </remarks>
public class UmbracoHelper
{
private static readonly HtmlStringUtilities StringUtilities = new HtmlStringUtilities();
private readonly IPublishedContentQuery _publishedContentQuery;
private readonly ITagQuery _tagQuery;
private readonly MembershipHelper _membershipHelper;
private readonly IUmbracoComponentRenderer _componentRenderer;
private readonly ICultureDictionaryFactory _cultureDictionaryFactory;
private readonly UmbracoContext _umbracoContext;
private IPublishedContent _currentPage;
private ICultureDictionary _cultureDictionary;
@@ -39,28 +36,26 @@ namespace Umbraco.Web
/// <summary>
/// Initializes a new instance of <see cref="UmbracoHelper"/>.
/// </summary>
/// <param name="umbracoContext">An Umbraco context.</param>
/// <param name="currentPage">The <see cref="IPublishedContent"/> item assigned to the helper.</param>
/// <param name="tagQuery"></param>
/// <param name="cultureDictionary"></param>
/// <param name="componentRenderer"></param>
/// <param name="publishedContentQuery"></param>
/// <param name="membershipHelper"></param>
/// <remarks>Sets the current page to the context's published content request's content item.</remarks>
public UmbracoHelper(UmbracoContext umbracoContext, ITagQuery tagQuery,
public UmbracoHelper(IPublishedContent currentPage,
ITagQuery tagQuery,
ICultureDictionaryFactory cultureDictionary,
IUmbracoComponentRenderer componentRenderer,
IPublishedContentQuery publishedContentQuery,
MembershipHelper membershipHelper)
{
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_tagQuery = tagQuery ?? throw new ArgumentNullException(nameof(tagQuery));
_cultureDictionaryFactory = cultureDictionary ?? throw new ArgumentNullException(nameof(cultureDictionary));
_componentRenderer = componentRenderer ?? throw new ArgumentNullException(nameof(componentRenderer));
_membershipHelper = membershipHelper ?? throw new ArgumentNullException(nameof(membershipHelper));
_publishedContentQuery = publishedContentQuery ?? throw new ArgumentNullException(nameof(publishedContentQuery));
if (_umbracoContext.IsFrontEndUmbracoRequest)
_currentPage = _umbracoContext.PublishedRequest.PublishedContent;
_currentPage = currentPage;
}
/// <summary>
@@ -77,7 +72,6 @@ namespace Umbraco.Web
private IUmbracoComponentRenderer ComponentRenderer => Ensure(_componentRenderer);
private ICultureDictionaryFactory CultureDictionaryFactory => Ensure(_cultureDictionaryFactory);
private UmbracoContext UmbracoContext => Ensure(_umbracoContext);
/// <summary>
/// Gets the tag context.
@@ -94,11 +88,6 @@ namespace Umbraco.Web
/// </summary>
public MembershipHelper MembershipHelper => Ensure(_membershipHelper);
/// <summary>
/// Gets the url provider.
/// </summary>
public UrlProvider UrlProvider => UmbracoContext.UrlProvider;
/// <summary>
/// Gets (or sets) the current <see cref="IPublishedContent"/> item assigned to the UmbracoHelper.
/// </summary>
@@ -106,14 +95,13 @@ namespace Umbraco.Web
/// <para>
/// Note that this is the assigned IPublishedContent item to the
/// UmbracoHelper, this is not necessarily the Current IPublishedContent
/// item being rendered. This IPublishedContent object is contextual to
/// the current UmbracoHelper instance.
/// item being rendered that is assigned to the UmbracoContext.
/// This IPublishedContent object is contextual to the current UmbracoHelper instance.
/// </para>
///<para>
/// In some cases accessing this property will throw an exception if
/// there is not IPublishedContent assigned to the Helper this will
/// only ever happen if the Helper is constructed with an UmbracoContext
/// and it is not a front-end request.
/// only ever happen if the Helper is constructed via DI during a non front-end request.
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">Thrown if the
@@ -129,7 +117,7 @@ namespace Umbraco.Web
}
throw new InvalidOperationException(
$"Cannot return the {nameof(IPublishedContent)} because the {nameof(UmbracoHelper)} was constructed with an {nameof(UmbracoContext)} and the current request is not a front-end request."
$"Cannot return the {nameof(IPublishedContent)} because the {nameof(UmbracoHelper)} was not constructed with an {nameof(IPublishedContent)}."
);
}
@@ -156,7 +144,7 @@ namespace Umbraco.Web
/// <returns></returns>
public IHtmlString RenderMacro(string alias)
{
return ComponentRenderer.RenderMacro(UmbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, new { });
return ComponentRenderer.RenderMacro(AssignedContentItem?.Id ?? 0, alias, new { });
}
/// <summary>
@@ -167,7 +155,7 @@ namespace Umbraco.Web
/// <returns></returns>
public IHtmlString RenderMacro(string alias, object parameters)
{
return ComponentRenderer.RenderMacro(UmbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, parameters.ToDictionary<object>());
return ComponentRenderer.RenderMacro(AssignedContentItem?.Id ?? 0, alias, parameters.ToDictionary<object>());
}
/// <summary>
@@ -178,7 +166,7 @@ namespace Umbraco.Web
/// <returns></returns>
public IHtmlString RenderMacro(string alias, IDictionary<string, object> parameters)
{
return ComponentRenderer.RenderMacro(UmbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, parameters);
return ComponentRenderer.RenderMacro(AssignedContentItem?.Id ?? 0, alias, parameters);
}
#endregion
@@ -242,41 +230,7 @@ namespace Umbraco.Web
#endregion
#region Urls
/// <summary>
/// Gets the url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="culture"></param>
/// <returns>The url for the content.</returns>
public string Url(int contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, culture);
}
/// <summary>
/// Gets the url of a content identified by its identifier, in a specified mode.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <param name="mode">The mode.</param>
/// <returns>The url for the content.</returns>
public string Url(int contentId, UrlProviderMode mode, string culture = null)
{
return UrlProvider.GetUrl(contentId, mode, culture);
}
/// <summary>
/// Gets the absolute url of a content identified by its identifier.
/// </summary>
/// <param name="contentId">The content identifier.</param>
/// <returns>The absolute url for the content.</returns>
public string UrlAbsolute(int contentId, string culture = null)
{
return UrlProvider.GetUrl(contentId, true, culture);
}
#endregion
#region Member/Content/Media from Udi
@@ -720,218 +674,10 @@ namespace Umbraco.Web
#endregion
#region Strings
/// <summary>
/// Replaces text line breaks with HTML line breaks
/// </summary>
/// <param name="text">The text.</param>
/// <returns>The text with text line breaks replaced with HTML line breaks (<br/>)</returns>
public IHtmlString ReplaceLineBreaksForHtml(string text)
{
return StringUtilities.ReplaceLineBreaksForHtml(text);
}
/// <summary>
/// Generates a hash based on the text string passed in. This method will detect the
/// security requirements (is FIPS enabled) and return an appropriate hash.
/// </summary>
/// <param name="text">The text to create a hash from</param>
/// <returns>Hash of the text string</returns>
public string CreateHash(string text)
{
return text.GenerateHash();
}
/// <summary>
/// Strips all HTML tags from a given string, all contents of the tags will remain.
/// </summary>
public HtmlString StripHtml(IHtmlString html, params string[] tags)
{
return StripHtml(html.ToHtmlString(), tags);
}
/// <summary>
/// Strips all HTML tags from a given string, all contents of the tags will remain.
/// </summary>
public HtmlString StripHtml(string html, params string[] tags)
{
return StringUtilities.StripHtmlTags(html, tags);
}
/// <summary>
/// Will take the first non-null value in the collection and return the value of it.
/// </summary>
public string Coalesce(params object[] args)
{
return StringUtilities.Coalesce(args);
}
/// <summary>
/// Joins any number of int/string/objects into one string
/// </summary>
public string Concatenate(params object[] args)
{
return StringUtilities.Concatenate(args);
}
/// <summary>
/// Joins any number of int/string/objects into one string and separates them with the string separator parameter.
/// </summary>
public string Join(string separator, params object[] args)
{
return StringUtilities.Join(separator, args);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(IHtmlString html, int length)
{
return Truncate(html.ToHtmlString(), length, true, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis)
{
return Truncate(html.ToHtmlString(), length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent)
{
return Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(string html, int length)
{
return Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(string html, int length, bool addElipsis)
{
return Truncate(html, length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given length, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent)
{
return StringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent);
}
#region Truncate by Words
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString TruncateByWords(string html, int words)
{
int length = StringUtilities.WordsToLength(html, words);
return Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString TruncateByWords(string html, int words, bool addElipsis)
{
int length = StringUtilities.WordsToLength(html, words);
return Truncate(html, length, addElipsis, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString TruncateByWords(IHtmlString html, int words)
{
int length = StringUtilities.WordsToLength(html.ToHtmlString(), words);
return Truncate(html, length, true, false);
}
/// <summary>
/// Truncates a string to a given amount of words, can add a ellipsis at the end (...). Method checks for open HTML tags, and makes sure to close them
/// </summary>
public IHtmlString TruncateByWords(IHtmlString html, int words, bool addElipsis)
{
int length = StringUtilities.WordsToLength(html.ToHtmlString(), words);
return Truncate(html, length, addElipsis, false);
}
#endregion
#endregion
#region If
/// <summary>
/// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned.
/// </summary>
public HtmlString If(bool test, string valueIfTrue, string valueIfFalse)
{
return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse);
}
/// <summary>
/// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned.
/// </summary>
public HtmlString If(bool test, string valueIfTrue)
{
return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty);
}
#endregion
/// <summary>
/// This is used in methods like BeginUmbracoForm and SurfaceAction to generate an encrypted string which gets submitted in a request for which
/// Umbraco can decrypt during the routing process in order to delegate the request to a specific MVC Controller.
/// </summary>
/// <param name="controllerName"></param>
/// <param name="controllerAction"></param>
/// <param name="area"></param>
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null)
{
if (string.IsNullOrEmpty(controllerName)) throw new ArgumentNullOrEmptyException(nameof(controllerName));
if (string.IsNullOrEmpty(controllerAction)) throw new ArgumentNullOrEmptyException(nameof(controllerAction));
if (area == null) throw new ArgumentNullException(nameof(area));
//need to create a params string as Base64 to put into our hidden field to use during the routes
var surfaceRouteParams = $"c={HttpUtility.UrlEncode(controllerName)}&a={HttpUtility.UrlEncode(controllerAction)}&ar={area}";
//checking if the additional route values is already a dictionary and convert to querystring
string additionalRouteValsAsQuery;
if (additionalRouteVals != null)
{
var additionalRouteValsAsDictionary = additionalRouteVals as Dictionary<string, object>;
if (additionalRouteValsAsDictionary != null)
additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString();
else
additionalRouteValsAsQuery = additionalRouteVals.ToDictionary<object>().ToQueryString();
}
else
additionalRouteValsAsQuery = null;
if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false)
surfaceRouteParams += "&" + additionalRouteValsAsQuery;
return surfaceRouteParams.EncryptWithMachineKey();
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
@@ -294,7 +295,7 @@ namespace Umbraco.Web
if (string.IsNullOrEmpty(action)) throw new ArgumentNullOrEmptyException(nameof(action));
if (string.IsNullOrEmpty(controllerName)) throw new ArgumentNullOrEmptyException(nameof(controllerName));
var encryptedRoute = UmbracoHelper.CreateEncryptedRouteString(controllerName, action, area, additionalRouteVals);
var encryptedRoute = CreateEncryptedRouteString(controllerName, action, area, additionalRouteVals);
var result = Current.UmbracoContext.OriginalRequestUrl.AbsolutePath.EnsureEndsWith('?') + "ufprt=" + encryptedRoute;
return result;
@@ -337,7 +338,7 @@ namespace Umbraco.Web
area = metaData.AreaName;
}
var encryptedRoute = UmbracoHelper.CreateEncryptedRouteString(metaData.ControllerName, action, area, additionalRouteVals);
var encryptedRoute = CreateEncryptedRouteString(metaData.ControllerName, action, area, additionalRouteVals);
var result = Current.UmbracoContext.OriginalRequestUrl.AbsolutePath.EnsureEndsWith('?') + "ufprt=" + encryptedRoute;
return result;
@@ -388,5 +389,41 @@ namespace Umbraco.Web
}
return null;
}
/// <summary>
/// This is used in methods like BeginUmbracoForm and SurfaceAction to generate an encrypted string which gets submitted in a request for which
/// Umbraco can decrypt during the routing process in order to delegate the request to a specific MVC Controller.
/// </summary>
/// <param name="controllerName"></param>
/// <param name="controllerAction"></param>
/// <param name="area"></param>
/// <param name="additionalRouteVals"></param>
/// <returns></returns>
internal static string CreateEncryptedRouteString(string controllerName, string controllerAction, string area, object additionalRouteVals = null)
{
if (string.IsNullOrEmpty(controllerName)) throw new ArgumentNullOrEmptyException(nameof(controllerName));
if (string.IsNullOrEmpty(controllerAction)) throw new ArgumentNullOrEmptyException(nameof(controllerAction));
if (area == null) throw new ArgumentNullException(nameof(area));
//need to create a params string as Base64 to put into our hidden field to use during the routes
var surfaceRouteParams = $"c={HttpUtility.UrlEncode(controllerName)}&a={HttpUtility.UrlEncode(controllerAction)}&ar={area}";
//checking if the additional route values is already a dictionary and convert to querystring
string additionalRouteValsAsQuery;
if (additionalRouteVals != null)
{
if (additionalRouteVals is Dictionary<string, object> additionalRouteValsAsDictionary)
additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString();
else
additionalRouteValsAsQuery = additionalRouteVals.ToDictionary<object>().ToQueryString();
}
else
additionalRouteValsAsQuery = null;
if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false)
surfaceRouteParams += "&" + additionalRouteValsAsQuery;
return surfaceRouteParams.EncryptWithMachineKey();
}
}
}