From 8329097974b56da85d16549e09b9b92ba85539db Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 6 Feb 2019 17:28:48 +0100 Subject: [PATCH] Review PR, adjustments --- .../CancellableEnumerableObjectEventArgs.cs | 24 ++--- .../Events/CancellableEventArgs.cs | 4 +- .../Events/CancellableObjectEventArgs.cs | 90 +------------------ ...ancellableObjectEventArgsOfTEventObject.cs | 82 +++++++++++++++++ .../Events/ContentPublishedEventArgs.cs | 19 ++-- .../Events/ContentPublishingEventArgs.cs | 17 ++-- .../Events/ContentSavedEventArgs.cs | 20 ++--- .../Events/ContentSavingEventArgs.cs | 31 ++++--- src/Umbraco.Core/Models/Content.cs | 24 ++--- src/Umbraco.Core/Models/ContentBase.cs | 37 ++++---- .../Models/ContentRepositoryExtensions.cs | 8 +- src/Umbraco.Core/Models/IContentBase.cs | 2 +- .../Repositories/IDocumentRepository.cs | 2 - .../Implement/DocumentRepository.cs | 22 +++-- src/Umbraco.Core/Services/IContentService.cs | 16 ++-- .../Services/Implement/ContentService.cs | 20 +++-- src/Umbraco.Core/Umbraco.Core.csproj | 1 + 17 files changed, 212 insertions(+), 207 deletions(-) create mode 100644 src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs diff --git a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs index 1a651ef348..1d52d0d847 100644 --- a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs @@ -1,34 +1,36 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Permissions; namespace Umbraco.Core.Events { - [HostProtection(SecurityAction.LinkDemand, SharedState = true)] - public class CancellableEnumerableObjectEventArgs : CancellableObjectEventArgs>, IEquatable> + /// + /// Represents event data, for events that support cancellation, and expose impacted objects. + /// + /// The type of the exposed, impacted objects. + public class CancellableEnumerableObjectEventArgs : CancellableObjectEventArgs>, IEquatable> { - public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(eventObject, canCancel, messages, additionalData) { } - public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages eventMessages) + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { } - public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, EventMessages eventMessages) + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) { } - public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel) + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel) : base(eventObject, canCancel) { } - public CancellableEnumerableObjectEventArgs(IEnumerable eventObject) + public CancellableEnumerableObjectEventArgs(IEnumerable eventObject) : base(eventObject) { } - public bool Equals(CancellableEnumerableObjectEventArgs other) + public bool Equals(CancellableEnumerableObjectEventArgs other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; @@ -41,7 +43,7 @@ namespace Umbraco.Core.Events if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return Equals((CancellableEnumerableObjectEventArgs)obj); + return Equals((CancellableEnumerableObjectEventArgs)obj); } public override int GetHashCode() @@ -49,4 +51,4 @@ namespace Umbraco.Core.Events return HashCodeHelper.GetHashCode(EventObject); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Events/CancellableEventArgs.cs b/src/Umbraco.Core/Events/CancellableEventArgs.cs index 19f576478f..d9d670ea59 100644 --- a/src/Umbraco.Core/Events/CancellableEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEventArgs.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Security.Permissions; namespace Umbraco.Core.Events { /// - /// Event args for that can support cancellation + /// Represents event data for events that support cancellation. /// - [HostProtection(SecurityAction.LinkDemand, SharedState = true)] public class CancellableEventArgs : EventArgs, IEquatable { private bool _cancel; diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs index 27ffb1b75d..daf36fd6c8 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Security.Permissions; -using Umbraco.Core.Models; +using System.Collections.Generic; namespace Umbraco.Core.Events { /// - /// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject + /// Provides a base class for classes representing event data, for events that support cancellation, and expose an impacted object. /// - [HostProtection(SecurityAction.LinkDemand, SharedState = true)] public abstract class CancellableObjectEventArgs : CancellableEventArgs { protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) @@ -41,90 +36,11 @@ namespace Umbraco.Core.Events } /// - /// Returns the object relating to the event + /// Gets or sets the impacted object. /// /// /// This is protected so that inheritors can expose it with their own name /// internal object EventObject { get; set; } - - } - - /// - /// Event args for a strongly typed object that can support cancellation - /// - /// - [HostProtection(SecurityAction.LinkDemand, SharedState = true)] - public class CancellableObjectEventArgs : CancellableObjectEventArgs, IEquatable> - { - public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) - : base(eventObject, canCancel, messages, additionalData) - { - } - - public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages) - : base(eventObject, canCancel, eventMessages) - { - } - - public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages) - : base(eventObject, eventMessages) - { - } - - public CancellableObjectEventArgs(T eventObject, bool canCancel) - : base(eventObject, canCancel) - { - } - - public CancellableObjectEventArgs(T eventObject) - : base(eventObject) - { - } - - /// - /// Returns the object relating to the event - /// - /// - /// This is protected so that inheritors can expose it with their own name - /// - protected new T EventObject - { - get { return (T) base.EventObject; } - set { base.EventObject = value; } - } - - public bool Equals(CancellableObjectEventArgs other) - { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); - } - - public override bool Equals(object obj) - { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((CancellableObjectEventArgs)obj); - } - - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); - } - } - - public static bool operator ==(CancellableObjectEventArgs left, CancellableObjectEventArgs right) - { - return Equals(left, right); - } - - public static bool operator !=(CancellableObjectEventArgs left, CancellableObjectEventArgs right) - { - return !Equals(left, right); - } } } diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs new file mode 100644 index 0000000000..ace2ce0a4f --- /dev/null +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgsOfTEventObject.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Events +{ + /// + /// Represent event data, for events that support cancellation, and expose an impacted object. + /// + /// The type of the exposed, impacted object. + public class CancellableObjectEventArgs : CancellableObjectEventArgs, IEquatable> + { + public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) + : base(eventObject, canCancel, messages, additionalData) + { + } + + public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel, EventMessages eventMessages) + : base(eventObject, canCancel, eventMessages) + { + } + + public CancellableObjectEventArgs(TEventObject eventObject, EventMessages eventMessages) + : base(eventObject, eventMessages) + { + } + + public CancellableObjectEventArgs(TEventObject eventObject, bool canCancel) + : base(eventObject, canCancel) + { + } + + public CancellableObjectEventArgs(TEventObject eventObject) + : base(eventObject) + { + } + + /// + /// Gets or sets the impacted object. + /// + /// + /// This is protected so that inheritors can expose it with their own name + /// + protected new TEventObject EventObject + { + get => (TEventObject) base.EventObject; + set => base.EventObject = value; + } + + public bool Equals(CancellableObjectEventArgs other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); + } + + public override bool Equals(object obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((CancellableObjectEventArgs)obj); + } + + public override int GetHashCode() + { + unchecked + { + return (base.GetHashCode() * 397) ^ EqualityComparer.Default.GetHashCode(EventObject); + } + } + + public static bool operator ==(CancellableObjectEventArgs left, CancellableObjectEventArgs right) + { + return Equals(left, right); + } + + public static bool operator !=(CancellableObjectEventArgs left, CancellableObjectEventArgs right) + { + return !Equals(left, right); + } + } +} diff --git a/src/Umbraco.Core/Events/ContentPublishedEventArgs.cs b/src/Umbraco.Core/Events/ContentPublishedEventArgs.cs index 589e447ba7..8c0690d591 100644 --- a/src/Umbraco.Core/Events/ContentPublishedEventArgs.cs +++ b/src/Umbraco.Core/Events/ContentPublishedEventArgs.cs @@ -1,29 +1,30 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Events { + /// + /// Represents event data for the Published event. + /// public class ContentPublishedEventArgs : PublishEventArgs { + /// + /// Initializes a new instance of the class. + /// public ContentPublishedEventArgs(IEnumerable eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) - { - } + { } /// /// Determines whether a culture has been published, during a Published event. /// public bool HasPublishedCulture(IContent content, string culture) - => content.WasPropertyDirty("_changedCulture_" + culture); + => content.WasPropertyDirty(ContentBase.ChangeTrackingPrefix.ChangedCulture + culture); /// /// Determines whether a culture has been unpublished, during a Published event. /// public bool HasUnpublishedCulture(IContent content, string culture) - => content.WasPropertyDirty("_unpublishedCulture_" + culture); - - - + => content.WasPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); } } diff --git a/src/Umbraco.Core/Events/ContentPublishingEventArgs.cs b/src/Umbraco.Core/Events/ContentPublishingEventArgs.cs index 35cbf63441..b64bb19def 100644 --- a/src/Umbraco.Core/Events/ContentPublishingEventArgs.cs +++ b/src/Umbraco.Core/Events/ContentPublishingEventArgs.cs @@ -1,21 +1,19 @@ -using System; -using System.Linq; -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Events { + /// + /// Represents event data for the Publishing event. + /// public class ContentPublishingEventArgs : PublishEventArgs { /// - /// Creates a new + /// Initializes a new instance of the class. /// - /// - /// public ContentPublishingEventArgs(IEnumerable eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) - { - } + { } /// /// Determines whether a culture is being published, during a Publishing event. @@ -27,7 +25,6 @@ namespace Umbraco.Core.Events /// Determines whether a culture is being unpublished, during a Publishing event. /// public bool IsUnpublishingCulture(IContent content, string culture) - => content.IsPropertyDirty("_unpublishedCulture_" + culture); //bit of a hack since we know that the content implementation tracks changes this way - + => content.IsPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); //bit of a hack since we know that the content implementation tracks changes this way } } diff --git a/src/Umbraco.Core/Events/ContentSavedEventArgs.cs b/src/Umbraco.Core/Events/ContentSavedEventArgs.cs index 4d4085b064..e2d8c25dd1 100644 --- a/src/Umbraco.Core/Events/ContentSavedEventArgs.cs +++ b/src/Umbraco.Core/Events/ContentSavedEventArgs.cs @@ -1,30 +1,24 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Events { + /// + /// Represents event data for the Saved event. + /// public class ContentSavedEventArgs : SaveEventArgs { - #region Constructors - /// - /// Creates a new + /// Initializes a new instance of the class. /// - /// - /// - /// public ContentSavedEventArgs(IEnumerable eventObject, EventMessages messages, IDictionary additionalData) : base(eventObject, false, messages, additionalData) - { - } - - #endregion + { } /// /// Determines whether a culture has been saved, during a Saved event. /// public bool HasSavedCulture(IContent content, string culture) - => content.WasPropertyDirty("_updatedCulture_" + culture); + => content.WasPropertyDirty(ContentBase.ChangeTrackingPrefix.UpdatedCulture + culture); } } diff --git a/src/Umbraco.Core/Events/ContentSavingEventArgs.cs b/src/Umbraco.Core/Events/ContentSavingEventArgs.cs index aa62f64349..384353ee2e 100644 --- a/src/Umbraco.Core/Events/ContentSavingEventArgs.cs +++ b/src/Umbraco.Core/Events/ContentSavingEventArgs.cs @@ -1,12 +1,15 @@ -using System.Linq; -using System.Collections.Generic; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Events { + /// + /// Represent event data for the Saving event. + /// public class ContentSavingEventArgs : SaveEventArgs { #region Factory Methods + /// /// Converts to while preserving all args state /// @@ -43,24 +46,32 @@ namespace Umbraco.Core.Events EventState = EventState, AdditionalData = AdditionalData }; - } + } + #endregion #region Constructors - public ContentSavingEventArgs(IEnumerable eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) - { - } + /// + /// Initializes a new instance of the class. + /// + public ContentSavingEventArgs(IEnumerable eventObject, EventMessages eventMessages) + : base(eventObject, eventMessages) + { } - public ContentSavingEventArgs(IContent eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) - { - } + /// + /// Initializes a new instance of the class. + /// + public ContentSavingEventArgs(IContent eventObject, EventMessages eventMessages) + : base(eventObject, eventMessages) + { } #endregion /// /// Determines whether a culture is being saved, during a Saving event. /// - public bool IsSavingCulture(IContent content, string culture) => content.CultureInfos.TryGetValue(culture, out var cultureInfo) && cultureInfo.IsDirty(); + public bool IsSavingCulture(IContent content, string culture) + => content.CultureInfos.TryGetValue(culture, out var cultureInfo) && cultureInfo.IsDirty(); } } diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 483ba8b0d2..f0c1915f75 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -385,19 +385,19 @@ namespace Umbraco.Core.Models public override bool IsPropertyDirty(string propertyName) { //Special check here since we want to check if the request is for changed cultures - if (propertyName.StartsWith("_publishedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.PublishedCulture)) { - var culture = propertyName.TrimStart("_publishedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.PublishedCulture); return _currentPublishCultureChanges.addedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_unpublishedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.UnpublishedCulture)) { - var culture = propertyName.TrimStart("_unpublishedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.UnpublishedCulture); return _currentPublishCultureChanges.removedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_changedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.ChangedCulture)) { - var culture = propertyName.TrimStart("_changedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.ChangedCulture); return _currentPublishCultureChanges.updatedCultures?.Contains(culture) ?? false; } @@ -409,19 +409,19 @@ namespace Umbraco.Core.Models public override bool WasPropertyDirty(string propertyName) { //Special check here since we want to check if the request is for changed cultures - if (propertyName.StartsWith("_publishedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.PublishedCulture)) { - var culture = propertyName.TrimStart("_publishedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.PublishedCulture); return _previousPublishCultureChanges.addedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_unpublishedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.UnpublishedCulture)) { - var culture = propertyName.TrimStart("_unpublishedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.UnpublishedCulture); return _previousPublishCultureChanges.removedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_changedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.ChangedCulture)) { - var culture = propertyName.TrimStart("_changedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.ChangedCulture); return _previousPublishCultureChanges.updatedCultures?.Contains(culture) ?? false; } diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 50de59931c..55922b485a 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -17,7 +17,6 @@ namespace Umbraco.Core.Models [DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")] public abstract class ContentBase : TreeEntityBase, IContentBase { - private int _contentTypeId; protected IContentTypeComposition ContentTypeBase; private int _writerId; @@ -29,6 +28,16 @@ namespace Umbraco.Core.Models private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _currentCultureChanges; private (HashSet addedCultures, HashSet removedCultures, HashSet updatedCultures) _previousCultureChanges; + public static class ChangeTrackingPrefix + { + public const string UpdatedCulture = "_updatedCulture_"; + public const string ChangedCulture = "_changedCulture_"; + public const string PublishedCulture = "_publishedCulture_"; + public const string UnpublishedCulture = "_unpublishedCulture_"; + public const string AddedCulture = "_addedCulture_"; + public const string RemovedCulture = "_removedCulture_"; + } + #endregion /// @@ -71,8 +80,6 @@ namespace Umbraco.Core.Models OnPropertyChanged(nameof(Properties)); } - - /// /// Id of the user who wrote/updated this entity /// @@ -402,19 +409,19 @@ namespace Umbraco.Core.Models return true; //Special check here since we want to check if the request is for changed cultures - if (propertyName.StartsWith("_addedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.AddedCulture)) { - var culture = propertyName.TrimStart("_addedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.AddedCulture); return _currentCultureChanges.addedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_removedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.RemovedCulture)) { - var culture = propertyName.TrimStart("_removedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.RemovedCulture); return _currentCultureChanges.removedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_updatedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.UpdatedCulture)) { - var culture = propertyName.TrimStart("_updatedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.UpdatedCulture); return _currentCultureChanges.updatedCultures?.Contains(culture) ?? false; } @@ -429,19 +436,19 @@ namespace Umbraco.Core.Models return true; //Special check here since we want to check if the request is for changed cultures - if (propertyName.StartsWith("_addedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.AddedCulture)) { - var culture = propertyName.TrimStart("_addedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.AddedCulture); return _previousCultureChanges.addedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_removedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.RemovedCulture)) { - var culture = propertyName.TrimStart("_removedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.RemovedCulture); return _previousCultureChanges.removedCultures?.Contains(culture) ?? false; } - if (propertyName.StartsWith("_updatedCulture_")) + if (propertyName.StartsWith(ChangeTrackingPrefix.UpdatedCulture)) { - var culture = propertyName.TrimStart("_updatedCulture_"); + var culture = propertyName.TrimStart(ChangeTrackingPrefix.UpdatedCulture); return _previousCultureChanges.updatedCultures?.Contains(culture) ?? false; } diff --git a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs index ca9bf57902..27678c047c 100644 --- a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs +++ b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Models return Array.Empty(); var culturesUnpublishing = content.CultureInfos.Values - .Where(x => content.IsPropertyDirty("_unpublishedCulture_" + x.Culture)) + .Where(x => content.IsPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + x.Culture)) .Select(x => x.Culture); return culturesUnpublishing.ToList(); @@ -88,8 +88,7 @@ namespace Umbraco.Core.Models { content.CultureInfos.Clear(); content.CultureInfos = null; - } - + } if (culture == null || culture == "*") content.Name = other.Name; @@ -158,8 +157,9 @@ namespace Umbraco.Core.Models if (!content.PublishCultureInfos.TryGetValue(culture, out var publishInfos)) continue; + // if it's not dirty, it means it hasn't changed so there's nothing to adjust if (!publishInfos.IsDirty()) - continue; //if it's not dirty, it means it hasn't changed so there's nothing to adjust + continue; content.PublishCultureInfos.AddOrUpdate(culture, publishInfos.Name, date); diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs index 1ebbfa1d49..1a6a6843f9 100644 --- a/src/Umbraco.Core/Models/IContentBase.cs +++ b/src/Umbraco.Core/Models/IContentBase.cs @@ -58,7 +58,7 @@ namespace Umbraco.Core.Models /// culture name, which must be get or set via the property. /// ContentCultureInfosCollection CultureInfos { get; set; } - + /// /// Gets the available cultures. /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs index d49c92f1bf..fc5382499f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs @@ -7,8 +7,6 @@ namespace Umbraco.Core.Persistence.Repositories { public interface IDocumentRepository : IContentRepository, IReadRepository { - - /// /// Clears the publishing schedule for all entries having an a date before (lower than, or equal to) a specified date. /// diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 04af52047c..d8e6fd2c0e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using NPoco; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -120,15 +119,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement break; case QueryType.Single: case QueryType.Many: + // R# may flag this ambiguous and red-squiggle it, but it is not + sql = sql.Select(r => + r.Select(documentDto => documentDto.ContentDto, r1 => + r1.Select(contentDto => contentDto.NodeDto)) + .Select(documentDto => documentDto.DocumentVersionDto, r1 => + r1.Select(documentVersionDto => documentVersionDto.ContentVersionDto)) + .Select(documentDto => documentDto.PublishedVersionDto, "pdv", r1 => + r1.Select(documentVersionDto => documentVersionDto.ContentVersionDto, "pcv"))) - //we've put this in a local function so that the below sql.Select statement doesn't have a problem - //thinking that the call is ambiguous - NPocoSqlExtensions.SqlRef SelectStatement(NPocoSqlExtensions.SqlRef r) => - r.Select(documentDto => documentDto.ContentDto, r1 => r1.Select(contentDto => contentDto.NodeDto)) - .Select(documentDto => documentDto.DocumentVersionDto, r1 => r1.Select(documentVersionDto => documentVersionDto.ContentVersionDto)) - .Select(documentDto => documentDto.PublishedVersionDto, "pdv", r1 => r1.Select(documentVersionDto => documentVersionDto.ContentVersionDto, "pcv")); - - sql = sql.Select(SelectStatement) // select the variant name, coalesce to the invariant name, as "variantName" .AndSelect(VariantNameSqlExpression + " AS variantName"); break; @@ -954,8 +953,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement #endregion - - protected override string ApplySystemOrdering(ref Sql sql, Ordering ordering) { // note: 'updater' is the user who created the latest draft version, @@ -1187,17 +1184,18 @@ namespace Umbraco.Core.Persistence.Repositories.Implement return result; } - private void SetVariations(Content content, IDictionary> contentVariations, IDictionary> documentVariations) { if (contentVariations.TryGetValue(content.VersionId, out var contentVariation)) foreach (var v in contentVariation) content.SetCultureInfo(v.Culture, v.Name, v.Date); + if (content.PublishedVersionId > 0 && contentVariations.TryGetValue(content.PublishedVersionId, out contentVariation)) { foreach (var v in contentVariation) content.SetPublishInfo(v.Culture, v.Name, v.Date); } + if (documentVariations.TryGetValue(content.Id, out var documentVariation)) content.SetCultureEdited(documentVariation.Where(x => x.Edited).Select(x => x.Culture)); } diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 600921ee78..942206ccc2 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -341,11 +341,10 @@ namespace Umbraco.Core.Services /// If the content type is variant, then culture can be either '*' or an actual culture, but neither 'null' nor /// 'empty'. If the content type is invariant, then culture can be either '*' or null or empty. /// - /// - /// - /// - /// - /// + /// The document to publish. + /// The culture to publish. + /// The identifier of the user performing the action. + /// A value indicating whether to raise events. PublishResult SaveAndPublish(IContent content, string culture = "*", int userId = 0, bool raiseEvents = true); /// @@ -356,11 +355,10 @@ namespace Umbraco.Core.Services /// When a culture is being published, it includes all varying values along with all invariant values. /// The document is *always* saved, even when publishing fails. /// - /// + /// The document to publish. /// The cultures to publish. - /// - /// - /// + /// The identifier of the user performing the action. + /// A value indicating whether to raise events. PublishResult SaveAndPublish(IContent content, string[] cultures, int userId = 0, bool raiseEvents = true); /// diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index ce7417722d..d034dad22d 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -908,8 +908,9 @@ namespace Umbraco.Core.Services.Implement : new PublishResult(PublishResultType.FailedPublishNothingToPublish, evtMsgs, content); } + // TODO: currently, no way to know which one failed if (cultures.Select(content.PublishCulture).Any(isValid => !isValid)) - return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content); //fixme: no way to know which one failed? + return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, content); return CommitDocumentChanges(content, userId, raiseEvents); } @@ -1055,9 +1056,10 @@ namespace Umbraco.Core.Services.Implement } // reset published state from temp values (publishing, unpublishing) to original value - // (published, unpublished) in order to save the document, unchanged - //TODO: why? this seems odd, were just setting the exact same value that it already has - // instead do we want to just set the PublishState? + // (published, unpublished) in order to save the document, unchanged - yes, this is odd, + // but: (a) it means we don't reproduce the PublishState logic here and (b) setting the + // PublishState to anything other than Publishing or Unpublishing - which is precisely + // what we want to do here - throws content.Published = content.Published; } } @@ -1080,9 +1082,10 @@ namespace Umbraco.Core.Services.Implement else { // reset published state from temp values (publishing, unpublishing) to original value - // (published, unpublished) in order to save the document, unchanged - //TODO: why? this seems odd, were just setting the exact same value that it already has - // instead do we want to just set the PublishState? + // (published, unpublished) in order to save the document, unchanged - yes, this is odd, + // but: (a) it means we don't reproduce the PublishState logic here and (b) setting the + // PublishState to anything other than Publishing or Unpublishing - which is precisely + // what we want to do here - throws content.Published = content.Published; } } @@ -1507,9 +1510,8 @@ namespace Umbraco.Core.Services.Implement Audit(AuditType.Publish, userId, document.Id, "Branch published"); // trigger events for the entire branch + // (SaveAndPublishBranchOne does *not* do it) scope.Events.Dispatch(TreeChanged, this, new TreeChange(document, TreeChangeTypes.RefreshBranch).ToEventArgs()); - - //fixme - in the SaveAndPublishBranchOne -> CommitDocumentChangesInternal publishing/published is going to be raised there, so are we raising it 2x for the same thing? scope.Events.Dispatch(Published, this, new ContentPublishedEventArgs(publishedDocuments, false, evtMsgs), nameof(Published)); scope.Complete(); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ab663b5a24..f6705f6619 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -302,6 +302,7 @@ +