diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index b3281e8967..d49244d9f9 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -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 } diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 8b637fe90e..5c1f4e2c83 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -48,7 +48,7 @@ namespace Umbraco.Core /// DropDown List. /// public const string DropDownListFlexible = "Umbraco.DropDown.Flexible"; - + /// /// Grid. /// @@ -105,9 +105,9 @@ namespace Umbraco.Core public const string MultipleTextstring = "Umbraco.MultipleTextstring"; /// - /// NoEdit. + /// Label. /// - public const string NoEdit = "Umbraco.NoEdit"; + public const string Label = "Umbraco.Label"; /// /// Picker Relations. @@ -118,7 +118,7 @@ namespace Umbraco.Core /// RadioButton list. /// public const string RadioButtonList = "Umbraco.RadioButtonList"; - + /// /// Slider. /// @@ -142,7 +142,7 @@ namespace Umbraco.Core /// /// TinyMCE /// - public const string TinyMce = "Umbraco.TinyMCEv3"; + public const string TinyMce = "Umbraco.TinyMCE"; /// /// Boolean. @@ -163,7 +163,7 @@ namespace Umbraco.Core /// Upload Field. /// public const string UploadField = "Umbraco.UploadField"; - + /// /// Email Address. /// diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index 1fefcf85d9..d67680d98a 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs @@ -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}"); diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 4fa687fa5d..a27db08881 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -135,6 +135,8 @@ namespace Umbraco.Core.Migrations.Upgrade .To("{940FD19A-00A8-4D5C-B8FF-939143585726}") .As("{0576E786-5C30-4000-B969-302B61E90CA3}"); + To("{E0CBE54D-A84F-4A8F-9B13-900945FD7ED9}"); + //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddTypedLabels.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddTypedLabels.cs index cb8a58f3e3..2f20f01728 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddTypedLabels.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/AddTypedLabels.cs @@ -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 }; diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RenameLabelAndRichTextPropertyEditorAliases.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RenameLabelAndRichTextPropertyEditorAliases.cs new file mode 100644 index 0000000000..1252a26e68 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RenameLabelAndRichTextPropertyEditorAliases.cs @@ -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 GetDataTypes(string editorAlias) + { + var dataTypes = Database.Fetch(Sql() + .Select() + .From() + .Where(x => x.EditorAlias == editorAlias)); + return dataTypes; + } + + } +} diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index 963ab7050f..c811f484bc 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -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; } diff --git a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs index 2b8a207491..d0c40b1e63 100644 --- a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core.PropertyEditors /// /// Represents a property editor for label properties. /// - [DataEditor(Constants.PropertyEditors.Aliases.NoEdit, "Label", "readonlyvalue", Icon = "icon-readonly")] + [DataEditor(Constants.PropertyEditors.Aliases.Label, "Label", "readonlyvalue", Icon = "icon-readonly")] public class LabelPropertyEditor : DataEditor { /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs index 1be37e9c94..05a5f15aaf 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs @@ -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) { diff --git a/src/Umbraco.Core/Services/Implement/MemberService.cs b/src/Umbraco.Core/Services/Implement/MemberService.cs index 3b35896769..5ce824de16 100644 --- a/src/Umbraco.Core/Services/Implement/MemberService.cs +++ b/src/Umbraco.Core/Services/Implement/MemberService.cs @@ -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, diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 29bc0ef62d..247fed0a5e 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -205,6 +205,7 @@ + diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs index eeab265df8..71490465d0 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/PublishedMediaCache.cs @@ -70,7 +70,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache /// /// /// - 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() diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 2d999f00cd..b558ce6c87 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -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)); } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index a9022554c9..f801d02c5b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -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() .Clear() .Append(); + + Composition.RegisterUnique(); } 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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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()); + var cache = new PublishedMediaCache(ServiceContext.MediaService, ServiceContext.UserService, searcher, new DictionaryAppCache(), ContentTypesCache, Factory.GetInstance(), Factory.GetInstance()); //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); diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 6141695738..93c6100a51 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -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(), context => { - var membershipHelper = new MembershipHelper(umbracoContextAccessor, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); - return new CustomDocumentController(Factory.GetInstance(), + var membershipHelper = new MembershipHelper( + umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + return new CustomDocumentController(Factory.GetInstance(), umbracoContextAccessor, Factory.GetInstance(), Factory.GetInstance(), Factory.GetInstance(), - new UmbracoHelper(umbracoContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper)); + new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), membershipHelper)); })); handler.GetHandlerForRoute(umbracoContext.HttpContext.Request.RequestContext, frequest); diff --git a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml b/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml index 517db639a0..2ec534334f 100644 --- a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml +++ b/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage-Random.xml @@ -71,7 +71,7 @@ Content content - Umbraco.TinyMCEv3 + Umbraco.TinyMCE ca90c950-0aff-4e72-b976-a30b1ac57dad Content False @@ -172,4 +172,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml b/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml index f6b4e2c160..39a7f102a5 100644 --- a/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml +++ b/src/Umbraco.Tests/Services/Importing/CompositionsTestPackage.xml @@ -324,7 +324,7 @@ AboutText aboutText - Umbraco.TinyMCEv3 + Umbraco.TinyMCE ca90c950-0aff-4e72-b976-a30b1ac57dad About False @@ -472,7 +472,7 @@ Content bodyText - Umbraco.TinyMCEv3 + Umbraco.TinyMCE ca90c950-0aff-4e72-b976-a30b1ac57dad Content False @@ -593,7 +593,7 @@ Content bodyText - Umbraco.TinyMCEv3 + Umbraco.TinyMCE ca90c950-0aff-4e72-b976-a30b1ac57dad Content False @@ -721,8 +721,8 @@ + @@ -777,7 +777,7 @@ @{ Layout = "umbLayout.cshtml"; - // If the editor has not explicitly provided the "Page title" property page + // If the editor has not explicitly provided the "Page title" property page // then just show the name of the page otherwise show the provided title var pageTitle = string.IsNullOrWhiteSpace(CurrentPage.Title) ? CurrentPage.Name @@ -787,8 +787,8 @@ // AncestorsOrSelf is all of the ancestors this page has in the tree // (1) means: go up to level 1 and stop looking for more ancestors when you get there // First() gets the first ancestor found (the home page, on level 1) - var homePage = CurrentPage.AncestorsOrSelf(1).First(); - + var homePage = CurrentPage.AncestorsOrSelf(1).First(); + // Find all pages with document type alias umbNewsOverview // We do that using the plural, umbNewsOverviews (note the extra "s" in the end) // Then take the first one, as we know there will only be on news overview page @@ -815,18 +815,18 @@ @foreach (var item in newsItems) { - // If the editor has not explicitly provided the "Page title" property page + // If the editor has not explicitly provided the "Page title" property page // then just show the name of the page otherwise show the provided title - var title = string.IsNullOrWhiteSpace(item.Title) - ? item.Name + var title = string.IsNullOrWhiteSpace(item.Title) + ? item.Name : item.Title; // If the editor has not explicitly set the publishDate property then show the create date - var dateTime = item.PublishDate == default(DateTime) - ? item.CreateDate + var dateTime = item.PublishDate == default(DateTime) + ? item.CreateDate : item.PublishDate; - +

