From 9b9c7c8e3abe63e7afd25d509710e5b8c676238b Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 30 Nov 2017 13:56:29 +0100 Subject: [PATCH] Refactor content service --- src/Umbraco.Core/Models/Content.cs | 213 +++-- src/Umbraco.Core/Models/ContentBase.cs | 168 +--- src/Umbraco.Core/Models/ContentTypeBase.cs | 4 + src/Umbraco.Core/Models/IContent.cs | 54 +- src/Umbraco.Core/Models/IContentBase.cs | 82 +- src/Umbraco.Core/Models/Property.cs | 271 +++--- src/Umbraco.Core/Models/PropertyType.cs | 7 +- .../Models/Rdbms/ContentTypeDto.cs | 2 +- .../Models/Rdbms/PropertyTypeDto.cs | 2 +- ...ontentFactory.cs => ContentBaseFactory.cs} | 441 ++++++---- .../Persistence/Factories/MediaFactory.cs | 114 --- .../Persistence/Factories/MemberFactory.cs | 124 --- .../Migrations/Initial/BaseDataCreation.cs | 41 +- .../TargetVersionEight/VariantsMigration.cs | 9 + .../Repositories/ContentRepository.cs | 20 +- .../Repositories/ContentTypeRepositoryBase.cs | 11 +- .../Interfaces/IRepositoryVersionable.cs | 24 +- .../Repositories/MediaRepository.cs | 10 +- .../Repositories/MemberRepository.cs | 10 +- .../Repositories/VersionableRepositoryBase.cs | 4 +- .../Publishing/ScheduledPublisher.cs | 19 +- src/Umbraco.Core/Services/ContentService.cs | 477 +++-------- .../Services/ContentServiceExtensions.cs | 4 +- .../Services/ContentTypeService.cs | 2 +- ...peServiceBaseOfTRepositoryTItemTService.cs | 48 +- src/Umbraco.Core/Services/DataTypeService.cs | 42 +- src/Umbraco.Core/Services/DomainService.cs | 12 +- src/Umbraco.Core/Services/FileService.cs | 6 +- src/Umbraco.Core/Services/IContentService.cs | 802 +++++++----------- .../Services/IContentTypeServiceBase.cs | 12 +- src/Umbraco.Core/Services/IDataTypeService.cs | 10 +- src/Umbraco.Core/Services/IDomainService.cs | 4 +- src/Umbraco.Core/Services/IFileService.cs | 2 +- src/Umbraco.Core/Services/IMediaService.cs | 10 +- .../Services/IPublicAccessService.cs | 8 +- src/Umbraco.Core/Services/MediaService.cs | 30 +- .../Services/NotificationService.cs | 2 +- src/Umbraco.Core/Services/OperationResult.cs | 238 ++++++ .../Services/OperationResultType.cs | 45 + src/Umbraco.Core/Services/OperationStatus.cs | 214 ----- .../Services/OperationStatusType.cs | 70 -- src/Umbraco.Core/Services/PackagingService.cs | 8 +- .../Services/PublicAccessService.cs | 32 +- src/Umbraco.Core/Services/PublishResult.cs | 36 + .../Services/PublishResultType.cs | 59 ++ src/Umbraco.Core/Services/PublishStatus.cs | 41 - .../Services/PublishStatusType.cs | 84 -- .../Services/ServiceWithResultExtensions.cs | 4 - src/Umbraco.Core/Services/UnPublishStatus.cs | 35 - .../Services/UnPublishedStatusType.cs | 26 - src/Umbraco.Core/Umbraco.Core.csproj | 14 +- .../Integration/ContentEventsTests.cs | 265 +++--- .../Integration/GetCultureTests.cs | 16 +- src/Umbraco.Tests/Models/ContentTests.cs | 2 +- src/Umbraco.Tests/Models/VariationTests.cs | 266 ++++++ .../NPocoTests/PetaPocoCachesTest.cs | 20 +- .../Repositories/ContentRepositoryTest.cs | 12 +- .../Publishing/PublishingStrategyTests.cs | 22 +- .../Scoping/ScopedNuCacheTests.cs | 6 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 14 +- .../Services/ContentServiceTests.cs | 420 ++++++--- .../Services/ContentTypeServiceTests.cs | 40 +- .../Services/PerformanceTests.cs | 4 +- .../Services/PublicAccessServiceTests.cs | 10 +- src/Umbraco.Tests/Services/TagServiceTests.cs | 9 +- .../Services/ThreadSafetyServiceTest.cs | 4 +- .../Services/UserServiceTests.cs | 68 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + .../umbraco/dialogs/ChangeDocType.aspx.cs | 3 +- src/Umbraco.Web/Editors/ContentController.cs | 76 +- .../Editors/ContentTypeController.cs | 4 +- .../Editors/ContentTypeControllerBase.cs | 10 +- src/Umbraco.Web/Editors/DataTypeController.cs | 2 +- src/Umbraco.Web/Editors/MediaController.cs | 2 +- .../Mapping/ContentTypeMapperProfile.cs | 2 + .../Mapping/ContentTypeProfileExtensions.cs | 2 + .../NuCache/PublishedSnapshotService.cs | 2 +- .../WebServices/BulkPublishController.cs | 47 +- .../WebServices/DomainsApiController.cs | 4 +- .../PackageActions/publishRootDocument.cs | 2 +- .../umbraco/dialogs/protectPage.aspx.cs | 4 +- 81 files changed, 2636 insertions(+), 2710 deletions(-) rename src/Umbraco.Core/Persistence/Factories/{ContentFactory.cs => ContentBaseFactory.cs} (50%) delete mode 100644 src/Umbraco.Core/Persistence/Factories/MediaFactory.cs delete mode 100644 src/Umbraco.Core/Persistence/Factories/MemberFactory.cs create mode 100644 src/Umbraco.Core/Services/OperationResult.cs create mode 100644 src/Umbraco.Core/Services/OperationResultType.cs delete mode 100644 src/Umbraco.Core/Services/OperationStatus.cs delete mode 100644 src/Umbraco.Core/Services/OperationStatusType.cs create mode 100644 src/Umbraco.Core/Services/PublishResult.cs create mode 100644 src/Umbraco.Core/Services/PublishResultType.cs delete mode 100644 src/Umbraco.Core/Services/PublishStatus.cs delete mode 100644 src/Umbraco.Core/Services/PublishStatusType.cs delete mode 100644 src/Umbraco.Core/Services/UnPublishStatus.cs delete mode 100644 src/Umbraco.Core/Services/UnPublishedStatusType.cs create mode 100644 src/Umbraco.Tests/Models/VariationTests.cs diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 316d2bb6b9..4a680eabc1 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -225,97 +226,87 @@ namespace Umbraco.Core.Models [DataMember] public bool Blueprint { get; internal set; } - /// - /// Publish the neutral value. - /// - internal virtual void PublishValues() + /// + public virtual void PublishAllValues() { - foreach (var property in Properties) - property.PublishValues(null, null); - _publishedState = PublishedState.Publishing; - } + if (ValidateAll().Any()) + throw new InvalidOperationException("Values are not valid."); - /// - /// Publish the culture value. - /// - internal virtual void PublishValues(int? nLanguageId) - { - foreach (var property in Properties) - property.PublishValues(nLanguageId, null); - _publishedState = PublishedState.Publishing; - } - - /// - /// Publish the segment value. - /// - internal virtual void PublishValues(string segment) - { - foreach (var property in Properties) - property.PublishValues(null, segment); - _publishedState = PublishedState.Publishing; - } - - /// - /// Publish the culture+segment value. - /// - internal virtual void PublishValues(int? nLanguageId, string segment) - { - foreach (var property in Properties) - property.PublishValues(nLanguageId, segment); - _publishedState = PublishedState.Publishing; - } - - /// - /// Publish all values. - /// - internal virtual void PublishAllValues() - { foreach (var property in Properties) property.PublishAllValues(); _publishedState = PublishedState.Publishing; } - internal virtual void CopyValues(IContentBase other, int? languageId, string segment, bool published = false) + /// + public virtual void PublishValues(int? languageId = null, string segment = null) { - if (other.ContentTypeId != ContentTypeId) - throw new InvalidOperationException("Cannot copy values from a different content type."); + if (Validate(languageId, segment).Any()) + throw new InvalidOperationException("Values are not valid."); - // clear all existing properties - // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails foreach (var property in Properties) - { - // skip properties that don't support the specified variation - if (!property.PropertyType.ValidateVariation(languageId, segment, false)) - continue; - - foreach (var pvalue in property.Values) - if (pvalue.LanguageId == languageId && pvalue.Segment == segment) - property.SetValue(pvalue.LanguageId, pvalue.Segment, null); - } - - // copy other properties - var otherProperties = other.Properties; - foreach (var otherProperty in otherProperties) - { - // skip properties that don't support the specified variation - if (!otherProperty.PropertyType.ValidateVariation(languageId, segment, false)) - continue; - - var alias = otherProperty.PropertyType.Alias; - SetValue(alias, languageId, segment, otherProperty.GetValue(languageId, segment, published)); - } + property.PublishValue(languageId, segment); + _publishedState = PublishedState.Publishing; } - internal virtual void CopyAllValues(IContentBase other, bool published = false) + /// + public virtual void PublishCultureValues(int? languageId = null) + { + if (ValidateCulture(languageId).Any()) + throw new InvalidOperationException("Values are not valid."); + + foreach (var property in Properties) + property.PublishCultureValues(languageId); + _publishedState = PublishedState.Publishing; + } + + /// + public virtual void ClearAllPublishedValues() + { + foreach (var property in Properties) + property.ClearPublishedAllValues(); + _publishedState = PublishedState.Publishing; + } + + /// + public virtual void ClearPublishedValues(int? languageId = null, string segment = null) + { + foreach (var property in Properties) + property.ClearPublishedValue(languageId, segment); + _publishedState = PublishedState.Publishing; + } + + /// + public virtual void ClearCulturePublishedValues(int? languageId = null) + { + foreach (var property in Properties) + property.ClearPublishedCultureValues(languageId); + _publishedState = PublishedState.Publishing; + } + + private bool IsCopyFromSelf(IContent other) + { + // copying from the same Id and VersionPk + return Id == other.Id && VersionPk == ((Content) other).VersionPk; + } + + /// + public virtual void CopyAllValues(IContent other) { if (other.ContentTypeId != ContentTypeId) throw new InvalidOperationException("Cannot copy values from a different content type."); - // clear all existing properties + // we could copy from another document entirely, + // or from another version of the same document, + // in which case there is a special case. + var published = IsCopyFromSelf(other); + // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails + + // clear all existing properties foreach (var property in Properties) foreach (var pvalue in property.Values) - property.SetValue(pvalue.LanguageId, pvalue.Segment, null); + if (property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) + property.SetValue(null, pvalue.LanguageId, pvalue.Segment); // copy other properties var otherProperties = other.Properties; @@ -324,8 +315,74 @@ namespace Umbraco.Core.Models var alias = otherProperty.PropertyType.Alias; foreach (var pvalue in otherProperty.Values) { + if (!otherProperty.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) + continue; var value = published ? pvalue.PublishedValue : pvalue.EditedValue; - SetValue(alias, pvalue.LanguageId, pvalue.Segment, value); + SetValue(alias, value, pvalue.LanguageId, pvalue.Segment); + } + } + } + + /// + public virtual void CopyValues(IContent other, int? languageId = null, string segment = null) + { + if (other.ContentTypeId != ContentTypeId) + throw new InvalidOperationException("Cannot copy values from a different content type."); + + var published = VersionPk > PublishedVersionPk; + + // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails + + // clear all existing properties + foreach (var property in Properties) + { + if (!property.PropertyType.ValidateVariation(languageId, segment, false)) + continue; + + foreach (var pvalue in property.Values) + if (pvalue.LanguageId == languageId && pvalue.Segment == segment) + property.SetValue(null, pvalue.LanguageId, pvalue.Segment); + } + + // copy other properties + var otherProperties = other.Properties; + foreach (var otherProperty in otherProperties) + { + if (!otherProperty.PropertyType.ValidateVariation(languageId, segment, false)) + continue; + + var alias = otherProperty.PropertyType.Alias; + SetValue(alias, otherProperty.GetValue(languageId, segment, published), languageId, segment); + } + } + + /// + public virtual void CopyCultureValues(IContent other, int? languageId = null) + { + if (other.ContentTypeId != ContentTypeId) + throw new InvalidOperationException("Cannot copy values from a different content type."); + + var published = VersionPk > PublishedVersionPk; + + // note: use property.SetValue(), don't assign pvalue.EditValue, else change tracking fails + + // clear all existing properties + foreach (var property in Properties) + foreach (var pvalue in property.Values) + if (pvalue.LanguageId == languageId && property.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) + property.SetValue(null, pvalue.LanguageId, pvalue.Segment); + + // copy other properties + var otherProperties = other.Properties; + foreach (var otherProperty in otherProperties) + { + var alias = otherProperty.PropertyType.Alias; + foreach (var pvalue in otherProperty.Values) + { + if (pvalue.LanguageId != languageId || !otherProperty.PropertyType.ValidateVariation(pvalue.LanguageId, pvalue.Segment, false)) + continue; + var value = published ? pvalue.PublishedValue : pvalue.EditedValue; + SetValue(alias, value, pvalue.LanguageId, pvalue.Segment); } } } @@ -373,16 +430,6 @@ namespace Umbraco.Core.Models _publishedState = _published ? PublishedState.Published : PublishedState.Unpublished; } - /// - /// Creates a deep clone of the current entity with its identity and it's property identities reset - /// - /// - [Obsolete("Use DeepCloneWithResetIdentities instead")] - public IContent Clone() - { - return DeepCloneWithResetIdentities(); - } - /// /// Creates a deep clone of the current entity with its identity and it's property identities reset /// diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index b92f53ad6d..f7d643e9a3 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -39,7 +39,6 @@ namespace Umbraco.Core.Models private string _name; private PropertyCollection _properties; - private readonly List _invalidProperties = new List(); [EditorBrowsable(EditorBrowsableState.Never)] IDictionary IUmbracoEntity.AdditionalData => _lazyAdditionalData.Value; @@ -263,132 +262,44 @@ namespace Umbraco.Core.Models #region Has, Get, Set, Publish Property Value - /// - /// Gets a value indicating whether the content entity has a property with the supplied alias. - /// - /// Indicates that the content entity has a property with the supplied alias, but - /// not necessarily that the content has a value for that property. Could be missing. + /// public virtual bool HasProperty(string propertyTypeAlias) => Properties.Contains(propertyTypeAlias); - /// - /// Gets the neutral value of a property. - /// - public virtual object GetValue(string propertyTypeAlias, bool published = false) - { - return Properties.TryGetValue(propertyTypeAlias, out var property) - ? property.GetValue(published) - : null; - } - - /// - /// Gets the culture value of a property. - /// - public virtual object GetValue(string propertyTypeAlias, int? languageId, bool published = false) - { - return Properties.TryGetValue(propertyTypeAlias, out var property) - ? property.GetValue(languageId, null, published) - : null; - } - - /// - /// Gets the segment value of a property. - /// - public virtual object GetValue(string propertyTypeAlias, string segment, bool published = false) - { - return Properties.TryGetValue(propertyTypeAlias, out var property) - ? property.GetValue(null, segment, published) - : null; - } - - /// - /// Gets the culture+segment value of a property. - /// - public virtual object GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false) + /// + public virtual object GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false) { return Properties.TryGetValue(propertyTypeAlias, out var property) ? property.GetValue(languageId, segment, published) : null; } - /// - /// Gets the typed neutral value of a property. - /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, bool published = false) + /// + public virtual TValue GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false) { if (!Properties.TryGetValue(propertyTypeAlias, out var property)) return default; - var convertAttempt = property.GetValue(published).TryConvertTo(); + var convertAttempt = property.GetValue(languageId, segment, published).TryConvertTo(); return convertAttempt.Success ? convertAttempt.Result : default; } - /// - /// Gets the typed culture value of a property. - /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, int? languageId, bool published = false) + /// + public virtual void SetValue(string propertyTypeAlias, object value, int? languageId = null, string segment = null) { - if (!Properties.TryGetValue(propertyTypeAlias, out var property)) - return default; + if (Properties.Contains(propertyTypeAlias)) + { + Properties[propertyTypeAlias].SetValue(value, languageId, segment); + return; + } - var convertAttempt = property.GetValue(languageId, null, published).TryConvertTo(); - return convertAttempt.Success ? convertAttempt.Result : default; - } + var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); + if (propertyType == null) + throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\"."); - /// - /// Gets the typed segment value of a property. - /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, string segment, bool published = false) - { - if (!Properties.TryGetValue(propertyTypeAlias, out var property)) - return default; - - var convertAttempt = property.GetValue(null, segment, published).TryConvertTo(); - return convertAttempt.Success ? convertAttempt.Result : default; - } - - /// - /// Gets the typed culture+segment value of a property. - /// - public virtual TPropertyValue GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false) - { - if (!Properties.TryGetValue(propertyTypeAlias, out var property)) - return default; - - var convertAttempt = property.GetValue(languageId, segment, published).TryConvertTo(); - return convertAttempt.Success ? convertAttempt.Result : default; - } - - /// - /// Sets the neutral (draft) value of a property. - /// - public virtual void SetValue(string propertyTypeAlias, object value) - { - SetValueOnProperty(propertyTypeAlias, null, null, value); - } - - /// - /// Sets the culture (draft) value of a property. - /// - public virtual void SetValue(string propertyTypeAlias, int? languageId, object value) - { - SetValueOnProperty(propertyTypeAlias, languageId, null, value); - } - - /// - /// Sets the culture+segment (draft) value of a property. - /// - public virtual void SetValue(string propertyTypeAlias, string segment, object value) - { - SetValueOnProperty(propertyTypeAlias, null, segment, value); - } - - /// - /// Sets the culture+segment (draft) value of a property. - /// - public virtual void SetValue(string propertyTypeAlias, int? languageId, string segment, object value) - { - SetValueOnProperty(propertyTypeAlias, languageId, segment, value); + var property = propertyType.CreateProperty(); + property.SetValue(value, languageId, segment); + Properties.Add(property); } // fixme - these three use an extension method that needs to be adapted too @@ -415,50 +326,25 @@ namespace Umbraco.Core.Models ContentExtensions.SetValue(this, propertyTypeAlias, value); } - /// - /// Sets the (edited) value of a property. - /// - private void SetValueOnProperty(string propertyTypeAlias, int? languageId, string segment, object value) - { - if (Properties.Contains(propertyTypeAlias)) - { - Properties[propertyTypeAlias].SetValue(languageId, segment, value); - return; - } - - var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); - if (propertyType == null) - throw new InvalidOperationException($"No PropertyType exists with the supplied alias \"{propertyTypeAlias}\"."); - - var property = propertyType.CreateProperty(); - property.SetValue(languageId, segment, value); - Properties.Add(property); - } - #endregion #region Validation - public virtual Property[] Validate() + public virtual Property[] ValidateAll() { - return Properties.Where(x => !x.IsValid()).ToArray(); + return Properties.Where(x => !x.IsAllValid()).ToArray(); } - public virtual Property[] Validate(int? languageId) - { - return Properties.Where(x => !x.IsValid(languageId)).ToArray(); - } - - public virtual Property[] Validate(string segment) - { - return Properties.Where(x => !x.IsValid(segment)).ToArray(); - } - - public virtual Property[] Validate(int? languageId, string segment) + public virtual Property[] Validate(int? languageId = null, string segment = null) { return Properties.Where(x => !x.IsValid(languageId, segment)).ToArray(); } + public virtual Property[] ValidateCulture(int? languageId = null) + { + return Properties.Where(x => !x.IsCultureValid(languageId)).ToArray(); + } + #endregion #region Dirty diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 53ec572aa4..c62f88af71 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -53,6 +53,8 @@ namespace Umbraco.Core.Models // ReSharper disable once VirtualMemberCallInConstructor _propertyTypes = new PropertyTypeCollection(IsPublishing); _propertyTypes.CollectionChanged += PropertyTypesChanged; + + _variations = ContentVariation.InvariantNeutral; } protected ContentTypeBase(IContentTypeBase parent) @@ -73,6 +75,8 @@ namespace Umbraco.Core.Models // ReSharper disable once VirtualMemberCallInConstructor _propertyTypes = new PropertyTypeCollection(IsPublishing); _propertyTypes.CollectionChanged += PropertyTypesChanged; + + _variations = ContentVariation.InvariantNeutral; } /// diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index bd21037cd6..d19bc1425c 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -31,15 +31,13 @@ namespace Umbraco.Core.Models /// /// Gets the template used to render the published version of the content. /// - /// When editing the content, the template can change, but this will - /// not until the content is published. + /// When editing the content, the template can change, but this will not until the content is published. ITemplate PublishTemplate { get; } /// /// Gets the name of the published version of the content. /// - /// When editing the content, the name can change, but this will - /// not until the content is published. + /// When editing the content, the name can change, but this will not until the content is published. string PublishName { get; } /// @@ -98,5 +96,53 @@ namespace Umbraco.Core.Models /// /// IContent DeepCloneWithResetIdentities(); + + /// + /// Publishes all values. + /// + /// The document must then be published via the content service. + void PublishAllValues(); + + /// + /// Publishes values. + /// + /// The document must then be published via the content service. + void PublishValues(int? languageId = null, string segment = null); + + /// + /// Publishes the culture/any values. + /// + /// The document must then be published via the content service. + void PublishCultureValues(int? languageId = null); + + /// + /// Clears all published values. + /// + void ClearAllPublishedValues(); + + /// + /// Clears published values. + /// + void ClearPublishedValues(int? languageId = null, string segment = null); + + /// + /// Clears the culture/any published values. + /// + void ClearCulturePublishedValues(int? languageId = null); + + /// + /// Copies values from another document. + /// + void CopyAllValues(IContent other); + + /// + /// Copies values from another document. + /// + void CopyValues(IContent other, int? languageId = null, string segment = null); + + /// + /// Copies culture/any values from another document. + /// + void CopyCultureValues(IContent other, int? languageId = null); } } diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index 1b01979f6f..ba0b86ea40 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -44,90 +44,40 @@ namespace Umbraco.Core.Models IEnumerable PropertyTypes { get; } /// - /// Gets a value indicating whether the content object has a property with the supplied alias. + /// Gets a value indicating whether the content entity has a property with the supplied alias. /// - /// Alias of the PropertyType - /// True if Property with given alias exists, otherwise False - bool HasProperty(string propertyTypeAlias); // fixme - what does this mean???? + /// Indicates that the content entity has a property with the supplied alias, but + /// not necessarily that the content has a value for that property. Could be missing. + bool HasProperty(string propertyTypeAlias); /// - /// Gets the neutral value of a Property + /// Gets the value of a Property /// - object GetValue(string propertyTypeAlias, bool published = false); + object GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false); /// - /// Gets the culture value of a Property + /// Gets the typed value of a Property /// - object GetValue(string propertyTypeAlias, int? languageId, bool published = false); + TValue GetValue(string propertyTypeAlias, int? languageId = null, string segment = null, bool published = false); /// - /// Gets the segment value of a Property + /// Sets the (edited) value of a Property /// - object GetValue(string propertyTypeAlias, string segment, bool published = false); + void SetValue(string propertyTypeAlias, object value, int? languageId = null, string segment = null); /// - /// Gets the culture+segment value of a Property + /// Gets a value indicating whether the content and all its properties values are valid. /// - object GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false); + Property[] ValidateAll(); /// - /// Gets the typed neutral value of a Property + /// Gets a value indicating whether the content and its properties values are valid. /// - TPropertyValue GetValue(string propertyTypeAlias, bool published = false); + Property[] Validate(int? languageId = null, string segment = null); /// - /// Gets the typed culture value of a Property + /// Gets a value indicating whether the content and its culture/any properties values are valid. /// - TPropertyValue GetValue(string propertyTypeAlias, int? languageId, bool published = false); - - /// - /// Gets the typed segment value of a Property - /// - TPropertyValue GetValue(string propertyTypeAlias, string segment, bool published = false); - - /// - /// Gets the typed culture+segment value of a Property - /// - TPropertyValue GetValue(string propertyTypeAlias, int? languageId, string segment, bool published = false); - - /// - /// Sets the neutral (edited) value of a Property - /// - void SetValue(string propertyTypeAlias, object value); - - /// - /// Sets the culture (edited) value of a Property - /// - void SetValue(string propertyTypeAlias, int? languageId, object value); - - /// - /// Sets the segment (edited) value of a Property - /// - void SetValue(string propertyTypeAlias, string segment, object value); - - /// - /// Sets the culture+segment (edited) value of a Property - /// - void SetValue(string propertyTypeAlias, int? languageId, string segment, object value); - - /// - /// Gets a value indicating whether the content and its invariant+neutral properties values are valid. - /// - Property[] Validate(); - - /// - /// Gets a value indicating whether the content and its culture+neutral properties values are valid for the specified culture. - /// - Property[] Validate(int? languageId); - - /// - /// Gets a value indicating whether the content and its invariant+segment values are valid for the specified segment. - /// - Property[] Validate(string segment); - - /// - /// Gets a value indicating whether the content and its culture+segment properties values are valid. - /// - Property[] Validate(int? languageId, string segment); + Property[] ValidateCulture(int? languageId = null); } } diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 80be404bfa..4492ff507d 100644 --- a/src/Umbraco.Core/Models/Property.cs +++ b/src/Umbraco.Core/Models/Property.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Drawing.Printing; using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -133,44 +132,12 @@ namespace Umbraco.Core.Models internal DataTypeDatabaseType DataTypeDatabaseType => _propertyType.DataTypeDatabaseType; /// - /// Gets the neutral value. + /// Gets the value. /// - public object GetValue(bool published = false) - { - if (!_propertyType.ValidateVariation(null, null, false)) return null; - return _pvalue == null ? null : GetPropertyValue(_pvalue, published); - } - - /// - /// Gets the culture value. - /// - public object GetValue(int? languageId, bool published = false) - { - if (!_propertyType.ValidateVariation(languageId, null, false)) return null; - if (_vvalues == null) return null; - return _vvalues.TryGetValue((languageId, null), out var pvalue) - ? GetPropertyValue(pvalue, published) - : null; - } - - /// - /// Gets the segment value. - /// - public object GetValue(string segment, bool published = false) - { - if (!_propertyType.ValidateVariation(null, segment, false)) return null; - if (_vvalues == null) return null; - return _vvalues.TryGetValue((null, segment), out var pvalue) - ? GetPropertyValue(pvalue, published) - : null; - } - - /// - /// Gets the culture+segment value. - /// - public object GetValue(int? languageId, string segment, bool published = false) + public object GetValue(int? languageId = null, string segment = null, bool published = false) { if (!_propertyType.ValidateVariation(languageId, segment, false)) return null; + if (!languageId.HasValue && segment == null) return GetPropertyValue(_pvalue, published); if (_vvalues == null) return null; return _vvalues.TryGetValue((languageId, segment), out var pvalue) ? GetPropertyValue(pvalue, published) @@ -184,18 +151,101 @@ namespace Umbraco.Core.Models : pvalue.EditedValue; } - internal void PublishValues(int? languageId, string segment) + // internal - must be invoked by the content item + internal void PublishAllValues() { + // throw if some values are not valid + if (!IsAllValid()) throw new InvalidOperationException("Some values are not valid."); + + // if invariant-neutral is supported, publish invariant-neutral + if (_propertyType.ValidateVariation(null, null, false)) + PublishPropertyValue(_pvalue); + + // publish everything not invariant-neutral that is supported + if (_vvalues != null) + { + var pvalues = _vvalues + .Where(x => _propertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) + .Select(x => x.Value); + foreach (var pvalue in pvalues) + PublishPropertyValue(pvalue); + } + } + + // internal - must be invoked by the content item + internal void PublishValue(int? languageId = null, string segment = null) + { + // throw if value is not valid, or if variation is not supported + if (!IsValid(languageId, segment)) throw new InvalidOperationException("Value is not valid."); _propertyType.ValidateVariation(languageId, segment, true); + (var pvalue, _) = GetPValue(languageId, segment, false); if (pvalue == null) return; PublishPropertyValue(pvalue); } - internal void PublishAllValues() + // internal - must be invoked by the content item + internal void PublishCultureValues(int? languageId = null) { - foreach (var pvalue in Values) - PublishPropertyValue(pvalue); + // throw if some values are not valid + if (!IsCultureValid(languageId)) throw new InvalidOperationException("Some values are not valid."); + + // if invariant and invariant-neutral is supported, publish invariant-neutral + if (!languageId.HasValue && _propertyType.ValidateVariation(null, null, false)) + PublishPropertyValue(_pvalue); + + // publish everything not invariant-neutral that matches the culture and is supported + if (_vvalues != null) + { + var pvalues = _vvalues + .Where(x => x.Value.LanguageId == languageId) + .Where(x => _propertyType.ValidateVariation(languageId, x.Value.Segment, false)) + .Select(x => x.Value); + foreach (var pvalue in pvalues) + PublishPropertyValue(pvalue); + } + } + + // internal - must be invoked by the content item + internal void ClearPublishedAllValues() + { + if (_propertyType.ValidateVariation(null, null, false)) + ClearPublishedPropertyValue(_pvalue); + + if (_vvalues != null) + { + var pvalues = _vvalues + .Where(x => _propertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) + .Select(x => x.Value); + foreach (var pvalue in pvalues) + ClearPublishedPropertyValue(pvalue); + } + } + + // internal - must be invoked by the content item + internal void ClearPublishedValue(int? languageId = null, string segment = null) + { + _propertyType.ValidateVariation(languageId, segment, true); + (var pvalue, _) = GetPValue(languageId, segment, false); + if (pvalue == null) return; + ClearPublishedPropertyValue(pvalue); + } + + // internal - must be invoked by the content item + internal void ClearPublishedCultureValues(int? languageId = null) + { + if (!languageId.HasValue && _propertyType.ValidateVariation(null, null, false)) + ClearPublishedPropertyValue(_pvalue); + + if (_vvalues != null) + { + var pvalues = _vvalues + .Where(x => x.Value.LanguageId == languageId) + .Where(x => _propertyType.ValidateVariation(languageId, x.Value.Segment, false)) + .Select(x => x.Value); + foreach (var pvalue in pvalues) + ClearPublishedPropertyValue(pvalue); + } } private void PublishPropertyValue(PropertyValue pvalue) @@ -207,48 +257,23 @@ namespace Umbraco.Core.Models DetectChanges(pvalue.EditedValue, origValue, Ps.Value.ValuesSelector, Ps.Value.PropertyValueComparer, false); } - /// - /// Sets a (edited) neutral value. - /// - public void SetValue(object value) + private void ClearPublishedPropertyValue(PropertyValue pvalue) { - _propertyType.ValidateVariation(null, null, true); - (var pvalue, var change) = GetPValue(true); - SetPropertyValue(pvalue, value, change); + if (!_propertyType.IsPublishing) + throw new NotSupportedException("Property type does not support publishing."); + var origValue = pvalue.PublishedValue; + pvalue.PublishedValue = ConvertSetValue(null); + DetectChanges(pvalue.EditedValue, origValue, Ps.Value.ValuesSelector, Ps.Value.PropertyValueComparer, false); } /// - /// Sets a (edited) culture value. + /// Sets a value. /// - public void SetValue(int? languageId, object value) - { - _propertyType.ValidateVariation(languageId, null, true); - (var pvalue, var change) = GetPValue(languageId, null, true); - SetPropertyValue(pvalue, value, change); - } - - /// - /// Sets a (edited) culture value. - /// - public void SetValue(string segment, object value) - { - _propertyType.ValidateVariation(null, segment, true); - (var pvalue, var change) = GetPValue(null, segment, true); - SetPropertyValue(pvalue, value, change); - } - - /// - /// Sets a (edited) culture+segment value. - /// - public void SetValue(int? languageId, string segment, object value) + public void SetValue(object value, int? languageId = null, string segment = null) { _propertyType.ValidateVariation(languageId, segment, true); (var pvalue, var change) = GetPValue(languageId, segment, true); - SetPropertyValue(pvalue, value, change); - } - private void SetPropertyValue(PropertyValue pvalue, object value, bool change) - { var origValue = pvalue.EditedValue; var setValue = ConvertSetValue(value); @@ -257,15 +282,11 @@ namespace Umbraco.Core.Models DetectChanges(setValue, origValue, Ps.Value.ValuesSelector, Ps.Value.PropertyValueComparer, change); } - // bypasses all changes detection and is the *only* to set the published value + // bypasses all changes detection and is the *only* way to set the published value internal void FactorySetValue(int? languageId, string segment, bool published, object value) { (var pvalue, _) = GetPValue(languageId, segment, true); - FactorySetPropertyValue(pvalue, published, value); - } - private void FactorySetPropertyValue(PropertyValue pvalue, bool published, object value) - { if (published && _propertyType.IsPublishing) pvalue.PublishedValue = value; else @@ -297,7 +318,7 @@ namespace Umbraco.Core.Models _vvalues = new Dictionary<(int?, string), PropertyValue>(); change = true; } - if (_vvalues.TryGetValue((languageId, segment), out var pvalue)) + if (!_vvalues.TryGetValue((languageId, segment), out var pvalue)) { if (!create) return (null, false); pvalue = _vvalues[(languageId, segment)] = new PropertyValue(); @@ -361,49 +382,61 @@ namespace Umbraco.Core.Models } /// - /// Gets a value indicating whether the (edited) neutral value is valid. + /// Gets a value indicating whether everything is valid. /// - /// An invalid value can be saved, but only valid values can be published. - public bool IsValid() - { - return IsValidValue(GetValue()); - } - - /// - /// Gets a value indicating whether the (edited) culture value is valid. - /// - /// An invalid value can be saved, but only valid values can be published. - public bool IsValid(int? languageId) - { - return IsValidValue(GetValue(languageId)); - } - - /// - /// Gets a value indicating whether the (edited) segment value is valid. - /// - /// An invalid value can be saved, but only valid values can be published. - public bool IsValid(string segment) - { - return IsValidValue(GetValue(segment)); - } - - /// - /// Gets a value indicating whether the (edited) culture+segment value is valid. - /// - /// An invalid value can be saved, but only valid values can be published. - public bool IsValid(int? languageId, string segment) - { - return IsValidValue(GetValue(languageId, segment)); - } - - /// - /// Gets a value indicating whether all (edited) values are valid. - /// - /// An invalid value can be saved, but only valid values can be published. + /// public bool IsAllValid() { - // fixme - what about missing, required values? - return _values.All(x => IsValidValue(x.EditedValue)); + // if invariant-neutral is supported, validate invariant-neutral + if (_propertyType.ValidateVariation(null, null, false)) + if (!IsValidValue(_pvalue)) return false; + + if (_vvalues == null) return IsValidValue(null); + + // validate everything not invariant-neutral that is supported + // fixme - broken - how can we figure out what is mandatory here? + + var pvalues = _vvalues + .Where(x => _propertyType.ValidateVariation(x.Value.LanguageId, x.Value.Segment, false)) + .Select(x => x.Value) + .ToArray(); + return pvalues.Length == 0 + ? IsValidValue(null) + : pvalues.All(x => IsValidValue(x.EditedValue)); + } + + /// + /// Gets a value indicating whether the culture/any values are valid. + /// + /// An invalid value can be saved, but only valid values can be published. + public bool IsCultureValid(int? languageId) + { + // if invariant and invariant-neutral is supported, validate invariant-neutral + if (!languageId.HasValue && _propertyType.ValidateVariation(null, null, false)) + if (!IsValidValue(_pvalue)) return false; + + // validate everything not invariant-neutral that matches the culture and is supported + // fixme - broken - how can we figure out what is mandatory here? + + if (_vvalues == null) return IsValidValue(null); + + var pvalues = _vvalues + .Where(x => x.Value.LanguageId == languageId) + .Where(x => _propertyType.ValidateVariation(languageId, x.Value.Segment, false)) + .Select(x => x.Value) + .ToArray(); + return pvalues.Length == 0 + ? IsValidValue(null) + : pvalues.All(x => IsValidValue(x.EditedValue)); + } + + /// + /// Gets a value indicating whether the value is valid. + /// + /// An invalid value can be saved, but only valid values can be published. + public bool IsValid(int? languageId = null, string segment = null) + { + return IsValidValue(GetValue(languageId, segment)); } /// diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 2582189068..cd5ac63bd3 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -42,6 +42,7 @@ namespace Umbraco.Core.Models _propertyEditorAlias = dataTypeDefinition.PropertyEditorAlias; _dataTypeDatabaseType = dataTypeDefinition.DatabaseType; + _variations = ContentVariation.InvariantNeutral; } public PropertyType(IDataTypeDefinition dataTypeDefinition, string propertyTypeAlias) @@ -69,6 +70,7 @@ namespace Umbraco.Core.Models _isExplicitDbType = isExplicitDbType; _propertyEditorAlias = propertyEditorAlias; _dataTypeDatabaseType = dataTypeDatabaseType; + _variations = ContentVariation.InvariantNeutral; } /// @@ -84,6 +86,7 @@ namespace Umbraco.Core.Models _propertyEditorAlias = propertyEditorAlias; _dataTypeDatabaseType = dataTypeDatabaseType; _alias = GetAlias(propertyTypeAlias); + _variations = ContentVariation.InvariantNeutral; } // ReSharper disable once ClassNeverInstantiated.Local @@ -241,7 +244,7 @@ namespace Umbraco.Core.Models public ContentVariation Variations { get => _variations; - internal set => SetPropertyValueAndDetectChanges(value, ref _variations, Ps.Value.VaryBy); + set => SetPropertyValueAndDetectChanges(value, ref _variations, Ps.Value.VaryBy); } public bool ValidateVariation(int? languageId, string segment, bool throwIfInvalid) @@ -264,7 +267,7 @@ namespace Umbraco.Core.Models if ((Variations & variation) == 0) { if (throwIfInvalid) - throw new InvalidOperationException($"Variation {variation} is invalid for property type \"{Alias}\"."); + throw new NotSupportedException($"Variation {variation} is invalid for property type \"{Alias}\"."); return false; } return true; diff --git a/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs index baa43ba3ae..840ab18122 100644 --- a/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/ContentTypeDto.cs @@ -44,7 +44,7 @@ namespace Umbraco.Core.Models.Rdbms public bool AllowAtRoot { get; set; } [Column("variations")] - [Constraint(Default = "0")] + [Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)] public byte Variations { get; set; } [ResultColumn] diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs index 06d203690f..6fab87ac96 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeDto.cs @@ -52,7 +52,7 @@ namespace Umbraco.Core.Models.Rdbms public string Description { get; set; } [Column("variations")] - [Constraint(Default = "0")] + [Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)] public byte Variations { get; set; } [ResultColumn] diff --git a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs similarity index 50% rename from src/Umbraco.Core/Persistence/Factories/ContentFactory.cs rename to src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs index 22f5191009..b49c8fe50e 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentBaseFactory.cs @@ -1,160 +1,281 @@ -using System; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Factories -{ - internal static class ContentFactory - { - /// - /// Builds an IContent item from a dto and content type. - /// - public static Content BuildEntity(DocumentDto dto, IContentType contentType) - { - var contentDto = dto.ContentDto; - var nodeDto = contentDto.NodeDto; - var documentVersionDto = dto.DocumentVersionDto; - var contentVersionDto = documentVersionDto.ContentVersionDto; - var publishedVersionDto = dto.PublishedVersionDto; - - var content = new Content(nodeDto.Text, nodeDto.ParentId, contentType); - - try - { - content.DisableChangeTracking(); - - content.Id = dto.NodeId; - content.Key = nodeDto.UniqueId; - content.Version = contentVersionDto.VersionId; - content.VersionPk = contentVersionDto.Id; - - content.Name = contentVersionDto.Text; - content.NodeName = contentVersionDto.Text; - - content.Path = nodeDto.Path; - content.Level = nodeDto.Level; - content.ParentId = nodeDto.ParentId; - content.SortOrder = nodeDto.SortOrder; - content.Trashed = nodeDto.Trashed; - - content.CreatorId = nodeDto.UserId ?? 0; - content.WriterId = contentVersionDto.UserId; - content.CreateDate = nodeDto.CreateDate; - content.UpdateDate = contentVersionDto.VersionDate; - - content.Published = dto.Published; - content.Edited = dto.Edited; - content.ExpireDate = dto.ExpiresDate; - content.ReleaseDate = dto.ReleaseDate; - - if (dto.Published) - { - content.PublishedVersionPk = publishedVersionDto.Id; - content.PublishDate = publishedVersionDto.ContentVersionDto.VersionDate; - content.PublishName = publishedVersionDto.ContentVersionDto.Text; - content.PublisherId = publishedVersionDto.ContentVersionDto.UserId; - } - - // templates = ignored, managed by the repository - - // reset dirty initial properties (U4-1946) - content.ResetDirtyProperties(false); - return content; - } - finally - { - content.EnableChangeTracking(); - } - } - - /// - /// Buils a dto from an IContent item. - /// - public static DocumentDto BuildDto(IContent entity, Guid objectType) - { - var contentDto = BuildContentDto(entity, objectType); - - var dto = new DocumentDto - { - NodeId = entity.Id, - Published = entity.Published, - ReleaseDate = entity.ReleaseDate, - ExpiresDate = entity.ExpireDate, - - ContentDto = contentDto, - DocumentVersionDto = BuildDocumentVersionDto(entity, contentDto) - }; - - return dto; - } - - private static ContentDto BuildContentDto(IContent entity, Guid objectType) - { - var dto = new ContentDto - { - NodeId = entity.Id, - ContentTypeId = entity.ContentTypeId, - - NodeDto = BuildNodeDto(entity, objectType) - }; - - return dto; - } - - private static NodeDto BuildNodeDto(IContent entity, Guid objectType) - { - var dto = new NodeDto - { - NodeId = entity.Id, - UniqueId = entity.Key, - ParentId = entity.ParentId, - Level = Convert.ToInt16(entity.Level), - Path = entity.Path, - SortOrder = entity.SortOrder, - Trashed = entity.Trashed, - UserId = entity.CreatorId, - Text = entity.Name, - NodeObjectType = objectType, - CreateDate = entity.CreateDate - }; - - return dto; - } - - // always build the current / VersionPk dto - // we're never going to build / save old versions (which are immutable) - private static DocumentVersionDto BuildDocumentVersionDto(IContent entity, ContentDto contentDto) - { - var dto = new DocumentVersionDto - { - Id = ((ContentBase) entity).VersionPk, - TemplateId = entity.Template?.Id, - Published = false, // always building the current, unpublished one - - ContentVersionDto = BuildContentVersionDto(entity, contentDto) - }; - - return dto; - } - - // always build the current / VersionPk dto - // we're never going to build / save old versions (which are immutable) - private static ContentVersionDto BuildContentVersionDto(IContent entity, ContentDto contentDto) - { - var dto = new ContentVersionDto - { - Id = ((ContentBase) entity).VersionPk, - NodeId = entity.Id, - VersionId = entity.Version, - VersionDate = entity.UpdateDate, - UserId = entity.WriterId, - Current = true, // always building the current one - Text = entity.Name, - - ContentDto = contentDto - }; - - return dto; - } - } -} +using System; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Factories +{ + internal class ContentBaseFactory + { + /// + /// Builds an IContent item from a dto and content type. + /// + public static Content BuildEntity(DocumentDto dto, IContentType contentType) + { + var contentDto = dto.ContentDto; + var nodeDto = contentDto.NodeDto; + var documentVersionDto = dto.DocumentVersionDto; + var contentVersionDto = documentVersionDto.ContentVersionDto; + var publishedVersionDto = dto.PublishedVersionDto; + + var content = new Content(nodeDto.Text, nodeDto.ParentId, contentType); + + try + { + content.DisableChangeTracking(); + + content.Id = dto.NodeId; + content.Key = nodeDto.UniqueId; + content.Version = contentVersionDto.VersionId; + content.VersionPk = contentVersionDto.Id; + + content.Name = contentVersionDto.Text; + content.NodeName = contentVersionDto.Text; + + content.Path = nodeDto.Path; + content.Level = nodeDto.Level; + content.ParentId = nodeDto.ParentId; + content.SortOrder = nodeDto.SortOrder; + content.Trashed = nodeDto.Trashed; + + content.CreatorId = nodeDto.UserId ?? 0; + content.WriterId = contentVersionDto.UserId; + content.CreateDate = nodeDto.CreateDate; + content.UpdateDate = contentVersionDto.VersionDate; + + content.Published = dto.Published; + content.Edited = dto.Edited; + content.ExpireDate = dto.ExpiresDate; + content.ReleaseDate = dto.ReleaseDate; + + // fixme - shall we get published infos or not? + //if (dto.Published) + if (publishedVersionDto != null) + { + content.PublishedVersionPk = publishedVersionDto.Id; + content.PublishDate = publishedVersionDto.ContentVersionDto.VersionDate; + content.PublishName = publishedVersionDto.ContentVersionDto.Text; + content.PublisherId = publishedVersionDto.ContentVersionDto.UserId; + } + + // templates = ignored, managed by the repository + + // reset dirty initial properties (U4-1946) + content.ResetDirtyProperties(false); + return content; + } + finally + { + content.EnableChangeTracking(); + } + } + + /// + /// Builds an IMedia item from a dto and content type. + /// + public static Models.Media BuildEntity(ContentDto dto, IMediaType contentType) + { + var nodeDto = dto.NodeDto; + var contentVersionDto = dto.ContentVersionDto; + + var content = new Models.Media(nodeDto.Text, nodeDto.ParentId, contentType); + + try + { + content.DisableChangeTracking(); + + content.Id = dto.NodeId; + content.Key = nodeDto.UniqueId; + content.Version = contentVersionDto.VersionId; + content.VersionPk = contentVersionDto.Id; + + // fixme missing names? + + content.Path = nodeDto.Path; + content.Level = nodeDto.Level; + content.ParentId = nodeDto.ParentId; + content.SortOrder = nodeDto.SortOrder; + content.Trashed = nodeDto.Trashed; + + content.CreatorId = nodeDto.UserId ?? 0; + content.WriterId = contentVersionDto.UserId; + content.CreateDate = nodeDto.CreateDate; + content.UpdateDate = contentVersionDto.VersionDate; + + // reset dirty initial properties (U4-1946) + content.ResetDirtyProperties(false); + return content; + } + finally + { + content.EnableChangeTracking(); + } + } + + /// + /// Builds an IMedia item from a dto and content type. + /// + public static Member BuildEntity(MemberDto dto, IMemberType contentType) + { + var nodeDto = dto.ContentDto.NodeDto; + var contentVersionDto = dto.ContentVersionDto; + + var content = new Member(nodeDto.Text, dto.Email, dto.LoginName, dto.Password, contentType); + + try + { + content.DisableChangeTracking(); + + content.Id = dto.NodeId; + content.Key = nodeDto.UniqueId; + content.Version = contentVersionDto.VersionId; + content.VersionPk = contentVersionDto.Id; + + // fixme missing names? + + content.Path = nodeDto.Path; + content.Level = nodeDto.Level; + content.ParentId = nodeDto.ParentId; + content.SortOrder = nodeDto.SortOrder; + content.Trashed = nodeDto.Trashed; + + content.CreatorId = nodeDto.UserId ?? 0; + content.WriterId = contentVersionDto.UserId; + content.CreateDate = nodeDto.CreateDate; + content.UpdateDate = contentVersionDto.VersionDate; + + content.ProviderUserKey = content.Key; // fixme explain + + // reset dirty initial properties (U4-1946) + content.ResetDirtyProperties(false); + return content; + } + finally + { + content.EnableChangeTracking(); + } + } + + /// + /// Buils a dto from an IContent item. + /// + public static DocumentDto BuildDto(IContent entity, Guid objectType) + { + var contentBase = (Content) entity; + var contentDto = BuildContentDto(contentBase, objectType); + + var dto = new DocumentDto + { + NodeId = entity.Id, + Published = entity.Published, + ReleaseDate = entity.ReleaseDate, + ExpiresDate = entity.ExpireDate, + + ContentDto = contentDto, + DocumentVersionDto = BuildDocumentVersionDto(contentBase, contentDto) + }; + + return dto; + } + + /// + /// Buils a dto from an IMedia item. + /// + public static ContentDto BuildDto(IMedia entity) + { + var contentBase = (Models.Media) entity; + var dto = BuildContentDto(contentBase, Constants.ObjectTypes.Media); + dto.ContentVersionDto = BuildContentVersionDto(contentBase, dto); + return dto; + } + + /// + /// Buils a dto from an IMember item. + /// + public static MemberDto BuildDto(IMember entity) + { + var member = (Member) entity; + var contentDto = BuildContentDto(member, Constants.ObjectTypes.Member); + + var dto = new MemberDto + { + Email = entity.Email, + LoginName = entity.Username, + NodeId = entity.Id, + Password = entity.RawPasswordValue, + + ContentDto = contentDto, + ContentVersionDto = BuildContentVersionDto(member, contentDto) + }; + return dto; + } + + private static ContentDto BuildContentDto(ContentBase entity, Guid objectType) + { + var dto = new ContentDto + { + NodeId = entity.Id, + ContentTypeId = entity.ContentTypeId, + + NodeDto = BuildNodeDto(entity, objectType) + }; + + return dto; + } + + private static NodeDto BuildNodeDto(ContentBase entity, Guid objectType) + { + var dto = new NodeDto + { + NodeId = entity.Id, + UniqueId = entity.Key, + ParentId = entity.ParentId, + Level = Convert.ToInt16(entity.Level), + Path = entity.Path, + SortOrder = entity.SortOrder, + Trashed = entity.Trashed, + UserId = entity.CreatorId, + Text = entity.Name, + NodeObjectType = objectType, + CreateDate = entity.CreateDate + }; + + return dto; + } + + // always build the current / VersionPk dto + // we're never going to build / save old versions (which are immutable) + private static ContentVersionDto BuildContentVersionDto(ContentBase entity, ContentDto contentDto) + { + var dto = new ContentVersionDto + { + Id = entity.VersionPk, + NodeId = entity.Id, + VersionId = entity.Version, + VersionDate = entity.UpdateDate, + UserId = entity.WriterId, + Current = true, // always building the current one + Text = entity.Name, + + ContentDto = contentDto + }; + + return dto; + } + + // always build the current / VersionPk dto + // we're never going to build / save old versions (which are immutable) + private static DocumentVersionDto BuildDocumentVersionDto(Content entity, ContentDto contentDto) + { + var dto = new DocumentVersionDto + { + Id = entity.VersionPk, + TemplateId = entity.Template?.Id, + Published = false, // always building the current, unpublished one + + ContentVersionDto = BuildContentVersionDto(entity, contentDto) + }; + + return dto; + } + } +} diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs deleted file mode 100644 index ef1a6abaa1..0000000000 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Factories -{ - internal class MediaFactory - { - /// - /// Builds an IMedia item from a dto and content type. - /// - public static Models.Media BuildEntity(ContentDto dto, IMediaType contentType) - { - var nodeDto = dto.NodeDto; - var contentVersionDto = dto.ContentVersionDto; - - var content = new Models.Media(nodeDto.Text, nodeDto.ParentId, contentType); - - try - { - content.DisableChangeTracking(); - - content.Id = dto.NodeId; - content.Key = nodeDto.UniqueId; - content.Version = contentVersionDto.VersionId; - content.VersionPk = contentVersionDto.Id; - - // fixme missing names? - - content.Path = nodeDto.Path; - content.Level = nodeDto.Level; - content.ParentId = nodeDto.ParentId; - content.SortOrder = nodeDto.SortOrder; - content.Trashed = nodeDto.Trashed; - - content.CreatorId = nodeDto.UserId ?? 0; - content.WriterId = contentVersionDto.UserId; - content.CreateDate = nodeDto.CreateDate; - content.UpdateDate = contentVersionDto.VersionDate; - - // reset dirty initial properties (U4-1946) - content.ResetDirtyProperties(false); - return content; - } - finally - { - content.EnableChangeTracking(); - } - } - - /// - /// Buils a dto from an IMedia item. - /// - public static ContentDto BuildDto(IMedia entity) - { - var dto = BuildContentDto(entity, Constants.ObjectTypes.Media); - dto.ContentVersionDto = BuildContentVersionDto(entity, dto); - return dto; - } - - private static ContentDto BuildContentDto(IMedia entity, Guid objectType) - { - var dto = new ContentDto - { - NodeId = entity.Id, - ContentTypeId = entity.ContentTypeId, - - NodeDto = BuildNodeDto(entity, objectType) - }; - - return dto; - } - - private static NodeDto BuildNodeDto(IMedia entity, Guid objectType) - { - var dto = new NodeDto - { - NodeId = entity.Id, - UniqueId = entity.Key, - ParentId = entity.ParentId, - Level = Convert.ToInt16(entity.Level), - Path = entity.Path, - SortOrder = entity.SortOrder, - Trashed = entity.Trashed, - UserId = entity.CreatorId, - Text = entity.Name, - NodeObjectType = objectType, - CreateDate = entity.CreateDate - }; - - return dto; - } - - // always build the current / VersionPk dto - // we're never going to build / save old versions (which are immutable) - private static ContentVersionDto BuildContentVersionDto(IMedia entity, ContentDto contentDto) - { - var dto = new ContentVersionDto - { - Id = ((ContentBase) entity).VersionPk, - NodeId = entity.Id, - VersionId = entity.Version, - VersionDate = entity.UpdateDate, - UserId = entity.WriterId, - Current = true, // always building the current one - Text = entity.Name, - - ContentDto = contentDto - }; - - return dto; - } - } -} diff --git a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs deleted file mode 100644 index fd9b2fb6c0..0000000000 --- a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Factories -{ - internal class MemberFactory - { - /// - /// Builds an IMedia item from a dto and content type. - /// - public static Member BuildEntity(MemberDto dto, IMemberType contentType) - { - var nodeDto = dto.ContentDto.NodeDto; - var contentVersionDto = dto.ContentVersionDto; - - var content = new Member(nodeDto.Text, dto.Email, dto.LoginName, dto.Password, contentType); - - try - { - content.DisableChangeTracking(); - - content.Id = dto.NodeId; - content.Key = nodeDto.UniqueId; - content.Version = contentVersionDto.VersionId; - content.VersionPk = contentVersionDto.Id; - - // fixme missing names? - - content.Path = nodeDto.Path; - content.Level = nodeDto.Level; - content.ParentId = nodeDto.ParentId; - content.SortOrder = nodeDto.SortOrder; - content.Trashed = nodeDto.Trashed; - - content.CreatorId = nodeDto.UserId ?? 0; - content.WriterId = contentVersionDto.UserId; - content.CreateDate = nodeDto.CreateDate; - content.UpdateDate = contentVersionDto.VersionDate; - - content.ProviderUserKey = content.Key; // fixme explain - - // reset dirty initial properties (U4-1946) - content.ResetDirtyProperties(false); - return content; - } - finally - { - content.EnableChangeTracking(); - } - } - - /// - /// Buils a dto from an IMember item. - /// - public static MemberDto BuildDto(IMember entity) - { - var contentDto = BuildContentDto(entity, Constants.ObjectTypes.Member); - - var dto = new MemberDto - { - Email = entity.Email, - LoginName = entity.Username, - NodeId = entity.Id, - Password = entity.RawPasswordValue, - - ContentDto = contentDto, - ContentVersionDto = BuildContentVersionDto(entity, contentDto) - }; - return dto; - } - - private static ContentDto BuildContentDto(IMember entity, Guid objectType) - { - var dto = new ContentDto - { - NodeId = entity.Id, - ContentTypeId = entity.ContentTypeId, - - NodeDto = BuildNodeDto(entity, objectType) - }; - - return dto; - } - - private static NodeDto BuildNodeDto(IMember entity, Guid objectType) - { - var dto = new NodeDto - { - NodeId = entity.Id, - UniqueId = entity.Key, - ParentId = entity.ParentId, - Level = Convert.ToInt16(entity.Level), - Path = entity.Path, - SortOrder = entity.SortOrder, - Trashed = entity.Trashed, - UserId = entity.CreatorId, - Text = entity.Name, - NodeObjectType = objectType, - CreateDate = entity.CreateDate - }; - - return dto; - } - - private static ContentVersionDto BuildContentVersionDto(IMember entity, ContentDto contentDto) - { - var dto = new ContentVersionDto - { - Id = ((ContentBase) entity).VersionPk, - NodeId = entity.Id, - VersionId = entity.Version, - VersionDate = entity.UpdateDate, - UserId = entity.WriterId, - Current = true, // always building the current one - Text = entity.Name, - - ContentDto = contentDto - }; - - return dto; - } - } -} diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 315e306cac..2f93313556 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -2,6 +2,7 @@ using NPoco; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Migrations.Initial @@ -137,10 +138,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void CreateContentTypeData() { - _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true }); - _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true }); - _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true }); - _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user" }); + _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user", Variations = (byte) ContentVariation.InvariantNeutral }); } private void CreateUserData() @@ -191,23 +192,23 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void CreatePropertyTypeData() { - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = Constants.DataTypes.DefaultMediaListView, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 27, UniqueId = 27.ToGuid(), DataTypeId = Constants.DataTypes.DefaultMediaListView, ContentTypeId = 1031, PropertyTypeGroupId = 5, Alias = "contents", Name = "Contents:", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); //membership property types - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null }); - _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = -92, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.InvariantNeutral }); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs index 561bd13250..1ff5cc8749 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs @@ -27,6 +27,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight Execute.DropKeysAndIndexes(); MigratePropertyData(); + MigrateContentAndPropertyTypes(); MigrateContent(); MigrateVersions(); @@ -108,6 +109,14 @@ HAVING COUNT(v2.id) <> 1").Any()) Rename.Table(PreTables.PropertyData).To(Constants.DatabaseSchema.Tables.PropertyData); } + private void MigrateContentAndPropertyTypes() + { + if (!ColumnExists(PreTables.ContentType, "variations")) + AddColumn(PreTables.ContentType, "variations"); + if (!ColumnExists(PreTables.PropertyType, "variations")) + AddColumn(PreTables.PropertyType, "variations"); + } + private void MigrateContent() { // if the table has already been renamed, we're done diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 88ac07c448..1cd799836c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -202,7 +202,7 @@ namespace Umbraco.Core.Persistence.Repositories return MapDtosToContent(Database.Fetch(sql), true); } - public override IContent GetByVersion(Guid versionId) + public override IContent GetVersion(Guid versionId) { var sql = GetBaseQuery(QueryType.Single, false) .Where(x => x.VersionId == versionId); @@ -245,7 +245,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.SanitizeEntityPropertiesForXmlStorage(); // create the dto - var dto = ContentFactory.BuildDto(entity, NodeObjectTypeId); + var dto = ContentBaseFactory.BuildDto(entity, NodeObjectTypeId); // derive path and level from parent var parent = GetParentNodeDto(entity.ParentId); @@ -323,7 +323,7 @@ namespace Umbraco.Core.Persistence.Repositories if (content.PublishedState == PublishedState.Publishing) dto.Published = true; dto.NodeId = nodeDto.NodeId; - content.Edited = dto.Edited = edited; + content.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited Database.Insert(dto); // trigger here, before we reset Published etc @@ -409,7 +409,7 @@ namespace Umbraco.Core.Persistence.Repositories } // create the dto - var dto = ContentFactory.BuildDto(entity, NodeObjectTypeId); + var dto = ContentBaseFactory.BuildDto(entity, NodeObjectTypeId); // update the node dto var nodeDto = dto.ContentDto.NodeDto; @@ -461,7 +461,7 @@ namespace Umbraco.Core.Persistence.Repositories dto.Published = true; else if (content.PublishedState == PublishedState.Unpublishing) dto.Published = false; - content.Edited = dto.Edited = edited; + content.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited Database.Update(dto); // if entity is publishing, update tags, else leave tags there @@ -783,7 +783,7 @@ namespace Umbraco.Core.Persistence.Repositories if (contentTypes.TryGetValue(contentTypeId, out var contentType) == false) contentTypes[contentTypeId] = contentType = _contentTypeRepository.Get(contentTypeId); - var c = content[i] = ContentFactory.BuildEntity(dto, contentType); + var c = content[i] = ContentBaseFactory.BuildEntity(dto, contentType); // need templates var templateId = dto.DocumentVersionDto.TemplateId; @@ -834,7 +834,7 @@ namespace Umbraco.Core.Persistence.Repositories private IContent MapDtoToContent(DocumentDto dto) { var contentType = _contentTypeRepository.Get(dto.ContentDto.ContentTypeId); - var content = ContentFactory.BuildEntity(dto, contentType); + var content = ContentBaseFactory.BuildEntity(dto, contentType); // get template if (dto.DocumentVersionDto.TemplateId.HasValue && dto.DocumentVersionDto.TemplateId.Value > 0) @@ -842,7 +842,11 @@ namespace Umbraco.Core.Persistence.Repositories // get properties - indexed by version id var versionId = dto.DocumentVersionDto.Id; - var publishedVersionId = dto.Published ? dto.PublishedVersionDto.Id : 0; + + // fixme - shall we get published properties or not? + //var publishedVersionId = dto.Published ? dto.PublishedVersionDto.Id : 0; + var publishedVersionId = dto.PublishedVersionDto != null ? dto.PublishedVersionDto.Id : 0; + var temp = new TempContent(dto.NodeId, versionId, publishedVersionId, contentType); var properties = GetPropertyCollections(new List> { temp }); content.Properties = properties[dto.DocumentVersionDto.Id]; diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs index 78b5073e52..74c73bb980 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepositoryBase.cs @@ -749,7 +749,7 @@ AND umbracoNode.id <> @id", { if (db == null) throw new ArgumentNullException(nameof(db)); - var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, + var sql = @"SELECT cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId, ParentTypes.parentContentTypeKey as chtParentKey, @@ -854,6 +854,7 @@ AND umbracoNode.id <> @id", NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, + Variations = (byte) currCt.ctVariations, //map the underlying node dto NodeDto = new NodeDto { @@ -889,7 +890,7 @@ AND umbracoNode.id <> @id", if (db == null) throw new ArgumentNullException(nameof(db)); var sql = @"SELECT cmsDocumentType.IsDefault as dtIsDefault, cmsDocumentType.templateNodeId as dtTemplateId, - cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, + cmsContentType.pk as ctPk, cmsContentType.alias as ctAlias, cmsContentType.allowAtRoot as ctAllowAtRoot, cmsContentType.description as ctDesc, cmsContentType.variations as ctVariations, cmsContentType.icon as ctIcon, cmsContentType.isContainer as ctIsContainer, cmsContentType.nodeId as ctId, cmsContentType.thumbnail as ctThumb, AllowedTypes.AllowedId as ctaAllowedId, AllowedTypes.SortOrder as ctaSortOrder, AllowedTypes.alias as ctaAlias, ParentTypes.parentContentTypeId as chtParentId,ParentTypes.parentContentTypeKey as chtParentKey, @@ -1030,6 +1031,7 @@ AND umbracoNode.id <> @id", NodeId = currCt.ctId, PrimaryKey = currCt.ctPk, Thumbnail = currCt.ctThumb, + Variations = (byte) currCt.ctVariations, //map the underlying node dto NodeDto = new NodeDto { @@ -1092,7 +1094,7 @@ ORDER BY contentTypeId, id"; pt.id AS id, pt.uniqueID AS " + sqlSyntax.GetQuotedColumnName("key") + @", pt.propertyTypeGroupId AS groupId, pt.Alias AS alias, pt." + sqlSyntax.GetQuotedColumnName("Description") + @" AS " + sqlSyntax.GetQuotedColumnName("desc") + @", pt.mandatory AS mandatory, - pt.Name AS name, pt.sortOrder AS sortOrder, pt.validationRegExp AS regexp, + pt.Name AS name, pt.sortOrder AS sortOrder, pt.validationRegExp AS regexp, pt.variations as variations, dt.nodeId as dataTypeId, dt.dbType as dbType, dt.propertyEditorAlias as editorAlias FROM cmsPropertyType pt INNER JOIN cmsDataType as dt ON pt.dataTypeId = dt.nodeId @@ -1161,7 +1163,8 @@ ORDER BY contentTypeId, groupId, id"; Name = prop.name, PropertyGroupId = propertyGroup == null ? null : new Lazy(() => propertyGroup.Id), SortOrder = prop.sortOrder, - ValidationRegExp = prop.regexp + ValidationRegExp = prop.regexp, + Variations = (ContentVariation) prop.variations }; propertyTypes.Add(propertyType); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRepositoryVersionable.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRepositoryVersionable.cs index da8beb6e59..29901dbe19 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRepositoryVersionable.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IRepositoryVersionable.cs @@ -35,31 +35,29 @@ namespace Umbraco.Core.Persistence.Repositories IEnumerable GetAllVersions(int nodeId); /// - /// Gets a list of all version Ids for the given content item + /// Gets a list of all version idenfitifers of an entity. /// /// - /// The maximum number of rows to return - /// - IEnumerable GetVersionIds(int id, int maxRows); + /// The maximum number of rows to return + IEnumerable GetVersionIds(int id, int topRows); /// - /// Gets a specific version of an . + /// Gets a specific version of an entity. /// - /// Id of the version to retrieve - /// An item - TEntity GetByVersion(Guid versionId); + /// The identifier of the version. + TEntity GetVersion(Guid versionId); /// - /// Deletes a specific version from an object. + /// Deletes a specific version of an entity. /// - /// Id of the version to delete + /// The identifier of the version to delete. void DeleteVersion(Guid versionId); /// - /// Deletes versions from an object prior to a specific date. + /// Deletes all versions of an entity, older than a date. /// - /// Id of the object to delete versions from - /// Latest version date + /// The identifier of the entity. + /// The date. void DeleteVersions(int nodeId, DateTime versionDate); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 65dc209067..0ec65e9028 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -167,7 +167,7 @@ namespace Umbraco.Core.Persistence.Repositories return MapDtosToContent(Database.Fetch(sql), true); } - public override IMedia GetByVersion(Guid versionId) + public override IMedia GetVersion(Guid versionId) { var sql = GetBaseQuery(QueryType.Single) .Where(x => x.VersionId == versionId); @@ -241,7 +241,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.SanitizeEntityPropertiesForXmlStorage(); // create the dto - var dto = MediaFactory.BuildDto(entity); + var dto = ContentBaseFactory.BuildDto(entity); // derive path and level from parent var parent = GetParentNodeDto(entity.ParentId); @@ -332,7 +332,7 @@ namespace Umbraco.Core.Persistence.Repositories } // create the dto - var dto = MediaFactory.BuildDto(entity); + var dto = ContentBaseFactory.BuildDto(entity); // update the node dto var nodeDto = dto.NodeDto; @@ -519,7 +519,7 @@ namespace Umbraco.Core.Persistence.Repositories if (contentTypes.TryGetValue(contentTypeId, out IMediaType contentType) == false) contentTypes[contentTypeId] = contentType = _mediaTypeRepository.Get(contentTypeId); - var c = content[i] = MediaFactory.BuildEntity(dto, contentType); + var c = content[i] = ContentBaseFactory.BuildEntity(dto, contentType); // need properties var versionId = dto.ContentVersionDto.Id; @@ -544,7 +544,7 @@ namespace Umbraco.Core.Persistence.Repositories private IMedia MapDtoToContent(ContentDto dto) { var contentType = _mediaTypeRepository.Get(dto.ContentTypeId); - var media = MediaFactory.BuildEntity(dto, contentType); + var media = ContentBaseFactory.BuildEntity(dto, contentType); // get properties - indexed by version id var versionId = dto.ContentVersionDto.Id; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 8d0d3df40f..246080dd16 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -205,7 +205,7 @@ namespace Umbraco.Core.Persistence.Repositories return MapDtosToContent(Database.Fetch(sql), true); } - public override IMember GetByVersion(Guid versionId) + public override IMember GetVersion(Guid versionId) { var sql = GetBaseQuery(QueryType.Single) .Where(x => x.VersionId == versionId); @@ -237,7 +237,7 @@ namespace Umbraco.Core.Persistence.Repositories entity.SanitizeEntityPropertiesForXmlStorage(); // create the dto - var dto = MemberFactory.BuildDto(entity); + var dto = ContentBaseFactory.BuildDto(entity); // derive path and level from parent var parent = GetParentNodeDto(entity.ParentId); @@ -339,7 +339,7 @@ namespace Umbraco.Core.Persistence.Repositories } // create the dto - var dto = MemberFactory.BuildDto(entity); + var dto = ContentBaseFactory.BuildDto(entity); // update the node dto var nodeDto = dto.ContentDto.NodeDto; @@ -569,7 +569,7 @@ namespace Umbraco.Core.Persistence.Repositories if (contentTypes.TryGetValue(contentTypeId, out var contentType) == false) contentTypes[contentTypeId] = contentType = _memberTypeRepository.Get(contentTypeId); - var c = content[i] = MemberFactory.BuildEntity(dto, contentType); + var c = content[i] = ContentBaseFactory.BuildEntity(dto, contentType); // need properties var versionId = dto.ContentVersionDto.Id; @@ -594,7 +594,7 @@ namespace Umbraco.Core.Persistence.Repositories private IMember MapDtoToContent(MemberDto dto) { var memberType = _memberTypeRepository.Get(dto.ContentDto.ContentTypeId); - var member = MemberFactory.BuildEntity(dto, memberType); + var member = ContentBaseFactory.BuildEntity(dto, memberType); // get properties - indexed by version id var versionId = dto.ContentVersionDto.Id; diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 11d4603212..550b26867e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -42,7 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories #region Versions // gets a specific version - public abstract TEntity GetByVersion(Guid versionId); + public abstract TEntity GetVersion(Guid versionId); // gets all versions, current first public abstract IEnumerable GetAllVersions(int nodeId); @@ -82,7 +82,7 @@ namespace Umbraco.Core.Persistence.Repositories PerformDeleteVersion(versionDto.NodeId, versionId); } - // deletes all version older than a date + // deletes all versions of an entity, older than a date. public virtual void DeleteVersions(int nodeId, DateTime versionDate) { // fixme test object node type? diff --git a/src/Umbraco.Core/Publishing/ScheduledPublisher.cs b/src/Umbraco.Core/Publishing/ScheduledPublisher.cs index acc21c6c95..86530f54d7 100644 --- a/src/Umbraco.Core/Publishing/ScheduledPublisher.cs +++ b/src/Umbraco.Core/Publishing/ScheduledPublisher.cs @@ -28,6 +28,7 @@ namespace Umbraco.Core.Publishing /// public int CheckPendingAndProcess() { + // fixme isn't this done in ContentService already? var counter = 0; var contentForRelease = _contentService.GetContentForRelease().ToArray(); if (contentForRelease.Length > 0) @@ -37,18 +38,12 @@ namespace Umbraco.Core.Publishing try { d.ReleaseDate = null; - var result = _contentService.SaveAndPublishWithStatus(d, d.GetWriterProfile().Id); - _logger.Debug($"Result of publish attempt: {result.Result.StatusType}"); + d.PublishValues(); // fixme variants? + var result = _contentService.SaveAndPublish(d, d.GetWriterProfile().Id); + _logger.Debug($"Result of publish attempt: {result.Result}"); if (result.Success == false) { - if (result.Exception != null) - { - _logger.Error("Could not published the document (" + d.Id + ") based on it's scheduled release, status result: " + result.Result.StatusType, result.Exception); - } - else - { - _logger.Warn("Could not published the document (" + d.Id + ") based on it's scheduled release. Status result: " + result.Result.StatusType); - } + _logger.Error($"Error publishing node {d.Id}"); } else { @@ -70,8 +65,8 @@ namespace Umbraco.Core.Publishing try { d.ExpireDate = null; - var result = _contentService.UnPublish(d, d.GetWriterProfile().Id); - if (result) + var result = _contentService.Unpublish(d, d.GetWriterProfile().Id); + if (result.Success) { counter++; } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 4c9c9bca16..0038739e6f 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Services /// /// Represents the Content Service, which is an easy access to operations involving /// - public class ContentService : ScopeRepositoryService, IContentService, IContentServiceOperations + public class ContentService : ScopeRepositoryService, IContentService { private readonly MediaFileSystem _mediaFileSystem; private IQuery _queryNotTrashed; @@ -94,7 +94,7 @@ namespace Umbraco.Core.Services /// assigned to an entity with a list of user id & permission pairs. /// /// - public void ReplaceContentPermissions(EntityPermissionSet permissionSet) + public void SetPermissions(EntityPermissionSet permissionSet) { using (var uow = UowProvider.CreateUnitOfWork()) { @@ -111,7 +111,7 @@ namespace Umbraco.Core.Services /// /// /// - public void AssignContentPermission(IContent entity, char permission, IEnumerable groupIds) + public void SetPermission(IContent entity, char permission, IEnumerable groupIds) { using (var uow = UowProvider.CreateUnitOfWork()) { @@ -127,7 +127,7 @@ namespace Umbraco.Core.Services /// /// /// - public EntityPermissionCollection GetPermissionsForEntity(IContent content) + public EntityPermissionCollection GetPermissions(IContent content) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { @@ -155,10 +155,10 @@ namespace Umbraco.Core.Services /// Alias of the /// Optional id of the user creating the content /// - public IContent CreateContent(string name, Guid parentId, string contentTypeAlias, int userId = 0) + public IContent Create(string name, Guid parentId, string contentTypeAlias, int userId = 0) { var parent = GetById(parentId); - return CreateContent(name, parent, contentTypeAlias, userId); + return Create(name, parent, contentTypeAlias, userId); } /// @@ -173,7 +173,7 @@ namespace Umbraco.Core.Services /// The alias of the content type. /// The optional id of the user creating the content. /// The content object. - public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0) + public IContent Create(string name, int parentId, string contentTypeAlias, int userId = 0) { var contentType = GetContentType(contentTypeAlias); if (contentType == null) @@ -233,7 +233,7 @@ namespace Umbraco.Core.Services /// The alias of the content type. /// The optional id of the user creating the content. /// The content object. - public IContent CreateContent(string name, IContent parent, string contentTypeAlias, int userId = 0) + public IContent Create(string name, IContent parent, string contentTypeAlias, int userId = 0) { if (parent == null) throw new ArgumentNullException(nameof(parent)); @@ -262,7 +262,7 @@ namespace Umbraco.Core.Services /// The alias of the content type. /// The optional id of the user creating the content. /// The content object. - public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0) + public IContent CreateAndSave(string name, int parentId, string contentTypeAlias, int userId = 0) { using (var uow = UowProvider.CreateUnitOfWork()) { @@ -294,7 +294,7 @@ namespace Umbraco.Core.Services /// The alias of the content type. /// The optional id of the user creating the content. /// The content object. - public IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0) + public IContent CreateAndSave(string name, IContent parent, string contentTypeAlias, int userId = 0) { if (parent == null) throw new ArgumentNullException(nameof(parent)); @@ -442,7 +442,7 @@ namespace Umbraco.Core.Services /// /// Id of the /// An Enumerable list of objects - public IEnumerable GetContentOfContentType(int id) + public IEnumerable GetByType(int id) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { @@ -486,13 +486,13 @@ namespace Umbraco.Core.Services /// /// Id of the version to retrieve /// An item - public IContent GetByVersion(Guid versionId) + public IContent GetVersion(Guid versionId) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { uow.ReadLock(Constants.Locks.ContentTree); var repository = uow.CreateRepository(); - return repository.GetByVersion(versionId); + return repository.GetVersion(versionId); } } @@ -720,7 +720,7 @@ namespace Umbraco.Core.Services /// Id of the Parent to retrieve Children from /// Full or partial name of the children /// An Enumerable list of objects - public IEnumerable GetChildrenByName(int parentId, string name) + public IEnumerable GetChildren(int parentId, string name) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { @@ -896,7 +896,7 @@ namespace Umbraco.Core.Services /// /// to check if anscestors are published /// True if the Content can be published, otherwise False - public bool IsPublishable(IContent content) + public bool IsPathPublishable(IContent content) { // fast if (content.ParentId == Constants.System.Root) return true; // root content is always publishable @@ -956,25 +956,15 @@ namespace Umbraco.Core.Services #region Save, Publish, Unpublish - /// - /// Saves a single object - /// - /// The to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - public void Save(IContent content, int userId = 0, bool raiseEvents = true) - { - ((IContentServiceOperations) this).Save(content, userId, raiseEvents); - } + // fixme - kill all those raiseEvents - /// - /// Saves a single object - /// - /// The to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - Attempt IContentServiceOperations.Save(IContent content, int userId, bool raiseEvents) + /// + public OperationResult Save(IContent content, int userId = 0, bool raiseEvents = true) { + var publishedState = ((Content) content).PublishedState; + if (publishedState != PublishedState.Published && publishedState != PublishedState.Unpublished) + throw new InvalidOperationException("Cannot save a (un)publishing, use the dedicated (un)publish method."); + var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -983,7 +973,7 @@ namespace Umbraco.Core.Services if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Cancel(evtMsgs); } if (string.IsNullOrWhiteSpace(content.Name)) @@ -1010,35 +1000,14 @@ namespace Umbraco.Core.Services var changeType = isNew ? TreeChangeTypes.RefreshBranch : TreeChangeTypes.RefreshNode; uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); Audit(uow, AuditType.Save, "Save Content performed by user", userId, content.Id); - uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Succeed(evtMsgs); } - /// - /// Saves a collection of objects. - /// - /// - /// If the collection of content contains new objects that references eachother by Id or ParentId, - /// then use the overload Save method with a collection of Lazy . - /// - /// Collection of to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - public void Save(IEnumerable contents, int userId = 0, bool raiseEvents = true) - { - ((IContentServiceOperations) this).Save(contents, userId, raiseEvents); - } - - /// - /// Saves a collection of objects. - /// - /// Collection of to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - Attempt IContentServiceOperations.Save(IEnumerable contents, int userId, bool raiseEvents) + /// + public OperationResult Save(IEnumerable contents, int userId = 0, bool raiseEvents = true) { var evtMsgs = EventMessagesFactory.Get(); var contentsA = contents.ToArray(); @@ -1049,7 +1018,7 @@ namespace Umbraco.Core.Services if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Cancel(evtMsgs); } var treeChanges = contentsA.Select(x => new TreeChange(x, @@ -1077,142 +1046,56 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Succeed(evtMsgs); } - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - [Obsolete("Use SaveAndPublishWithStatus instead, that method will provide more detailed information on the outcome")] - public bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true) - { - var result = SaveAndPublishDo(content, userId, raiseEvents); - return result.Success; - } - - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - Attempt IContentServiceOperations.SaveAndPublish(IContent content, int userId, bool raiseEvents) + /// + public PublishResult SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true) { return SaveAndPublishDo(content, userId, raiseEvents); } - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - public bool Publish(IContent content, int userId = 0) + /// + public PublishResult Unpublish(IContent content, int userId = 0) { - var result = SaveAndPublishDo(content, userId); - Logger.Info("Call was made to ContentService.Publish, use PublishWithStatus instead since that method will provide more detailed information on the outcome"); - return result.Success; + var evtMsgs = EventMessagesFactory.Get(); + + using (var uow = UowProvider.CreateUnitOfWork()) + { + uow.WriteLock(Constants.Locks.ContentTree); + var repository = uow.CreateRepository(); + + var newest = GetById(content.Id); // ensure we have the newest version + if (content.Version != newest.Version) // but use the original object if it's already the newest version + content = newest; + if (content.Published == false) + { + uow.Complete(); + return new PublishResult(PublishResultType.SuccessAlready, evtMsgs, content); // already unpublished + } + + // strategy + // fixme should we still complete the uow? don't want to rollback here! + var attempt = StrategyCanUnPublish(uow, content, userId, evtMsgs); + if (attempt.Success == false) return attempt; // causes rollback + attempt = StrategyUnPublish(uow, content, true, userId, evtMsgs); + if (attempt.Success == false) return attempt; // causes rollback + + content.WriterId = userId; + repository.AddOrUpdate(content); + + uow.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); + uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); + Audit(uow, AuditType.UnPublish, "UnPublish performed by user", userId, content.Id); + + uow.Complete(); + } + + return new PublishResult(PublishResultType.Success, evtMsgs, content); } - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// The published status attempt - Attempt IContentServiceOperations.Publish(IContent content, int userId) - { - return SaveAndPublishDo(content, userId); - } - - /// - /// UnPublishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if unpublishing succeeded, otherwise False - public bool UnPublish(IContent content, int userId = 0) - { - return ((IContentServiceOperations) this).UnPublish(content, userId).Success; - } - - /// - /// UnPublishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if unpublishing succeeded, otherwise False - Attempt IContentServiceOperations.UnPublish(IContent content, int userId) - { - return UnPublishDo(content, userId); - } - - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - public Attempt SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true) - { - return ((IContentServiceOperations) this).SaveAndPublish(content, userId, raiseEvents); - } - - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - public Attempt PublishWithStatus(IContent content, int userId = 0) - { - return ((IContentServiceOperations) this).Publish(content, userId); - } - - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - [Obsolete("Use PublishWithChildrenWithStatus instead, that method will provide more detailed information on the outcome and also allows the includeUnpublished flag")] - public bool PublishWithChildren(IContent content, int userId = 0) - { - // this used to just return false only when the parent content failed, otherwise would - // always return true so we'll do the same thing for the moment - - var result = PublishWithChildrenDo(content, userId, true); - - // FirstOrDefault() is a pain to use with structs and result contain Attempt structs - // so use this code, which is fast and works - and please ReSharper do NOT suggest otherwise - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var r in result) - if (r.Result.ContentItem.Id == content.Id) return r.Success; - return false; - } - - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// set to true if you want to also publish children that are currently unpublished - /// True if publishing succeeded, otherwise False - public IEnumerable> PublishWithChildrenWithStatus(IContent content, int userId = 0, bool includeUnpublished = false) - { - return ((IContentServiceOperations) this).PublishWithChildren(content, userId, includeUnpublished); - } - - /// - /// Used to perform scheduled publishing/unpublishing - /// - public IEnumerable> PerformScheduledPublish() + /// + public IEnumerable PerformScheduledPublish() { using (var uow = UowProvider.CreateUnitOfWork()) { @@ -1220,18 +1103,19 @@ namespace Umbraco.Core.Services foreach (var d in GetContentForRelease(uow)) { - d.ReleaseDate = null; - var result = ((IContentServiceOperations) this).SaveAndPublish(d, d.WriterId); - if (result.Success == false) + PublishResult result; + try { - if (result.Exception != null) - { - Logger.Error("Could not published the document (" + d.Id + ") based on it's scheduled release, status result: " + result.Result.StatusType, result.Exception); - } - else - { - Logger.Warn("Could not published the document (" + d.Id + ") based on it's scheduled release. Status result: " + result.Result.StatusType); - } + d.ReleaseDate = null; + d.PublishValues(); // fixme variants? + result = SaveAndPublish(d, d.WriterId); + if (result.Success == false) + Logger.Error($"Failed to publish document id={d.Id}, reason={result.Result}."); + } + catch (Exception e) + { + Logger.Error($"Failed to publish document id={d.Id}, an exception was thrown.", e); + throw; } yield return result; } @@ -1240,11 +1124,13 @@ namespace Umbraco.Core.Services try { d.ExpireDate = null; - ((IContentServiceOperations) this).UnPublish(d, d.WriterId); + var result = Unpublish(d, d.WriterId); + if (result.Success == false) + Logger.Error($"Failed to unpublish document id={d.Id}, reason={result.Result}."); } - catch (Exception ee) + catch (Exception e) { - Logger.Error($"Error unpublishing node {d.Id}", ee); + Logger.Error($"Failed to unpublish document id={d.Id}, an exception was thrown.", e); throw; } } @@ -1253,14 +1139,8 @@ namespace Umbraco.Core.Services } } - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// - /// The list of statuses for all published items - IEnumerable> IContentServiceOperations.PublishWithChildren(IContent content, int userId, bool includeUnpublished) + /// + public IEnumerable PublishWithChildren(IContent content, int userId, bool includeUnpublished) { return PublishWithChildrenDo(content, userId, includeUnpublished); } @@ -1269,30 +1149,8 @@ namespace Umbraco.Core.Services #region Delete - /// - /// Permanently deletes an object as well as all of its Children. - /// - /// - /// This method will also delete associated media files, child content and possibly associated domains. - /// - /// Please note that this method will completely remove the Content from the database - /// The to delete - /// Optional Id of the User deleting the Content - public void Delete(IContent content, int userId = 0) - { - ((IContentServiceOperations) this).Delete(content, userId); - } - - /// - /// Permanently deletes an object. - /// - /// - /// This method will also delete associated media files, child content and possibly associated domains. - /// - /// Please note that this method will completely remove the Content from the database - /// The to delete - /// Optional Id of the User deleting the Content - Attempt IContentServiceOperations.Delete(IContent content, int userId) + /// + public OperationResult Delete(IContent content, int userId) { var evtMsgs = EventMessagesFactory.Get(); @@ -1302,7 +1160,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Cancel(evtMsgs); } uow.WriteLock(Constants.Locks.ContentTree); @@ -1322,7 +1180,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Succeed(evtMsgs); } private void DeleteLocked(IScopeUnitOfWork uow, IContentRepository repository, IContent content) @@ -1412,7 +1270,7 @@ namespace Umbraco.Core.Services if (deletePriorVersions) { - var content = GetByVersion(versionId); + var content = GetVersion(versionId); // fixme nesting uow? DeleteVersions(id, content.UpdateDate, userId); } @@ -1434,24 +1292,8 @@ namespace Umbraco.Core.Services #region Move, RecycleBin - /// - /// Deletes an object by moving it to the Recycle Bin - /// - /// Move an item to the Recycle Bin will result in the item being unpublished - /// The to delete - /// Optional Id of the User deleting the Content - public void MoveToRecycleBin(IContent content, int userId = 0) - { - ((IContentServiceOperations) this).MoveToRecycleBin(content, userId); - } - - /// - /// Deletes an object by moving it to the Recycle Bin - /// - /// Move an item to the Recycle Bin will result in the item being unpublished - /// The to delete - /// Optional Id of the User deleting the Content - Attempt IContentServiceOperations.MoveToRecycleBin(IContent content, int userId) + /// + public OperationResult MoveToRecycleBin(IContent content, int userId) { var evtMsgs = EventMessagesFactory.Get(); var moves = new List>(); @@ -1467,7 +1309,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Trashing, this, moveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); // causes rollback + return OperationResult.Cancel(evtMsgs); // causes rollback } // if it's published we may want to force-unpublish it - that would be backward-compatible... but... @@ -1491,7 +1333,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Succeed(evtMsgs); } /// @@ -1723,7 +1565,7 @@ namespace Umbraco.Core.Services copy.WriterId = userId; //get the current permissions, if there are any explicit ones they need to be copied - var currentPermissions = GetPermissionsForEntity(content); + var currentPermissions = GetPermissions(content); currentPermissions.RemoveWhere(p => p.IsDefaultPermissions); // save and flush because we need the ID for the recursive Copying events @@ -1835,7 +1677,7 @@ namespace Umbraco.Core.Services var repository = uow.CreateRepository(); var currContent = repository.Get(id); - var origContent = repository.GetByVersion(versionId); + var origContent = repository.GetVersion(versionId); var rollbackEventArgs = new RollbackEventArgs(origContent); if (uow.Events.DispatchCancelable(RollingBack, this, rollbackEventArgs)) @@ -1850,8 +1692,11 @@ namespace Umbraco.Core.Services // pk > published pk = special, rollback to current 'edit' version // // in that last case, we want to copy the published values + // what-if there's no 'published' version for now? + // fixme WE DON'T WANT TO DO THIS HERE! var copyPublished = ((Content) origContent).VersionPk > ((Content) origContent).PublishedVersionPk; - ((Content) currContent).CopyAllValues(origContent, copyPublished); + //((Content) currContent).CopyAllValues(origContent, copyPublished); + ((Content) currContent).CopyAllValues(origContent); currContent.WriterId = userId; // builtin values @@ -2014,13 +1859,13 @@ namespace Umbraco.Core.Services /// then the list will only contain one status item, otherwise it will contain status items for it and all of it's descendants that /// are to be published. /// - private IEnumerable> PublishWithChildrenDo(IContent content, int userId = 0, bool includeUnpublished = false) + private IEnumerable PublishWithChildrenDo(IContent content, int userId = 0, bool includeUnpublished = false) { if (content == null) throw new ArgumentNullException(nameof(content)); var evtMsgs = EventMessagesFactory.Get(); var publishedItems = new List(); // this is for events - Attempt[] attempts; + PublishResult[] attempts; using (var uow = UowProvider.CreateUnitOfWork()) { @@ -2042,11 +1887,11 @@ namespace Umbraco.Core.Services var alreadyChecked = new[] { content }; attempts = StrategyPublishWithChildren(uow, contents, alreadyChecked, userId, evtMsgs, includeUnpublished).ToArray(); - foreach (var status in attempts.Where(x => x.Success).Select(x => x.Result)) + foreach (var status in attempts.Where(x => x.Success)) { // save them all, even those that are .Success because of (.StatusType == PublishStatusType.SuccessAlreadyPublished) // so we bump the date etc - var publishedItem = status.ContentItem; + var publishedItem = status.Content; publishedItem.WriterId = userId; repository.AddOrUpdate(publishedItem); publishedItems.Add(publishedItem); @@ -2062,51 +1907,6 @@ namespace Umbraco.Core.Services return attempts; } - - /// - /// UnPublishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if unpublishing succeeded, otherwise False - private Attempt UnPublishDo(IContent content, int userId = 0) - { - var evtMsgs = EventMessagesFactory.Get(); - - using (var uow = UowProvider.CreateUnitOfWork()) - { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - - var newest = GetById(content.Id); // ensure we have the newest version - if (content.Version != newest.Version) // but use the original object if it's already the newest version - content = newest; - if (content.Published == false) - { - uow.Complete(); - return Attempt.Succeed(new UnPublishStatus(UnPublishedStatusType.SuccessAlreadyUnPublished, evtMsgs, content)); // already unpublished - } - - // strategy - // fixme should we still complete the uow? don't want to rollback here! - var attempt = StrategyCanUnPublish(uow, content, userId, evtMsgs); - if (attempt == false) return attempt; // causes rollback - attempt = StrategyUnPublish(uow, content, true, userId, evtMsgs); - if (attempt == false) return attempt; // causes rollback - - content.WriterId = userId; - repository.AddOrUpdate(content); - - uow.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); - Audit(uow, AuditType.UnPublish, "UnPublish performed by user", userId, content.Id); - - uow.Complete(); - } - - return Attempt.Succeed(new UnPublishStatus(UnPublishedStatusType.Success, evtMsgs, content)); - } - /// /// Saves and Publishes a single object /// @@ -2114,10 +1914,10 @@ namespace Umbraco.Core.Services /// Optional Id of the User issueing the publishing /// Optional boolean indicating whether or not to raise save events. /// True if publishing succeeded, otherwise False - private Attempt SaveAndPublishDo(IContent content, int userId = 0, bool raiseEvents = true) + private PublishResult SaveAndPublishDo(IContent content, int userId = 0, bool raiseEvents = true) { var evtMsgs = EventMessagesFactory.Get(); - Attempt status; + PublishResult status; using (var uow = UowProvider.CreateUnitOfWork()) { @@ -2125,7 +1925,7 @@ namespace Umbraco.Core.Services if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { uow.Complete(); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedCancelledByEvent, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); } var isNew = content.IsNewEntity(); @@ -2148,10 +1948,6 @@ namespace Umbraco.Core.Services content.CreatorId = userId; content.WriterId = userId; - // fixme - this should be done OUTSIDE the service - // but for the time being... it needs to be done - ((Content) content).PublishAllValues(); - repository.AddOrUpdate(content); if (raiseEvents) // always @@ -2177,7 +1973,7 @@ namespace Umbraco.Core.Services // if was not published and now is... descendants that were 'published' (but // had an unpublished ancestor) are 're-published' ie not explicitely published // but back as 'published' nevertheless - if (isNew == false && previouslyPublished == false &&HasChildren(content.Id)) + if (isNew == false && previouslyPublished == false && HasChildren(content.Id)) { var descendants = GetPublishedDescendantsLocked(uow, repository, content).ToArray(); uow.Events.Dispatch(Published, this, new PublishEventArgs(descendants, false, false), "Published"); @@ -2341,12 +2137,12 @@ namespace Umbraco.Core.Services // prob. want to find nicer names? - internal Attempt StrategyCanPublish(IScopeUnitOfWork uow, IContent content, int userId, bool checkPath, EventMessages evtMsgs) + internal PublishResult StrategyCanPublish(IScopeUnitOfWork uow, IContent content, int userId, bool checkPath, EventMessages evtMsgs) { if (uow.Events.DispatchCancelable(Publishing, this, new PublishEventArgs(content, evtMsgs))) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' will not be published, the event was cancelled."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedCancelledByEvent, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); } // check if the content is valid @@ -2354,31 +2150,31 @@ namespace Umbraco.Core.Services if (invalidProperties.Any()) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' could not be published because of invalid properties."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedContentInvalid, evtMsgs, content) + return new PublishResult(PublishResultType.FailedContentInvalid, evtMsgs, content) { InvalidProperties = invalidProperties - }); + }; } // check if the Content is Expired if (content.Status == ContentStatus.Expired) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' has expired and could not be published."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedHasExpired, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedHasExpired, evtMsgs, content); } // check if the Content is Awaiting Release if (content.Status == ContentStatus.AwaitingRelease) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' is awaiting release and could not be published."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedAwaitingRelease, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedAwaitingRelease, evtMsgs, content); } // check if the Content is Trashed if (content.Status == ContentStatus.Trashed) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' is trashed and could not be published."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedIsTrashed, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedIsTrashed, evtMsgs, content); } // check if the content can be path-published @@ -2394,21 +2190,21 @@ namespace Umbraco.Core.Services if (pathIsOk == false) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' could not be published because its parent is not published."); - return Attempt.Fail(new PublishStatus(PublishStatusType.FailedPathNotPublished, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedPathNotPublished, evtMsgs, content); } } - return Attempt.Succeed(new PublishStatus(content, evtMsgs)); + return new PublishResult(evtMsgs, content); } - internal Attempt StrategyPublish(IScopeUnitOfWork uow, IContent content, bool alreadyCheckedCanPublish, int userId, EventMessages evtMsgs) + internal PublishResult StrategyPublish(IScopeUnitOfWork uow, IContent content, bool alreadyCheckedCanPublish, int userId, EventMessages evtMsgs) { // note: when used at top-level, StrategyCanPublish with checkPath=true should have run already // and alreadyCheckedCanPublish should be true, so not checking again. when used at nested level, // there is no need to check the path again. so, checkPath=false in StrategyCanPublish below is ok var attempt = alreadyCheckedCanPublish - ? Attempt.Succeed(new PublishStatus(content, evtMsgs)) // already know we can + ? new PublishResult(evtMsgs, content) // already know we can : StrategyCanPublish(uow, content, userId, /*checkPath:*/ false, evtMsgs); // else check if (attempt.Success == false) return attempt; @@ -2448,9 +2244,9 @@ namespace Umbraco.Core.Services /// - if includeUnpublished is true, process the underlying branch /// - else, do not process the underlying branch /// - internal IEnumerable> StrategyPublishWithChildren(IScopeUnitOfWork uow, IEnumerable contents, IEnumerable alreadyChecked, int userId, EventMessages evtMsgs, bool includeUnpublished = true) + internal IEnumerable StrategyPublishWithChildren(IScopeUnitOfWork uow, IEnumerable contents, IEnumerable alreadyChecked, int userId, EventMessages evtMsgs, bool includeUnpublished = true) { - var statuses = new List>(); + var statuses = new List(); var alreadyCheckedA = (alreadyChecked ?? Enumerable.Empty()).ToArray(); // list of ids that we exclude because they could not be published @@ -2475,7 +2271,7 @@ namespace Umbraco.Core.Services if (content.Published && content.Level > topLevel) // topLevel we DO want to (re)publish { // newest is published already - statuses.Add(Attempt.Succeed(new PublishStatus(PublishStatusType.SuccessAlreadyPublished, evtMsgs, content))); + statuses.Add(new PublishResult(PublishResultType.SuccessAlready, evtMsgs, content)); continue; } @@ -2501,25 +2297,25 @@ namespace Umbraco.Core.Services return statuses; } - internal Attempt StrategyCanUnPublish(IScopeUnitOfWork uow, IContent content, int userId, EventMessages evtMsgs) + internal PublishResult StrategyCanUnPublish(IScopeUnitOfWork uow, IContent content, int userId, EventMessages evtMsgs) { // fire UnPublishing event if (uow.Events.DispatchCancelable(UnPublishing, this, new PublishEventArgs(content, evtMsgs))) { Logger.Info($"Content '{content.Name}' with Id '{content.Id}' will not be unpublished, the event was cancelled."); - return Attempt.Fail(new UnPublishStatus(UnPublishedStatusType.FailedCancelledByEvent, evtMsgs, content)); + return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); } - return Attempt.Succeed(new UnPublishStatus(content, evtMsgs)); + return new PublishResult(evtMsgs, content); } - internal Attempt StrategyUnPublish(IScopeUnitOfWork uow, IContent content, bool alreadyCheckedCanUnPublish, int userId, EventMessages evtMsgs) + internal PublishResult StrategyUnPublish(IScopeUnitOfWork uow, IContent content, bool alreadyCheckedCanUnPublish, int userId, EventMessages evtMsgs) { // content should (is assumed to) be the newest version, which may not be published, // don't know how to test this, so it's not verified var attempt = alreadyCheckedCanUnPublish - ? Attempt.Succeed(new UnPublishStatus(content, evtMsgs)) // already know we can + ? new PublishResult(evtMsgs, content) // already know we can : StrategyCanUnPublish(uow, content, userId, evtMsgs); if (attempt.Success == false) return attempt; @@ -2541,7 +2337,7 @@ namespace Umbraco.Core.Services return attempt; } - internal IEnumerable> StrategyUnPublish(IScopeUnitOfWork uow, IEnumerable content, int userId, EventMessages evtMsgs) + internal IEnumerable StrategyUnPublish(IScopeUnitOfWork uow, IEnumerable content, int userId, EventMessages evtMsgs) { return content.Select(x => StrategyUnPublish(uow, x, false, userId, evtMsgs)); } @@ -2560,7 +2356,7 @@ namespace Umbraco.Core.Services /// /// Id of the /// Optional Id of the user issueing the delete operation - public void DeleteContentOfTypes(IEnumerable contentTypeIds, int userId = 0) + public void DeleteOfTypes(IEnumerable contentTypeIds, int userId = 0) { //TODO: This currently this is called from the ContentTypeService but that needs to change, // if we are deleting a content type, we should just delete the data and do this operation slightly differently. @@ -2637,12 +2433,11 @@ namespace Umbraco.Core.Services /// This needs extra care and attention as its potentially a dangerous and extensive operation /// Id of the /// Optional id of the user deleting the media - public void DeleteContentOfType(int contentTypeId, int userId = 0) + public void DeleteOfType(int contentTypeId, int userId = 0) { - DeleteContentOfTypes(new[] { contentTypeId }, userId); + DeleteOfTypes(new[] { contentTypeId }, userId); } - private IContentType GetContentType(IScopeUnitOfWork uow, string contentTypeAlias) { if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias)); @@ -2761,16 +2556,16 @@ namespace Umbraco.Core.Services return content; } - public IEnumerable GetBlueprintsForContentTypes(params int[] documentTypeIds) + public IEnumerable GetBlueprintsForContentTypes(params int[] contentTypeId) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { var repository = uow.CreateRepository(); var query = Query(); - if (documentTypeIds.Length > 0) + if (contentTypeId.Length > 0) { - query.Where(x => documentTypeIds.Contains(x.ContentTypeId)); + query.Where(x => contentTypeId.Contains(x.ContentTypeId)); } return repository.GetByQuery(query).Select(x => { diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index 3d5bbfa4ed..2f6e043c88 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Services if (guidUdi == null) throw new InvalidOperationException("The UDI provided isn't of type " + typeof(GuidUdi) + " which is required by content"); var parent = contentService.GetById(guidUdi.Guid); - return contentService.CreateContent(name, parent, mediaTypeAlias, userId); + return contentService.Create(name, parent, mediaTypeAlias, userId); } /// @@ -50,7 +50,7 @@ namespace Umbraco.Core.Services /// public static void RemoveContentPermissions(this IContentService contentService, int contentId) { - contentService.ReplaceContentPermissions(new EntityPermissionSet(contentId, new EntityPermissionCollection())); + contentService.SetPermissions(new EntityPermissionSet(contentId, new EntityPermissionCollection())); } /// diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index f2631918f1..24bf580fd6 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Services protected override void DeleteItemsOfTypes(IEnumerable typeIds) { foreach (var typeId in typeIds) - ContentService.DeleteContentOfType(typeId); + ContentService.DeleteOfType(typeId); } /// diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index 38bc1d695b..2319dd9e32 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -640,7 +640,7 @@ namespace Umbraco.Core.Services return clone; } - public Attempt> Copy(TItem copying, int containerId) + public Attempt> Copy(TItem copying, int containerId) { var evtMsgs = EventMessagesFactory.Get(); @@ -684,18 +684,18 @@ namespace Umbraco.Core.Services } catch (DataOperationException ex) { - return OperationStatus.Attempt.Fail(ex.Operation, evtMsgs); // causes rollback + return OperationResult.Attempt.Fail(ex.Operation, evtMsgs); // causes rollback } } - return OperationStatus.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs, copy); + return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs, copy); } #endregion #region Move - public Attempt> Move(TItem moving, int containerId) + public Attempt> Move(TItem moving, int containerId) { var evtMsgs = EventMessagesFactory.Get(); @@ -707,7 +707,7 @@ namespace Umbraco.Core.Services if (OnMovingCancelled(uow, moveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); + return OperationResult.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); } uow.WriteLock(WriteLockIds); // also for containers @@ -730,7 +730,7 @@ namespace Umbraco.Core.Services catch (DataOperationException ex) { uow.Complete(); - return OperationStatus.Attempt.Fail(ex.Operation, evtMsgs); + return OperationResult.Attempt.Fail(ex.Operation, evtMsgs); } // note: not raising any Changed event here because moving a content type under another container @@ -742,7 +742,7 @@ namespace Umbraco.Core.Services OnMoved(uow, moveEventArgs); } - return OperationStatus.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs); + return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs); } #endregion @@ -753,7 +753,7 @@ namespace Umbraco.Core.Services protected Guid ContainerObjectType => EntityContainer.GetContainerObjectType(ContainedObjectType); - public Attempt> CreateContainer(int parentId, string name, int userId = 0) + public Attempt> CreateContainer(int parentId, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -774,7 +774,7 @@ namespace Umbraco.Core.Services if (OnSavingContainerCancelled(uow, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs, container); + return OperationResult.Attempt.Cancel(evtMsgs, container); } repo.AddOrUpdate(container); @@ -784,17 +784,17 @@ namespace Umbraco.Core.Services OnSavedContainer(uow, saveEventArgs); //TODO: Audit trail ? - return OperationStatus.Attempt.Succeed(evtMsgs, container); + return OperationResult.Attempt.Succeed(evtMsgs, container); } catch (Exception ex) { uow.Complete(); - return OperationStatus.Attempt.Fail(OperationStatusType.FailedCancelledByEvent, evtMsgs, ex); + return OperationResult.Attempt.Fail(OperationResultType.FailedCancelledByEvent, evtMsgs, ex); } } } - public Attempt SaveContainer(EntityContainer container, int userId = 0) + public Attempt SaveContainer(EntityContainer container, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); @@ -802,13 +802,13 @@ namespace Umbraco.Core.Services if (container.ContainerObjectType != containerObjectType) { var ex = new InvalidOperationException("Not a container of the proper type."); - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } if (container.HasIdentity && container.IsPropertyDirty("ParentId")) { var ex = new InvalidOperationException("Cannot save a container with a modified parent, move the container instead."); - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } using (var uow = UowProvider.CreateUnitOfWork()) @@ -816,7 +816,7 @@ namespace Umbraco.Core.Services if (OnSavingContainerCancelled(uow, new SaveEventArgs(container, evtMsgs))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } uow.WriteLock(WriteLockIds); // also for containers @@ -830,7 +830,7 @@ namespace Umbraco.Core.Services //TODO: Audit trail ? - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } public EntityContainer GetContainer(int containerId) @@ -891,7 +891,7 @@ namespace Umbraco.Core.Services } } - public Attempt DeleteContainer(int containerId, int userId = 0) + public Attempt DeleteContainer(int containerId, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -900,7 +900,7 @@ namespace Umbraco.Core.Services var repo = uow.CreateContainerRepository(ContainerObjectType); var container = repo.Get(containerId); - if (container == null) return OperationStatus.Attempt.NoOperation(evtMsgs); + if (container == null) return OperationResult.Attempt.NoOperation(evtMsgs); var erepo = uow.CreateRepository(); var entity = erepo.Get(container.Id); @@ -908,14 +908,14 @@ namespace Umbraco.Core.Services { // fixme - here and everywhere, original v8 would not Complete, thus causing rollback = ? uow.Complete(); - return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCannot, evtMsgs)); + return Attempt.Fail(new OperationResult(OperationResultType.FailedCannot, evtMsgs)); } var deleteEventArgs = new DeleteEventArgs(container, evtMsgs); if (OnDeletingContainerCancelled(uow, deleteEventArgs)) { uow.Complete(); - return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs)); + return Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, evtMsgs)); } repo.Delete(container); @@ -924,12 +924,12 @@ namespace Umbraco.Core.Services deleteEventArgs.CanCancel = false; OnDeletedContainer(uow, deleteEventArgs); - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); //TODO: Audit trail ? } } - public Attempt> RenameContainer(int id, string name, int userId = 0) + public Attempt> RenameContainer(int id, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -951,11 +951,11 @@ namespace Umbraco.Core.Services OnRenamedContainer(uow, new SaveEventArgs(container, evtMsgs)); - return OperationStatus.Attempt.Succeed(OperationStatusType.Success, evtMsgs, container); + return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } catch (Exception ex) { - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } } } diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index dd18848d8a..6ed5c477c4 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Services #region Containers - public Attempt> CreateContainer(int parentId, string name, int userId = 0) + public Attempt> CreateContainer(int parentId, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -41,7 +41,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs, container); + return OperationResult.Attempt.Cancel(evtMsgs, container); } repo.AddOrUpdate(container); @@ -50,11 +50,11 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs)); //TODO: Audit trail ? - return OperationStatus.Attempt.Succeed(evtMsgs, container); + return OperationResult.Attempt.Succeed(evtMsgs, container); } catch (Exception ex) { - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } } } @@ -109,20 +109,20 @@ namespace Umbraco.Core.Services } } - public Attempt SaveContainer(EntityContainer container, int userId = 0) + public Attempt SaveContainer(EntityContainer container, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); if (container.ContainedObjectType != Constants.ObjectTypes.DataType) { var ex = new InvalidOperationException("Not a " + Constants.ObjectTypes.DataType + " container."); - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } if (container.HasIdentity && container.IsPropertyDirty("ParentId")) { var ex = new InvalidOperationException("Cannot save a container with a modified parent, move the container instead."); - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } using (var uow = UowProvider.CreateUnitOfWork()) @@ -130,7 +130,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var repo = uow.CreateRepository(); @@ -141,27 +141,27 @@ namespace Umbraco.Core.Services } //TODO: Audit trail ? - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } - public Attempt DeleteContainer(int containerId, int userId = 0) + public Attempt DeleteContainer(int containerId, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) { var repo = uow.CreateRepository(); var container = repo.Get(containerId); - if (container == null) return OperationStatus.Attempt.NoOperation(evtMsgs); + if (container == null) return OperationResult.Attempt.NoOperation(evtMsgs); var erepo = uow.CreateRepository(); var entity = erepo.Get(container.Id); if (entity.HasChildren()) // because container.HasChildren() does not work? - return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCannot, evtMsgs)); // causes rollback + return Attempt.Fail(new OperationResult(OperationResultType.FailedCannot, evtMsgs)); // causes rollback if (uow.Events.DispatchCancelable(DeletingContainer, this, new DeleteEventArgs(container, evtMsgs))) { uow.Complete(); - return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs)); + return Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, evtMsgs)); } repo.Delete(container); @@ -171,10 +171,10 @@ namespace Umbraco.Core.Services } //TODO: Audit trail ? - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } - public Attempt> RenameContainer(int id, string name, int userId = 0) + public Attempt> RenameContainer(int id, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); using (var uow = UowProvider.CreateUnitOfWork()) @@ -197,11 +197,11 @@ namespace Umbraco.Core.Services // fixme - triggering SavedContainer with a different name?! uow.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs), "RenamedContainer"); - return OperationStatus.Attempt.Succeed(OperationStatusType.Success, evtMsgs, container); + return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } catch (Exception ex) { - return OperationStatus.Attempt.Fail(evtMsgs, ex); + return OperationResult.Attempt.Fail(evtMsgs, ex); } } } @@ -326,7 +326,7 @@ namespace Umbraco.Core.Services } } - public Attempt> Move(IDataTypeDefinition toMove, int parentId) + public Attempt> Move(IDataTypeDefinition toMove, int parentId) { var evtMsgs = EventMessagesFactory.Get(); var moveInfo = new List>(); @@ -338,7 +338,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); + return OperationResult.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); } var containerRepository = uow.CreateRepository(); @@ -363,11 +363,11 @@ namespace Umbraco.Core.Services catch (DataOperationException ex) { uow.Complete(); // fixme what are we doing here exactly? - return OperationStatus.Attempt.Fail(ex.Operation, evtMsgs); + return OperationResult.Attempt.Fail(ex.Operation, evtMsgs); } } - return OperationStatus.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs); + return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs); } /// diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index b241dbad60..57869e3772 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -27,7 +27,7 @@ namespace Umbraco.Core.Services } } - public Attempt Delete(IDomain domain) + public Attempt Delete(IDomain domain) { var evtMsgs = EventMessagesFactory.Get(); @@ -37,7 +37,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var repository = uow.CreateRepository(); @@ -48,7 +48,7 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Deleted, this, deleteEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } public IDomain GetByName(string name) @@ -87,7 +87,7 @@ namespace Umbraco.Core.Services } } - public Attempt Save(IDomain domainEntity) + public Attempt Save(IDomain domainEntity) { var evtMsgs = EventMessagesFactory.Get(); @@ -97,7 +97,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var repository = uow.CreateRepository(); @@ -107,7 +107,7 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Saved, this, saveEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } #region Event Handlers diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index ec29b7ca38..76aca5f5e7 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -321,7 +321,7 @@ namespace Umbraco.Core.Services /// /// The template created /// - public Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = 0) + public Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = 0) { var template = new Template(contentTypeName, //NOTE: We are NOT passing in the content type alias here, we want to use it's name since we don't @@ -348,7 +348,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(SavingTemplate, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Fail(OperationStatusType.FailedCancelledByEvent, evtMsgs, template); + return OperationResult.Attempt.Fail(OperationResultType.FailedCancelledByEvent, evtMsgs, template); } var repository = uow.CreateRepository(); @@ -360,7 +360,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(OperationStatusType.Success, evtMsgs, template); + return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, template); } public ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0) diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index dd1c137969..46e12784b2 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Xml; -using System.Xml.Linq; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -10,605 +8,423 @@ using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Services { - /// - /// A temporary interface until we are in v8, this is used to return a different result for the same method and this interface gets implemented - /// explicitly. These methods will replace the normal ones in IContentService in v8 and this will be removed. - /// - public interface IContentServiceOperations - { - //TODO: Remove this class in v8 - - //TODO: There's probably more that needs to be added like the EmptyRecycleBin, etc... - - /// - /// Saves a single object - /// - /// The to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - Attempt Save(IContent content, int userId = 0, bool raiseEvents = true); - - /// - /// Saves a collection of objects. - /// - /// Collection of to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - Attempt Save(IEnumerable contents, int userId = 0, bool raiseEvents = true); - - /// - /// Permanently deletes an object. - /// - /// - /// This method will also delete associated media files, child content and possibly associated domains. - /// - /// Please note that this method will completely remove the Content from the database - /// The to delete - /// Optional Id of the User deleting the Content - Attempt Delete(IContent content, int userId = 0); - - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// The published status attempt - Attempt Publish(IContent content, int userId = 0); - - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// - /// The list of statuses for all published items - IEnumerable> PublishWithChildren(IContent content, int userId = 0, bool includeUnpublished = false); - - /// - /// Used to perform scheduled publishing/unpublishing - /// - IEnumerable> PerformScheduledPublish(); - - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - Attempt SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true); - - /// - /// Deletes an object by moving it to the Recycle Bin - /// - /// Move an item to the Recycle Bin will result in the item being unpublished - /// The to delete - /// Optional Id of the User deleting the Content - Attempt MoveToRecycleBin(IContent content, int userId = 0); - - /// - /// UnPublishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if unpublishing succeeded, otherwise False - Attempt UnPublish(IContent content, int userId = 0); - } - /// /// Defines the ContentService, which is an easy access to operations involving /// public interface IContentService : IContentServiceBase { - IEnumerable GetBlueprintsForContentTypes(params int[] documentTypeIds); + #region Blueprints + + /// + /// Gets a blueprint. + /// IContent GetBlueprintById(int id); + + /// + /// Gets a blueprint. + /// IContent GetBlueprintById(Guid id); + + /// + /// Gets blueprints for a content type. + /// + IEnumerable GetBlueprintsForContentTypes(params int[] documentTypeId); + + /// + /// Saves a blueprint. + /// void SaveBlueprint(IContent content, int userId = 0); + + /// + /// Deletes a blueprint. + /// void DeleteBlueprint(IContent content, int userId = 0); + + /// + /// Creates a new content item from a blueprint. + /// IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0); - int CountPublished(string contentTypeAlias = null); - int Count(string contentTypeAlias = null); - int CountChildren(int parentId, string contentTypeAlias = null); - int CountDescendants(int parentId, string contentTypeAlias = null); + #endregion + + #region Get, Count Documents /// - /// Used to bulk update the permissions set for a content item. This will replace all permissions - /// assigned to an entity with a list of user group id & permission pairs. + /// Gets a document. /// - /// - void ReplaceContentPermissions(EntityPermissionSet permissionSet); - - /// - /// Assigns a single permission to the current content item for the specified user group ids - /// - /// - /// - /// - void AssignContentPermission(IContent entity, char permission, IEnumerable groupIds); - - /// - /// Returns implicit/inherited permissions assigned to the content item for all user groups - /// - /// - /// - EntityPermissionCollection GetPermissionsForEntity(IContent content); - - bool SendToPublication(IContent content, int userId = 0); - - IEnumerable GetByIds(IEnumerable ids); - IEnumerable GetByIds(IEnumerable ids); - - /// - /// Creates an object using the alias of the - /// that this Content should based on. - /// - /// - /// Note that using this method will simply return a new IContent without any identity - /// as it has not yet been persisted. It is intended as a shortcut to creating new content objects - /// that does not invoke a save operation against the database. - /// - /// Name of the Content object - /// Id of Parent for the new Content - /// Alias of the - /// Optional id of the user creating the content - /// - IContent CreateContent(string name, Guid parentId, string contentTypeAlias, int userId = 0); - - /// - /// Creates an object using the alias of the - /// that this Content should based on. - /// - /// - /// Note that using this method will simply return a new IContent without any identity - /// as it has not yet been persisted. It is intended as a shortcut to creating new content objects - /// that does not invoke a save operation against the database. - /// - /// Name of the Content object - /// Id of Parent for the new Content - /// Alias of the - /// Optional id of the user creating the content - /// - IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0); - - /// - /// Creates an object using the alias of the - /// that this Content should based on. - /// - /// - /// Note that using this method will simply return a new IContent without any identity - /// as it has not yet been persisted. It is intended as a shortcut to creating new content objects - /// that does not invoke a save operation against the database. - /// - /// Name of the Content object - /// Parent object for the new Content - /// Alias of the - /// Optional id of the user creating the content - /// - IContent CreateContent(string name, IContent parent, string contentTypeAlias, int userId = 0); - - /// - /// Gets an object by Id - /// - /// Id of the Content to retrieve - /// IContent GetById(int id); /// - /// Gets an object by its 'UniqueId' + /// Gets a document. /// - /// Guid key of the Content to retrieve - /// IContent GetById(Guid key); /// - /// Gets a collection of objects by the Id of the + /// Gets documents. /// - /// Id of the - /// An Enumerable list of objects - IEnumerable GetContentOfContentType(int id); + IEnumerable GetByIds(IEnumerable ids); /// - /// Gets a collection of objects by Level + /// Gets documents. + /// + IEnumerable GetByIds(IEnumerable ids); + + /// + /// Gets documents of a given document type. + /// + IEnumerable GetByType(int documentTypeId); + + /// + /// Gets documents at a given level. /// - /// The level to retrieve Content from - /// An Enumerable list of objects IEnumerable GetByLevel(int level); /// - /// Gets a collection of objects by Parent Id + /// Gets child documents of a given parent. /// - /// Id of the Parent to retrieve Children from - /// An Enumerable list of objects - IEnumerable GetChildren(int id); + IEnumerable GetChildren(int parentId); /// - /// Gets a collection of objects by Parent Id + /// Gets child documents of a document, (partially) matching a name. /// - /// Id of the Parent to retrieve Children from - /// Page number - /// Page size - /// Total records query would return without paging - /// Field to order by - /// Direction to order by - /// Search text filter - /// An Enumerable list of objects + IEnumerable GetChildren(int parentId, string name); + + /// + /// Gets the parent of a document. + /// + IContent GetParent(int id); + + /// + /// Gets the parent of a document. + /// + IContent GetParent(IContent content); + + /// + /// Gets ancestor documents of a document. + /// + IEnumerable GetAncestors(int id); + + /// + /// Gets ancestor documents of a document. + /// + IEnumerable GetAncestors(IContent content); + + /// + /// Gets descendant documents of a document. + /// + IEnumerable GetDescendants(int id); + + /// + /// Gets descendant documents of a document. + /// + IEnumerable GetDescendants(IContent content); + + /// + /// Gets all versions of a document. + /// + /// Versions are ordered with current first, then most recent first. + IEnumerable GetVersions(int id); + + /// + /// Gets top versions of a document. + /// + /// Versions are ordered with current first, then most recent first. + IEnumerable GetVersionIds(int id, int topRows); + + /// + /// Gets a version of a document. + /// + IContent GetVersion(Guid versionId); + + /// + /// Gets root-level documents. + /// + IEnumerable GetRootContent(); + + /// + /// Gets documents with an expiration date greater then today. + /// + IEnumerable GetContentForExpiration(); + + /// + /// Gets documents with a release date greater then today. + /// + IEnumerable GetContentForRelease(); + + /// + /// Gets documents in the recycle bin. + /// + IEnumerable GetContentInRecycleBin(); + + /// + /// Gets child documents of a given parent. + /// + /// The parent identifier. + /// The page number. + /// The page size. + /// Total number of documents. + /// A field to order by. + /// The ordering direction. + /// Search text filter. IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = ""); /// - /// Gets a collection of objects by Parent Id + /// Gets child documents of a given parent. /// - /// Id of the Parent to retrieve Children from - /// Page number - /// Page size - /// Total records query would return without paging - /// Field to order by - /// Direction to order by - /// Flag to indicate when ordering by system field - /// Search text filter - /// An Enumerable list of objects + /// The parent identifier. + /// The page number. + /// The page size. + /// Total number of documents. + /// A field to order by. + /// The ordering direction. + /// A flag indicating whether the ordering field is a system field. + /// Query filter. IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter); /// - /// Gets a collection of objects by Parent Id + /// Gets descendant documents of a given parent. /// - /// Id of the Parent to retrieve Descendants from - /// Page number - /// Page size - /// Total records query would return without paging - /// Field to order by - /// Direction to order by - /// Search text filter - /// An Enumerable list of objects + /// The parent identifier. + /// The page number. + /// The page size. + /// Total number of documents. + /// A field to order by. + /// The ordering direction. + /// Search text filter. IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = ""); /// - /// Gets a collection of objects by Parent Id + /// Gets descendant documents of a given parent. /// - /// Id of the Parent to retrieve Descendants from - /// Page number - /// Page size - /// Total records query would return without paging - /// Field to order by - /// Direction to order by - /// Flag to indicate when ordering by system field - /// - /// An Enumerable list of objects + /// The parent identifier. + /// The page number. + /// The page size. + /// Total number of documents. + /// A field to order by. + /// The ordering direction. + /// A flag indicating whether the ordering field is a system field. + /// Query filter. IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, bool orderBySystemField, IQuery filter); /// - /// Gets a collection of an objects versions by its Id + /// Counts documents of a given document type. /// - /// - /// An Enumerable list of objects - IEnumerable GetVersions(int id); + int Count(string documentTypeAlias = null); /// - /// Gets a list of all version Ids for the given content, item ordered so latest is first. + /// Counts published documents of a given document type. /// - /// - /// The maximum number of rows to return - /// - IEnumerable GetVersionIds(int id, int maxRows); + int CountPublished(string documentTypeAlias = null); /// - /// Gets a collection of objects, which reside at the first level / root + /// Counts child documents of a given parent, of a given document type. /// - /// An Enumerable list of objects - IEnumerable GetRootContent(); + int CountChildren(int parentId, string documentTypeAlias = null); /// - /// Gets a collection of objects, which has an expiration date greater then today + /// Counts descendant documents of a given parent, of a given document type. /// - /// An Enumerable list of objects - IEnumerable GetContentForExpiration(); + int CountDescendants(int parentId, string documentTypeAlias = null); /// - /// Gets a collection of objects, which has a release date greater then today + /// Gets a value indicating whether a document has children. /// - /// An Enumerable list of objects - IEnumerable GetContentForRelease(); + bool HasChildren(int id); + + #endregion + + #region Save, Delete Document /// - /// Gets a collection of an objects, which resides in the Recycle Bin + /// Saves a document. /// - /// An Enumerable list of objects - IEnumerable GetContentInRecycleBin(); + OperationResult Save(IContent content, int userId = 0, bool raiseEvents = true); /// - /// Saves a single object + /// Saves documents. /// - /// The to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - void Save(IContent content, int userId = 0, bool raiseEvents = true); + // fixme why only 1 result not 1 per content?! + OperationResult Save(IEnumerable contents, int userId = 0, bool raiseEvents = true); /// - /// Saves a collection of objects. + /// Deletes a document. /// - /// Collection of to save - /// Optional Id of the User saving the Content - /// Optional boolean indicating whether or not to raise events. - void Save(IEnumerable contents, int userId = 0, bool raiseEvents = true); + /// + /// This method will also delete associated media files, child content and possibly associated domains. + /// This method entirely clears the content from the database. + /// + OperationResult Delete(IContent content, int userId = 0); /// - /// Deletes all content of specified type. All children of deleted content is moved to Recycle Bin. + /// Deletes all documents of a given document type. /// - /// This needs extra care and attention as its potentially a dangerous and extensive operation - /// Id of the - /// Optional Id of the user issueing the delete operation - void DeleteContentOfType(int contentTypeId, int userId = 0); + /// + /// All non-deleted descendants of the deleted documents are moved to the recycle bin. + /// This operation is potentially dangerous and expensive. + /// + void DeleteOfType(int documentTypeId, int userId = 0); /// - /// Deletes all content of the specified types. All Descendants of deleted content that is not of these types is moved to Recycle Bin. + /// Deletes all documents of given document types. /// - /// This needs extra care and attention as its potentially a dangerous and extensive operation - /// Ids of the s - /// Optional Id of the user issueing the delete operation - void DeleteContentOfTypes(IEnumerable contentTypeIds, int userId = 0); + /// + /// All non-deleted descendants of the deleted documents are moved to the recycle bin. + /// This operation is potentially dangerous and expensive. + /// + void DeleteOfTypes(IEnumerable contentTypeIds, int userId = 0); /// - /// Permanently deletes versions from an object prior to a specific date. + /// Deletes versions of a document prior to a given date. /// - /// Id of the object to delete versions from - /// Latest version date - /// Optional Id of the User deleting versions of a Content object - void DeleteVersions(int id, DateTime versionDate, int userId = 0); + void DeleteVersions(int id, DateTime date, int userId = 0); /// - /// Permanently deletes a specific version from an object. + /// Deletes a version of a document. /// - /// Id of the object to delete a version from - /// Id of the version to delete - /// Boolean indicating whether to delete versions prior to the versionId - /// Optional Id of the User deleting versions of a Content object void DeleteVersion(int id, Guid versionId, bool deletePriorVersions, int userId = 0); - /// - /// Deletes an object by moving it to the Recycle Bin - /// - /// Move an item to the Recycle Bin will result in the item being unpublished - /// The to delete - /// Optional Id of the User deleting the Content - void MoveToRecycleBin(IContent content, int userId = 0); + #endregion + + #region Move, Copy, Sort Document /// - /// Moves an object to a new location + /// Moves a document under a new parent. /// - /// The to move - /// Id of the Content's new Parent - /// Optional Id of the User moving the Content void Move(IContent content, int parentId, int userId = 0); /// - /// Empties the Recycle Bin by deleting all that resides in the bin + /// Copies a document. + /// + /// + /// Recursively copies all children. + /// + IContent Copy(IContent content, int parentId, bool relateToOriginal, int userId = 0); + + /// + /// Copies a document. + /// + /// + /// Optionaly recursively copies all children. + /// + IContent Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, int userId = 0); + + /// + /// Moves a document to the recycle bin. + /// + OperationResult MoveToRecycleBin(IContent content, int userId = 0); + + /// + /// Empties the recycle bin. /// void EmptyRecycleBin(); /// - /// Rollback an object to a previous version. - /// This will create a new version, which is a copy of all the old data. + /// Sorts documents. /// - /// Id of the being rolled back - /// Id of the version to rollback to - /// Optional Id of the User issueing the rollback of the Content - /// The newly created object - IContent Rollback(int id, Guid versionId, int userId = 0); - - /// - /// Gets a collection of objects by its name or partial name - /// - /// Id of the Parent to retrieve Children from - /// Full or partial name of the children - /// An Enumerable list of objects - IEnumerable GetChildrenByName(int parentId, string name); - - /// - /// Gets a collection of objects by Parent Id - /// - /// Id of the Parent to retrieve Descendants from - /// An Enumerable list of objects - IEnumerable GetDescendants(int id); - - /// - /// Gets a collection of objects by Parent Id - /// - /// item to retrieve Descendants from - /// An Enumerable list of objects - IEnumerable GetDescendants(IContent content); - - /// - /// Gets a specific version of an item. - /// - /// Id of the version to retrieve - /// An item - IContent GetByVersion(Guid versionId); - - /// - /// Checks whether an item has any children - /// - /// Id of the - /// True if the content has any children otherwise False - bool HasChildren(int id); - - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - bool Publish(IContent content, int userId = 0); - - /// - /// Publishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// The published status attempt - Attempt PublishWithStatus(IContent content, int userId = 0); - - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Use PublishWithChildrenWithStatus instead, that method will provide more detailed information on the outcome and also allows the includeUnpublished flag")] - bool PublishWithChildren(IContent content, int userId = 0); - - /// - /// Publishes a object and all its children - /// - /// The to publish along with its children - /// Optional Id of the User issueing the publishing - /// - /// The list of statuses for all published items - IEnumerable> PublishWithChildrenWithStatus(IContent content, int userId = 0, bool includeUnpublished = false); - - /// - /// UnPublishes a single object - /// - /// The to publish - /// Optional Id of the User issueing the publishing - /// True if unpublishing succeeded, otherwise False - bool UnPublish(IContent content, int userId = 0); - - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - [Obsolete("Use SaveAndPublishWithStatus instead, that method will provide more detailed information on the outcome")] - [EditorBrowsable(EditorBrowsableState.Never)] - bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true); - - /// - /// Saves and Publishes a single object - /// - /// The to save and publish - /// Optional Id of the User issueing the publishing - /// Optional boolean indicating whether or not to raise save events. - /// True if publishing succeeded, otherwise False - Attempt SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true); - - /// - /// Permanently deletes an object. - /// - /// - /// This method will also delete associated media files, child content and possibly associated domains. - /// - /// Please note that this method will completely remove the Content from the database - /// The to delete - /// Optional Id of the User deleting the Content - void Delete(IContent content, int userId = 0); - - /// - /// Copies an object by creating a new Content object of the same type and copies all data from the current - /// to the new copy, which is returned. Recursively copies all children. - /// - /// The to copy - /// Id of the Content's new Parent - /// Boolean indicating whether the copy should be related to the original - /// Optional Id of the User copying the Content - /// The newly created object - IContent Copy(IContent content, int parentId, bool relateToOriginal, int userId = 0); - - /// - /// Copies an object by creating a new Content object of the same type and copies all data from the current - /// to the new copy which is returned. - /// - /// The to copy - /// Id of the Content's new Parent - /// Boolean indicating whether the copy should be related to the original - /// A value indicating whether to recursively copy children. - /// Optional Id of the User copying the Content - /// The newly created object - IContent Copy(IContent content, int parentId, bool relateToOriginal, bool recursive, int userId = 0); - - /// - /// Checks if the passed in can be published based on the anscestors publish state. - /// - /// to check if anscestors are published - /// True if the Content can be published, otherwise False - bool IsPublishable(IContent content); - - /// - /// Gets a collection of objects, which are ancestors of the current content. - /// - /// Id of the to retrieve ancestors for - /// An Enumerable list of objects - IEnumerable GetAncestors(int id); - - /// - /// Gets a collection of objects, which are ancestors of the current content. - /// - /// to retrieve ancestors for - /// An Enumerable list of objects - IEnumerable GetAncestors(IContent content); - - /// - /// Sorts a collection of objects by updating the SortOrder according - /// to the ordering of items in the passed in . - /// - /// - /// Using this method will ensure that the Published-state is maintained upon sorting - /// so the cache is updated accordingly - as needed. - /// - /// - /// - /// - /// True if sorting succeeded, otherwise False bool Sort(IEnumerable items, int userId = 0, bool raiseEvents = true); - /// - /// Gets the parent of the current content as an item. - /// - /// Id of the to retrieve the parent from - /// Parent object - IContent GetParent(int id); + #endregion + + #region Publish Document /// - /// Gets the parent of the current content as an item. + /// Saves and publishes a document. /// - /// to retrieve the parent from - /// Parent object - IContent GetParent(IContent content); + /// Property values must first be published at document level. + PublishResult SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true); /// - /// Creates and saves an object using the alias of the - /// that this Content should based on. + /// Unpublishes a document. /// - /// - /// This method returns an object that has been persisted to the database - /// and therefor has an identity. - /// - /// Name of the Content object - /// Parent object for the new Content - /// Alias of the - /// Optional id of the user creating the content - /// - IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0); + PublishResult Unpublish(IContent content, int userId = 0); /// - /// Creates and saves an object using the alias of the - /// that this Content should based on. + /// Publishes a document and all its children. /// - /// - /// This method returns an object that has been persisted to the database - /// and therefor has an identity. - /// - /// Name of the Content object - /// Id of Parent for the new Content - /// Alias of the - /// Optional id of the user creating the content - /// - IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0); + IEnumerable PublishWithChildren(IContent content, int userId = 0, bool includeUnpublished = false); + + /// + /// Gets a value indicating whether a document is path-publishable. + /// + /// A document is path-publishable when all its ancestors are published. + bool IsPathPublishable(IContent content); + + /// + /// Gets a value indicating whether a document is path-published. + /// + /// A document is path-published when all its ancestors, and the document itself, are published. + bool IsPathPublished(IContent content); + + /// + /// Saves a document and raises the "sent to publication" events. + /// + bool SendToPublication(IContent content, int userId = 0); + + /// + /// Publishes and unpublishes scheduled documents. + /// + IEnumerable PerformScheduledPublish(); + + // fixme missing the differnt type of properties - should we do it manually? + /// + /// Rolls a document back a previous version. + /// + IContent Rollback(int id, Guid versionId, int userId = 0); + + #endregion + + #region Permissions + + /// + /// Gets permissions assigned to a document. + /// + EntityPermissionCollection GetPermissions(IContent content); + + /// + /// Sets the permission of a document. + /// + /// Replaces all permissions with the new set of permissions. + void SetPermissions(EntityPermissionSet permissionSet); + + /// + /// Assigns a permission to a document. + /// + /// Adds the permission to existing permissions. + void SetPermission(IContent entity, char permission, IEnumerable groupIds); + + #endregion + + #region Create + + /// + /// Creates a document. + /// + IContent Create(string name, Guid parentId, string documentTypeAlias, int userId = 0); + + /// + /// Creates a document. + /// + IContent Create(string name, int parentId, string documentTypeAlias, int userId = 0); + + /// + /// Creates a document. + /// + IContent Create(string name, IContent parent, string documentTypeAlias, int userId = 0); + + /// + /// Creates and saves a document. + /// + IContent CreateAndSave(string name, int parentId, string contentTypeAlias, int userId = 0); + + /// + /// Creates and saves a document. + /// + IContent CreateAndSave(string name, IContent parent, string contentTypeAlias, int userId = 0); + + #endregion } } diff --git a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs index 80fe26c01b..bc091535d3 100644 --- a/src/Umbraco.Core/Services/IContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentTypeServiceBase.cs @@ -41,18 +41,18 @@ namespace Umbraco.Core.Services /// bool HasContainerInPath(string contentPath); - Attempt> CreateContainer(int parentContainerId, string name, int userId = 0); - Attempt SaveContainer(EntityContainer container, int userId = 0); + Attempt> CreateContainer(int parentContainerId, string name, int userId = 0); + Attempt SaveContainer(EntityContainer container, int userId = 0); EntityContainer GetContainer(int containerId); EntityContainer GetContainer(Guid containerId); IEnumerable GetContainers(int[] containerIds); IEnumerable GetContainers(TItem contentType); IEnumerable GetContainers(string folderName, int level); - Attempt DeleteContainer(int containerId, int userId = 0); - Attempt> RenameContainer(int id, string name, int userId = 0); + Attempt DeleteContainer(int containerId, int userId = 0); + Attempt> RenameContainer(int id, string name, int userId = 0); - Attempt> Move(TItem moving, int containerId); - Attempt> Copy(TItem copying, int containerId); + Attempt> Move(TItem moving, int containerId); + Attempt> Copy(TItem copying, int containerId); TItem Copy(TItem original, string alias, string name, int parentId = -1); TItem Copy(TItem original, string alias, string name, TItem parent); } diff --git a/src/Umbraco.Core/Services/IDataTypeService.cs b/src/Umbraco.Core/Services/IDataTypeService.cs index 253bf845f2..660e06b365 100644 --- a/src/Umbraco.Core/Services/IDataTypeService.cs +++ b/src/Umbraco.Core/Services/IDataTypeService.cs @@ -9,15 +9,15 @@ namespace Umbraco.Core.Services /// public interface IDataTypeService : IService { - Attempt> CreateContainer(int parentId, string name, int userId = 0); - Attempt SaveContainer(EntityContainer container, int userId = 0); + Attempt> CreateContainer(int parentId, string name, int userId = 0); + Attempt SaveContainer(EntityContainer container, int userId = 0); EntityContainer GetContainer(int containerId); EntityContainer GetContainer(Guid containerId); IEnumerable GetContainers(string folderName, int level); IEnumerable GetContainers(IDataTypeDefinition dataTypeDefinition); IEnumerable GetContainers(int[] containerIds); - Attempt DeleteContainer(int containerId, int userId = 0); - Attempt> RenameContainer(int id, string name, int userId = 0); + Attempt DeleteContainer(int containerId, int userId = 0); + Attempt> RenameContainer(int id, string name, int userId = 0); /// /// Gets a by its Name @@ -138,7 +138,7 @@ namespace Umbraco.Core.Services /// PreValue as a string string GetPreValueAsString(int id); - Attempt> Move(IDataTypeDefinition toMove, int parentId); + Attempt> Move(IDataTypeDefinition toMove, int parentId); } } diff --git a/src/Umbraco.Core/Services/IDomainService.cs b/src/Umbraco.Core/Services/IDomainService.cs index 4c79f58016..70c986bf07 100644 --- a/src/Umbraco.Core/Services/IDomainService.cs +++ b/src/Umbraco.Core/Services/IDomainService.cs @@ -6,11 +6,11 @@ namespace Umbraco.Core.Services public interface IDomainService : IService { bool Exists(string domainName); - Attempt Delete(IDomain domain); + Attempt Delete(IDomain domain); IDomain GetByName(string name); IDomain GetById(int id); IEnumerable GetAll(bool includeWildcards); IEnumerable GetAssignedDomains(int contentId, bool includeWildcards); - Attempt Save(IDomain domainEntity); + Attempt Save(IDomain domainEntity); } } diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 09ff9869ad..91ac7c25ea 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -202,7 +202,7 @@ namespace Umbraco.Core.Services /// /// The template created /// - Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = 0); + Attempt> CreateTemplateForContentType(string contentTypeAlias, string contentTypeName, int userId = 0); ITemplate CreateTemplateWithIdentity(string name, string content, ITemplate masterTemplate = null, int userId = 0); diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index 90b933c411..63cd816b16 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Services /// /// The to delete /// Id of the User deleting the Media - Attempt MoveToRecycleBin(IMedia media, int userId = 0); + Attempt MoveToRecycleBin(IMedia media, int userId = 0); /// /// Permanently deletes an object @@ -36,7 +36,7 @@ namespace Umbraco.Core.Services /// /// The to delete /// Id of the User deleting the Media - Attempt Delete(IMedia media, int userId = 0); + Attempt Delete(IMedia media, int userId = 0); /// /// Saves a single object @@ -44,7 +44,7 @@ namespace Umbraco.Core.Services /// The to save /// Id of the User saving the Media /// Optional boolean indicating whether or not to raise events. - Attempt Save(IMedia media, int userId = 0, bool raiseEvents = true); + Attempt Save(IMedia media, int userId = 0, bool raiseEvents = true); /// /// Saves a collection of objects @@ -52,7 +52,7 @@ namespace Umbraco.Core.Services /// Collection of to save /// Id of the User saving the Media /// Optional boolean indicating whether or not to raise events. - Attempt Save(IEnumerable medias, int userId = 0, bool raiseEvents = true); + Attempt Save(IEnumerable medias, int userId = 0, bool raiseEvents = true); } /// @@ -312,7 +312,7 @@ namespace Umbraco.Core.Services /// /// Id of the version to retrieve /// An item - IMedia GetByVersion(Guid versionId); + IMedia GetVersion(Guid versionId); /// /// Gets a collection of an objects versions by Id diff --git a/src/Umbraco.Core/Services/IPublicAccessService.cs b/src/Umbraco.Core/Services/IPublicAccessService.cs index c66be1433b..6878e3f62d 100644 --- a/src/Umbraco.Core/Services/IPublicAccessService.cs +++ b/src/Umbraco.Core/Services/IPublicAccessService.cs @@ -50,7 +50,7 @@ namespace Umbraco.Core.Services /// /// /// - Attempt> AddRule(IContent content, string ruleType, string ruleValue); + Attempt> AddRule(IContent content, string ruleType, string ruleValue); /// /// Removes a rule @@ -58,19 +58,19 @@ namespace Umbraco.Core.Services /// /// /// - Attempt RemoveRule(IContent content, string ruleType, string ruleValue); + Attempt RemoveRule(IContent content, string ruleType, string ruleValue); /// /// Saves the entry /// /// - Attempt Save(PublicAccessEntry entry); + Attempt Save(PublicAccessEntry entry); /// /// Deletes the entry and all associated rules /// /// - Attempt Delete(PublicAccessEntry entry); + Attempt Delete(PublicAccessEntry entry); } } diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 6c92bdda99..6eb9d24bae 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -417,13 +417,13 @@ namespace Umbraco.Core.Services /// /// Id of the version to retrieve /// An item - public IMedia GetByVersion(Guid versionId) + public IMedia GetVersion(Guid versionId) { using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) { uow.ReadLock(Constants.Locks.MediaTree); var repository = uow.CreateRepository(); - return repository.GetByVersion(versionId); + return repository.GetVersion(versionId); } } @@ -791,7 +791,7 @@ namespace Umbraco.Core.Services /// The to save /// Id of the User saving the Media /// Optional boolean indicating whether or not to raise events. - Attempt IMediaServiceOperations.Save(IMedia media, int userId, bool raiseEvents) + Attempt IMediaServiceOperations.Save(IMedia media, int userId, bool raiseEvents) { var evtMsgs = EventMessagesFactory.Get(); @@ -801,7 +801,7 @@ namespace Umbraco.Core.Services if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } // poor man's validation? @@ -829,7 +829,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } /// @@ -849,7 +849,7 @@ namespace Umbraco.Core.Services /// Collection of to save /// Id of the User saving the Media /// Optional boolean indicating whether or not to raise events. - Attempt IMediaServiceOperations.Save(IEnumerable medias, int userId, bool raiseEvents) + Attempt IMediaServiceOperations.Save(IEnumerable medias, int userId, bool raiseEvents) { var evtMsgs = EventMessagesFactory.Get(); var mediasA = medias.ToArray(); @@ -860,7 +860,7 @@ namespace Umbraco.Core.Services if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs(mediasA, evtMsgs))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var treeChanges = mediasA.Select(x => new TreeChange(x, @@ -886,7 +886,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } #endregion @@ -912,7 +912,7 @@ namespace Umbraco.Core.Services /// /// The to delete /// Id of the User deleting the Media - Attempt IMediaServiceOperations.Delete(IMedia media, int userId) + Attempt IMediaServiceOperations.Delete(IMedia media, int userId) { var evtMsgs = EventMessagesFactory.Get(); @@ -921,7 +921,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs(media, evtMsgs))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } uow.WriteLock(Constants.Locks.MediaTree); @@ -935,7 +935,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } private void DeleteLocked(IScopeUnitOfWork uow, IMediaRepository repository, IMedia media) @@ -1047,7 +1047,7 @@ namespace Umbraco.Core.Services IMediaRepository repository = null; if (deletePriorVersions) { - var media = GetByVersion(versionId); + var media = GetVersion(versionId); DeleteVersions(uow, ref repository, id, media.UpdateDate, userId); } @@ -1085,7 +1085,7 @@ namespace Umbraco.Core.Services /// /// The to delete /// Id of the User deleting the Media - Attempt IMediaServiceOperations.MoveToRecycleBin(IMedia media, int userId) + Attempt IMediaServiceOperations.MoveToRecycleBin(IMedia media, int userId) { var evtMsgs = EventMessagesFactory.Get(); var moves = new List>(); @@ -1102,7 +1102,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Trashing, this, new MoveEventArgs(new MoveEventInfo(media, originalPath, Constants.System.RecycleBinMedia)))) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } PerformMoveLocked(repository, media, Constants.System.RecycleBinMedia, null, userId, moves, true); @@ -1119,7 +1119,7 @@ namespace Umbraco.Core.Services uow.Complete(); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } /// diff --git a/src/Umbraco.Core/Services/NotificationService.cs b/src/Umbraco.Core/Services/NotificationService.cs index a89cafc5bf..906fbe03ec 100644 --- a/src/Umbraco.Core/Services/NotificationService.cs +++ b/src/Umbraco.Core/Services/NotificationService.cs @@ -116,7 +116,7 @@ namespace Umbraco.Core.Services // we are only selecting the top 2 rows since that is all we need var allVersions = _contentService.GetVersionIds(contentId, 2).ToList(); var prevVersionIndex = allVersions.Count > 1 ? 1 : 0; - return _contentService.GetByVersion(allVersions[prevVersionIndex]); + return _contentService.GetVersion(allVersions[prevVersionIndex]); } /// diff --git a/src/Umbraco.Core/Services/OperationResult.cs b/src/Umbraco.Core/Services/OperationResult.cs new file mode 100644 index 0000000000..d22fd0147f --- /dev/null +++ b/src/Umbraco.Core/Services/OperationResult.cs @@ -0,0 +1,238 @@ +using System; +using Umbraco.Core.Events; + +namespace Umbraco.Core.Services +{ + // FIXME + // no need for Attempt - the operation result SHOULD KNOW if it's a success or a failure! + // but then each WhateverResultType must + + /// + /// Represents the result of a service operation. + /// + /// The type of the result type. + public class OperationResult + where TResultType : struct + { + /// + /// Initializes a new instance of the class. + /// + public OperationResult(TResultType result, EventMessages eventMessages) + { + Result = result; + EventMessages = eventMessages; + } + + static OperationResult() + { + // ensure that TResultType is an enum and the underlying type is byte + // so we can safely cast in Success and test against 128 for failures + var type = typeof(TResultType); + if (type.IsEnum == false) + throw new InvalidOperationException($"Type {type} is not an enum."); + if (Enum.GetUnderlyingType(type) != typeof (byte)) + throw new InvalidOperationException($"Enum {type} underlying type is not ."); + } + + /// + /// Gets a value indicating whether the operation was successful. + /// + public bool Success => ((byte) (object) Result & 128) == 0; // we *know* it's a byte + + /// + /// Gets the result of the operation. + /// + public TResultType Result { get; } + + /// + /// Gets the event messages produced by the operation. + /// + public EventMessages EventMessages { get; } + } + + /// + /// + /// Represents the result of a service operation for a given entity. + /// + /// The type of the result type. + /// The type of the entity. + public class OperationResult : OperationResult + where TResultType : struct + { + /// + /// + /// Initializes a new instance of the class. + /// + /// The status of the operation. + /// Event messages produced by the operation. + public OperationResult(TResultType result, EventMessages eventMessages) + : base(result, eventMessages) + { } + + /// + /// + /// Initializes a new instance of the class. + /// + public OperationResult(TResultType result, EventMessages eventMessages, TEntity entity) + : base(result, eventMessages) + { + Entity = entity; + } + + /// + /// Gets the entity. + /// + public TEntity Entity { get; } + } + + /// + /// + /// Represents the default operation result. + /// + public class OperationResult : OperationResult + { + /// + /// + /// Initializes a new instance of the class with a status and event messages. + /// + /// The status of the operation. + /// Event messages produced by the operation. + public OperationResult(OperationResultType result, EventMessages eventMessages) + : base(result, eventMessages) + { } + + public static OperationResult Succeed(EventMessages eventMessages) + { + return new OperationResult(OperationResultType.Success, eventMessages); + } + + public static OperationResult Cancel(EventMessages eventMessages) + { + return new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages); + } + + // fixme wtf? + internal static class Attempt + { + /// + /// Creates a successful operation attempt. + /// + /// The event messages produced by the operation. + /// A new attempt instance. + public static Attempt Succeed(EventMessages eventMessages) + { + return Core.Attempt.Succeed(new OperationResult(OperationResultType.Success, eventMessages)); + } + + public static Attempt> Succeed(EventMessages eventMessages) + { + return Core.Attempt.Succeed(new OperationResult(OperationResultType.Success, eventMessages)); + } + + public static Attempt> Succeed(EventMessages eventMessages, TValue value) + { + return Core.Attempt.Succeed(new OperationResult(OperationResultType.Success, eventMessages, value)); + } + + public static Attempt> Succeed(TStatusType statusType, EventMessages eventMessages) + where TStatusType : struct + { + return Core.Attempt.Succeed(new OperationResult(statusType, eventMessages)); + } + + public static Attempt> Succeed(TStatusType statusType, EventMessages eventMessages, TValue value) + where TStatusType : struct + { + return Core.Attempt.Succeed(new OperationResult(statusType, eventMessages, value)); + } + + /// + /// Creates a successful operation attempt indicating that nothing was done. + /// + /// The event messages produced by the operation. + /// A new attempt instance. + public static Attempt NoOperation(EventMessages eventMessages) + { + return Core.Attempt.Succeed(new OperationResult(OperationResultType.NoOperation, eventMessages)); + } + + /// + /// Creates a failed operation attempt indicating that the operation has been cancelled. + /// + /// The event messages produced by the operation. + /// A new attempt instance. + public static Attempt Cancel(EventMessages eventMessages) + { + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages)); + } + + public static Attempt> Cancel(EventMessages eventMessages) + { + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages)); + } + + public static Attempt> Cancel(EventMessages eventMessages, TValue value) + { + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages, value)); + } + + /// + /// Creates a failed operation attempt indicating that an exception was thrown during the operation. + /// + /// The event messages produced by the operation. + /// The exception that caused the operation to fail. + /// A new attempt instance. + public static Attempt Fail(EventMessages eventMessages, Exception exception) + { + eventMessages.Add(new EventMessage("", exception.Message, EventMessageType.Error)); + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception); + } + + public static Attempt> Fail(EventMessages eventMessages, Exception exception) + { + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages)); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages)); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, TValue value) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value)); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); + } + + public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, TValue value, Exception exception) + where TStatusType : struct + { + return Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value), exception); + } + + public static Attempt> Cannot(EventMessages eventMessages) + { + return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCannot, eventMessages)); + } + } + } +} diff --git a/src/Umbraco.Core/Services/OperationResultType.cs b/src/Umbraco.Core/Services/OperationResultType.cs new file mode 100644 index 0000000000..9310741ca5 --- /dev/null +++ b/src/Umbraco.Core/Services/OperationResultType.cs @@ -0,0 +1,45 @@ +namespace Umbraco.Core.Services +{ + /// + /// A value indicating the result of an operation. + /// + public enum OperationResultType : byte + { + // all "ResultType" enums must be byte-based, and declare Failed = 128, and declare + // every failure codes as >128 - see OperationResult and OperationResultType for details. + + /// + /// The operation was successful. + /// + Success = 0, + + /// + /// The operation failed. + /// + /// All values above this value indicate a failure. + Failed = 128, + + /// + /// The operation could not complete because of invalid preconditions (eg creating a reference + /// to an item that does not exist). + /// + FailedCannot = Failed | 2, + + /// + /// The operation has been cancelled by an event handler. + /// + FailedCancelledByEvent = Failed | 4, + + /// + /// The operation could not complete due to an exception. + /// + FailedExceptionThrown = Failed | 5, + + /// + /// No operation has been executed because it was not needed (eg deleting an item that doesn't exist). + /// + NoOperation = Failed | 6, // fixme shouldn't it be a success? + + //TODO: In the future, we might need to add more operations statuses, potentially like 'FailedByPermissions', etc... + } +} diff --git a/src/Umbraco.Core/Services/OperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus.cs deleted file mode 100644 index 5b87852c24..0000000000 --- a/src/Umbraco.Core/Services/OperationStatus.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using Umbraco.Core.Events; - -namespace Umbraco.Core.Services -{ - /// - /// Represents the status of a service operation. - /// - /// The type of the status type. - public class OperationStatus - where TStatusType : struct - { - /// - /// Initializes a new instance of the class with a status and event messages. - /// - /// The status of the operation. - /// Event messages produced by the operation. - public OperationStatus(TStatusType statusType, EventMessages eventMessages) - { - StatusType = statusType; - EventMessages = eventMessages ?? throw new ArgumentNullException(nameof(eventMessages)); - } - - /// - /// Gets or sets the status of the operation. - /// - /// May be internally updated during the operation, but should NOT be updated once the operation has completed. - public TStatusType StatusType { get; internal set; } - - /// - /// Gets the event messages produced by the operation. - /// - public EventMessages EventMessages { get; } - } - - /// - /// - /// Represents the status of a service operation that manages (processes, produces...) a value. - /// - /// The type of the status type. - /// The type of the value. - public class OperationStatus : OperationStatus - where TStatusType : struct - { - /// - /// - /// Initializes a new instance of the class with a status type and event messages. - /// - /// The status of the operation. - /// Event messages produced by the operation. - public OperationStatus(TStatusType statusType, EventMessages eventMessages) - : base(statusType, eventMessages) - { } - - /// - /// - /// Initializes a new instance of the class with a status type, event messages and a value. - /// - /// The status of the operation. - /// Event messages produced by the operation. - /// The value managed by the operation. - public OperationStatus(TStatusType statusType, EventMessages eventMessages, TValue value) - : base(statusType, eventMessages) - { - Value = value; - } - - /// - /// Gets the value managed by the operation. - /// - public TValue Value { get; } - } - - /// - /// - /// Represents the default operation status. - /// - /// Also provides static helper methods to create operation statuses. - public class OperationStatus : OperationStatus - { - /// - /// - /// Initializes a new instance of the class with a status and event messages. - /// - /// The status of the operation. - /// Event messages produced by the operation. - public OperationStatus(OperationStatusType statusType, EventMessages eventMessages) - : base(statusType, eventMessages) - { } - - internal static class Attempt - { - /// - /// Creates a successful operation attempt. - /// - /// The event messages produced by the operation. - /// A new attempt instance. - public static Attempt Succeed(EventMessages eventMessages) - { - return Core.Attempt.Succeed(new OperationStatus(OperationStatusType.Success, eventMessages)); - } - - public static Attempt> Succeed(EventMessages eventMessages) - { - return Core.Attempt.Succeed(new OperationStatus(OperationStatusType.Success, eventMessages)); - } - - public static Attempt> Succeed(EventMessages eventMessages, TValue value) - { - return Core.Attempt.Succeed(new OperationStatus(OperationStatusType.Success, eventMessages, value)); - } - - public static Attempt> Succeed(TStatusType statusType, EventMessages eventMessages) - where TStatusType : struct - { - return Core.Attempt.Succeed(new OperationStatus(statusType, eventMessages)); - } - - public static Attempt> Succeed(TStatusType statusType, EventMessages eventMessages, TValue value) - where TStatusType : struct - { - return Core.Attempt.Succeed(new OperationStatus(statusType, eventMessages, value)); - } - - /// - /// Creates a successful operation attempt indicating that nothing was done. - /// - /// The event messages produced by the operation. - /// A new attempt instance. - public static Attempt NoOperation(EventMessages eventMessages) - { - return Core.Attempt.Succeed(new OperationStatus(OperationStatusType.NoOperation, eventMessages)); - } - - /// - /// Creates a failed operation attempt indicating that the operation has been cancelled. - /// - /// The event messages produced by the operation. - /// A new attempt instance. - public static Attempt Cancel(EventMessages eventMessages) - { - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages)); - } - - public static Attempt> Cancel(EventMessages eventMessages) - { - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages)); - } - - public static Attempt> Cancel(EventMessages eventMessages, TValue value) - { - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages, value)); - } - - /// - /// Creates a failed operation attempt indicating that an exception was thrown during the operation. - /// - /// The event messages produced by the operation. - /// The exception that caused the operation to fail. - /// A new attempt instance. - public static Attempt Fail(EventMessages eventMessages, Exception exception) - { - eventMessages.Add(new EventMessage("", exception.Message, EventMessageType.Error)); - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedExceptionThrown, eventMessages), exception); - } - - public static Attempt> Fail(EventMessages eventMessages, Exception exception) - { - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedExceptionThrown, eventMessages), exception); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages)); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages), exception); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages)); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, TValue value) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages, value)); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, Exception exception) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages), exception); - } - - public static Attempt> Fail(TStatusType statusType, EventMessages eventMessages, TValue value, Exception exception) - where TStatusType : struct - { - return Core.Attempt.Fail(new OperationStatus(statusType, eventMessages, value), exception); - } - - public static Attempt> Cannot(EventMessages eventMessages) - { - return Core.Attempt.Fail(new OperationStatus(OperationStatusType.FailedCannot, eventMessages)); - } - } - } -} diff --git a/src/Umbraco.Core/Services/OperationStatusType.cs b/src/Umbraco.Core/Services/OperationStatusType.cs deleted file mode 100644 index bc4295bdbf..0000000000 --- a/src/Umbraco.Core/Services/OperationStatusType.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace Umbraco.Core.Services -{ - /// - /// A value indicating the result of an operation. - /// - /// Do NOT compare against a hard-coded numeric value to check for success or failure, - /// but instead use the IsSuccess() extension method defined below - which should be the unique - /// place where the numeric test should take place. - /// - public enum OperationStatusType - { - /// - /// The operation was successful. - /// - Success = 0, - - // Values below this value indicate a success, values above it indicate a failure. - // This value is considered a failure. - //Reserved = 10, - - /// - /// The operation could not complete because of invalid preconditions (eg creating a reference - /// to an item that does not exist). - /// - FailedCannot = 12, - - /// - /// The operation has been cancelled by an event handler. - /// - FailedCancelledByEvent = 14, - - /// - /// The operation could not complete due to an exception. - /// - FailedExceptionThrown = 15, - - /// - /// No operation has been executed because it was not needed (eg deleting an item that doesn't exist). - /// - NoOperation = 100, - - //TODO: In the future, we might need to add more operations statuses, potentially like 'FailedByPermissions', etc... - } - - /// - /// Provides extension methods for the enum. - /// - public static class OperationStatusTypeExtensions - { - /// - /// Gets a value indicating whether the status indicates a success. - /// - /// The status. - /// A value indicating whether the status indicates a success. - public static bool IsSuccess(this OperationStatusType status) - { - return (int) status < 10; - } - - /// - /// Gets a value indicating whether the status indicates a failure. - /// - /// The status. - /// A value indicating whether the status indicates a failure. - public static bool IsFailure(this OperationStatusType status) - { - return (int) status >= 10; - } - } -} diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index cc2b677e73..e078af3416 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -482,7 +482,7 @@ namespace Umbraco.Core.Services _logger.Error("Could not create folder: " + rootFolder, tryCreateFolder.Exception); throw tryCreateFolder.Exception; } - var rootFolderId = tryCreateFolder.Result.Value.Id; + var rootFolderId = tryCreateFolder.Result.Entity.Id; current = _contentTypeService.GetContainer(rootFolderId); } @@ -516,7 +516,7 @@ namespace Umbraco.Core.Services _logger.Error("Could not create folder: " + folderName, tryCreateFolder.Exception); throw tryCreateFolder.Exception; } - return _contentTypeService.GetContainer(tryCreateFolder.Result.Value.Id); + return _contentTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); } private IContentType CreateContentTypeFromXml(XElement documentType) @@ -948,7 +948,7 @@ namespace Umbraco.Core.Services _logger.Error("Could not create folder: " + rootFolder, tryCreateFolder.Exception); throw tryCreateFolder.Exception; } - current = _dataTypeService.GetContainer(tryCreateFolder.Result.Value.Id); + current = _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); } importedFolders.Add(name, current.Id); @@ -981,7 +981,7 @@ namespace Umbraco.Core.Services _logger.Error("Could not create folder: " + folderName, tryCreateFolder.Exception); throw tryCreateFolder.Exception; } - return _dataTypeService.GetContainer(tryCreateFolder.Result.Value.Id); + return _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id); } private void SavePrevaluesFromXml(List dataTypes, IEnumerable dataTypeElements) diff --git a/src/Umbraco.Core/Services/PublicAccessService.cs b/src/Umbraco.Core/Services/PublicAccessService.cs index 1b7f3e1e18..e88e263819 100644 --- a/src/Umbraco.Core/Services/PublicAccessService.cs +++ b/src/Umbraco.Core/Services/PublicAccessService.cs @@ -106,7 +106,7 @@ namespace Umbraco.Core.Services /// /// /// - public Attempt> AddRule(IContent content, string ruleType, string ruleValue) + public Attempt> AddRule(IContent content, string ruleType, string ruleValue) { var evtMsgs = EventMessagesFactory.Get(); PublicAccessEntry entry; @@ -116,7 +116,7 @@ namespace Umbraco.Core.Services entry = repo.GetAll().FirstOrDefault(x => x.ProtectedNodeId == content.Id); if (entry == null) - return OperationStatus.Attempt.Cannot(evtMsgs); // causes rollback + return OperationResult.Attempt.Cannot(evtMsgs); // causes rollback var existingRule = entry.Rules.FirstOrDefault(x => x.RuleType == ruleType && x.RuleValue == ruleValue); if (existingRule == null) @@ -126,14 +126,14 @@ namespace Umbraco.Core.Services else { //If they are both the same already then there's nothing to update, exit - return OperationStatus.Attempt.Succeed(evtMsgs, entry); + return OperationResult.Attempt.Succeed(evtMsgs, entry); } var saveEventArgs = new SaveEventArgs(entry, evtMsgs); if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs, entry); + return OperationResult.Attempt.Cancel(evtMsgs, entry); } repo.AddOrUpdate(entry); @@ -144,7 +144,7 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Saved, this, saveEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs, entry); + return OperationResult.Attempt.Succeed(evtMsgs, entry); } /// @@ -153,7 +153,7 @@ namespace Umbraco.Core.Services /// /// /// - public Attempt RemoveRule(IContent content, string ruleType, string ruleValue) + public Attempt RemoveRule(IContent content, string ruleType, string ruleValue) { var evtMsgs = EventMessagesFactory.Get(); PublicAccessEntry entry; @@ -162,10 +162,10 @@ namespace Umbraco.Core.Services var repo = uow.CreateRepository(); entry = repo.GetAll().FirstOrDefault(x => x.ProtectedNodeId == content.Id); - if (entry == null) return Attempt.Fail(); // causes rollback + if (entry == null) return Attempt.Fail(); // causes rollback var existingRule = entry.Rules.FirstOrDefault(x => x.RuleType == ruleType && x.RuleValue == ruleValue); - if (existingRule == null) return Attempt.Fail(); // causes rollback + if (existingRule == null) return Attempt.Fail(); // causes rollback entry.RemoveRule(existingRule); @@ -173,7 +173,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } repo.AddOrUpdate(entry); @@ -183,14 +183,14 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Saved, this, saveEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } /// /// Saves the entry /// /// - public Attempt Save(PublicAccessEntry entry) + public Attempt Save(PublicAccessEntry entry) { var evtMsgs = EventMessagesFactory.Get(); @@ -200,7 +200,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var repo = uow.CreateRepository(); @@ -211,14 +211,14 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Saved, this, saveEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } /// /// Deletes the entry and all associated rules /// /// - public Attempt Delete(PublicAccessEntry entry) + public Attempt Delete(PublicAccessEntry entry) { var evtMsgs = EventMessagesFactory.Get(); @@ -228,7 +228,7 @@ namespace Umbraco.Core.Services if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { uow.Complete(); - return OperationStatus.Attempt.Cancel(evtMsgs); + return OperationResult.Attempt.Cancel(evtMsgs); } var repo = uow.CreateRepository(); @@ -239,7 +239,7 @@ namespace Umbraco.Core.Services uow.Events.Dispatch(Deleted, this, deleteEventArgs); } - return OperationStatus.Attempt.Succeed(evtMsgs); + return OperationResult.Attempt.Succeed(evtMsgs); } /// diff --git a/src/Umbraco.Core/Services/PublishResult.cs b/src/Umbraco.Core/Services/PublishResult.cs new file mode 100644 index 0000000000..aeb981d74b --- /dev/null +++ b/src/Umbraco.Core/Services/PublishResult.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using Umbraco.Core.Events; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + /// + /// Represents the result of publishing a document. + /// + public class PublishResult : OperationResult + { + /// + /// Initializes a new instance of the class. + /// + public PublishResult(PublishResultType resultType, EventMessages eventMessages, IContent content) + : base(resultType, eventMessages, content) + { } + + /// + /// Initializes a new instance of the class. + /// + public PublishResult(EventMessages eventMessages, IContent content) + : base(PublishResultType.Success, eventMessages, content) + { } + + /// + /// Gets the document. + /// + public IContent Content => Entity; + + /// + /// Gets or sets the invalid properties, if the status failed due to validation. + /// + public IEnumerable InvalidProperties { get; set; } + } +} diff --git a/src/Umbraco.Core/Services/PublishResultType.cs b/src/Umbraco.Core/Services/PublishResultType.cs new file mode 100644 index 0000000000..1ecb447b66 --- /dev/null +++ b/src/Umbraco.Core/Services/PublishResultType.cs @@ -0,0 +1,59 @@ +namespace Umbraco.Core.Services +{ + /// + /// A value indicating the result of (un)publishing a content item. + /// + public enum PublishResultType : byte + { + // all "ResultType" enums must be byte-based, and declare Failed = 128, and declare + // every failure codes as >128 - see OperationResult and OperationResultType for details. + + /// + /// The (un)publishing was successful. + /// + Success = 0, + + /// + /// The item was already (un)published. + /// + SuccessAlready = 1, + + /// + /// The operation failed. + /// + /// All values above this value indicate a failure. + Failed = 128, + + /// + /// The content could not be published because it's ancestor path isn't published. + /// + FailedPathNotPublished = Failed | 1, + + /// + /// The content item was scheduled to be un-published and it has expired so we cannot force it to be + /// published again as part of a bulk publish operation. + /// + FailedHasExpired = Failed | 2, + + /// + /// The content item is scheduled to be released in the future and therefore we cannot force it to + /// be published during a bulk publish operation. + /// + FailedAwaitingRelease = Failed | 3, + + /// + /// The content item could not be published because it is in the trash. + /// + FailedIsTrashed = Failed | 4, + + /// + /// The publish action has been cancelled by an event handler. + /// + FailedCancelledByEvent = Failed | 5, + + /// + /// The content item could not be published because it contains invalid data (has not passed validation requirements). + /// + FailedContentInvalid = Failed | 6 + } +} diff --git a/src/Umbraco.Core/Services/PublishStatus.cs b/src/Umbraco.Core/Services/PublishStatus.cs deleted file mode 100644 index ea465a5907..0000000000 --- a/src/Umbraco.Core/Services/PublishStatus.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Events; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Services -{ - /// - /// Represents the result of publishing a content item. - /// - public class PublishStatus : OperationStatus - { - /// - /// Creates a new instance of the class with a status type, event messages, and a content item. - /// - /// The status of the operation. - /// Event messages produced by the operation. - /// The content item. - public PublishStatus(PublishStatusType statusType, EventMessages eventMessages, IContent content) - : base(statusType, eventMessages, content) - { } - - /// - /// Creates a new successful instance of the class with a event messages, and a content item. - /// - /// Event messages produced by the operation. - /// The content item. - public PublishStatus(IContent content, EventMessages eventMessages) - : base(PublishStatusType.Success, eventMessages, content) - { } - - /// - /// Gets the content item. - /// - public IContent ContentItem => Value; - - /// - /// Gets or sets the invalid properties, if the status failed due to validation. - /// - public IEnumerable InvalidProperties { get; set; } - } -} diff --git a/src/Umbraco.Core/Services/PublishStatusType.cs b/src/Umbraco.Core/Services/PublishStatusType.cs deleted file mode 100644 index a391a6914d..0000000000 --- a/src/Umbraco.Core/Services/PublishStatusType.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace Umbraco.Core.Services -{ - /// - /// A value indicating the result of publishing a content item. - /// - /// Do NOT compare against a hard-coded numeric value to check for success or failure, - /// but instead use the IsSuccess() extension method defined below - which should be the unique - /// place where the numeric test should take place. - /// - public enum PublishStatusType - { - /// - /// The publishing was successful. - /// - Success = 0, - - /// - /// The item was already published. - /// - SuccessAlreadyPublished = 1, - - // Values below this value indicate a success, values above it indicate a failure. - // This value is considered a failure. - //Reserved = 10, - - /// - /// The content could not be published because it's ancestor path isn't published. - /// - FailedPathNotPublished = 11, - - /// - /// The content item was scheduled to be un-published and it has expired so we cannot force it to be - /// published again as part of a bulk publish operation. - /// - FailedHasExpired = 12, - - /// - /// The content item is scheduled to be released in the future and therefore we cannot force it to - /// be published during a bulk publish operation. - /// - FailedAwaitingRelease = 13, - - /// - /// The content item could not be published because it is in the trash. - /// - FailedIsTrashed = 14, - - /// - /// The publish action has been cancelled by an event handler. - /// - FailedCancelledByEvent = 15, - - /// - /// The content item could not be published because it contains invalid data (has not passed validation requirements). - /// - FailedContentInvalid = 16 - } - - /// - /// Provides extension methods for the enum. - /// - public static class PublicStatusTypeExtensions - { - /// - /// Gets a value indicating whether the status indicates a success. - /// - /// The status. - /// A value indicating whether the status indicates a success. - public static bool IsSuccess(this PublishStatusType status) - { - return (int) status < 10; - } - - /// - /// Gets a value indicating whether the status indicates a failure. - /// - /// The status. - /// A value indicating whether the status indicates a failure. - public static bool IsFailure(this PublishStatusType status) - { - return (int) status >= 10; - } - } -} diff --git a/src/Umbraco.Core/Services/ServiceWithResultExtensions.cs b/src/Umbraco.Core/Services/ServiceWithResultExtensions.cs index f9c993a3b8..f64a10540f 100644 --- a/src/Umbraco.Core/Services/ServiceWithResultExtensions.cs +++ b/src/Umbraco.Core/Services/ServiceWithResultExtensions.cs @@ -9,10 +9,6 @@ /// public static class ServiceWithResultExtensions { - public static IContentServiceOperations WithResult(this IContentService contentService) - { - return (IContentServiceOperations)contentService; - } public static IMediaServiceOperations WithResult(this IMediaService mediaService) { return (IMediaServiceOperations)mediaService; diff --git a/src/Umbraco.Core/Services/UnPublishStatus.cs b/src/Umbraco.Core/Services/UnPublishStatus.cs deleted file mode 100644 index ff305ab0b3..0000000000 --- a/src/Umbraco.Core/Services/UnPublishStatus.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Umbraco.Core.Events; -using Umbraco.Core.Models; - -namespace Umbraco.Core.Services -{ - /// - /// Represents the result of unpublishing a content item. - /// - public class UnPublishStatus : OperationStatus - { - /// - /// Creates a new instance of the class with a status type, event messages, and a content item. - /// - /// The status of the operation. - /// Event messages produced by the operation. - /// The content item. - public UnPublishStatus(UnPublishedStatusType statusType, EventMessages eventMessages, IContent content) - : base(statusType, eventMessages, content) - { } - - /// - /// Creates a new successful instance of the class with a event messages, and a content item. - /// - /// Event messages produced by the operation. - /// The content item. - public UnPublishStatus(IContent content, EventMessages eventMessages) - : base(UnPublishedStatusType.Success, eventMessages, content) - { } - - /// - /// Gets the content item. - /// - public IContent ContentItem => Value; - } -} diff --git a/src/Umbraco.Core/Services/UnPublishedStatusType.cs b/src/Umbraco.Core/Services/UnPublishedStatusType.cs deleted file mode 100644 index aafa567ef9..0000000000 --- a/src/Umbraco.Core/Services/UnPublishedStatusType.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Umbraco.Core.Services -{ - /// - /// A status type of the result of unpublishing a content item - /// - /// - /// Anything less than 10 = Success! - /// - public enum UnPublishedStatusType - { - /// - /// The unpublishing was successful. - /// - Success = 0, - - /// - /// The item was already unpublished - /// - SuccessAlreadyUnPublished = 1, - - /// - /// The publish action has been cancelled by an event handler - /// - FailedCancelledByEvent = 14, - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 910ff98203..5521f6c969 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -805,7 +805,6 @@ - @@ -813,8 +812,7 @@ - - + @@ -1377,13 +1375,13 @@ - - + + - - + + @@ -1394,8 +1392,6 @@ - - diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index 95db52f881..5a0d4c086a 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -102,15 +102,18 @@ namespace Umbraco.Tests.Integration private IContent CreateBranch() { var content1 = MockedContent.CreateSimpleContent(_contentType, "Content1"); - ServiceContext.ContentService.SaveAndPublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); // 2 (published) // .1 (published) // .2 (not published) var content2 = MockedContent.CreateSimpleContent(_contentType, "Content2", content1); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content21 = MockedContent.CreateSimpleContent(_contentType, "Content21", content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content21); + content21.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content21); var content22 = MockedContent.CreateSimpleContent(_contentType, "Content22", content2); ServiceContext.ContentService.Save(content22); @@ -128,11 +131,13 @@ namespace Umbraco.Tests.Integration // .1 (published) // .2 (not published) var content4 = MockedContent.CreateSimpleContent(_contentType, "Content4", content1); - ServiceContext.ContentService.SaveAndPublishWithStatus(content4); + content4.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content4); content4.Name = "Content4X"; ServiceContext.ContentService.Save(content4); var content41 = MockedContent.CreateSimpleContent(_contentType, "Content41", content4); - ServiceContext.ContentService.SaveAndPublishWithStatus(content41); + content41.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content41); var content42 = MockedContent.CreateSimpleContent(_contentType, "Content42", content4); ServiceContext.ContentService.Save(content42); @@ -140,12 +145,14 @@ namespace Umbraco.Tests.Integration // .1 (published) // .2 (not published) var content5 = MockedContent.CreateSimpleContent(_contentType, "Content5", content1); - ServiceContext.ContentService.SaveAndPublishWithStatus(content5); + content5.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content5); var content51 = MockedContent.CreateSimpleContent(_contentType, "Content51", content5); - ServiceContext.ContentService.SaveAndPublishWithStatus(content51); + content51.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content51); var content52 = MockedContent.CreateSimpleContent(_contentType, "Content52", content5); ServiceContext.ContentService.Save(content52); - ServiceContext.ContentService.UnPublish(content5); + ServiceContext.ContentService.Unpublish(content5); return content1; } @@ -416,7 +423,8 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); content.Name = "changed"; @@ -452,7 +460,8 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); content.SortOrder = 666; @@ -488,7 +497,8 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); content.Properties.First().SetValue("changed"); @@ -527,7 +537,8 @@ namespace Umbraco.Tests.Integration ResetEvents(); content.Name = "changed"; - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -547,11 +558,13 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); content.Name = "changed"; - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -577,7 +590,8 @@ namespace Umbraco.Tests.Integration ResetEvents(); content.Name = "changed"; - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -600,11 +614,13 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); content.Name = "changed"; - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -624,10 +640,11 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); - ServiceContext.ContentService.UnPublish(content); + ServiceContext.ContentService.Unpublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -647,12 +664,13 @@ namespace Umbraco.Tests.Integration var content = ServiceContext.ContentService.GetRootContent().FirstOrDefault(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); content.Name = "changed"; ServiceContext.ContentService.Save(content); ResetEvents(); - ServiceContext.ContentService.UnPublish(content); + ServiceContext.ContentService.Unpublish(content); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -684,7 +702,7 @@ namespace Umbraco.Tests.Integration var content1 = CreateBranch(); ResetEvents(); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -704,10 +722,11 @@ namespace Umbraco.Tests.Integration // - published page cache :: refresh root & descendants, database (level, sortOrder) order var content1 = CreateBranch(); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); ResetEvents(); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); Assert.AreEqual(2, _msgCount); Assert.AreEqual(2, _events.Count); @@ -736,10 +755,10 @@ namespace Umbraco.Tests.Integration // rule? var content1 = CreateBranch(); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); ResetEvents(); - ServiceContext.ContentService.PublishWithChildrenWithStatus(content1, 0, false); + ServiceContext.ContentService.PublishWithChildren(content1, 0, false); Assert.AreEqual(6, _msgCount); Assert.AreEqual(6, _events.Count); @@ -772,10 +791,10 @@ namespace Umbraco.Tests.Integration // rule? var content1 = CreateBranch(); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); ResetEvents(); - ServiceContext.ContentService.PublishWithChildrenWithStatus(content1, 0, true); + ServiceContext.ContentService.PublishWithChildren(content1, 0, true); Assert.AreEqual(14, _msgCount); Assert.AreEqual(14, _events.Count); @@ -949,7 +968,8 @@ namespace Umbraco.Tests.Integration var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); ServiceContext.ContentService.MoveToRecycleBin(content); @@ -972,7 +992,8 @@ namespace Umbraco.Tests.Integration var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ServiceContext.ContentService.MoveToRecycleBin(content); ResetEvents(); @@ -996,7 +1017,8 @@ namespace Umbraco.Tests.Integration var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); content.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content); @@ -1166,7 +1188,8 @@ namespace Umbraco.Tests.Integration { var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); ServiceContext.ContentService.Delete(content); @@ -1185,7 +1208,8 @@ namespace Umbraco.Tests.Integration { var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); content.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content); @@ -1206,11 +1230,13 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.SaveAndPublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); - ServiceContext.ContentService.UnPublish(content1); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); + ServiceContext.ContentService.Unpublish(content1); ResetEvents(); ServiceContext.ContentService.Delete(content2); @@ -1290,7 +1316,8 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); @@ -1311,7 +1338,8 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); content1.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content1); var content2 = CreateContent(); @@ -1336,7 +1364,8 @@ namespace Umbraco.Tests.Integration Assert.IsNotNull(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content2.Id); @@ -1357,11 +1386,13 @@ namespace Umbraco.Tests.Integration Assert.IsNotNull(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content3 = CreateContent(); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); - ServiceContext.ContentService.UnPublish(content2); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); + ServiceContext.ContentService.Unpublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content3.Id); @@ -1380,10 +1411,12 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content2.Id); @@ -1402,14 +1435,17 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content3 = CreateContent(content2.Id); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); - ServiceContext.ContentService.UnPublish(content2); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); + ServiceContext.ContentService.Unpublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content3.Id); @@ -1428,12 +1464,14 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); content1.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content2.Id); @@ -1452,16 +1490,19 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); content1.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content1); var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content3 = CreateContent(content2.Id); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); - ServiceContext.ContentService.UnPublish(content2); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); + ServiceContext.ContentService.Unpublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content3.Id); @@ -1480,14 +1521,17 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); - ServiceContext.ContentService.UnPublish(content1); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); ResetEvents(); ServiceContext.ContentService.Move(content2, content3.Id); @@ -1506,18 +1550,22 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); - ServiceContext.ContentService.UnPublish(content1); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); var content4 = CreateContent(content3.Id); Assert.IsNotNull(content4); - ServiceContext.ContentService.PublishWithStatus(content4); - ServiceContext.ContentService.UnPublish(content3); + content4.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content4); + ServiceContext.ContentService.Unpublish(content3); ResetEvents(); ServiceContext.ContentService.Move(content2, content4.Id); @@ -1536,16 +1584,19 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); content2.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content2); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); ResetEvents(); ServiceContext.ContentService.Move(content2, content3.Id); @@ -1564,20 +1615,24 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); content2.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content2); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); - ServiceContext.ContentService.PublishWithStatus(content3); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); var content4 = CreateContent(content3.Id); Assert.IsNotNull(content4); - ServiceContext.ContentService.PublishWithStatus(content4); - ServiceContext.ContentService.UnPublish(content3); + content4.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content4); + ServiceContext.ContentService.Unpublish(content3); ResetEvents(); ServiceContext.ContentService.Move(content2, content4.Id); @@ -1596,11 +1651,13 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); - ServiceContext.ContentService.UnPublish(content1); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); @@ -1621,13 +1678,15 @@ namespace Umbraco.Tests.Integration { var content1 = CreateContent(); Assert.IsNotNull(content1); - ServiceContext.ContentService.PublishWithStatus(content1); + content1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content1); var content2 = CreateContent(content1.Id); Assert.IsNotNull(content2); - ServiceContext.ContentService.PublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); content2.Properties.First().SetValue("changed"); ServiceContext.ContentService.Save(content2); - ServiceContext.ContentService.UnPublish(content1); + ServiceContext.ContentService.Unpublish(content1); var content3 = CreateContent(); Assert.IsNotNull(content3); @@ -1703,7 +1762,8 @@ namespace Umbraco.Tests.Integration var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content2.Id); @@ -1756,11 +1816,13 @@ namespace Umbraco.Tests.Integration var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content3 = CreateContent(content2.Id); Assert.IsNotNull(content3); - ServiceContext.ContentService.SaveAndPublishWithStatus(content3); - ServiceContext.ContentService.UnPublish(content2); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); + ServiceContext.ContentService.Unpublish(content2); ResetEvents(); ServiceContext.ContentService.Move(content1, content3.Id); @@ -1813,7 +1875,8 @@ namespace Umbraco.Tests.Integration var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); ServiceContext.ContentService.Move(content1, content2.Id); @@ -1922,11 +1985,13 @@ namespace Umbraco.Tests.Integration var content2 = CreateContent(); Assert.IsNotNull(content2); - ServiceContext.ContentService.SaveAndPublishWithStatus(content2); + content2.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content2); var content3 = CreateContent(content2.Id); Assert.IsNotNull(content3); - ServiceContext.ContentService.SaveAndPublishWithStatus(content3); - ServiceContext.ContentService.UnPublish(content2); + content3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content3); + ServiceContext.ContentService.Unpublish(content2); ServiceContext.ContentService.Move(content1, content3.Id); @@ -2000,7 +2065,8 @@ namespace Umbraco.Tests.Integration { var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); var copy = ServiceContext.ContentService.Copy(content, Constants.System.Root, false); @@ -2019,7 +2085,8 @@ namespace Umbraco.Tests.Integration { var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); var content2 = CreateContent(); Assert.IsNotNull(content2); ServiceContext.ContentService.Move(content, content2.Id); @@ -2041,7 +2108,8 @@ namespace Umbraco.Tests.Integration { var content = CreateBranch(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); ResetEvents(); var copy = ServiceContext.ContentService.Copy(content, Constants.System.Root, false); @@ -2082,15 +2150,18 @@ namespace Umbraco.Tests.Integration { var content = CreateContent(); Assert.IsNotNull(content); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); var v1 = content.Version; content.Properties.First().SetValue("changed"); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); var v2 = content.Version; content.Properties.First().SetValue("again"); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); var v3 = content.Version; Console.WriteLine(v1); @@ -2122,11 +2193,13 @@ namespace Umbraco.Tests.Integration Assert.IsFalse(content.IsPropertyDirty("Published")); Assert.IsFalse(content.WasPropertyDirty("Published")); - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.IsFalse(content.IsPropertyDirty("Published")); Assert.IsTrue(content.WasPropertyDirty("Published")); // has just been published - ServiceContext.ContentService.PublishWithStatus(content); + content.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(content); Assert.IsFalse(content.IsPropertyDirty("Published")); Assert.IsFalse(content.WasPropertyDirty("Published")); // was published already } diff --git a/src/Umbraco.Tests/Integration/GetCultureTests.cs b/src/Umbraco.Tests/Integration/GetCultureTests.cs index ed9be5c9ed..dd86b44af8 100644 --- a/src/Umbraco.Tests/Integration/GetCultureTests.cs +++ b/src/Umbraco.Tests/Integration/GetCultureTests.cs @@ -28,10 +28,10 @@ namespace Umbraco.Tests.Integration contentTypeService.Save(contentType); var contentService = ServiceContext.ContentService; - var c1 = contentService.CreateContentWithIdentity("content", -1, "umbBlah"); - var c2 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); - var c3 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); - var c4 = contentService.CreateContentWithIdentity("content", c3, "umbBlah"); + var c1 = contentService.CreateAndSave("content", -1, "umbBlah"); + var c2 = contentService.CreateAndSave("content", c1, "umbBlah"); + var c3 = contentService.CreateAndSave("content", c1, "umbBlah"); + var c4 = contentService.CreateAndSave("content", c3, "umbBlah"); foreach (var l in ServiceContext.LocalizationService.GetAllLanguages().Where(x => x.CultureName != "en-US").ToArray()) ServiceContext.LocalizationService.Delete(l); @@ -76,10 +76,10 @@ namespace Umbraco.Tests.Integration contentTypeService.Save(contentType); var contentService = ServiceContext.ContentService; - var c1 = contentService.CreateContentWithIdentity("content", -1, "umbBlah"); - var c2 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); - var c3 = contentService.CreateContentWithIdentity("content", c1, "umbBlah"); - var c4 = contentService.CreateContentWithIdentity("content", c3, "umbBlah"); + var c1 = contentService.CreateAndSave("content", -1, "umbBlah"); + var c2 = contentService.CreateAndSave("content", c1, "umbBlah"); + var c3 = contentService.CreateAndSave("content", c1, "umbBlah"); + var c4 = contentService.CreateAndSave("content", c3, "umbBlah"); foreach (var l in ServiceContext.LocalizationService.GetAllLanguages().Where(x => x.CultureName != "en-US").ToArray()) ServiceContext.LocalizationService.Delete(l); diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 7f66de5a68..93068b5c5a 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Models content.Key = new Guid("29181B97-CB8F-403F-86DE-5FEB497F4800"); // Act - var clone = content.Clone(); + var clone = content.DeepCloneWithResetIdentities(); // Assert Assert.AreNotSame(clone, content); diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs new file mode 100644 index 0000000000..51f45cd1bd --- /dev/null +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -0,0 +1,266 @@ +using System; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Models +{ + // fixme - need to reorg our tests! + // fixme - test IsDirty on properties + + [TestFixture] + public class VariationTests + { + [SetUp] + public void SetUp() + { + // annoying, but content type wants short string helper ;( + SettingsForTests.Reset(); + } + + [Test] + public void PropertyTests() + { + var propertyType = new PropertyType("editor", DataTypeDatabaseType.Nvarchar) { Alias = "prop" }; + var prop = new Property(propertyType); + + // can set value + // and get edited and published value + // because non-publishing + prop.SetValue("a"); + Assert.AreEqual("a", prop.GetValue()); + Assert.AreEqual("a", prop.GetValue(published: true)); + + // illegal, 'cos non-publishing + Assert.Throws(() => prop.PublishValue()); + + // change + propertyType.IsPublishing = true; + + // can get value + // and now published value is null + Assert.AreEqual("a", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + + // cannot set non-supported variation value + Assert.Throws(() => prop.SetValue("x", 1)); + Assert.IsNull(prop.GetValue(1)); + + // can publish value + // and get edited and published values + prop.PublishValue(); + Assert.AreEqual("a", prop.GetValue()); + Assert.AreEqual("a", prop.GetValue(published: true)); + + // can set value + // and get edited and published values + prop.SetValue("b"); + Assert.AreEqual("b", prop.GetValue()); + Assert.AreEqual("a", prop.GetValue(published: true)); + + // can clear value + prop.ClearPublishedValue(); + Assert.AreEqual("b", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + + // change + propertyType.Variations |= ContentVariation.CultureNeutral; + + // can set value + // and get values + prop.SetValue("c", 1); + Assert.AreEqual("b", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.IsNull(prop.GetValue(1, published: true)); + + // can publish value + // and get edited and published values + prop.PublishValue(1); + Assert.AreEqual("b", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.AreEqual("c", prop.GetValue(1, published: true)); + + // can clear all + prop.ClearPublishedAllValues(); + Assert.AreEqual("b", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.IsNull(prop.GetValue(1, published: true)); + + // can publish all + prop.PublishAllValues(); + Assert.AreEqual("b", prop.GetValue()); + Assert.AreEqual("b", prop.GetValue(published: true)); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.AreEqual("c", prop.GetValue(1, published: true)); + + // same for culture + prop.ClearPublishedCultureValues(1); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.IsNull(prop.GetValue(1, published: true)); + prop.PublishCultureValues(1); + Assert.AreEqual("c", prop.GetValue(1)); + Assert.AreEqual("c", prop.GetValue(1, published: true)); + + prop.ClearPublishedCultureValues(); + Assert.AreEqual("b", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + prop.PublishCultureValues(); + Assert.AreEqual("b", prop.GetValue()); + Assert.AreEqual("b", prop.GetValue(published: true)); + } + + [Test] + public void ContentTests() + { + var propertyType = new PropertyType("editor", DataTypeDatabaseType.Nvarchar) { Alias = "prop" }; + var contentType = new ContentType(-1) { Alias = "contentType" }; + contentType.AddPropertyType(propertyType); + + var content = new Content("content", -1, contentType) { Id = 1, VersionPk = 1 }; + + // can set value + // and get edited value, published is null + // because publishing + content.SetValue("prop", "a"); + Assert.AreEqual("a", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + + // cannot set non-supported variation value + Assert.Throws(() => content.SetValue("prop", "x", 1)); + Assert.IsNull(content.GetValue("prop", 1)); + + // can publish value + // and get edited and published values + content.PublishValues(); + Assert.AreEqual("a", content.GetValue("prop")); + Assert.AreEqual("a", content.GetValue("prop", published: true)); + + // can set value + // and get edited and published values + content.SetValue("prop", "b"); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.AreEqual("a", content.GetValue("prop", published: true)); + + // can clear value + content.ClearPublishedValues(); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + + // change + propertyType.Variations |= ContentVariation.CultureNeutral; + + // can set value + // and get values + content.SetValue("prop", "c", 1); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.IsNull(content.GetValue("prop", 1, published: true)); + + // can publish value + // and get edited and published values + content.PublishValues(1); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.AreEqual("c", content.GetValue("prop", 1, published: true)); + + // can clear all + content.ClearAllPublishedValues(); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.IsNull(content.GetValue("prop", 1, published: true)); + + // can publish all + content.PublishAllValues(); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.AreEqual("b", content.GetValue("prop", published: true)); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.AreEqual("c", content.GetValue("prop", 1, published: true)); + + // same for culture + content.ClearCulturePublishedValues(1); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.IsNull(content.GetValue("prop", 1, published: true)); + content.PublishCultureValues(1); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.AreEqual("c", content.GetValue("prop", 1, published: true)); + + content.ClearCulturePublishedValues(); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + content.PublishCultureValues(); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.AreEqual("b", content.GetValue("prop", published: true)); + + var other = new Content("other", -1, contentType) { Id = 2, VersionPk = 1 }; + other.SetValue("prop", "o"); + other.SetValue("prop", "o1", 1); + + // can copy other's edited value + content.CopyAllValues(other); + Assert.AreEqual("o", content.GetValue("prop")); + Assert.AreEqual("b", content.GetValue("prop", published: true)); + Assert.AreEqual("o1", content.GetValue("prop", 1)); + Assert.AreEqual("c", content.GetValue("prop", 1, published: true)); + + // can copy self's published value + content.CopyAllValues(content); + Assert.AreEqual("b", content.GetValue("prop")); + Assert.AreEqual("b", content.GetValue("prop", published: true)); + Assert.AreEqual("c", content.GetValue("prop", 1)); + Assert.AreEqual("c", content.GetValue("prop", 1, published: true)); + } + + [Test] + public void IsDirtyTests() + { + var propertyType = new PropertyType("editor", DataTypeDatabaseType.Nvarchar) { Alias = "prop" }; + var prop = new Property(propertyType); + var contentType = new ContentType(-1) { Alias = "contentType" }; + contentType.AddPropertyType(propertyType); + + var content = new Content("content", -1, contentType) { Id = 1, VersionPk = 1 }; + + prop.SetValue("a"); + Assert.AreEqual("a", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + + Assert.IsTrue(prop.IsDirty()); + + content.SetValue("prop", "a"); + Assert.AreEqual("a", content.GetValue("prop")); + Assert.IsNull(content.GetValue("prop", published: true)); + + Assert.IsTrue(content.IsDirty()); + Assert.IsTrue(content.IsAnyUserPropertyDirty()); + // how can we tell which variation was dirty? + } + + [Test] + public void ValidationTests() + { + var propertyType = new PropertyType("editor", DataTypeDatabaseType.Nvarchar) { Alias = "prop", IsPublishing = true }; + var prop = new Property(propertyType); + + prop.SetValue("a"); + Assert.AreEqual("a", prop.GetValue()); + Assert.IsNull(prop.GetValue(published: true)); + + Assert.IsTrue(prop.IsValid()); + + propertyType.Mandatory = true; + Assert.IsTrue(prop.IsValid()); + + prop.SetValue(null); + Assert.IsFalse(prop.IsValid()); + + // cannot publish, because invalid + Assert.Throws(() => prop.PublishValue()); + } + } +} diff --git a/src/Umbraco.Tests/Persistence/NPocoTests/PetaPocoCachesTest.cs b/src/Umbraco.Tests/Persistence/NPocoTests/PetaPocoCachesTest.cs index 2e2bb7b56c..e761c6abec 100644 --- a/src/Umbraco.Tests/Persistence/NPocoTests/PetaPocoCachesTest.cs +++ b/src/Umbraco.Tests/Persistence/NPocoTests/PetaPocoCachesTest.cs @@ -116,7 +116,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests contentService.CountChildren(id3); - contentService.Count(contentTypeAlias: alias1); + contentService.Count(documentTypeAlias: alias1); contentService.Count(); @@ -144,7 +144,7 @@ namespace Umbraco.Tests.Persistence.NPocoTests Path = "-1," + id1 }); - contentService.GetByVersion(Guid.NewGuid()); + contentService.GetVersion(Guid.NewGuid()); } private void CreateStuff(out int id1, out int id2, out int id3, out string alias) @@ -156,26 +156,26 @@ namespace Umbraco.Tests.Persistence.NPocoTests for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); + contentService.CreateAndSave("Test", -1, "umbTextpage", 0); } var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType(ctAlias, "test Doc Type"); contentTypeService.Save(contentType); for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); + contentService.CreateAndSave("Test", -1, ctAlias, 0); } - var parent = contentService.CreateContentWithIdentity("Test", -1, ctAlias, 0); + var parent = contentService.CreateAndSave("Test", -1, ctAlias, 0); id1 = parent.Id; for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", parent, ctAlias); + contentService.CreateAndSave("Test", parent, ctAlias); } IContent current = parent; for (int i = 0; i < 20; i++) { - current = contentService.CreateContentWithIdentity("Test", current, ctAlias); + current = contentService.CreateAndSave("Test", current, ctAlias); } contentType = MockedContentTypes.CreateSimpleContentType("umbMandatory" + Guid.NewGuid().ToString("N"), "Mandatory Doc Type", true); contentType.PropertyGroups.First().PropertyTypes.Add( @@ -186,12 +186,14 @@ namespace Umbraco.Tests.Persistence.NPocoTests contentTypeService.Save(contentType); var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); id2 = content1.Id; var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); id3 = content2.Id; contentService.MoveToRecycleBin(content1); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 6cee65363c..e2dde45b46 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -155,7 +155,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(true, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -172,7 +171,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(true, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // unpublish = no impact on versions ((Content) content1).PublishedState = PublishedState.Unpublishing; @@ -188,7 +186,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(false, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -204,7 +201,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(false, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // publish = version ((Content) content1).PublishValues(); @@ -221,7 +217,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(true, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // change something // save = update the current (draft) version @@ -240,7 +235,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(true, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // publish = new version content1.Name = "name-4"; @@ -259,7 +253,6 @@ namespace Umbraco.Tests.Persistence.Repositories // misc checks Assert.AreEqual(true, unitOfWork.Database.ExecuteScalar("SELECT published FROM uDocument WHERE nodeId=@id", new { id = content1.Id })); - Console.WriteLine(unitOfWork.Database.ExecuteScalar("SELECT updateDate FROM uContent WHERE nodeId=@id", new { id = content1.Id })); // all versions var allVersions = repository.GetAllVersions(content1.Id).ToArray(); @@ -274,7 +267,7 @@ namespace Umbraco.Tests.Persistence.Repositories } // get older version - var content = repository.GetByVersion(versions[versions.Count - 4]); + var content = repository.GetVersion(versions[versions.Count - 4]); Assert.IsNotNull(content.Version); Assert.AreEqual(versions[versions.Count - 4], content.Version); Assert.AreEqual("name-4", content1.Name); @@ -657,8 +650,7 @@ namespace Umbraco.Tests.Persistence.Repositories // publish them all foreach (var content in result) { - ((Content) content).PublishAllValues(); - ((Content) content).PublishedState = PublishedState.Publishing; + content.PublishValues(); repository.AddOrUpdate(content); } unitOfWork.Flush(); diff --git a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs index fee20afc18..493a21855d 100644 --- a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs +++ b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Publishing var result = ((ContentService)ServiceContext.ContentService).StrategyPublishWithChildren(uow, listToPublish, null, 0, evtMsgs, true); Assert.AreEqual(listToPublish.Count() - 2, result.Count(x => x.Success)); - Assert.IsTrue(result.Where(x => x.Success).Select(x => x.Result.ContentItem.Id) + Assert.IsTrue(result.Where(x => x.Success).Select(x => x.Content.Id) .ContainsAll(listToPublish.Where(x => x.Name != "Invalid Content" && x.Name != "Sub Sub Sub").Select(x => x.Id))); } @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Publishing var result = ((ContentService)ServiceContext.ContentService).StrategyPublishWithChildren(uow, listToPublish, null, 0, evtMsgs); Assert.AreEqual(listToPublish.Count() - 2, result.Count(x => x.Success)); - Assert.IsTrue(result.Where(x => x.Success).Select(x => x.Result.ContentItem.Id) + Assert.IsTrue(result.Where(x => x.Success).Select(x => x.Content.Id) .ContainsAll(listToPublish.Where(x => x.Name != "Text Page 2" && x.Name != "Text Page 3").Select(x => x.Id))); } @@ -113,12 +113,12 @@ namespace Umbraco.Tests.Publishing //publish root and nodes at it's children level var uow = TestObjects.GetUnitOfWorkMock(); var result1 = ((ContentService)ServiceContext.ContentService).StrategyPublish(uow, _homePage, false, 0, evtMsgs); - Assert.IsTrue(result1); + Assert.IsTrue(result1.Success); Assert.IsTrue(_homePage.Published); foreach (var c in ServiceContext.ContentService.GetChildren(_homePage.Id)) { var r = ((ContentService)ServiceContext.ContentService).StrategyPublish(uow, c, false, 0, evtMsgs); - Assert.IsTrue(r); + Assert.IsTrue(r.Success); Assert.IsTrue(c.Published); } @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Publishing //all of them will be SuccessAlreadyPublished unless the unpublished one gets included, in that case //we'll have a 'Success' result which we don't want. // NOTE - not true, we'll have Success for _homePage because we DO want to publish it - Assert.AreEqual(1, result.Count(x => x.Result.StatusType == PublishStatusType.Success)); + Assert.AreEqual(1, result.Count(x => x.Result == PublishResultType.Success)); } [Test] @@ -143,14 +143,14 @@ namespace Umbraco.Tests.Publishing //publish root and nodes at it's children level var uow = TestObjects.GetUnitOfWorkMock(); var result1 = ((ContentService)ServiceContext.ContentService).StrategyPublish(uow, _homePage, false, 0, evtMsgs); - Assert.IsTrue(result1); + Assert.IsTrue(result1.Success); Assert.IsTrue(_homePage.Published); //NOTE (MCH) This isn't persisted, so not really a good test as it will look like the result should be something else. foreach (var c in ServiceContext.ContentService.GetChildren(_homePage.Id)) { var r = ((ContentService)ServiceContext.ContentService).StrategyPublish(uow, c, false, 0, evtMsgs); - Assert.IsTrue(r); + Assert.IsTrue(r.Success); Assert.IsTrue(c.Published); } @@ -168,10 +168,10 @@ namespace Umbraco.Tests.Publishing .Concat(ServiceContext.ContentService.GetDescendants(_homePage)); var result = ((ContentService)ServiceContext.ContentService).StrategyPublishWithChildren(uow, contents, null, 0, evtMsgs, true); - Assert.AreEqual(4, result.Count(x => x.Result.StatusType == PublishStatusType.Success)); - Assert.AreEqual(0, result.Count(x => x.Result.StatusType == PublishStatusType.SuccessAlreadyPublished)); - Assert.IsTrue(result.First(x => x.Result.StatusType == PublishStatusType.Success).Success); - Assert.IsTrue(result.First(x => x.Result.StatusType == PublishStatusType.Success).Result.ContentItem.Published); + Assert.AreEqual(4, result.Count(x => x.Result == PublishResultType.Success)); + Assert.AreEqual(0, result.Count(x => x.Result == PublishResultType.SuccessAlready)); + Assert.IsTrue(result.First(x => x.Result == PublishResultType.Success).Success); + Assert.IsTrue(result.First(x => x.Result == PublishResultType.Success).Content.Published); } [NUnit.Framework.Ignore("fixme - ignored test")] diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 406a3e1ccb..bcb7178799 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -135,7 +135,8 @@ namespace Umbraco.Tests.Scoping using (var scope = ScopeProvider.CreateScope()) { - Current.Services.ContentService.SaveAndPublishWithStatus(item); + item.PublishValues(); + Current.Services.ContentService.SaveAndPublish(item); scope.Complete(); } @@ -149,7 +150,8 @@ namespace Umbraco.Tests.Scoping using (var scope = ScopeProvider.CreateScope()) { item.Name = "changed"; - Current.Services.ContentService.SaveAndPublishWithStatus(item); + item.PublishValues(); + Current.Services.ContentService.SaveAndPublish(item); if (complete) scope.Complete(); diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 5ec5fcb954..bc5801182c 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -122,9 +122,11 @@ namespace Umbraco.Tests.Scoping using (var scope = ScopeProvider.CreateScope()) { - Current.Services.ContentService.SaveAndPublishWithStatus(item); // should create an xml clone + item.PublishValues(); + Current.Services.ContentService.SaveAndPublish(item); // should create an xml clone item.Name = "changed"; - Current.Services.ContentService.SaveAndPublishWithStatus(item); // should re-use the xml clone + item.PublishValues(); + Current.Services.ContentService.SaveAndPublish(item); // should re-use the xml clone // this should never change Assert.AreEqual(beforeOuterXml, beforeXml.OuterXml); @@ -145,7 +147,7 @@ namespace Umbraco.Tests.Scoping // note // this means that, as long as ppl don't create scopes, they'll see their - // changes right after SaveAndPublishWithStatus, but if they create scopes, + // changes right after SaveAndPublish, but if they create scopes, // they will have to wail until the scope is completed, ie wait until the // events trigger, to use eg GetUrl etc @@ -227,12 +229,14 @@ namespace Umbraco.Tests.Scoping using (var scope = ScopeProvider.CreateScope()) { - Current.Services.ContentService.SaveAndPublishWithStatus(item); + item.PublishValues(); + Current.Services.ContentService.SaveAndPublish(item); for (var i = 0; i < count; i++) { var temp = new Content("content_" + i, -1, contentType); - Current.Services.ContentService.SaveAndPublishWithStatus(temp); + temp.PublishValues(); + Current.Services.ContentService.SaveAndPublish(temp); ids[i] = temp.Id; } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index f63e9d2a84..b99a4ebf88 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -178,14 +178,17 @@ namespace Umbraco.Tests.Services { var contentService = ServiceContext.ContentService; var root = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 1); - Assert.IsTrue(contentService.PublishWithStatus(root).Success); - var content = contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); - Assert.IsTrue(contentService.PublishWithStatus(content).Success); + root.PublishValues(); + Assert.IsTrue(contentService.SaveAndPublish(root).Success); + var content = contentService.CreateAndSave("Test", -1, "umbTextpage", 0); + content.PublishValues(); + Assert.IsTrue(contentService.SaveAndPublish(content).Success); var hierarchy = CreateContentHierarchy().OrderBy(x => x.Level).ToArray(); contentService.Save(hierarchy, 0); foreach (var c in hierarchy) { - Assert.IsTrue(contentService.PublishWithStatus(c).Success); + c.PublishValues(); + Assert.IsTrue(contentService.SaveAndPublish(c).Success); } //now make the data corrupted :/ @@ -200,7 +203,7 @@ namespace Umbraco.Tests.Services // here we get all descendants by the path of the node being moved to bin, and unpublish all of them. // since the path is invalid, there's logic in here to fix that if it's possible and re-persist the entity. - var moveResult = ServiceContext.ContentService.WithResult().MoveToRecycleBin(content); + var moveResult = ServiceContext.ContentService.MoveToRecycleBin(content); Assert.IsTrue(moveResult.Success); @@ -223,7 +226,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act - var content = contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); + var content = contentService.CreateAndSave("Test", -1, "umbTextpage", 0); content.ReleaseDate = DateTime.Now.AddHours(2); contentService.Save(content, 0); @@ -234,7 +237,8 @@ namespace Umbraco.Tests.Services // Assert - Assert.IsTrue(contentService.PublishWithStatus(content).Success); + content.PublishValues(); + Assert.IsTrue(contentService.SaveAndPublish(content).Success); } [Test] @@ -244,11 +248,12 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act - var content = contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); + var content = contentService.CreateAndSave("Test", -1, "umbTextpage", 0); for (var i = 0; i < 20; i++) { content.SetValue("bodyText", "hello world " + Guid.NewGuid()); - contentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); } // Assert @@ -269,7 +274,7 @@ namespace Umbraco.Tests.Services var results = new List(); for (var i = 0; i < 20; i++) { - results.Add(contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0)); + results.Add(contentService.CreateAndSave("Test", -1, "umbTextpage", 0)); } var sortedGet = contentService.GetByIds(new[] {results[10].Id, results[5].Id, results[12].Id}).ToArray(); @@ -289,7 +294,7 @@ namespace Umbraco.Tests.Services // Act for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", -1, "umbTextpage", 0); + contentService.CreateAndSave("Test", -1, "umbTextpage", 0); } // Assert @@ -308,11 +313,11 @@ namespace Umbraco.Tests.Services // Act for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0); + contentService.CreateAndSave("Test", -1, "umbBlah", 0); } // Assert - Assert.AreEqual(20, contentService.Count(contentTypeAlias: "umbBlah")); + Assert.AreEqual(20, contentService.Count(documentTypeAlias: "umbBlah")); } [Test] @@ -323,12 +328,12 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type"); contentTypeService.Save(contentType); - var parent = contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0); + var parent = contentService.CreateAndSave("Test", -1, "umbBlah", 0); // Act for (int i = 0; i < 20; i++) { - contentService.CreateContentWithIdentity("Test", parent, "umbBlah"); + contentService.CreateAndSave("Test", parent, "umbBlah"); } // Assert @@ -343,13 +348,13 @@ namespace Umbraco.Tests.Services var contentTypeService = ServiceContext.ContentTypeService; var contentType = MockedContentTypes.CreateSimpleContentType("umbBlah", "test Doc Type"); contentTypeService.Save(contentType); - var parent = contentService.CreateContentWithIdentity("Test", -1, "umbBlah", 0); + var parent = contentService.CreateAndSave("Test", -1, "umbBlah", 0); // Act IContent current = parent; for (int i = 0; i < 20; i++) { - current = contentService.CreateContentWithIdentity("Test", current, "umbBlah"); + current = contentService.CreateAndSave("Test", current, "umbBlah"); } // Assert @@ -386,11 +391,13 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags", "plus" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); // verify var tags = tagService.GetTagsForEntity(content1.Id); @@ -425,7 +432,8 @@ namespace Umbraco.Tests.Services allTags = tagService.GetAllContentTags(); Assert.AreEqual(4, allTags.Count()); - contentService.PublishWithStatus(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); Assert.IsTrue(content1.Published); @@ -454,11 +462,13 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags", "bam" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); // verify var tags = tagService.GetTagsForEntity(content1.Id); @@ -466,8 +476,8 @@ namespace Umbraco.Tests.Services var allTags = tagService.GetAllContentTags(); Assert.AreEqual(5, allTags.Count()); - contentService.UnPublish(content1); - contentService.UnPublish(content2); + contentService.Unpublish(content1); + contentService.Unpublish(content2); // fixme - killing the rest of this test // this is not working consistently even in 7 when unpublishing a branch @@ -493,8 +503,10 @@ namespace Umbraco.Tests.Services allTags = tagService.GetAllContentTags(); Assert.AreEqual(0, allTags.Count()); - contentService.PublishWithStatus(content1); - contentService.PublishWithStatus(content2); + content1.PublishValues(); + contentService.SaveAndPublish(content1); + content2.PublishValues(); + contentService.SaveAndPublish(content2); // tags are back tags = tagService.GetTagsForEntity(content1.Id); @@ -522,11 +534,13 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags", "plus" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", content1.Id); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); // verify var tags = tagService.GetTagsForEntity(content1.Id); @@ -560,7 +574,8 @@ namespace Umbraco.Tests.Services allTags = tagService.GetAllContentTags(); Assert.AreEqual(0, allTags.Count()); - contentService.PublishWithStatus(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); Assert.IsTrue(content1.Published); @@ -597,14 +612,16 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags", "bam" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); - contentService.UnPublish(content1); - contentService.UnPublish(content2); + contentService.Unpublish(content1); + contentService.Unpublish(content2); // fixme - killing the rest of this test // this is not working consistently even in 7 when unpublishing a branch @@ -616,7 +633,8 @@ namespace Umbraco.Tests.Services var allTags = tagService.GetAllContentTags(); Assert.AreEqual(0, allTags.Count()); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); tags = tagService.GetTagsForEntity(content2.Id); Assert.AreEqual(4, tags.Count()); @@ -641,13 +659,15 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "hello", "world", "some", "tags", "bam" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", content1); content2.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); - contentService.UnPublish(content1); + contentService.Unpublish(content1); var tags = tagService.GetTagsForEntity(content1.Id); Assert.AreEqual(0, tags.Count()); @@ -660,7 +680,8 @@ namespace Umbraco.Tests.Services var allTags = tagService.GetAllContentTags(); Assert.AreEqual(0, allTags.Count()); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); tags = tagService.GetTagsForEntity(content2.Id); Assert.AreEqual(4, tags.Count()); @@ -703,7 +724,7 @@ namespace Umbraco.Tests.Services contentService.Save(child2); // Act - contentService.PublishWithChildrenWithStatus(content, includeUnpublished: true); + contentService.PublishWithChildren(content, includeUnpublished: true); // Assert var propertyTypeId = contentType.PropertyTypes.Single(x => x.Alias == "tags").Id; @@ -740,7 +761,8 @@ namespace Umbraco.Tests.Services // create a content with tags and publish var content = MockedContent.CreateSimpleContent(contentType, "Tagged content", -1); content.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // edit tags and save content.SetTags("tags", new[] { "another", "world" }, false); @@ -779,7 +801,8 @@ namespace Umbraco.Tests.Services // Act content.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.Publish(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Assert Assert.AreEqual(4, content.Properties["tags"].GetValue().ToString().Split(',').Distinct().Count()); @@ -809,11 +832,13 @@ namespace Umbraco.Tests.Services contentTypeService.Save(contentType); var content = MockedContent.CreateSimpleContent(contentType, "Tagged content", -1); content.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.PublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Act content.SetTags("tags", new[] { "another", "world" }, false); - contentService.PublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Assert Assert.AreEqual(5, content.Properties["tags"].GetValue().ToString().Split(',').Distinct().Count()); @@ -843,11 +868,13 @@ namespace Umbraco.Tests.Services contentTypeService.Save(contentType); var content = MockedContent.CreateSimpleContent(contentType, "Tagged content", -1); content.SetTags("tags", new[] { "hello", "world", "some", "tags" }, true); - contentService.PublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Act content.RemoveTags("tags", new[] { "some", "world" }); - contentService.PublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Assert Assert.AreEqual(2, content.Properties["tags"].GetValue().ToString().Split(',').Distinct().Count()); @@ -869,7 +896,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act - var content = contentService.CreateContent("Test", -1, "umbTextpage", 0); + var content = contentService.Create("Test", -1, "umbTextpage", 0); // Assert Assert.That(content, Is.Not.Null); @@ -883,7 +910,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act - var content = contentService.CreateContent("Test", -1, "umbTextpage", 0); + var content = contentService.Create("Test", -1, "umbTextpage", 0); // Assert Assert.That(content, Is.Not.Null); @@ -897,7 +924,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act - var content = contentService.CreateContent("Test", -1, "umbTextpage"); + var content = contentService.Create("Test", -1, "umbTextpage"); // Assert Assert.That(content, Is.Not.Null); @@ -933,7 +960,7 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; // Act & Assert - Assert.Throws(() => contentService.CreateContent("Test", -1, "umbAliasDoesntExist")); + Assert.Throws(() => contentService.Create("Test", -1, "umbAliasDoesntExist")); } [Test] @@ -1029,7 +1056,8 @@ namespace Umbraco.Tests.Services var parent = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 2); Assert.IsFalse(parent.Published); - ServiceContext.ContentService.Publish(parent); // publishing parent, so Text Page 2 can be updated. + parent.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(parent); // publishing parent, so Text Page 2 can be updated. var content = contentService.GetById(NodeDto.NodeIdSeed + 4); Assert.IsFalse(content.Published); @@ -1041,14 +1069,16 @@ namespace Umbraco.Tests.Services content.Name = "Text Page 2 Updated"; content.SetValue("author", "Jane Doe"); - contentService.SaveAndPublishWithStatus(content); // publishes the current version, creates a version + content.PublishValues(); + contentService.SaveAndPublish(content); // publishes the current version, creates a version var version2 = content.Version; Console.WriteLine($"2 e={((Content) content).VersionPk} p={((Content) content).PublishedVersionPk}"); content.Name = "Text Page 2 ReUpdated"; content.SetValue("author", "Bob Hope"); - contentService.SaveAndPublishWithStatus(content); // publishes again, creates a version + content.PublishValues(); + contentService.SaveAndPublish(content); // publishes again, creates a version var version3 = content.Version; Console.WriteLine($"3 e={((Content) content).VersionPk} p={((Content) content).PublishedVersionPk}"); @@ -1114,10 +1144,12 @@ namespace Umbraco.Tests.Services // Arrange var contentService = ServiceContext.ContentService; var root = contentService.GetById(NodeDto.NodeIdSeed + 2); - contentService.SaveAndPublishWithStatus(root); + root.PublishValues(); + contentService.SaveAndPublish(root); var content = contentService.GetById(NodeDto.NodeIdSeed + 4); content.ExpireDate = DateTime.Now.AddSeconds(1); - contentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); // Act Thread.Sleep(new TimeSpan(0, 0, 0, 2)); @@ -1166,7 +1198,8 @@ namespace Umbraco.Tests.Services // Arrange var contentService = ServiceContext.ContentService; var content = contentService.GetById(NodeDto.NodeIdSeed + 2); - bool published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); var provider = TestObjects.GetScopeUnitOfWorkProvider(Logger); using (var uow = provider.CreateUnitOfWork()) @@ -1175,11 +1208,11 @@ namespace Umbraco.Tests.Services } // Act - bool unpublished = contentService.UnPublish(content, 0); + var unpublished = contentService.Unpublish(content, 0); // Assert - Assert.That(published, Is.True); - Assert.That(unpublished, Is.True); + Assert.That(published.Success, Is.True); + Assert.That(unpublished.Success, Is.True); Assert.That(content.Published, Is.False); using (var uow = provider.CreateUnitOfWork()) @@ -1196,10 +1229,11 @@ namespace Umbraco.Tests.Services var content = contentService.GetById(NodeDto.NodeIdSeed + 2); // Act - bool published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert - Assert.That(published, Is.True); + Assert.That(published.Success, Is.True); Assert.That(content.Published, Is.True); } @@ -1208,14 +1242,15 @@ namespace Umbraco.Tests.Services { // Arrange var contentService = ServiceContext.ContentService; - var parent = contentService.CreateContent("parent", -1, "umbTextpage"); - contentService.SaveAndPublishWithStatus(parent); - var content = contentService.CreateContent("child", parent, "umbTextpage"); + var parent = contentService.Create("parent", -1, "umbTextpage"); + parent.PublishValues(); + contentService.SaveAndPublish(parent); + var content = contentService.Create("child", parent, "umbTextpage"); contentService.Save(content); - Assert.IsTrue(contentService.IsPublishable(content)); - contentService.UnPublish(parent); - Assert.IsFalse(contentService.IsPublishable(content)); + Assert.IsTrue(contentService.IsPathPublishable(content)); + contentService.Unpublish(parent); + Assert.IsFalse(contentService.IsPathPublishable(content)); } [Test] @@ -1234,7 +1269,8 @@ namespace Umbraco.Tests.Services Assert.AreEqual("Home", content.Name); content.Name = "foo"; - var published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); Assert.That(published, Is.True); Assert.That(content.Published, Is.True); @@ -1273,13 +1309,15 @@ namespace Umbraco.Tests.Services // Act var parent = contentService.GetById(NodeDto.NodeIdSeed + 2); - bool parentPublished = contentService.Publish(parent, 0); - bool published = contentService.Publish(content, 0); + parent.PublishValues(); + var parentPublished = contentService.SaveAndPublish(parent, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert - Assert.That(parentPublished, Is.True); - Assert.That(published, Is.False); - Assert.That(content.Validate(), Is.False); + Assert.That(parentPublished.Success, Is.True); + Assert.That(published.Success, Is.False); + Assert.IsNotEmpty(content.Validate()); Assert.That(parent.Published, Is.True); Assert.That(content.Published, Is.False); } @@ -1292,11 +1330,11 @@ namespace Umbraco.Tests.Services var content = contentService.GetById(NodeDto.NodeIdSeed + 2); // Act - bool published = contentService.PublishWithChildren(content, 0); + var published = contentService.PublishWithChildren(content, 0); var children = contentService.GetChildren(NodeDto.NodeIdSeed + 2); // Assert - Assert.That(published, Is.True);//Nothing was cancelled, so should be true + Assert.That(published.All(x => x.Success), Is.True);//Nothing was cancelled, so should be true Assert.That(content.Published, Is.True);//No restrictions, so should be published Assert.That(children.First(x => x.Id == NodeDto.NodeIdSeed + 3).Published, Is.True);//Released 5 mins ago, so should be published } @@ -1311,14 +1349,16 @@ namespace Umbraco.Tests.Services contentService.Save(content); var parent = contentService.GetById(NodeDto.NodeIdSeed + 2); - bool parentPublished = contentService.Publish(parent, 0);//Publish root Home node to enable publishing of 'NodeDto.NodeIdSeed + 3' + parent.PublishValues(); + var parentPublished = contentService.SaveAndPublish(parent, 0);//Publish root Home node to enable publishing of 'NodeDto.NodeIdSeed + 3' // Act - bool published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert - Assert.That(parentPublished, Is.True); - Assert.That(published, Is.False); + Assert.That(parentPublished.Success, Is.True); + Assert.That(published.Success, Is.False); Assert.That(content.Published, Is.False); } @@ -1332,14 +1372,16 @@ namespace Umbraco.Tests.Services contentService.Save(content, 0); var parent = contentService.GetById(NodeDto.NodeIdSeed + 2); - bool parentPublished = contentService.Publish(parent, 0);//Publish root Home node to enable publishing of 'NodeDto.NodeIdSeed + 3' + parent.PublishValues(); + var parentPublished = contentService.SaveAndPublish(parent, 0);//Publish root Home node to enable publishing of 'NodeDto.NodeIdSeed + 3' // Act - bool published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert - Assert.That(parentPublished, Is.True); - Assert.That(published, Is.False); + Assert.That(parentPublished.Success, Is.True); + Assert.That(published.Success, Is.False); Assert.That(content.Published, Is.False); } @@ -1348,14 +1390,14 @@ namespace Umbraco.Tests.Services { // Arrange var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Subpage with Unpublisehed Parent", NodeDto.NodeIdSeed + 2, "umbTextpage", 0); + var content = contentService.Create("Subpage with Unpublisehed Parent", NodeDto.NodeIdSeed + 2, "umbTextpage", 0); contentService.Save(content, 0); // Act - bool published = contentService.PublishWithChildren(content, 0); + var published = contentService.PublishWithChildren(content, 0); // Assert - Assert.That(published, Is.False); + Assert.That(published.All(x => x.Success), Is.False); Assert.That(content.Published, Is.False); } @@ -1367,10 +1409,11 @@ namespace Umbraco.Tests.Services var content = contentService.GetById(NodeDto.NodeIdSeed + 5); // Act - bool published = contentService.Publish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert - Assert.That(published, Is.False); + Assert.That(published.Success, Is.False); Assert.That(content.Published, Is.False); Assert.That(content.Trashed, Is.True); } @@ -1380,16 +1423,17 @@ namespace Umbraco.Tests.Services { // Arrange var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Home US", - 1, "umbTextpage", 0); + var content = contentService.Create("Home US", - 1, "umbTextpage", 0); content.SetValue("author", "Barack Obama"); // Act - bool published = contentService.SaveAndPublish(content, 0); + content.PublishValues(); + var published = contentService.SaveAndPublish(content, 0); // Assert Assert.That(content.HasIdentity, Is.True); Assert.That(content.Published, Is.True); - Assert.That(published, Is.True); + Assert.IsTrue(published.Success); } /// @@ -1404,16 +1448,18 @@ namespace Umbraco.Tests.Services { // Arrange var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Home US", -1, "umbTextpage", 0); + var content = contentService.Create("Home US", -1, "umbTextpage", 0); content.SetValue("author", "Barack Obama"); // Act + content.PublishValues(); var published = contentService.SaveAndPublish(content, 0); - var childContent = contentService.CreateContent("Child", content.Id, "umbTextpage", 0); + var childContent = contentService.Create("Child", content.Id, "umbTextpage", 0); // Reset all identity properties childContent.Id = 0; childContent.Path = null; ((Content)childContent).ResetIdentity(); + childContent.PublishValues(); var childPublished = contentService.SaveAndPublish(childContent, 0); // Assert @@ -1432,10 +1478,12 @@ namespace Umbraco.Tests.Services var contentService = ServiceContext.ContentService; var root = contentService.GetById(NodeDto.NodeIdSeed + 2); - var rootPublished = contentService.Publish(root); + root.PublishValues(); + var rootPublished = contentService.SaveAndPublish(root); var content = contentService.GetById(NodeDto.NodeIdSeed + 4); content.Properties["title"].SetValue(content.Properties["title"].GetValue() + " Published"); + content.PublishValues(); var contentPublished = contentService.SaveAndPublish(content); var publishedVersion = content.Version; @@ -1448,8 +1496,8 @@ namespace Umbraco.Tests.Services Assert.AreNotEqual(0, publishedDescendants.Count); // Assert - Assert.IsTrue(rootPublished); - Assert.IsTrue(contentPublished); + Assert.IsTrue(rootPublished.Success); + Assert.IsTrue(contentPublished.Success); //Console.WriteLine(publishedVersion); //foreach (var d in publishedDescendants) Console.WriteLine(d.Version); @@ -1458,7 +1506,7 @@ namespace Umbraco.Tests.Services //Ensure that the published content version has the correct property value and is marked as published var publishedContentVersion = publishedDescendants.First(x => x.Version == publishedVersion); Assert.That(publishedContentVersion.Published, Is.True); - Assert.That(publishedContentVersion.Properties["title"].GetValue(true), Contains.Substring("Published")); + Assert.That(publishedContentVersion.Properties["title"].GetValue(published: true), Contains.Substring("Published")); // and has the correct draft properties Assert.That(publishedContentVersion.Properties["title"].GetValue(), Contains.Substring("Saved")); @@ -1466,7 +1514,7 @@ namespace Umbraco.Tests.Services //Ensure that the latest version of the content is ok var currentContent = contentService.GetById(NodeDto.NodeIdSeed + 4); Assert.That(currentContent.Published, Is.True); - Assert.That(currentContent.Properties["title"].GetValue(true), Contains.Substring("Published")); + Assert.That(currentContent.Properties["title"].GetValue(published: true), Contains.Substring("Published")); Assert.That(currentContent.Properties["title"].GetValue(), Contains.Substring("Saved")); Assert.That(currentContent.Version, Is.EqualTo(publishedContentVersion.Version)); } @@ -1476,7 +1524,7 @@ namespace Umbraco.Tests.Services { // Arrange var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Home US", - 1, "umbTextpage", 0); + var content = contentService.Create("Home US", - 1, "umbTextpage", 0); content.SetValue("author", "Barack Obama"); // Act @@ -1531,9 +1579,9 @@ namespace Umbraco.Tests.Services var contentType = contentTypeService.Get("umbTextpage"); // Act - contentService.DeleteContentOfType(contentType.Id); + contentService.DeleteOfType(contentType.Id); var rootContent = contentService.GetRootContent(); - var contents = contentService.GetContentOfContentType(contentType.Id); + var contents = contentService.GetByType(contentType.Id); // Assert Assert.That(rootContent.Any(), Is.False); @@ -1636,7 +1684,7 @@ namespace Umbraco.Tests.Services var childPage = MockedContent.CreateSimpleContent(contentType, "child", parentPage); ServiceContext.ContentService.Save(childPage); //assign explicit permissions to the child - ServiceContext.ContentService.AssignContentPermission(childPage, 'A', new[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(childPage, 'A', new[] { userGroup.Id }); //Ok, now copy, what should happen is the childPage will retain it's own permissions var parentPage2 = MockedContent.CreateSimpleContent(contentType); @@ -1668,7 +1716,7 @@ namespace Umbraco.Tests.Services var parentPage = MockedContent.CreateSimpleContent(contentType); ServiceContext.ContentService.Save(parentPage); - ServiceContext.ContentService.AssignContentPermission(parentPage, 'A', new[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parentPage, 'A', new[] { userGroup.Id }); var childPage1 = MockedContent.CreateSimpleContent(contentType, "child1", parentPage); ServiceContext.ContentService.Save(childPage1); @@ -1692,7 +1740,7 @@ namespace Umbraco.Tests.Services //create a new parent with a new permission structure var parentPage2 = MockedContent.CreateSimpleContent(contentType); ServiceContext.ContentService.Save(parentPage2); - ServiceContext.ContentService.AssignContentPermission(parentPage2, 'B', new[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parentPage2, 'B', new[] { userGroup.Id }); //Now copy, what should happen is the child pages will now have permissions inherited from the new parent var copy = ServiceContext.ContentService.Copy(childPage1, parentPage2.Id, false, true); @@ -1735,12 +1783,14 @@ namespace Umbraco.Tests.Services content1.PropertyValues(obj); content1.ResetDirtyProperties(false); ServiceContext.ContentService.Save(content1, 0); - Assert.IsTrue(ServiceContext.ContentService.PublishWithStatus(content1, 0).Success); + content1.PublishValues(); + Assert.IsTrue(ServiceContext.ContentService.SaveAndPublish(content1, 0).Success); var content2 = MockedContent.CreateBasicContent(contentType); content2.PropertyValues(obj); content2.ResetDirtyProperties(false); ServiceContext.ContentService.Save(content2, 0); - Assert.IsTrue(ServiceContext.ContentService.PublishWithStatus(content2, 0).Success); + content2.PublishValues(); + Assert.IsTrue(ServiceContext.ContentService.SaveAndPublish(content2, 0).Success); var editorGroup = ServiceContext.UserService.GetUserGroupByAlias("editor"); editorGroup.StartContentId = content1.Id; @@ -1767,7 +1817,7 @@ namespace Umbraco.Tests.Services var userGroup = ServiceContext.UserService.GetUserGroupByAlias(user.Groups.First().Alias); Assert.IsNotNull(ServiceContext.NotificationService.CreateNotification(user, content1, "X")); - ServiceContext.ContentService.AssignContentPermission(content1, 'A', new[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content1, 'A', new[] { userGroup.Id }); Assert.IsTrue(ServiceContext.DomainService.Save(new UmbracoDomain("www.test.com", "en-AU") { @@ -1876,13 +1926,15 @@ namespace Umbraco.Tests.Services var content = MockedContent.CreateSimpleContent(contentType, "Simple Text Page", -1); var prop = content.Properties.First(); content.SetTags(prop.Alias, new[] {"hello", "world"}, true); - contentService.PublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); var copy = contentService.Copy(content, content.ParentId, false, 0); var copiedTags = ServiceContext.TagService.GetTagsForEntity(copy.Id).ToArray(); Assert.AreEqual(0, copiedTags.Length); - contentService.PublishWithStatus(copy); + copy.PublishValues(); + contentService.SaveAndPublish(copy); copiedTags = ServiceContext.TagService.GetTagsForEntity(copy.Id).ToArray(); Assert.AreEqual(2, copiedTags.Length); @@ -1898,7 +1950,8 @@ namespace Umbraco.Tests.Services var parent = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 2); Assert.IsFalse(parent.Published); - ServiceContext.ContentService.Publish(parent); // publishing parent, so Text Page 2 can be updated. + parent.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(parent); // publishing parent, so Text Page 2 can be updated. var content = contentService.GetById(NodeDto.NodeIdSeed + 4); Assert.IsFalse(content.Published); @@ -1914,7 +1967,8 @@ namespace Umbraco.Tests.Services // non published = edited Assert.IsTrue(content.Edited); - contentService.SaveAndPublishWithStatus(content); // new version + content.PublishValues(); + contentService.SaveAndPublish(content); // new version var version2 = content.Version; Assert.AreNotEqual(version1, version2); @@ -1938,7 +1992,8 @@ namespace Umbraco.Tests.Services content.Name = "Text Page 2 ReReUpdated"; - contentService.SaveAndPublishWithStatus(content); // new version + content.PublishValues(); + contentService.SaveAndPublish(content); // new version var version3 = content.Version; Assert.AreNotEqual(version2, version3); @@ -1968,7 +2023,7 @@ namespace Umbraco.Tests.Services Assert.AreEqual("Text Page 2 Updated", rollback.Name); // published props and name are still there - Assert.AreEqual("Jane Doe", rollback.GetValue("author", true)); + Assert.AreEqual("Jane Doe", rollback.GetValue("author", published: true)); Assert.AreEqual("Text Page 2 ReReUpdated", rollback.PublishName); // rollback all values to current version @@ -1985,7 +2040,8 @@ namespace Umbraco.Tests.Services content = contentService.GetById(content.Id); Assert.AreEqual("Text Page 2 ReReUpdated", content.Name); Assert.AreEqual("Jane Doe", content.GetValue("author")); - contentService.SaveAndPublishWithStatus(content); + content.PublishValues(); + contentService.SaveAndPublish(content); Assert.IsFalse(content.Edited); content.Name = "Xxx"; content.SetValue("author", "Bob Doe"); @@ -2092,7 +2148,7 @@ namespace Umbraco.Tests.Services public void Ensure_Content_Xml_Created() { var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Home US", -1, "umbTextpage", 0); + var content = contentService.Create("Home US", -1, "umbTextpage", 0); content.SetValue("author", "Barack Obama"); contentService.Save(content); @@ -2102,7 +2158,8 @@ namespace Umbraco.Tests.Services Assert.IsFalse(uow.Database.Exists(content.Id)); } - contentService.Publish(content); + content.PublishValues(); + contentService.SaveAndPublish(content); using (var uow = UowProvider.CreateUnitOfWork()) { @@ -2114,7 +2171,7 @@ namespace Umbraco.Tests.Services public void Ensure_Preview_Xml_Created() { var contentService = ServiceContext.ContentService; - var content = contentService.CreateContent("Home US", -1, "umbTextpage", 0); + var content = contentService.Create("Home US", -1, "umbTextpage", 0); content.SetValue("author", "Barack Obama"); contentService.Save(content); @@ -2193,6 +2250,137 @@ namespace Umbraco.Tests.Services Assert.That(total, Is.EqualTo(10)); } + [Test] + public void PublishingTest() + { + var contentType = new ContentType(-1) + { + Alias = "foo", + Name = "Foo" + }; + + var properties = new PropertyTypeCollection(true) + { + new PropertyType("test", DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Mandatory = false, DataTypeDefinitionId = -88 }, + }; + + contentType.PropertyGroups.Add(new PropertyGroup(properties) { Name = "content" }); + + contentType.SetDefaultTemplate(new Template("Textpage", "textpage")); + ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! + ServiceContext.ContentTypeService.Save(contentType); + + var contentService = ServiceContext.ContentService; + var content = contentService.Create("foo", -1, "foo"); + contentService.Save(content); + + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + content = contentService.GetById(content.Id); + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + content.SetValue("title", "foo"); + Assert.IsTrue(content.Edited); + + contentService.Save(content); + + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + content = contentService.GetById(content.Id); + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + var versions = contentService.GetVersions(content.Id); + Assert.AreEqual(1, versions.Count()); + + // publish content + // becomes Published, !Edited + // creates a new version + // can get published property values + content.PublishValues(); + contentService.SaveAndPublish(content); + + Assert.IsTrue(content.Published); + Assert.IsFalse(content.Edited); + + content = contentService.GetById(content.Id); + Assert.IsTrue(content.Published); + Assert.IsFalse(content.Edited); + + versions = contentService.GetVersions(content.Id); + Assert.AreEqual(2, versions.Count()); + + Assert.AreEqual("foo", content.GetValue("title", published: true)); + Assert.AreEqual("foo", content.GetValue("title")); + + // unpublish content + // becomes !Published, Edited + contentService.Unpublish(content); + + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + Assert.AreEqual("foo", content.GetValue("title", published: true)); + Assert.AreEqual("foo", content.GetValue("title")); + + var vpk = ((Content) content).VersionPk; + var ppk = ((Content) content).PublishedVersionPk; + + content = contentService.GetById(content.Id); + Assert.IsFalse(content.Published); + Assert.IsTrue(content.Edited); + + // fixme - depending on 1 line in ContentBaseFactory.BuildEntity + // the published infos can be gone or not + // if gone, it's not consistent with above + Assert.AreEqual(vpk, ((Content) content).VersionPk); + Assert.AreEqual(ppk, ((Content) content).PublishedVersionPk); // still there + + // fixme - depending on 1 line in ContentRepository.MapDtoToContent + // the published values can be null or not + // if null, it's not consistent with above + //Assert.IsNull(content.GetValue("title", published: true)); + Assert.AreEqual("foo", content.GetValue("title", published: true)); // still there + Assert.AreEqual("foo", content.GetValue("title")); + + versions = contentService.GetVersions(content.Id); + Assert.AreEqual(2, versions.Count()); + + // ah - we have a problem here - since we're not published we don't have published values + // and therefore we cannot "just" republish the content - we need to publish some values + // so... that's not really an option + // + //contentService.SaveAndPublish(content); + + // fixme - what shall we do of all this? + /* + // this basically republishes a content + // what if it never was published? + // what if it has changes? + // do we want to "publish" only some variants, or the entire content? + contentService.Publish(content); + + Assert.IsTrue(content.Published); + Assert.IsFalse(content.Edited); + + // fixme - should it be 2 or 3 + versions = contentService.GetVersions(content.Id); + Assert.AreEqual(2, versions.Count()); + + // fixme - now test rollbacks + var version = contentService.GetByVersion(content.Id); // test that it gets a version - should be GetVersion + var previousVersion = contentService.GetVersions(content.Id).Skip(1).FirstOrDefault(); // need an optimized way to do this + content.CopyValues(version); // copies the edited value - always + content.Template = version.Template; + content.Name = version.Name; + contentService.Save(content); // this is effectively a rollback? + contentService.Rollback(content); // just kill the method and offer options on values + template + name... + */ + } + private IEnumerable CreateContentHierarchy() { var contentType = ServiceContext.ContentTypeService.Get("umbTextpage"); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs index ca638136c6..a90e154eb0 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceTests.cs @@ -85,7 +85,8 @@ namespace Umbraco.Tests.Services var contentType = contentTypes[index]; var contentItem = MockedContent.CreateSimpleContent(contentType, "MyName_" + index + "_" + i, parentId); ServiceContext.ContentService.Save(contentItem); - ServiceContext.ContentService.Publish(contentItem); + contentItem.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(contentItem); parentId = contentItem.Id; ids.Add(contentItem.Id); @@ -185,7 +186,8 @@ namespace Umbraco.Tests.Services var contentType = contentTypes[index]; var contentItem = MockedContent.CreateSimpleContent(contentType, "MyName_" + index + "_" + i, parentId); ServiceContext.ContentService.Save(contentItem); - ServiceContext.ContentService.Publish(contentItem); + contentItem.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(contentItem); parentId = contentItem.Id; } } @@ -220,17 +222,20 @@ namespace Umbraco.Tests.Services var root = MockedContent.CreateSimpleContent(contentType1, "Root", -1); ServiceContext.ContentService.Save(root); - ServiceContext.ContentService.Publish(root); + root.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(root); var level1 = MockedContent.CreateSimpleContent(contentType2, "L1", root.Id); ServiceContext.ContentService.Save(level1); - ServiceContext.ContentService.Publish(level1); + level1.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(level1); for (int i = 0; i < 2; i++) { var level3 = MockedContent.CreateSimpleContent(contentType3, "L2" + i, level1.Id); ServiceContext.ContentService.Save(level3); - ServiceContext.ContentService.Publish(level3); + level3.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(level3); } ServiceContext.ContentTypeService.Delete(contentType1); @@ -259,7 +264,8 @@ namespace Umbraco.Tests.Services ServiceContext.FileService.SaveTemplate(contentType1.DefaultTemplate); ServiceContext.ContentTypeService.Save(contentType1); IContent contentItem = MockedContent.CreateTextpageContent(contentType1, "Testing", -1); - ServiceContext.ContentService.SaveAndPublishWithStatus(contentItem); + contentItem.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(contentItem); var initProps = contentItem.Properties.Count; var initPropTypes = contentItem.PropertyTypes.Count(); @@ -287,11 +293,17 @@ namespace Umbraco.Tests.Services var contentItems1 = MockedContent.CreateTextpageContent(contentType1, -1, 10).ToArray(); foreach (var x in contentItems1) - ServiceContext.ContentService.SaveAndPublishWithStatus(x); + { + x.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(x); + } var contentItems2 = MockedContent.CreateTextpageContent(contentType2, -1, 5).ToArray(); foreach (var x in contentItems2) - ServiceContext.ContentService.SaveAndPublishWithStatus(x); + { + x.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(x); + } // make sure we have everything using (var scope = ScopeProvider.CreateScope()) @@ -346,7 +358,10 @@ namespace Umbraco.Tests.Services ServiceContext.ContentTypeService.Save(contentType1); var contentItems1 = MockedContent.CreateTextpageContent(contentType1, -1, 10).ToArray(); foreach (var x in contentItems1) - ServiceContext.ContentService.SaveAndPublishWithStatus(x); + { + x.PublishValues(); + ServiceContext.ContentService.SaveAndPublish(x); + } var alias = contentType1.PropertyTypes.First().Alias; var elementToMatch = "<" + alias + ">"; @@ -477,8 +492,9 @@ namespace Umbraco.Tests.Services cts.Save(ctHomePage); // Act - var homeDoc = cs.CreateContent("Home Page", -1, contentTypeAlias); - cs.SaveAndPublishWithStatus(homeDoc); + var homeDoc = cs.Create("Home Page", -1, contentTypeAlias); + homeDoc.PublishValues(); + cs.SaveAndPublish(homeDoc); // Assert Assert.That(ctBase.HasIdentity, Is.True); @@ -552,7 +568,7 @@ namespace Umbraco.Tests.Services var childContentType = MockedContentTypes.CreateSimpleContentType("childPage", "Child Page", contentType, true, "Child Content"); cts.Save(childContentType); var cs = ServiceContext.ContentService; - var content = cs.CreateContent("Page 1", -1, childContentType.Alias); + var content = cs.Create("Page 1", -1, childContentType.Alias); cs.Save(content); cts.Delete(contentType); diff --git a/src/Umbraco.Tests/Services/PerformanceTests.cs b/src/Umbraco.Tests/Services/PerformanceTests.cs index 375b0c409f..2626d255a6 100644 --- a/src/Umbraco.Tests/Services/PerformanceTests.cs +++ b/src/Umbraco.Tests/Services/PerformanceTests.cs @@ -122,7 +122,7 @@ namespace Umbraco.Tests.Services { //get all content items that are published of this type - var published = contentSvc.GetContentOfContentType(contentTypeId).Where(content => content.Published); + var published = contentSvc.GetByType(contentTypeId).Where(content => content.Published); Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId)); } } @@ -246,6 +246,7 @@ namespace Umbraco.Tests.Services var result = new List(); ServiceContext.ContentTypeService.Save(contentType1); IContent lastParent = MockedContent.CreateSimpleContent(contentType1); + lastParent.PublishValues(); ServiceContext.ContentService.SaveAndPublish(lastParent); result.Add(lastParent); //create 20 deep @@ -259,6 +260,7 @@ namespace Umbraco.Tests.Services //only publish evens if (j % 2 == 0) { + content.PublishValues(); ServiceContext.ContentService.SaveAndPublish(content); } else diff --git a/src/Umbraco.Tests/Services/PublicAccessServiceTests.cs b/src/Umbraco.Tests/Services/PublicAccessServiceTests.cs index d8657dbda4..0f70376544 100644 --- a/src/Umbraco.Tests/Services/PublicAccessServiceTests.cs +++ b/src/Umbraco.Tests/Services/PublicAccessServiceTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Services // Assert Assert.IsTrue(result.Success); - Assert.AreEqual(OperationStatusType.Success, result.Result.StatusType); + Assert.AreEqual(OperationResultType.Success, result.Result.Result); Assert.IsTrue(entry.HasIdentity); Assert.AreNotEqual(entry.Key, Guid.Empty); Assert.AreEqual(c.Id, entry.LoginNodeId); @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Services // Assert Assert.IsTrue(updated.Success); - Assert.AreEqual(OperationStatusType.Success, updated.Result.StatusType); + Assert.AreEqual(OperationResultType.Success, updated.Result.Result); Assert.AreEqual(2, entry.Rules.Count()); } @@ -113,8 +113,8 @@ namespace Umbraco.Tests.Services // Assert Assert.IsTrue(updated1.Success); Assert.IsTrue(updated2.Success); - Assert.AreEqual(OperationStatusType.Success, updated1.Result.StatusType); - Assert.AreEqual(OperationStatusType.Success, updated2.Result.StatusType); + Assert.AreEqual(OperationResultType.Success, updated1.Result.Result); + Assert.AreEqual(OperationResultType.Success, updated2.Result.Result); Assert.AreEqual(3, entry.Rules.Count()); } @@ -152,7 +152,7 @@ namespace Umbraco.Tests.Services // Assert Assert.IsTrue(removed.Success); - Assert.AreEqual(OperationStatusType.Success, removed.Result.StatusType); + Assert.AreEqual(OperationResultType.Success, removed.Result.Result); Assert.AreEqual(1, entry.Rules.Count()); Assert.AreEqual("TestValue2", entry.Rules.ElementAt(0).RuleValue); } diff --git a/src/Umbraco.Tests/Services/TagServiceTests.cs b/src/Umbraco.Tests/Services/TagServiceTests.cs index 9426dc96ee..1fe62c3b82 100644 --- a/src/Umbraco.Tests/Services/TagServiceTests.cs +++ b/src/Umbraco.Tests/Services/TagServiceTests.cs @@ -33,15 +33,18 @@ namespace Umbraco.Tests.Services var content1 = MockedContent.CreateSimpleContent(contentType, "Tagged content 1", -1); content1.SetTags("tags", new[] { "cow", "pig", "goat" }, true); - contentService.Publish(content1); + content1.PublishValues(); + contentService.SaveAndPublish(content1); var content2 = MockedContent.CreateSimpleContent(contentType, "Tagged content 2", -1); content2.SetTags("tags", new[] { "cow", "pig" }, true); - contentService.Publish(content2); + content2.PublishValues(); + contentService.SaveAndPublish(content2); var content3 = MockedContent.CreateSimpleContent(contentType, "Tagged content 3", -1); content3.SetTags("tags", new[] { "cow" }, true); - contentService.Publish(content3); + content3.PublishValues(); + contentService.SaveAndPublish(content3); // Act var tags = tagService.GetAllContentTags() diff --git a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs index 1e4668d8da..f4d679641e 100644 --- a/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs +++ b/src/Umbraco.Tests/Services/ThreadSafetyServiceTest.cs @@ -115,7 +115,7 @@ namespace Umbraco.Tests.Services Debug.WriteLine("[{0}] Running...", Thread.CurrentThread.ManagedThreadId); var name1 = "test-" + Guid.NewGuid(); - var content1 = contentService.CreateContent(name1, -1, "umbTextpage"); + var content1 = contentService.Create(name1, -1, "umbTextpage"); Debug.WriteLine("[{0}] Saving content #1.", Thread.CurrentThread.ManagedThreadId); Save(contentService, content1); @@ -123,7 +123,7 @@ namespace Umbraco.Tests.Services Thread.Sleep(100); //quick pause for maximum overlap! var name2 = "test-" + Guid.NewGuid(); - var content2 = contentService.CreateContent(name2, -1, "umbTextpage"); + var content2 = contentService.Create(name2, -1, "umbTextpage"); Debug.WriteLine("[{0}] Saving content #2.", Thread.CurrentThread.ManagedThreadId); Save(contentService, content2); diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index 06ed895410..93ca3dfa2c 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -67,12 +67,12 @@ namespace Umbraco.Tests.Services MockedContent.CreateSimpleContent(contentType) }; ServiceContext.ContentService.Save(content); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[2], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[2], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); // Act var permissions = userService.GetPermissions(user, content[0].Id, content[1].Id, content[2].Id).ToArray(); @@ -100,12 +100,12 @@ namespace Umbraco.Tests.Services MockedContent.CreateSimpleContent(contentType) }; ServiceContext.ContentService.Save(content); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content.ElementAt(2), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content.ElementAt(2), ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); // Act var permissions = userService.GetPermissions(userGroup, false, content[0].Id, content[1].Id, content[2].Id).ToArray(); @@ -133,11 +133,11 @@ namespace Umbraco.Tests.Services MockedContent.CreateSimpleContent(contentType) }; ServiceContext.ContentService.Save(content); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); // Act var permissions = userService.GetPermissions(userGroup, true, content[0].Id, content[1].Id, content[2].Id) @@ -177,12 +177,12 @@ namespace Umbraco.Tests.Services }; ServiceContext.ContentService.Save(content); //assign permissions - we aren't assigning anything explicit for group3 and nothing explicit for content[2] /w group2 - ServiceContext.ContentService.AssignContentPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup1.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup2.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup2.Id }); - ServiceContext.ContentService.AssignContentPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup1.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup1.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup2.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup1.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup2.Id }); + ServiceContext.ContentService.SetPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup1.Id }); // Act //we don't pass in any nodes so it will return all of them @@ -246,12 +246,12 @@ namespace Umbraco.Tests.Services MockedContent.CreateSimpleContent(contentType) }; ServiceContext.ContentService.Save(content); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[0], ActionMove.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[1], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(content[2], ActionDelete.Instance.Letter, new int[] { userGroup.Id }); // Act //we don't pass in any nodes so it will return all of them @@ -409,11 +409,11 @@ namespace Umbraco.Tests.Services var child2 = MockedContent.CreateSimpleContent(contentType, "child2", child1); ServiceContext.ContentService.Save(child2); - ServiceContext.ContentService.AssignContentPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(parent, ActionMove.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); - ServiceContext.ContentService.AssignContentPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parent, ActionMove.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id }); + ServiceContext.ContentService.SetPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id }); // Act var permissions = userService.GetPermissionsForPath(userGroup, child2.Path); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 8366aa22f2..019cfe243c 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -224,6 +224,7 @@ + diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs index 2435c946c4..7757a27fd5 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs +++ b/src/Umbraco.Web.UI/umbraco/dialogs/ChangeDocType.aspx.cs @@ -250,7 +250,8 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs // Publish if the content was already published if (wasPublished) { - Services.ContentService.Publish(_content, user.Id); + // no values to publish, really + Services.ContentService.SaveAndPublish(_content, user.Id); } // Sync the tree diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index a5da00d59b..d54a4e6bdf 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -91,7 +91,7 @@ namespace Umbraco.Web.Editors if (content == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); //current permissions explicitly assigned to this content item - var contentPermissions = Services.ContentService.GetPermissionsForEntity(content) + var contentPermissions = Services.ContentService.GetPermissions(content) .ToDictionary(x => x.UserGroupId, x => x); var allUserGroups = Services.UserService.GetAllUserGroups().ToArray(); @@ -167,7 +167,7 @@ namespace Umbraco.Web.Editors .ToDictionary(x => Convert.ToInt32(x.Id), x => x); //get the actual assigned permissions - var assignedPermissionsByGroup = Services.ContentService.GetPermissionsForEntity(content).ToArray(); + var assignedPermissionsByGroup = Services.ContentService.GetPermissions(content).ToArray(); //iterate over assigned and update the defaults with the real values foreach (var assignedGroupPermission in assignedPermissionsByGroup) @@ -294,7 +294,7 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - var emptyContent = Services.ContentService.CreateContent("", parentId, contentType.Alias, Security.GetUserId()); + var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId()); var mapped = Mapper.Map(emptyContent); //remove this tab if it exists: umbContainerView @@ -501,8 +501,7 @@ namespace Umbraco.Web.Editors /// [FileUploadCleanupFilter] [ContentPostValidate] - public ContentItemDisplay PostSaveBlueprint( - [ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) + public ContentItemDisplay PostSaveBlueprint([ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) { var contentItemDisplay = PostSaveInternal(contentItem, content => @@ -511,7 +510,7 @@ namespace Umbraco.Web.Editors Services.ContentService.SaveBlueprint(contentItem.PersistedContent, Security.CurrentUser.Id); //we need to reuse the underlying logic so return the result that it wants - return Attempt.Succeed(new OperationStatus(OperationStatusType.Success, new EventMessages())); + return OperationResult.Succeed(new EventMessages()); }); SetupBlueprint(contentItemDisplay, contentItemDisplay.PersistedContent); @@ -524,15 +523,12 @@ namespace Umbraco.Web.Editors /// [FileUploadCleanupFilter] [ContentPostValidate] - public ContentItemDisplay PostSave( - [ModelBinder(typeof(ContentItemBinder))] - ContentItemSave contentItem) + public ContentItemDisplay PostSave([ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) { - return PostSaveInternal(contentItem, - content => Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id)); + return PostSaveInternal(contentItem, content => Services.ContentService.Save(contentItem.PersistedContent, Security.CurrentUser.Id)); } - private ContentItemDisplay PostSaveInternal(ContentItemSave contentItem, Func> saveMethod) + private ContentItemDisplay PostSaveInternal(ContentItemSave contentItem, Func saveMethod) { //If we've reached here it means: // * Our model has been bound @@ -573,7 +569,7 @@ namespace Umbraco.Web.Editors } //initialize this to successful - var publishStatus = Attempt.Succeed(); + var publishStatus = new PublishResult(null, contentItem.PersistedContent); var wasCancelled = false; if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew) @@ -581,7 +577,7 @@ namespace Umbraco.Web.Editors //save the item var saveResult = saveMethod(contentItem.PersistedContent); - wasCancelled = saveResult.Success == false && saveResult.Result.StatusType == OperationStatusType.FailedCancelledByEvent; + wasCancelled = saveResult.Success == false && saveResult.Result == OperationResultType.FailedCancelledByEvent; } else if (contentItem.Action == ContentSaveAction.SendPublish || contentItem.Action == ContentSaveAction.SendPublishNew) { @@ -591,8 +587,9 @@ namespace Umbraco.Web.Editors else { //publish the item and check if it worked, if not we will show a diff msg below - publishStatus = Services.ContentService.SaveAndPublishWithStatus(contentItem.PersistedContent, Security.CurrentUser.Id); - wasCancelled = publishStatus.Result.StatusType == PublishStatusType.FailedCancelledByEvent; + contentItem.PersistedContent.PublishValues(); // fixme variants? + publishStatus = Services.ContentService.SaveAndPublish(contentItem.PersistedContent, Security.CurrentUser.Id); + wasCancelled = publishStatus.Result == PublishResultType.FailedCancelledByEvent; } //return the updated model @@ -632,7 +629,7 @@ namespace Umbraco.Web.Editors break; case ContentSaveAction.Publish: case ContentSaveAction.PublishNew: - ShowMessageForPublishStatus(publishStatus.Result, display); + ShowMessageForPublishStatus(publishStatus, display); break; } @@ -671,11 +668,12 @@ namespace Umbraco.Web.Editors return HandleContentNotFound(id, false); } - var publishResult = Services.ContentService.PublishWithStatus(foundContent, Security.GetUserId()); + foundContent.PublishValues(); // fixme variants? + var publishResult = Services.ContentService.SaveAndPublish(foundContent, Security.GetUserId()); if (publishResult.Success == false) { var notificationModel = new SimpleNotificationModel(); - ShowMessageForPublishStatus(publishResult.Result, notificationModel); + ShowMessageForPublishStatus(publishResult, notificationModel); return Request.CreateValidationErrorResponse(notificationModel); } @@ -724,8 +722,8 @@ namespace Umbraco.Web.Editors //if the current item is in the recycle bin if (foundContent.Trashed == false) { - var moveResult = Services.ContentService.WithResult().MoveToRecycleBin(foundContent, Security.GetUserId()); - if (moveResult == false) + var moveResult = Services.ContentService.MoveToRecycleBin(foundContent, Security.GetUserId()); + if (moveResult.Success == false) { //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. @@ -734,8 +732,8 @@ namespace Umbraco.Web.Editors } else { - var deleteResult = Services.ContentService.WithResult().Delete(foundContent, Security.GetUserId()); - if (deleteResult == false) + var deleteResult = Services.ContentService.Delete(foundContent, Security.GetUserId()); + if (deleteResult.Success == false) { //returning an object of INotificationModel will ensure that any pending // notification messages are added to the response. @@ -851,11 +849,11 @@ namespace Umbraco.Web.Editors if (foundContent == null) HandleContentNotFound(id); - var unpublishResult = Services.ContentService.WithResult().UnPublish(foundContent, Security.CurrentUser.Id); + var unpublishResult = Services.ContentService.Unpublish(foundContent, Security.CurrentUser.Id); var content = Mapper.Map(foundContent); - if (unpublishResult == false) + if (unpublishResult.Success == false) { AddCancelMessage(content); throw new HttpResponseException(Request.CreateValidationErrorResponse(content)); @@ -967,50 +965,50 @@ namespace Umbraco.Web.Editors return toMove; } - private void ShowMessageForPublishStatus(PublishStatus status, INotificationModel display) + private void ShowMessageForPublishStatus(PublishResult status, INotificationModel display) { - switch (status.StatusType) + switch (status.Result) { - case PublishStatusType.Success: - case PublishStatusType.SuccessAlreadyPublished: + case PublishResultType.Success: + case PublishResultType.SuccessAlready: display.AddSuccessNotification( Services.TextService.Localize("speechBubbles/editContentPublishedHeader"), Services.TextService.Localize("speechBubbles/editContentPublishedText")); break; - case PublishStatusType.FailedPathNotPublished: + case PublishResultType.FailedPathNotPublished: display.AddWarningNotification( Services.TextService.Localize("publish"), Services.TextService.Localize("publish/contentPublishedFailedByParent", - new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim()); + new[] { string.Format("{0} ({1})", status.Content.Name, status.Content.Id) }).Trim()); break; - case PublishStatusType.FailedCancelledByEvent: + case PublishResultType.FailedCancelledByEvent: AddCancelMessage(display, "publish", "speechBubbles/contentPublishedFailedByEvent"); break; - case PublishStatusType.FailedAwaitingRelease: + case PublishResultType.FailedAwaitingRelease: display.AddWarningNotification( Services.TextService.Localize("publish"), Services.TextService.Localize("publish/contentPublishedFailedAwaitingRelease", - new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim()); + new[] { string.Format("{0} ({1})", status.Content.Name, status.Content.Id) }).Trim()); break; - case PublishStatusType.FailedHasExpired: + case PublishResultType.FailedHasExpired: display.AddWarningNotification( Services.TextService.Localize("publish"), Services.TextService.Localize("publish/contentPublishedFailedExpired", new[] { - string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), + string.Format("{0} ({1})", status.Content.Name, status.Content.Id), }).Trim()); break; - case PublishStatusType.FailedIsTrashed: + case PublishResultType.FailedIsTrashed: //TODO: We should add proper error messaging for this! break; - case PublishStatusType.FailedContentInvalid: + case PublishResultType.FailedContentInvalid: display.AddWarningNotification( Services.TextService.Localize("publish"), Services.TextService.Localize("publish/contentPublishedFailedInvalid", new[] { - string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id), + string.Format("{0} ({1})", status.Content.Name, status.Content.Id), string.Join(",", status.InvalidProperties.Select(x => x.Alias)) }).Trim()); break; diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 761d0fdb3a..2380f09079 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -188,9 +188,9 @@ namespace Umbraco.Web.Editors Logger.Warn( "Could not create a template for the Content Type: {0}, status: {1}", () => ctSave.Alias, - () => tryCreateTemplate.Result.StatusType); + () => tryCreateTemplate.Result.Result); } - template = tryCreateTemplate.Result.Value; + template = tryCreateTemplate.Result.Entity; } //make sure the template alias is set on the default and allowed template so we can map it back diff --git a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs index dbbe626af6..227db6db31 100644 --- a/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs +++ b/src/Umbraco.Web/Editors/ContentTypeControllerBase.cs @@ -250,7 +250,7 @@ namespace Umbraco.Web.Editors protected HttpResponseMessage PerformMove( MoveOrCopy move, Func getContentType, - Func>> doMove) + Func>> doMove) where TContentType : IContentTypeComposition { var toMove = getContentType(move.Id); @@ -267,7 +267,7 @@ namespace Umbraco.Web.Editors return response; } - switch (result.Result.StatusType) + switch (result.Result.Result) { case MoveOperationStatusType.FailedParentNotFound: return Request.CreateResponse(HttpStatusCode.NotFound); @@ -294,7 +294,7 @@ namespace Umbraco.Web.Editors protected HttpResponseMessage PerformCopy( MoveOrCopy move, Func getContentType, - Func>> doCopy) + Func>> doCopy) { var toMove = getContentType(move.Id); if (toMove == null) @@ -305,13 +305,13 @@ namespace Umbraco.Web.Editors var result = doCopy(toMove, move.ParentId); if (result.Success) { - var copy = result.Result.Value; + var copy = result.Result.Entity; var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(copy.Path, Encoding.UTF8, "application/json"); return response; } - switch (result.Result.StatusType) + switch (result.Result.Result) { case MoveOperationStatusType.FailedParentNotFound: return Request.CreateResponse(HttpStatusCode.NotFound); diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs index 1fa31a7b43..ca0c00455b 100644 --- a/src/Umbraco.Web/Editors/DataTypeController.cs +++ b/src/Umbraco.Web/Editors/DataTypeController.cs @@ -248,7 +248,7 @@ namespace Umbraco.Web.Editors return response; } - switch (result.Result.StatusType) + switch (result.Result.Result) { case MoveOperationStatusType.FailedParentNotFound: return Request.CreateResponse(HttpStatusCode.NotFound); diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 92eec6fac4..a203225318 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -518,7 +518,7 @@ namespace Umbraco.Web.Editors //If the item is new and the operation was cancelled, we need to return a different // status code so the UI can handle it since it won't be able to redirect since there // is no Id to redirect to! - if (saveStatus.Result.StatusType == OperationStatusType.FailedCancelledByEvent && IsCreatingAction(contentItem.Action)) + if (saveStatus.Result.Result == OperationResultType.FailedCancelledByEvent && IsCreatingAction(contentItem.Action)) { throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); } diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs index 009d0cae2c..c1155116e3 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeMapperProfile.cs @@ -185,6 +185,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.PropertyEditorAlias, opt => opt.Ignore()) .ForMember(dest => dest.DeletedDate, opt => opt.Ignore()) + .ForMember(dto => dto.Variations, opt => opt.Ignore()) // fixme - change when UI supports it! + //only map if it is actually set .ForMember(dest => dest.Id, opt => opt.Condition(source => source.Id > 0)) //only map if it is actually set, if it's not set, it needs to be handled differently and will be taken care of in the diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs index 244b15329e..b1302a951c 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeProfileExtensions.cs @@ -180,6 +180,8 @@ namespace Umbraco.Web.Models.Mapping // ignore, composition is managed in AfterMapContentTypeSaveToEntity .ForMember(dest => dest.ContentTypeComposition, opt => opt.Ignore()) + .ForMember(dto => dto.Variations, opt => opt.Ignore()) // fixme - change when UI supports it! + .ForMember( dest => dest.AllowedContentTypes, opt => opt.MapFrom(src => src.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i)))) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index 4048e95a69..64089a5de8 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -1159,7 +1159,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var data = new Dictionary(); foreach (var prop in content.Properties) { - var value = prop.GetValue(published); + var value = prop.GetValue(published: published); //if (value != null) //{ // var e = propertyEditorResolver.GetByAlias(prop.PropertyType.PropertyEditorAlias); diff --git a/src/Umbraco.Web/WebServices/BulkPublishController.cs b/src/Umbraco.Web/WebServices/BulkPublishController.cs index 5dba6c3438..55e78a97bc 100644 --- a/src/Umbraco.Web/WebServices/BulkPublishController.cs +++ b/src/Umbraco.Web/WebServices/BulkPublishController.cs @@ -29,31 +29,32 @@ namespace Umbraco.Web.WebServices if (publishDescendants == false) { - var result = Services.ContentService.SaveAndPublishWithStatus(content, Security.CurrentUser.Id); + content.PublishValues(); // fixme variants? + var result = Services.ContentService.SaveAndPublish(content, Security.CurrentUser.Id); return Json(new { success = result.Success, - message = GetMessageForStatus(result.Result) + message = GetMessageForStatus(result) }); } else { var result = Services.ContentService - .PublishWithChildrenWithStatus(content, Security.CurrentUser.Id, includeUnpublished) + .PublishWithChildren(content, Security.CurrentUser.Id, includeUnpublished) .ToArray(); return Json(new { success = result.All(x => x.Success), - message = GetMessageForStatuses(result.Select(x => x.Result).ToArray(), content) + message = GetMessageForStatuses(result.ToArray(), content) }); } } - private string GetMessageForStatuses(PublishStatus[] statuses, IContent doc) + private string GetMessageForStatuses(PublishResult[] statuses, IContent doc) { //if all are successful then just say it was successful - if (statuses.All(x => x.StatusType.IsSuccess())) + if (statuses.All(x => x.Success)) { return Services.TextService.Localize("publish/nodePublishAll", new[] { doc.Name}); } @@ -61,7 +62,7 @@ namespace Umbraco.Web.WebServices //if they are not all successful the we'll add each error message to the output (one per line) var sb = new StringBuilder(); foreach (var msg in statuses - .Where(x => ((int)x.StatusType) >= 10) + .Where(x => ((int)x.Result) >= 10) .Select(GetMessageForStatus) .Where(msg => msg.IsNullOrWhiteSpace() == false)) { @@ -70,31 +71,31 @@ namespace Umbraco.Web.WebServices return sb.ToString(); } - private string GetMessageForStatus(PublishStatus status) + private string GetMessageForStatus(PublishResult status) { - switch (status.StatusType) + switch (status.Result) { - case PublishStatusType.Success: - case PublishStatusType.SuccessAlreadyPublished: - return Services.TextService.Localize("publish/nodePublish", new[] { status.ContentItem.Name}); - case PublishStatusType.FailedPathNotPublished: + case PublishResultType.Success: + case PublishResultType.SuccessAlready: + return Services.TextService.Localize("publish/nodePublish", new[] { status.Content.Name}); + case PublishResultType.FailedPathNotPublished: return Services.TextService.Localize("publish/contentPublishedFailedByParent", - new [] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }); - case PublishStatusType.FailedHasExpired: - case PublishStatusType.FailedAwaitingRelease: - case PublishStatusType.FailedIsTrashed: - return "Cannot publish document with a status of " + status.StatusType; - case PublishStatusType.FailedCancelledByEvent: + new [] { string.Format("{0} ({1})", status.Content.Name, status.Content.Id) }); + case PublishResultType.FailedHasExpired: + case PublishResultType.FailedAwaitingRelease: + case PublishResultType.FailedIsTrashed: + return "Cannot publish document with a status of " + status.Result; + case PublishResultType.FailedCancelledByEvent: return Services.TextService.Localize("publish/contentPublishedFailedByEvent", - new [] { string.Format("'{0}' ({1})", status.ContentItem.Name, status.ContentItem.Id) }); - case PublishStatusType.FailedContentInvalid: + new [] { string.Format("'{0}' ({1})", status.Content.Name, status.Content.Id) }); + case PublishResultType.FailedContentInvalid: return Services.TextService.Localize("publish/contentPublishedFailedInvalid", new []{ - string.Format("'{0}' ({1})", status.ContentItem.Name, status.ContentItem.Id), + string.Format("'{0}' ({1})", status.Content.Name, status.Content.Id), string.Format("'{0}'", string.Join(", ", status.InvalidProperties.Select(x => x.Alias))) }); default: - return status.StatusType.ToString(); + return status.Result.ToString(); } } } diff --git a/src/Umbraco.Web/WebServices/DomainsApiController.cs b/src/Umbraco.Web/WebServices/DomainsApiController.cs index 94c425c8d7..d74a225aee 100644 --- a/src/Umbraco.Web/WebServices/DomainsApiController.cs +++ b/src/Umbraco.Web/WebServices/DomainsApiController.cs @@ -74,7 +74,7 @@ namespace Umbraco.Web.WebServices { var response = Request.CreateResponse(HttpStatusCode.BadRequest); response.Content = new StringContent("Saving domain failed"); - response.ReasonPhrase = saveAttempt.Result.StatusType.ToString(); + response.ReasonPhrase = saveAttempt.Result.Result.ToString(); throw new HttpResponseException(response); } } @@ -150,7 +150,7 @@ namespace Umbraco.Web.WebServices { var response = Request.CreateResponse(HttpStatusCode.BadRequest); response.Content = new StringContent("Saving new domain failed"); - response.ReasonPhrase = saveAttempt.Result.StatusType.ToString(); + response.ReasonPhrase = saveAttempt.Result.Result.ToString(); throw new HttpResponseException(response); } } diff --git a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs index e29a6f8cb8..f3d419b6f9 100644 --- a/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs +++ b/src/Umbraco.Web/_Legacy/PackageActions/publishRootDocument.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web._Legacy.PackageActions { if (rootDoc.Name.Trim() == documentName.Trim() && rootDoc != null && rootDoc.ContentType != null) { - Current.Services.ContentService.PublishWithChildrenWithStatus(rootDoc, 0, true); + Current.Services.ContentService.PublishWithChildren(rootDoc, 0, true); break; } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs index fa60bd90c8..1969cada5c 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs @@ -161,7 +161,7 @@ namespace umbraco.presentation.umbraco.dialogs Constants.Conventions.PublicAccess.MemberRoleRuleType, role); - if (entry.Success == false && entry.Result.Value == null) + if (entry.Success == false && entry.Result.Entity == null) { throw new Exception("Document is not protected!"); } @@ -176,7 +176,7 @@ namespace umbraco.presentation.umbraco.dialogs Constants.Conventions.PublicAccess.MemberUsernameRuleType, membershipUserName); - if (entry.Success == false && entry.Result.Value == null) + if (entry.Success == false && entry.Result.Entity == null) { throw new Exception("Document is not protected!"); }