@title

@@ -869,11 +869,11 @@ @{ Layout = "umbLayout.cshtml"; - // If the editor has not explicitly provided the "Page title" property page + // If the editor has not explicitly provided the "Page title" property page // then just show the name of the page otherwise show the provided title var pageTitle = string.IsNullOrWhiteSpace(CurrentPage.Title) ? CurrentPage.Name - : CurrentPage.Title; + : CurrentPage.Title; }
@@ -892,7 +892,7 @@ } @CurrentPage.BodyText -
+ @@ -921,4 +921,4 @@ - \ No newline at end of file + diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 4cca5f195b..c6bbebf550 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -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(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/hello/world/1234")); - var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); + var membershipHelper = new MembershipHelper(umbCtx.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); - var umbHelper = new UmbracoHelper(umbCtx, + var umbHelper = new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index d7dcf8e79a..6de467f32f 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -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 }); diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index b69451547e..57381eb287 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -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(); // ReSharper disable once UnusedVariable - var helper = new UmbracoHelper(umbracoContext, + var helper = new UmbracoHelper(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 5aa1588ef2..55ceee0c1e 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -262,7 +262,7 @@ - + @@ -491,6 +491,7 @@ + diff --git a/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs b/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs index ba19f41e74..a301dfbd04 100644 --- a/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/HtmlHelperExtensionMethodsTests.cs @@ -7,6 +7,9 @@ namespace Umbraco.Tests.Web.Mvc [TestFixture] public class HtmlHelperExtensionMethodsTests { + private const string SampleWithAnchorElement = "Hello world, this is some text with a link"; + private const string SampleWithBoldAndAnchorElements = "Hello world, this is some text with a link"; + [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("
hello world
", 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…", 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…", 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…", 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 with…", 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…", 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, this is…", 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 with…", 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, is some text with a link"; + + 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); + } } } diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index eca6a6e144..846ee4b7d8 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -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(), Mock.Of(), Mock.Of(), Mock.Of(query => query.Content(2) == content.Object), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); + new MembershipHelper(umbracoContext.HttpContext, Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of())); var ctrl = new TestSurfaceController(umbracoContextAccessor, helper); var result = ctrl.GetContent(2) as PublishedContentResult; diff --git a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs b/src/Umbraco.Tests/Web/UmbracoHelperTests.cs similarity index 59% rename from src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs rename to src/Umbraco.Tests/Web/UmbracoHelperTests.cs index b7b85cc4de..b23b5bd6b7 100644 --- a/src/Umbraco.Tests/FrontEnd/UmbracoHelperTests.cs +++ b/src/Umbraco.Tests/Web/UmbracoHelperTests.cs @@ -1,184 +1,30 @@ 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 with a link"; - private const string SampleWithBoldAndAnchorElements = "Hello world, this is some text with a link"; + { [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…", 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…", 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…", 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 with…", 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() - { - {"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…", 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, this is…", 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 with…", 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, is some text with a link"; - - 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] public static void Converting_Boxed_34_To_An_Int_Returns_34() diff --git a/src/Umbraco.Tests/Web/UrlHelperExtensionTests.cs b/src/Umbraco.Tests/Web/UrlHelperExtensionTests.cs new file mode 100644 index 0000000000..a4b96ab4ff --- /dev/null +++ b/src/Umbraco.Tests/Web/UrlHelperExtensionTests.cs @@ -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() + { + {"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); + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 03ed7aadaf..e6b8bae30c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -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; @@ -213,24 +213,7 @@ $scope.page.showPreviewButton = true; } - - // 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); - } + createButtons($scope.content); + }; /** @@ -896,6 +876,18 @@ $scope.infiniteModel.close($scope.infiniteModel); } }; + + /** + * 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 () { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js index 5556308e06..effa21e581 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js @@ -17,7 +17,9 @@ onSelectVariant: "&", onOpenSplitView: "&", onSelectApp: "&", - onSelectAppAnchor: "&" + onSelectAppAnchor: "&", + onBack: "&?", + showBack: " + on-select-app-anchor="appAnchorChanged(app, anchor)" + on-back="onBack()" + show-back="!(infiniteModel && infiniteModel.infiniteMode)" + > @@ -59,7 +62,7 @@ + on-select-app-anchor="vm.selectAppAnchor(app, anchor)" + on-back="vm.onBack()" + show-back="vm.showBack"> diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html index 34c7792055..94fb7edae8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content.html @@ -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()" diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html index 09d46fcf4c..227a08c54f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html @@ -69,7 +69,7 @@ -
+
-
+
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 /// 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; diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs index 0a24bbb4d2..e49754dff9 100644 --- a/src/Umbraco.Web/Editors/DataTypeController.cs +++ b/src/Umbraco.Web/Editors/DataTypeController.cs @@ -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(dt); } diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index e55cff10c4..9e91bb1d99 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -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; diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index dccc5594fa..99adf71742 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -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 + + /// + /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. + /// + public static IHtmlString If(this HtmlHelper html, bool test, string valueIfTrue, string valueIfFalse) + { + return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse); + } + + /// + /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. + /// + 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(); + + /// + /// Replaces text line breaks with HTML line breaks + /// + /// + /// The text. + /// The text with text line breaks replaced with HTML line breaks (
)
+ public static IHtmlString ReplaceLineBreaksForHtml(this HtmlHelper helper, string text) + { + return StringUtilities.ReplaceLineBreaksForHtml(text); + } + + /// + /// 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. + /// + /// + /// The text to create a hash from + /// Hash of the text string + public static string CreateHash(this HtmlHelper helper, string text) + { + return text.GenerateHash(); + } + + /// + /// Strips all HTML tags from a given string, all contents of the tags will remain. + /// + public static IHtmlString StripHtml(this HtmlHelper helper, IHtmlString html, params string[] tags) + { + return helper.StripHtml(html.ToHtmlString(), tags); + } + + /// + /// Strips all HTML tags from a given string, all contents of the tags will remain. + /// + public static IHtmlString StripHtml(this HtmlHelper helper, string html, params string[] tags) + { + return StringUtilities.StripHtmlTags(html, tags); + } + + /// + /// Will take the first non-null value in the collection and return the value of it. + /// + public static string Coalesce(this HtmlHelper helper, params object[] args) + { + return StringUtilities.Coalesce(args); + } + + /// + /// Joins any number of int/string/objects into one string + /// + public static string Concatenate(this HtmlHelper helper, params object[] args) + { + return StringUtilities.Concatenate(args); + } + + /// + /// Joins any number of int/string/objects into one string and separates them with the string separator parameter. + /// + public static string Join(this HtmlHelper helper, string separator, params object[] args) + { + return StringUtilities.Join(separator, args); + } + + /// + /// 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 + /// + public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length) + { + return helper.Truncate(html.ToHtmlString(), length, true, false); + } + + /// + /// 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 + /// + public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length, bool addElipsis) + { + return helper.Truncate(html.ToHtmlString(), length, addElipsis, false); + } + + /// + /// 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 + /// + public static IHtmlString Truncate(this HtmlHelper helper, IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent) + { + return helper.Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent); + } + + /// + /// 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 + /// + public static IHtmlString Truncate(this HtmlHelper helper, string html, int length) + { + return helper.Truncate(html, length, true, false); + } + + /// + /// 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 + /// + public static IHtmlString Truncate(this HtmlHelper helper, string html, int length, bool addElipsis) + { + return helper.Truncate(html, length, addElipsis, false); + } + + /// + /// 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 + /// + 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 + + /// + /// 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 + /// + public static IHtmlString TruncateByWords(this HtmlHelper helper, string html, int words) + { + int length = StringUtilities.WordsToLength(html, words); + + return helper.Truncate(html, length, true, false); + } + + /// + /// 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 + /// + 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); + } + + /// + /// 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 + /// + 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); + } + + /// + /// 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 + /// + 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 } } diff --git a/src/Umbraco.Web/HybridAccessorBase.cs b/src/Umbraco.Web/HybridAccessorBase.cs index 669b929fd6..ec18b6f3d4 100644 --- a/src/Umbraco.Web/HybridAccessorBase.cs +++ b/src/Umbraco.Web/HybridAccessorBase.cs @@ -4,7 +4,16 @@ using Umbraco.Core; namespace Umbraco.Web { - internal abstract class HybridAccessorBase + /// + /// Provides a base class for hybrid accessors. + /// + /// The type of the accessed object. + /// + /// 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. + /// + public abstract class HybridAccessorBase 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) { diff --git a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs index e8a07b0f4c..d5d03d58bb 100644 --- a/src/Umbraco.Web/HybridUmbracoContextAccessor.cs +++ b/src/Umbraco.Web/HybridUmbracoContextAccessor.cs @@ -1,17 +1,27 @@ namespace Umbraco.Web { + /// + /// Implements a hybrid . + /// internal class HybridUmbracoContextAccessor : HybridAccessorBase, IUmbracoContextAccessor { + /// + /// Initializes a new instance of the class. + /// public HybridUmbracoContextAccessor(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor) { } + /// protected override string ItemKey => "Umbraco.Web.HybridUmbracoContextAccessor"; + /// + /// Gets or sets the object. + /// public UmbracoContext UmbracoContext { - get { return Value; } - set { Value = value; } + get => Value; + set => Value = value; } } } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicConverter.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicConverter.cs index 006954fcb2..effa59fd63 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicConverter.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyBasicConverter.cs @@ -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 diff --git a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs index 517889277c..1e93618547 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs @@ -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 diff --git a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs index bbbf5e2746..ea0411eb15 100644 --- a/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/PropertyTypeGroupResolver.cs @@ -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]; } diff --git a/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs b/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs new file mode 100644 index 0000000000..cb002e11b0 --- /dev/null +++ b/src/Umbraco.Web/Models/PublishedContent/HybridVariationContextAccessor.cs @@ -0,0 +1,26 @@ +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Web.Models.PublishedContent +{ + /// + /// Implements a hybrid . + /// + internal class HybridVariationContextAccessor : HybridAccessorBase, IVariationContextAccessor + { + public HybridVariationContextAccessor(IHttpContextAccessor httpContextAccessor) + : base(httpContextAccessor) + { } + + /// + protected override string ItemKey => "Umbraco.Web.HybridVariationContextAccessor"; + + /// + /// Gets or sets the object. + /// + public VariationContext VariationContext + { + get => Value; + set => Value = value; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 8a7565265f..39933b49be 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -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,50 +86,52 @@ namespace Umbraco.Web.Models /// public virtual string GetUrl(string culture = null) // TODO: consider .GetCulture("fr-FR").Url { - var umbracoContext = _umbracoContextAccessor.UmbracoContext; - switch (ItemType) - { - case PublishedItemType.Content: - 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); + switch (ItemType) + { + case PublishedItemType.Content: + var umbracoContext = UmbracoContextAccessor.UmbracoContext; - case PublishedItemType.Media: - var prop = GetProperty(Constants.Conventions.Media.File); - if (prop?.GetValue() == null) - { - return string.Empty; - } + 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."); - var propType = ContentType.GetPropertyType(Constants.Conventions.Media.File); - - // TODO: consider implementing media url providers - // note: that one does not support variations - //This is a hack - since we now have 2 properties that support a URL: upload and cropper, we need to detect this since we always - // want to return the normal URL and the cropper stores data as json - 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 - - var stronglyTyped = prop.GetValue() as ImageCropperValue; - if (stronglyTyped != null) - { - return stronglyTyped.Src; - } - return prop.GetValue()?.ToString(); - } + return umbracoContext.UrlProvider.GetUrl(this, culture); + case PublishedItemType.Media: + var prop = GetProperty(Constants.Conventions.Media.File); + if (prop?.GetValue() == null) + { return string.Empty; + } - default: - throw new NotSupportedException(); - } + var propType = ContentType.GetPropertyType(Constants.Conventions.Media.File); + + // TODO: consider implementing media url providers + // note: that one does not support variations + //This is a hack - since we now have 2 properties that support a URL: upload and cropper, we need to detect this since we always + // want to return the normal URL and the cropper stores data as json + switch (propType.EditorAlias) + { + case Constants.PropertyEditors.Aliases.UploadField: + + return prop.GetValue().ToString(); + case Constants.PropertyEditors.Aliases.ImageCropper: + //get the url from the json format + + var stronglyTyped = prop.GetValue() as ImageCropperValue; + if (stronglyTyped != null) + { + return stronglyTyped.Src; + } + return prop.GetValue()?.ToString(); + } + + return string.Empty; + + default: + throw new NotSupportedException(); + } } /// diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index aa19918ca9..3526a6daeb 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -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,... diff --git a/src/Umbraco.Web/Routing/UrlProvider.cs b/src/Umbraco.Web/Routing/UrlProvider.cs index da64d46046..0662d46f49 100644 --- a/src/Umbraco.Web/Routing/UrlProvider.cs +++ b/src/Umbraco.Web/Routing/UrlProvider.cs @@ -246,7 +246,7 @@ namespace Umbraco.Web.Routing /// public IEnumerable 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()); } #endregion diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index b4f947bb5d..91859b3e5b 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -72,8 +72,12 @@ namespace Umbraco.Web.Runtime // setup mvc and webapi services SetupMvcAndWebApi(); - // client dependency - ConfigureClientDependency(_globalSettings); + // 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,10 +259,7 @@ 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); + ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer); } } } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 599ace1bce..79712e01f1 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -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())); - composition.Register(); + composition.Register(Lifetime.Request); + composition.Register(factory => factory.GetInstance().PublishedSnapshot.Members); // register accessors for cultures composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); // 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(); + composition.Register(factory => + { + var umbCtx = factory.GetInstance(); + return new UmbracoHelper(umbCtx.IsFrontEndUmbracoRequest ? umbCtx.PublishedRequest?.PublishedContent : null, + factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), + factory.GetInstance()); + }); else composition.Register(_ => new UmbracoHelper()); diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index cd87d9dd37..5e9beeff29 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -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); } } diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 7e00304c8c..3bb6951d9a 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -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 ///
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; } /// /// Check if a document object is protected by the "Protect Pages" functionality in umbraco @@ -103,17 +101,9 @@ namespace Umbraco.Web.Security /// /// /// - /// - /// 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. - /// 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); } /// @@ -703,7 +693,7 @@ namespace Umbraco.Web.Security /// public virtual Attempt 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); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 133da122a1..126e725a50 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -202,6 +202,7 @@ + diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index c67c1da02d..8ab6f8c946 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -189,6 +189,78 @@ namespace Umbraco.Web private set => _previewing = value; } + #region Urls + + /// + /// Gets the url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The url for the content. + public string Url(int contentId, string culture = null) + { + return UrlProvider.GetUrl(contentId, culture); + } + + /// + /// Gets the url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The url for the content. + public string Url(Guid contentId, string culture = null) + { + return UrlProvider.GetUrl(contentId, culture); + } + + /// + /// Gets the url of a content identified by its identifier, in a specified mode. + /// + /// The content identifier. + /// The mode. + /// + /// The url for the content. + public string Url(int contentId, UrlProviderMode mode, string culture = null) + { + return UrlProvider.GetUrl(contentId, mode, culture); + } + + /// + /// Gets the url of a content identified by its identifier, in a specified mode. + /// + /// The content identifier. + /// The mode. + /// + /// The url for the content. + public string Url(Guid contentId, UrlProviderMode mode, string culture = null) + { + return UrlProvider.GetUrl(contentId, mode, culture); + } + + /// + /// Gets the absolute url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The absolute url for the content. + public string UrlAbsolute(int contentId, string culture = null) + { + return UrlProvider.GetUrl(contentId, true, culture); + } + + /// + /// Gets the absolute url of a content identified by its identifier. + /// + /// The content identifier. + /// + /// The absolute url for the content. + public string UrlAbsolute(Guid contentId, string culture = null) + { + return UrlProvider.GetUrl(contentId, true, culture); + } + + #endregion + private string PreviewToken { get diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index d2da4d1646..b2045bacfb 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -22,14 +22,11 @@ namespace Umbraco.Web /// 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 /// /// Initializes a new instance of . /// - /// An Umbraco context. + /// The item assigned to the helper. /// /// /// /// /// /// Sets the current page to the context's published content request's content item. - 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; } /// @@ -77,7 +72,6 @@ namespace Umbraco.Web private IUmbracoComponentRenderer ComponentRenderer => Ensure(_componentRenderer); private ICultureDictionaryFactory CultureDictionaryFactory => Ensure(_cultureDictionaryFactory); - private UmbracoContext UmbracoContext => Ensure(_umbracoContext); /// /// Gets the tag context. @@ -94,11 +88,6 @@ namespace Umbraco.Web /// public MembershipHelper MembershipHelper => Ensure(_membershipHelper); - /// - /// Gets the url provider. - /// - public UrlProvider UrlProvider => UmbracoContext.UrlProvider; - /// /// Gets (or sets) the current item assigned to the UmbracoHelper. /// @@ -106,14 +95,13 @@ namespace Umbraco.Web /// /// 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. /// /// /// 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. /// /// /// 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 /// public IHtmlString RenderMacro(string alias) { - return ComponentRenderer.RenderMacro(UmbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, new { }); + return ComponentRenderer.RenderMacro(AssignedContentItem?.Id ?? 0, alias, new { }); } /// @@ -167,7 +155,7 @@ namespace Umbraco.Web /// public IHtmlString RenderMacro(string alias, object parameters) { - return ComponentRenderer.RenderMacro(UmbracoContext.PublishedRequest?.PublishedContent?.Id ?? 0, alias, parameters.ToDictionary()); + return ComponentRenderer.RenderMacro(AssignedContentItem?.Id ?? 0, alias, parameters.ToDictionary()); } /// @@ -178,7 +166,7 @@ namespace Umbraco.Web /// public IHtmlString RenderMacro(string alias, IDictionary 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 - - /// - /// Gets the url of a content identified by its identifier. - /// - /// The content identifier. - /// - /// The url for the content. - public string Url(int contentId, string culture = null) - { - return UrlProvider.GetUrl(contentId, culture); - } - - /// - /// Gets the url of a content identified by its identifier, in a specified mode. - /// - /// The content identifier. - /// The mode. - /// The url for the content. - public string Url(int contentId, UrlProviderMode mode, string culture = null) - { - return UrlProvider.GetUrl(contentId, mode, culture); - } - - /// - /// Gets the absolute url of a content identified by its identifier. - /// - /// The content identifier. - /// The absolute url for the content. - 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 + - /// - /// Replaces text line breaks with HTML line breaks - /// - /// The text. - /// The text with text line breaks replaced with HTML line breaks (
)
- public IHtmlString ReplaceLineBreaksForHtml(string text) - { - return StringUtilities.ReplaceLineBreaksForHtml(text); - } + - /// - /// 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. - /// - /// The text to create a hash from - /// Hash of the text string - public string CreateHash(string text) - { - return text.GenerateHash(); - } - - /// - /// Strips all HTML tags from a given string, all contents of the tags will remain. - /// - public HtmlString StripHtml(IHtmlString html, params string[] tags) - { - return StripHtml(html.ToHtmlString(), tags); - } - - /// - /// Strips all HTML tags from a given string, all contents of the tags will remain. - /// - public HtmlString StripHtml(string html, params string[] tags) - { - return StringUtilities.StripHtmlTags(html, tags); - } - - /// - /// Will take the first non-null value in the collection and return the value of it. - /// - public string Coalesce(params object[] args) - { - return StringUtilities.Coalesce(args); - } - - /// - /// Joins any number of int/string/objects into one string - /// - public string Concatenate(params object[] args) - { - return StringUtilities.Concatenate(args); - } - - /// - /// Joins any number of int/string/objects into one string and separates them with the string separator parameter. - /// - public string Join(string separator, params object[] args) - { - return StringUtilities.Join(separator, args); - } - - /// - /// 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 - /// - public IHtmlString Truncate(IHtmlString html, int length) - { - return Truncate(html.ToHtmlString(), length, true, false); - } - - /// - /// 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 - /// - public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis) - { - return Truncate(html.ToHtmlString(), length, addElipsis, false); - } - - /// - /// 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 - /// - public IHtmlString Truncate(IHtmlString html, int length, bool addElipsis, bool treatTagsAsContent) - { - return Truncate(html.ToHtmlString(), length, addElipsis, treatTagsAsContent); - } - - /// - /// 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 - /// - public IHtmlString Truncate(string html, int length) - { - return Truncate(html, length, true, false); - } - - /// - /// 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 - /// - public IHtmlString Truncate(string html, int length, bool addElipsis) - { - return Truncate(html, length, addElipsis, false); - } - - /// - /// 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 - /// - public IHtmlString Truncate(string html, int length, bool addElipsis, bool treatTagsAsContent) - { - return StringUtilities.Truncate(html, length, addElipsis, treatTagsAsContent); - } - - #region Truncate by Words - - /// - /// 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 - /// - public IHtmlString TruncateByWords(string html, int words) - { - int length = StringUtilities.WordsToLength(html, words); - - return Truncate(html, length, true, false); - } - - /// - /// 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 - /// - public IHtmlString TruncateByWords(string html, int words, bool addElipsis) - { - int length = StringUtilities.WordsToLength(html, words); - - return Truncate(html, length, addElipsis, false); - } - - /// - /// 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 - /// - public IHtmlString TruncateByWords(IHtmlString html, int words) - { - int length = StringUtilities.WordsToLength(html.ToHtmlString(), words); - - return Truncate(html, length, true, false); - } - - /// - /// 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 - /// - 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 - - /// - /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. - /// - public HtmlString If(bool test, string valueIfTrue, string valueIfFalse) - { - return test ? new HtmlString(valueIfTrue) : new HtmlString(valueIfFalse); - } - - /// - /// If the test is true, the string valueIfTrue will be returned, otherwise the valueIfFalse will be returned. - /// - public HtmlString If(bool test, string valueIfTrue) - { - return test ? new HtmlString(valueIfTrue) : new HtmlString(string.Empty); - } - - #endregion - - /// - /// 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. - /// - /// - /// - /// - /// - /// - 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; - if (additionalRouteValsAsDictionary != null) - additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); - else - additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); - } - else - additionalRouteValsAsQuery = null; - - if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false) - surfaceRouteParams += "&" + additionalRouteValsAsQuery; - - return surfaceRouteParams.EncryptWithMachineKey(); - } + } } diff --git a/src/Umbraco.Web/UrlHelperRenderExtensions.cs b/src/Umbraco.Web/UrlHelperRenderExtensions.cs index cc5000bb19..6f7fbacf7a 100644 --- a/src/Umbraco.Web/UrlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/UrlHelperRenderExtensions.cs @@ -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; } + + /// + /// 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. + /// + /// + /// + /// + /// + /// + 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 additionalRouteValsAsDictionary) + additionalRouteValsAsQuery = additionalRouteValsAsDictionary.ToQueryString(); + else + additionalRouteValsAsQuery = additionalRouteVals.ToDictionary().ToQueryString(); + } + else + additionalRouteValsAsQuery = null; + + if (additionalRouteValsAsQuery.IsNullOrWhiteSpace() == false) + surfaceRouteParams += "&" + additionalRouteValsAsQuery; + + return surfaceRouteParams.EncryptWithMachineKey(); + } } }