From de13f7e3618bb01d43808b5dc098d01aebc912ec Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Sat, 9 Feb 2013 04:05:01 +0600 Subject: [PATCH] WIP ... Fixes: #U4-1666, Updates documentService to not have to manually refresh content cache (and fix the unpublishing too since that logic wasn't correct) Adds DebuggerDisplay support to ContentBase and Entity for better debugging info. Adds new internal publishing methods to support publishing all children or only children previously published. This also adds new support for getting a published result back even with bulk publishing. Updates the publish dialog with new code and to use the new API based on issue #U4-1669. Adds UmbracoUser property to AuthenticatedUmbracoController, Adds all common properties to the abstract UmbracoController. Changes the legacy Document to allow content cache to be automatically refreshed (based on events) --- .../Configuration/GlobalSettings.cs | 10 + src/Umbraco.Core/Models/Content.cs | 1 + src/Umbraco.Core/Models/ContentBase.cs | 2 + src/Umbraco.Core/Models/EntityBase/Entity.cs | 2 + src/Umbraco.Core/Models/IContent.cs | 3 +- .../Publishing/BasePublishingStrategy.cs | 18 ++ src/Umbraco.Core/Publishing/PublishStatus.cs | 29 +++ .../Publishing/PublishStatusType.cs | 40 +++ .../Publishing/PublishingStrategy.cs | 227 +++++++++++------- src/Umbraco.Core/Services/ContentService.cs | 22 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 + src/Umbraco.Core/UrlHelperExtensions.cs | 11 + .../Publishing/PublishingStrategyTests.cs | 67 +++++- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 9 + .../umbraco/dialogs/Publish.aspx.cs | 15 ++ .../umbraco/dialogs/Publish.aspx.designer.cs | 51 ++++ .../umbraco/dialogs/publish.aspx | 175 ++++++-------- .../umbraco_client/Dialogs/PublishDialog.css | 23 ++ .../umbraco_client/Dialogs/PublishDialog.js | 83 +++++++ src/Umbraco.Web/Mvc/RenderMvcController.cs | 53 +--- .../Mvc/UmbracoAuthorizeAttribute.cs | 3 +- .../Mvc/UmbracoAuthorizedController.cs | 68 +++++- src/Umbraco.Web/Mvc/UmbracoController.cs | 63 +++++ src/Umbraco.Web/UI/Pages/BasePage.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 16 +- .../WebServices/SaveFileController.cs | 21 +- .../umbraco.presentation/library.cs | 5 +- .../umbraco.presentation/publishingService.cs | 30 +-- .../Modules/CreateModule/CreateModule.cs | 9 +- .../umbraco/dialogs/publish.aspx | 119 --------- .../umbraco/dialogs/publish.aspx.cs | 95 +++++++- .../umbraco/dialogs/publish.aspx.designer.cs | 96 -------- .../umbraco/editContent.aspx.cs | 2 - .../umbraco/uQuery/DocumentExtensions.cs | 7 +- .../umbraco/webservices/publication.asmx.cs | 16 +- src/umbraco.cms/businesslogic/web/Document.cs | 2 +- .../documents/documentService.cs | 36 +-- 37 files changed, 880 insertions(+), 553 deletions(-) create mode 100644 src/Umbraco.Core/Publishing/PublishStatus.cs create mode 100644 src/Umbraco.Core/Publishing/PublishStatusType.cs create mode 100644 src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs create mode 100644 src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.designer.cs create mode 100644 src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.css create mode 100644 src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.js create mode 100644 src/Umbraco.Web/Mvc/UmbracoController.cs delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.designer.cs diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 7e6e2d53b5..c10b14ffcb 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -532,6 +532,16 @@ namespace Umbraco.Core.Configuration return context.Request.Path.ToLower().IndexOf(SystemDirectories.Umbraco.ToLower() + "/liveediting.aspx") > -1; } + public static bool RequestIsInUmbracoApplication(HttpContextBase context) + { + return context.Request.Path.ToLower().IndexOf(IOHelper.ResolveUrl(SystemDirectories.Umbraco).ToLower()) > -1; + } + + public static bool RequestIsLiveEditRedirector(HttpContextBase context) + { + return context.Request.Path.ToLower().IndexOf(SystemDirectories.Umbraco.ToLower() + "/liveediting.aspx") > -1; + } + /// /// Gets a value indicating whether umbraco should force a secure (https) connection to the backoffice. /// diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 631f88075e..2e99396707 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.Serialization; diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 6def10748f..3ddf71308e 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; @@ -13,6 +14,7 @@ namespace Umbraco.Core.Models /// /// Represents an abstract class for base Content properties and methods /// + [DebuggerDisplay("Id: {Id}, Name: {Name}, ContentType: {ContentTypeBase.Alias}")] public abstract class ContentBase : Entity, IContentBase { protected IContentTypeComposition ContentTypeBase; diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index 6c081ea0b4..95be4851e7 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -12,6 +13,7 @@ namespace Umbraco.Core.Models.EntityBase /// [Serializable] [DataContract(IsReference = true)] + [DebuggerDisplay("Id: {Id}")] public abstract class Entity : IEntity, ICanBeDirty { private bool _hasIdentity; diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 230b6693e5..7926c595b0 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -1,10 +1,11 @@ using System; +using System.Diagnostics; namespace Umbraco.Core.Models { /// /// Defines a Content object - /// + /// public interface IContent : IContentBase { /// diff --git a/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs b/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs index d126140c04..9ce2032b57 100644 --- a/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs +++ b/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs @@ -8,6 +8,24 @@ namespace Umbraco.Core.Publishing /// public abstract class BasePublishingStrategy : IPublishingStrategy { + + protected internal abstract Attempt PublishInternal(IContent content, int userId); + + /// + /// Publishes a list of content items + /// + /// + /// + /// + /// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and + /// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions + /// that have yet to be published. + /// + /// + protected internal abstract IEnumerable> PublishWithChildrenInternal(IEnumerable content, int userId, bool includeUnpublishedDocuments = true); + + protected internal abstract IEnumerable> UnPublishInternal(IEnumerable content, int userId); + public abstract bool Publish(IContent content, int userId); public abstract bool PublishWithChildren(IEnumerable content, int userId); public abstract bool UnPublish(IContent content, int userId); diff --git a/src/Umbraco.Core/Publishing/PublishStatus.cs b/src/Umbraco.Core/Publishing/PublishStatus.cs new file mode 100644 index 0000000000..e406c3fff5 --- /dev/null +++ b/src/Umbraco.Core/Publishing/PublishStatus.cs @@ -0,0 +1,29 @@ +using Umbraco.Core.Models; + +namespace Umbraco.Core.Publishing +{ + /// + /// The result of publishing a content item + /// + public class PublishStatus + { + public IContent ContentItem { get; private set; } + public PublishStatusType StatusType { get; private set; } + + public PublishStatus(IContent content, PublishStatusType statusType) + { + ContentItem = content; + StatusType = statusType; + } + + /// + /// Creates a successful publish status + /// + public PublishStatus(IContent content) + : this(content, PublishStatusType.Success) + { + } + + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Publishing/PublishStatusType.cs b/src/Umbraco.Core/Publishing/PublishStatusType.cs new file mode 100644 index 0000000000..59d063f41d --- /dev/null +++ b/src/Umbraco.Core/Publishing/PublishStatusType.cs @@ -0,0 +1,40 @@ +namespace Umbraco.Core.Publishing +{ + /// + /// A status type of the result of publishing a content item + /// + public enum PublishStatusType + { + /// + /// The publishing was successful. + /// + Success, + + /// + /// 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, + + /// + /// 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, + + /// + /// The content item is in the trash, it cannot be published + /// + FailedIsTrashed, + + /// + /// The publish action has been cancelled by an event handler + /// + FailedCancelledByEvent, + + /// + /// The content item contains invalid data (has not passed validation requirements) + /// + FailedContentInvalid + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Publishing/PublishingStrategy.cs b/src/Umbraco.Core/Publishing/PublishingStrategy.cs index 17a80be37b..8dfd36b8f6 100644 --- a/src/Umbraco.Core/Publishing/PublishingStrategy.cs +++ b/src/Umbraco.Core/Publishing/PublishingStrategy.cs @@ -4,6 +4,7 @@ using System.Linq; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core; namespace Umbraco.Core.Publishing { @@ -12,8 +13,46 @@ namespace Umbraco.Core.Publishing /// public class PublishingStrategy : BasePublishingStrategy { - public PublishingStrategy() + + protected internal override Attempt PublishInternal(IContent content, int userId) { + if (Publishing.IsRaisedEventCancelled(new PublishEventArgs(content), this)) + return new Attempt(false, new PublishStatus(content, PublishStatusType.FailedCancelledByEvent)); + + //Check if the Content is Expired to verify that it can in fact be published + if (content.Status == ContentStatus.Expired) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' has expired and could not be published.", + content.Name, content.Id)); + return new Attempt(false, new PublishStatus(content, PublishStatusType.FailedHasExpired)); + } + + //Check if the Content is Awaiting Release to verify that it can in fact be published + if (content.Status == ContentStatus.AwaitingRelease) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.", + content.Name, content.Id)); + return new Attempt(false, new PublishStatus(content, PublishStatusType.FailedAwaitingRelease)); + } + + //Check if the Content is Trashed to verify that it can in fact be published + if (content.Status == ContentStatus.Trashed) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.", + content.Name, content.Id)); + return new Attempt(false, new PublishStatus(content, PublishStatusType.FailedIsTrashed)); + } + + content.ChangePublishedState(PublishedState.Published); + + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' has been published.", + content.Name, content.Id)); + + return new Attempt(true, new PublishStatus(content)); } /// @@ -24,43 +63,79 @@ namespace Umbraco.Core.Publishing /// True if the publish operation was successfull and not cancelled, otherwise false public override bool Publish(IContent content, int userId) { - if (Publishing.IsRaisedEventCancelled(new PublishEventArgs(content), this)) - return false; + return PublishInternal(content, userId).Success; + } - //Check if the Content is Expired to verify that it can in fact be published - if (content.Status == ContentStatus.Expired) + /// + /// Publishes a list of content items + /// + /// + /// + /// + /// By default this is set to true which means that it will publish any content item in the list that is completely unpublished and + /// not visible on the front-end. If set to false, this will only publish content that is live on the front-end but has new versions + /// that have yet to be published. + /// + /// + protected internal override IEnumerable> PublishWithChildrenInternal(IEnumerable content, int userId, bool includeUnpublishedDocuments = true) + { + var statuses = new List>(); + + /* Only update content thats not already been published - we want to loop through + * all unpublished content to write skipped content (expired and awaiting release) to log. + */ + foreach (var item in content.Where(x => x.Published == false)) { + //Check if this item has never been published + if (!includeUnpublishedDocuments && !item.HasPublishedVersion()) + { + //this item does not have a published version and the flag is set to not include them + continue; + } + + //Fire Publishing event + if (Publishing.IsRaisedEventCancelled(new PublishEventArgs(item), this)) + + //Check if the Content is Expired to verify that it can in fact be published + if (item.Status == ContentStatus.Expired) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' has expired and could not be published.", + item.Name, item.Id)); + statuses.Add(new Attempt(false, new PublishStatus(item, PublishStatusType.FailedHasExpired))); + continue; + } + + //Check if the Content is Awaiting Release to verify that it can in fact be published + if (item.Status == ContentStatus.AwaitingRelease) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.", + item.Name, item.Id)); + statuses.Add(new Attempt(false, new PublishStatus(item, PublishStatusType.FailedAwaitingRelease))); + continue; + } + + //Check if the Content is Trashed to verify that it can in fact be published + if (item.Status == ContentStatus.Trashed) + { + LogHelper.Info( + string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.", + item.Name, item.Id)); + statuses.Add(new Attempt(false, new PublishStatus(item, PublishStatusType.FailedIsTrashed))); + continue; + } + + item.ChangePublishedState(PublishedState.Published); + LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has expired and could not be published.", - content.Name, content.Id)); - return false; + string.Format("Content '{0}' with Id '{1}' has been published.", + item.Name, item.Id)); + + statuses.Add(new Attempt(true, new PublishStatus(item))); } - //Check if the Content is Awaiting Release to verify that it can in fact be published - if (content.Status == ContentStatus.AwaitingRelease) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.", - content.Name, content.Id)); - return false; - } - - //Check if the Content is Trashed to verify that it can in fact be published - if (content.Status == ContentStatus.Trashed) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.", - content.Name, content.Id)); - return false; - } - - content.ChangePublishedState(PublishedState.Published); - - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has been published.", - content.Name, content.Id)); - - return true; + return statuses; } /// @@ -71,48 +146,14 @@ namespace Umbraco.Core.Publishing /// True if the publish operation was successfull and not cancelled, otherwise false public override bool PublishWithChildren(IEnumerable content, int userId) { - /* Only update content thats not already been published - we want to loop through - * all unpublished content to write skipped content (expired and awaiting release) to log. - */ - foreach (var item in content.Where(x => x.Published == false)) - { - //Fire Publishing event - if (Publishing.IsRaisedEventCancelled(new PublishEventArgs(item), this)) - - //Check if the Content is Expired to verify that it can in fact be published - if (item.Status == ContentStatus.Expired) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has expired and could not be published.", - item.Name, item.Id)); - continue; - } - - //Check if the Content is Awaiting Release to verify that it can in fact be published - if (item.Status == ContentStatus.AwaitingRelease) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' is awaiting release and could not be published.", - item.Name, item.Id)); - continue; - } - - //Check if the Content is Trashed to verify that it can in fact be published - if (item.Status == ContentStatus.Trashed) - { - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' is trashed and could not be published.", - item.Name, item.Id)); - continue; - } - - item.ChangePublishedState(PublishedState.Published); - - LogHelper.Info( - string.Format("Content '{0}' with Id '{1}' has been published.", - item.Name, item.Id)); - } - + var result = PublishWithChildrenInternal(content, userId); + + //NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)... + // ... if one item couldn't be published it wouldn't be correct to return false. + // in retrospect it should have returned a list of with Ids and Publish Status + // come to think of it ... the cache would still be updated for a failed item or at least tried updated. + // It would call the Published event for the entire list, but if the Published property isn't set to True it + // wouldn't actually update the cache for that item. But not really ideal nevertheless... return true; } @@ -147,20 +188,19 @@ namespace Umbraco.Core.Publishing return true; } - /// - /// Unpublishes a list of Content - /// - /// An enumerable list of - /// Id of the User issueing the unpublish operation - /// True if the unpublish operation was successfull and not cancelled, otherwise false - public override bool UnPublish(IEnumerable content, int userId) + protected internal override IEnumerable> UnPublishInternal(IEnumerable content, int userId) { + var result = new List>(); + //Only update content thats already been published foreach (var item in content.Where(x => x.Published == true)) { //Fire UnPublishing event if (UnPublishing.IsRaisedEventCancelled(new PublishEventArgs(item), this)) - return false; + { + result.Add(new Attempt(false, new PublishStatus(item, PublishStatusType.FailedCancelledByEvent))); + continue; + } //If Content has a release date set to before now, it should be removed so it doesn't interrupt an unpublish //Otherwise it would remain released == published @@ -178,8 +218,29 @@ namespace Umbraco.Core.Publishing LogHelper.Info( string.Format("Content '{0}' with Id '{1}' has been unpublished.", item.Name, item.Id)); + + result.Add(new Attempt(true, new PublishStatus(item))); } + return result; + } + + /// + /// Unpublishes a list of Content + /// + /// An enumerable list of + /// Id of the User issueing the unpublish operation + /// True if the unpublish operation was successfull and not cancelled, otherwise false + public override bool UnPublish(IEnumerable content, int userId) + { + var result = UnPublishInternal(content, userId); + + //NOTE: This previously always returned true so I've left it that way. It returned true because (from Morten)... + // ... if one item couldn't be published it wouldn't be correct to return false. + // in retrospect it should have returned a list of with Ids and Publish Status + // come to think of it ... the cache would still be updated for a failed item or at least tried updated. + // It would call the Published event for the entire list, but if the Published property isn't set to True it + // wouldn't actually update the cache for that item. But not really ideal nevertheless... return true; } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index ec1d53867e..fbad5073e4 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1017,16 +1017,17 @@ namespace Umbraco.Core.Services return SaveAndPublishDo(content, omitCacheRefresh, userId); } - /// - /// Internal method that Publishes a object and all its children for legacy purposes. - /// - /// The to publish along with its children - /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will not update the cache. - /// Optional Id of the User issueing the publishing - /// True if publishing succeeded, otherwise False - internal bool PublishWithChildren(IContent content, bool omitCacheRefresh = true, int userId = 0) + /// + /// Internal method that Publishes a object and all its children for legacy purposes. + /// + /// The to publish along with its children + /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will not update the cache. + /// Optional Id of the User issueing the publishing + /// If set to true, this will also publish descendants that are completely unpublished, normally this will only publish children that have previously been published + /// True if publishing succeeded, otherwise False + internal bool PublishWithChildren(IContent content, bool omitCacheRefresh = true, int userId = 0, bool includeUnpublished = false) { - return PublishWithChildrenDo(content, omitCacheRefresh, userId); + return PublishWithChildrenDo(content, omitCacheRefresh, userId, includeUnpublished); } /// @@ -1142,8 +1143,9 @@ namespace Umbraco.Core.Services /// The to publish along with its children /// Optional boolean to avoid having the cache refreshed when calling this Publish method. By default this method will update the cache. /// Optional Id of the User issueing the publishing + /// If set to true, this will also publish descendants that are completely unpublished, normally this will only publish children that have previously been published /// True if publishing succeeded, otherwise False - private bool PublishWithChildrenDo(IContent content, bool omitCacheRefresh = false, int userId = 0) + private bool PublishWithChildrenDo(IContent content, bool omitCacheRefresh = false, int userId = 0, bool includeUnpublished = false) { //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published if (content.ParentId != -1 && content.ParentId != -20 && IsPublishable(content) == false) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b21f82b8b5..4db747c5c1 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -636,6 +636,8 @@ + + diff --git a/src/Umbraco.Core/UrlHelperExtensions.cs b/src/Umbraco.Core/UrlHelperExtensions.cs index 9755dc24cc..0a0f4aaecc 100644 --- a/src/Umbraco.Core/UrlHelperExtensions.cs +++ b/src/Umbraco.Core/UrlHelperExtensions.cs @@ -23,5 +23,16 @@ namespace Umbraco.Core return result.TrimEnd("SavePartialView"); } + /// + /// Returns the base path (not including the 'action') of the MVC controller "BulkPublishController" + /// + /// + /// + public static string GetBulkPublishServicePath(this UrlHelper url) + { + var result = url.Action("PublishDocument", "BulkPublish", new { area = GlobalSettings.UmbracoMvcArea }); + return result.TrimEnd("PublishDocument"); + } + } } diff --git a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs index 0c601a227b..83a11814e1 100644 --- a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs +++ b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs @@ -7,10 +7,12 @@ using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Persistence; +using Umbraco.Core.Publishing; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using umbraco.editorControls.tinyMCE3; using umbraco.interfaces; +using System.Linq; namespace Umbraco.Tests.Publishing { @@ -58,6 +60,56 @@ namespace Umbraco.Tests.Publishing UmbracoSettings.ResetSetters(); } + private IContent _homePage; + + [Test] + public void Publishes_Many_Ignores_Unpublished_Items() + { + var strategy = new PublishingStrategy(); + + //publish root and nodes at it's children level + var result1 = strategy.Publish(_homePage, 0); + Assert.IsTrue(result1); + Assert.IsTrue(_homePage.Published); + foreach (var c in ServiceContext.ContentService.GetChildren(_homePage.Id)) + { + var r = strategy.Publish(c, 0); + Assert.IsTrue(r); + Assert.IsTrue(c.Published); + } + + //ok, all are published except the deepest descendant, we will pass in a flag to not include it to + //be published + var result = strategy.PublishWithChildrenInternal( + ServiceContext.ContentService.GetDescendants(_homePage).Concat(new[] {_homePage}), 0, false); + Assert.AreEqual(0, result.Count()); + } + + [Test] + public void Publishes_Many_Does_Not_Ignore_Unpublished_Items() + { + var strategy = new PublishingStrategy(); + + //publish root and nodes at it's children level + var result1 = strategy.Publish(_homePage, 0); + Assert.IsTrue(result1); + Assert.IsTrue(_homePage.Published); + foreach (var c in ServiceContext.ContentService.GetChildren(_homePage.Id)) + { + var r = strategy.Publish(c, 0); + Assert.IsTrue(r); + Assert.IsTrue(c.Published); + } + + //ok, all are published except the deepest descendant, we will pass in a flag to include it to + //be published + var result = strategy.PublishWithChildrenInternal( + ServiceContext.ContentService.GetDescendants(_homePage).Concat(new[] { _homePage }), 0, true); + Assert.AreEqual(1, result.Count()); + Assert.IsTrue(result.First().Success); + Assert.IsTrue(result.First().Result.ContentItem.Published); + } + [Test] public void Can_Publish_And_Update_Xml_Cache() { @@ -73,16 +125,21 @@ namespace Umbraco.Tests.Publishing ServiceContext.ContentTypeService.Save(contentType); //Create and Save Content "Homepage" based on "umbTextpage" -> 1046 - Content textpage = MockedContent.CreateSimpleContent(contentType); - ServiceContext.ContentService.Save(textpage, 0); + _homePage = MockedContent.CreateSimpleContent(contentType); + ServiceContext.ContentService.Save(_homePage, 0); //Create and Save Content "Text Page 1" based on "umbTextpage" -> 1047 - Content subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", textpage.Id); + Content subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", _homePage.Id); ServiceContext.ContentService.Save(subpage, 0); - //Create and Save Content "Text Page 1" based on "umbTextpage" -> 1048 - Content subpage2 = MockedContent.CreateSimpleContent(contentType, "Text Page 2", textpage.Id); + //Create and Save Content "Text Page 2" based on "umbTextpage" -> 1048 + Content subpage2 = MockedContent.CreateSimpleContent(contentType, "Text Page 2", _homePage.Id); ServiceContext.ContentService.Save(subpage2, 0); + + //Create and Save Content "Text Page 3" based on "umbTextpage" -> 1048 + Content subpage3 = MockedContent.CreateSimpleContent(contentType, "Text Page 3", subpage2.Id); + ServiceContext.ContentService.Save(subpage3, 0); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 13de47d66e..568fd21aa1 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -375,6 +375,13 @@ EditMacro.aspx + + publish.aspx + ASPXCodeBehind + + + publish.aspx + ASPXCodeBehind @@ -712,6 +719,8 @@ + + diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs new file mode 100644 index 0000000000..d9bdf2cd44 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Umbraco.Web.UI.Pages; + +namespace Umbraco.Web.UI.Umbraco.Dialogs +{ + public partial class Publish : UmbracoEnsuredPage + { + protected int TotalNodesToPublish { get; private set; } + protected string PageName { get; private set; } + protected int DocumentId { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.designer.cs b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.designer.cs new file mode 100644 index 0000000000..ee386da7b8 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.designer.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Umbraco.Web.UI.Umbraco.Dialogs { + + + public partial class Publish { + + /// + /// JsInclude1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; + + /// + /// JsInclude2 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude2; + + /// + /// CssInclude1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.CssInclude CssInclude1; + + /// + /// ProgBar1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.ProgressBar ProgBar1; + } +} diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/publish.aspx b/src/Umbraco.Web.UI/umbraco/dialogs/publish.aspx index b402e89381..2c065d0d75 100644 --- a/src/Umbraco.Web.UI/umbraco/dialogs/publish.aspx +++ b/src/Umbraco.Web.UI/umbraco/dialogs/publish.aspx @@ -1,119 +1,86 @@ -<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" Codebehind="publish.aspx.cs" AutoEventWireup="True" Inherits="umbraco.dialogs.publish" %> +<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" CodeBehind="Publish.aspx.cs" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Umbraco.Dialogs.Publish" %> + +<%@ Import Namespace="Umbraco.Core" %> +<%@ Import Namespace="Umbraco.Web" %> <%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> <%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - + - - - -
-
-

- <%= umbraco.ui.Text("publish", "publishHelp", pageName, base.getUser()) %> -

- -

- -

- - <%= umbraco.ui.Text("publish", "includeUnpublished")%> +
+
+

+ <%= umbraco.ui.Text("publish", "publishHelp", PageName, UmbracoUser) %> +

+ +
+ +
-

+ +
+ + +
+ + + + <%= umbraco.ui.Text("general","or") %> + + + <%=umbraco.ui.Text("general", "cancel", UmbracoUser)%> + +
- - <%= umbraco.ui.Text("general","or") %> <%=umbraco.ui.Text("general", "cancel", this.getUser())%> -
- - + + diff --git a/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.css b/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.css new file mode 100644 index 0000000000..3e0aa5e809 --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.css @@ -0,0 +1,23 @@ +#includeUnpublished { + margin-left: 16px; + margin-bottom: 20px; + margin-top: 5px; +} + +#animDiv > div { + width: 230px; + margin-left:auto; + margin-right:auto; +} + +#container a { + color: blue; +} + +.disabled { + color: #999; +} + +#feedbackMsg > div { + padding: 5px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.js b/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.js new file mode 100644 index 0000000000..3995c9165b --- /dev/null +++ b/src/Umbraco.Web.UI/umbraco_client/Dialogs/PublishDialog.js @@ -0,0 +1,83 @@ +Umbraco.Sys.registerNamespace("Umbraco.Dialogs"); + +(function ($) { + + Umbraco.Dialogs.PublishDialog = base2.Base.extend({ + + //private methods/variables + _opts: null, + + // Constructor + constructor: function () { + }, + + //public methods + + init: function (opts) { + /// Initializes the class and any UI bindings + + // Merge options with default + this._opts = $.extend({ + + }, opts); + + var self = this; + + //The knockout js view model for the selected item + var koViewModel = { + publishAll: ko.observable(false), + includeUnpublished: ko.observable(false), + processStatus: ko.observable("init"), + isSuccessful: ko.observable(false), + closeDialog: function () { + UmbClientMgr.closeModalWindow(); + }, + startPublish: function() { + this.processStatus("publishing"); + + $.post(self._opts.restServiceLocation + "PublishDocument", + JSON.stringify({ + documentId: self._opts.documentId + }), + function (e) { + if (e.success) { + self.submitSuccess(e.message, e.header); + } else { + self.submitFailure(e.message, e.header); + } + }); + } + }; + //ensure includeUnpublished is always false if publishAll is ever false + koViewModel.publishAll.subscribe(function (newValue) { + if (newValue === false) { + koViewModel.includeUnpublished(false); + } + }); + + ko.applyBindings(koViewModel); + } + + + }, { + //Static members + + //private methods/variables + _instance: null, + + // Singleton accessor + getInstance: function () { + if (this._instance == null) + this._instance = new Umbraco.Dialogs.PublishDialog(); + return this._instance; + } + }); + + //Set defaults for jQuery ajax calls. + $.ajaxSetup({ + dataType: 'json', + cache: false, + contentType: 'application/json; charset=utf-8' + }); + +})(jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 92e2715a0b..9b8c5b505d 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -11,7 +11,11 @@ using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { - public class RenderMvcController : Controller + + /// + /// A controller to render front-end requests + /// + public class RenderMvcController : UmbracoController { public RenderMvcController() @@ -21,46 +25,13 @@ namespace Umbraco.Web.Mvc private PublishedContentRequest _publishedContentRequest; - private UmbracoHelper _umbraco; - /// - /// Returns an UmbracoHelper object - /// - public UmbracoHelper Umbraco - { - get { return _umbraco ?? (_umbraco = new UmbracoHelper(UmbracoContext)); } - } - - /// - /// Returns the current UmbracoContext - /// - protected UmbracoContext UmbracoContext - { - get { return PublishedContentRequest.RoutingContext.UmbracoContext; } - } - - /// - /// Returns the current ApplicationContext - /// - public ApplicationContext ApplicationContext - { - get { return UmbracoContext.Application; } - } - - /// - /// Returns a ServiceContext - /// - public ServiceContext Services - { - get { return ApplicationContext.Services; } - } - - /// - /// Returns a DatabaseContext - /// - public DatabaseContext DatabaseContext - { - get { return ApplicationContext.DatabaseContext; } - } + /// + /// Returns the current UmbracoContext + /// + protected new UmbracoContext UmbracoContext + { + get { return PublishedContentRequest.RoutingContext.UmbracoContext; } + } /// /// Returns the Current published content item for rendering the content diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index 5d25dd69de..d357dead13 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -2,6 +2,7 @@ using System.Web; using System.Web.Mvc; using Umbraco.Core; +using Umbraco.Web.Security; using umbraco.BasePages; namespace Umbraco.Web.Mvc @@ -43,7 +44,7 @@ namespace Umbraco.Web.Mvc //we need to that the app is configured and that a user is logged in if (!_applicationContext.IsConfigured) return false; - var isLoggedIn = BasePage.ValidateUserContextID(BasePage.umbracoUserContextID); + var isLoggedIn = WebSecurity.ValidateUserContextId(WebSecurity.UmbracoUserContextId); return isLoggedIn; } catch (Exception) diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index 044109ee12..0006867568 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -1,11 +1,16 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; +using Umbraco.Core.Configuration; +using Umbraco.Web.Routing; +using Umbraco.Web.Security; +using umbraco.BusinessLogic; namespace Umbraco.Web.Mvc { - /// + /// /// A base MVC controller for use in the back office that ensures that every call to it authorizes the current user. /// /// @@ -13,7 +18,64 @@ namespace Umbraco.Web.Mvc /// authorization of each method can use this attribute instead of inheriting from this controller. /// [UmbracoAuthorize] - public abstract class UmbracoAuthorizedController : Controller + public abstract class UmbracoAuthorizedController : UmbracoController { + + private User _user; + private bool _userisValidated = false; + + /// + /// The current user ID + /// + private int _uid = 0; + + /// + /// The page timeout in seconds. + /// + private long _timeout = 0; + + /// + /// Returns the currently logged in Umbraco User + /// + protected User UmbracoUser + { + get + { + if (!_userisValidated) ValidateUser(); + return _user; + } + } + + private void ValidateUser() + { + if ((WebSecurity.UmbracoUserContextId != "")) + { + _uid = WebSecurity.GetUserId(WebSecurity.UmbracoUserContextId); + _timeout = WebSecurity.GetTimeout(WebSecurity.UmbracoUserContextId); + + if (_timeout > DateTime.Now.Ticks) + { + _user = global::umbraco.BusinessLogic.User.GetUser(_uid); + + // Check for console access + if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext))) + { + throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator"); + } + _userisValidated = true; + WebSecurity.UpdateLogin(_timeout); + } + else + { + throw new ArgumentException("User has timed out!!"); + } + } + else + { + throw new InvalidOperationException("The user has no umbraco contextid - try logging in"); + } + + } + } } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs new file mode 100644 index 0000000000..78dc6502fc --- /dev/null +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -0,0 +1,63 @@ +using System; +using System.Web.Mvc; +using Umbraco.Core; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Mvc +{ + /// + /// A base controller class containing all of the Umbraco objects as properties that a developer requires + /// + public abstract class UmbracoController : Controller + { + protected UmbracoController(UmbracoContext umbracoContext) + { + if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); + UmbracoContext = umbracoContext; + } + + protected UmbracoController() + : this(UmbracoContext.Current) + { + + } + + private UmbracoHelper _umbraco; + /// + /// Returns an UmbracoHelper object + /// + public UmbracoHelper Umbraco + { + get { return _umbraco ?? (_umbraco = new UmbracoHelper(UmbracoContext)); } + } + + /// + /// Returns the current UmbracoContext + /// + protected UmbracoContext UmbracoContext { get; private set; } + + /// + /// Returns the current ApplicationContext + /// + public ApplicationContext ApplicationContext + { + get { return UmbracoContext.Application; } + } + + /// + /// Returns a ServiceContext + /// + public ServiceContext Services + { + get { return ApplicationContext.Services; } + } + + /// + /// Returns a DatabaseContext + /// + public DatabaseContext DatabaseContext + { + get { return ApplicationContext.DatabaseContext; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/UI/Pages/BasePage.cs b/src/Umbraco.Web/UI/Pages/BasePage.cs index 00b456ef56..a7a60616e8 100644 --- a/src/Umbraco.Web/UI/Pages/BasePage.cs +++ b/src/Umbraco.Web/UI/Pages/BasePage.cs @@ -104,7 +104,7 @@ namespace Umbraco.Web.UI.Pages _user = global::umbraco.BusinessLogic.User.GetUser(_uid); // Check for console access - if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext.Current))) + if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(Context) && !GlobalSettings.RequestIsLiveEditRedirector(Context))) { throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator"); } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index de75f975b0..bf6848f623 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -302,6 +302,7 @@ + @@ -406,6 +407,9 @@ ASPXCodeBehind + + ASPXCodeBehind + ASPXCodeBehind @@ -1230,13 +1234,6 @@ protectPage.aspx - - publish.aspx - ASPXCodeBehind - - - publish.aspx - RegexWs.aspx ASPXCodeBehind @@ -1767,7 +1764,9 @@ - + + ASPXCodeBehind + ASPXCodeBehind @@ -1830,7 +1829,6 @@ - diff --git a/src/Umbraco.Web/WebServices/SaveFileController.cs b/src/Umbraco.Web/WebServices/SaveFileController.cs index 3665c3470f..2371aa001c 100644 --- a/src/Umbraco.Web/WebServices/SaveFileController.cs +++ b/src/Umbraco.Web/WebServices/SaveFileController.cs @@ -19,7 +19,26 @@ using Umbraco.Core; namespace Umbraco.Web.WebServices { - /// + /// + /// A REST controller used for the publish dialog in order to publish bulk items at once + /// + public class BulkPublishController : UmbracoAuthorizedController + { + /// + /// Publishes an document + /// + /// + /// A Json array containing objects with the child id's of the document and it's current published status + [HttpPost] + public JsonResult PublishDocument(int documentId, bool publishChildren) + { + //var doc = Services.ContentService.GetById(documentId); + //if (Services.ContentService.PublishWithChildren(doc, UmbracoUser.Id)) + return null; + } + } + + /// /// A REST controller used to save files such as templates, partial views, macro files, etc... /// /// diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs index 10dd8ec202..03e157fa4b 100644 --- a/src/Umbraco.Web/umbraco.presentation/library.cs +++ b/src/Umbraco.Web/umbraco.presentation/library.cs @@ -232,10 +232,7 @@ namespace umbraco /// internal static void UpdateDocumentCache(Document doc) { - if (UmbracoSettings.UseDistributedCalls) - DistributedCache.Instance.RefreshPageCache(doc.Id); - else - content.Instance.UpdateDocumentCache(doc); + DistributedCache.Instance.RefreshPageCache(doc.Id); } diff --git a/src/Umbraco.Web/umbraco.presentation/publishingService.cs b/src/Umbraco.Web/umbraco.presentation/publishingService.cs index f1d30e7005..be039bcd63 100644 --- a/src/Umbraco.Web/umbraco.presentation/publishingService.cs +++ b/src/Umbraco.Web/umbraco.presentation/publishingService.cs @@ -15,31 +15,26 @@ namespace umbraco.presentation /// public class publishingService { - private static Hashtable scheduledTaskTimes = new Hashtable(); - private static bool isPublishingRunning = false; + private static readonly Hashtable ScheduledTaskTimes = new Hashtable(); + private static bool _isPublishingRunning = false; public static void CheckPublishing(object sender) { - if(isPublishingRunning) + if(_isPublishingRunning) return; - isPublishingRunning = true; + _isPublishingRunning = true; try { // DO not run publishing if content is re-loading if(!content.Instance.isInitializing) { - foreach (Document d in Document.GetDocumentsForRelease()) + foreach (var d in Document.GetDocumentsForRelease()) { try { - //d.HttpContext = (HttpContext)sender; - d.ReleaseDate = DateTime.MinValue; //new DateTime(1, 1, 1); // Causes release date to be null - - d.Publish(d.User); - library.UpdateDocumentCache(d); - + d.SaveAndPublish(d.User); } catch(Exception ee) { @@ -48,9 +43,6 @@ namespace umbraco.presentation } foreach(Document d in Document.GetDocumentsForExpiration()) { - //d.HttpContext = (HttpContext)sender; - //d.Published = false; - try { d.ExpireDate = DateTime.MinValue; @@ -78,20 +70,20 @@ namespace umbraco.presentation foreach (XmlNode task in tasks) { bool runTask = false; - if (!scheduledTaskTimes.ContainsKey(task.Attributes.GetNamedItem("alias").Value)) + if (!ScheduledTaskTimes.ContainsKey(task.Attributes.GetNamedItem("alias").Value)) { runTask = true; - scheduledTaskTimes.Add(task.Attributes.GetNamedItem("alias").Value, DateTime.Now); + ScheduledTaskTimes.Add(task.Attributes.GetNamedItem("alias").Value, DateTime.Now); } // Add 1 second to timespan to compensate for differencies in timer else if ( new TimeSpan(DateTime.Now.Ticks - - ((DateTime) scheduledTaskTimes[task.Attributes.GetNamedItem("alias").Value]).Ticks).TotalSeconds + + ((DateTime) ScheduledTaskTimes[task.Attributes.GetNamedItem("alias").Value]).Ticks).TotalSeconds + 1 >= int.Parse(task.Attributes.GetNamedItem("interval").Value)) { runTask = true; - scheduledTaskTimes[task.Attributes.GetNamedItem("alias").Value] = DateTime.Now; + ScheduledTaskTimes[task.Attributes.GetNamedItem("alias").Value] = DateTime.Now; } if (runTask) @@ -115,7 +107,7 @@ namespace umbraco.presentation } finally { - isPublishingRunning = false; + _isPublishingRunning = false; } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs index fd353d09cc..43748c80bd 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/LiveEditing/Modules/CreateModule/CreateModule.cs @@ -128,11 +128,10 @@ namespace umbraco.presentation.LiveEditing.Modules.CreateModule switch (e.Type) { case "createcontent": - int userid = BasePages.UmbracoEnsuredPage.GetUserId(BasePages.UmbracoEnsuredPage.umbracoUserContextID); - DocumentType typeToCreate = new DocumentType(Convert.ToInt32(m_AllowedDocTypesDropdown.SelectedValue)); - Document newDoc = Document.MakeNew(m_NameTextBox.Text, typeToCreate, new global::umbraco.BusinessLogic.User(userid), (int)UmbracoContext.Current.PageId); - newDoc.Publish(new global::umbraco.BusinessLogic.User(userid)); - library.UpdateDocumentCache(newDoc); + var userid = BasePages.UmbracoEnsuredPage.GetUserId(BasePages.UmbracoEnsuredPage.umbracoUserContextID); + var typeToCreate = new DocumentType(Convert.ToInt32(m_AllowedDocTypesDropdown.SelectedValue)); + var newDoc = Document.MakeNew(m_NameTextBox.Text, typeToCreate, new BusinessLogic.User(userid), (int)UmbracoContext.Current.PageId); + newDoc.SaveAndPublish(new BusinessLogic.User(userid)); Page.Response.Redirect(library.NiceUrl(newDoc.Id), false); break; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx deleted file mode 100644 index b402e89381..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx +++ /dev/null @@ -1,119 +0,0 @@ -<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" Codebehind="publish.aspx.cs" AutoEventWireup="True" Inherits="umbraco.dialogs.publish" %> -<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %> -<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %> - - - - - - - - - - - - - -
-
-

- <%= umbraco.ui.Text("publish", "publishHelp", pageName, base.getUser()) %> -

- -

- -

- - <%= umbraco.ui.Text("publish", "includeUnpublished")%> -
-

-
- - <%= umbraco.ui.Text("general","or") %> <%=umbraco.ui.Text("general", "cancel", this.getUser())%> -
- - - -
- - - - - - - -
\ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs index bfe92ef3c6..8c526a4d6f 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; @@ -11,6 +12,7 @@ using System.Web.UI.HtmlControls; using System.Threading; using Umbraco.Core.Logging; +using umbraco.cms.businesslogic.web; using umbraco.cms.helpers; using umbraco.BasePages; @@ -89,7 +91,7 @@ namespace umbraco.dialogs //PPH added load balancing... //content.Instance.PublishNode(documents); - foreach (cms.businesslogic.web.Document doc in documents) + foreach (cms.businesslogic.web.Document doc in _documents) { if (doc.Published) { @@ -132,19 +134,19 @@ namespace umbraco.dialogs theEnd.Visible = true; } } - private System.Collections.Generic.List documents = new System.Collections.Generic.List(); + private readonly List _documents = new List(); - private void doPublishSubs(cms.businesslogic.web.Document d) + private void doPublishSubs(Document d) { if (d.Published || PublishUnpublishedItems.Checked) { - if (d.PublishWithResult(base.getUser())) + if (d.PublishWithResult(UmbracoUser)) { // Needed for supporting distributed calls if (UmbracoSettings.UseDistributedCalls) library.UpdateDocumentCache(d); else - documents.Add(d); + _documents.Add(d); nodesPublished++; Application.Lock(); @@ -168,5 +170,86 @@ namespace umbraco.dialogs ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx")); } + + /// + /// masterPagePrefix control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal masterPagePrefix; + + /// + /// JsInclude1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; + + /// + /// TheForm control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel TheForm; + + /// + /// PublishAll control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox PublishAll; + + /// + /// PublishUnpublishedItems control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox PublishUnpublishedItems; + + /// + /// ok control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button ok; + + /// + /// ProgBar1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.ProgressBar ProgBar1; + + /// + /// theEnd control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel theEnd; + + /// + /// feedbackMsg control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::umbraco.uicontrols.Feedback feedbackMsg; } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.designer.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.designer.cs deleted file mode 100644 index d9ebc3eefe..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/publish.aspx.designer.cs +++ /dev/null @@ -1,96 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace umbraco.dialogs { - - - public partial class publish { - - /// - /// masterPagePrefix control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal masterPagePrefix; - - /// - /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// TheForm control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel TheForm; - - /// - /// PublishAll control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox PublishAll; - - /// - /// PublishUnpublishedItems control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox PublishUnpublishedItems; - - /// - /// ok control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button ok; - - /// - /// ProgBar1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.ProgressBar ProgBar1; - - /// - /// theEnd control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel theEnd; - - /// - /// feedbackMsg control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Feedback feedbackMsg; - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs index 09487683c5..e2ece7bf2f 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs @@ -448,8 +448,6 @@ namespace umbraco.cms.presentation tp.ErrorControl.Visible = false; } } - //Audit trail... - Log.Add(LogTypes.Save, UmbracoUser, _document.Id, ""); if (_dpRelease.DateTime > new DateTime(1753, 1, 1) && _dpRelease.DateTime < new DateTime(9999, 12, 31)) _document.ReleaseDate = _dpRelease.DateTime; diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs index de897b6209..b89fddf8a4 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/uQuery/DocumentExtensions.cs @@ -240,18 +240,15 @@ namespace umbraco { if (useAdminUser) { - document.Publish(new User(0)); + document.SaveAndPublish(new User(0)); } else { if (User.GetCurrent() != null) { - document.Publish(User.GetCurrent()); + document.SaveAndPublish(User.GetCurrent()); } } - - library.UpdateDocumentCache(document); - return document; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/publication.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/publication.asmx.cs index 56fbdf7ae0..c68d7a7bf7 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/publication.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/publication.asmx.cs @@ -13,12 +13,7 @@ namespace umbraco.webservices [ScriptService] public class publication : WebService { - public publication() - { - //CODEGEN: This call is required by the ASP.NET Web Services Designer - InitializeComponent(); - } - + [WebMethod] [ScriptMethod] public int GetPublicationStatus(string key) @@ -82,14 +77,7 @@ namespace umbraco.webservices //Required by the Web Services Designer private IContainer components = null; - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - } + /// /// Clean up any resources being used. diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 8164317df1..690b3a0750 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -801,7 +801,7 @@ namespace umbraco.cms.businesslogic.web if (!e.Cancel) { - var result = ((ContentService)ApplicationContext.Current.Services.ContentService).Publish(Content, true, u.Id); + var result = ((ContentService)ApplicationContext.Current.Services.ContentService).Publish(Content, false, u.Id); _published = result; FireAfterPublish(e); diff --git a/src/umbraco.webservices/documents/documentService.cs b/src/umbraco.webservices/documents/documentService.cs index 634033cffd..70e25c16f3 100644 --- a/src/umbraco.webservices/documents/documentService.cs +++ b/src/umbraco.webservices/documents/documentService.cs @@ -36,31 +36,31 @@ namespace umbraco.webservices.documents if (carrier.ParentID == 0) throw new Exception("Document needs a parent"); if (carrier.DocumentTypeID == 0) throw new Exception("Documenttype must be specified"); if (carrier.Id != 0) throw new Exception("ID cannot be specifed when creating. Must be 0"); - if (carrier.Name == null || carrier.Name.Length == 0) carrier.Name = "unnamed"; + if (string.IsNullOrEmpty(carrier.Name)) carrier.Name = "unnamed"; - umbraco.BusinessLogic.User user = GetUser(username, password); + var user = GetUser(username, password); // We get the documenttype - umbraco.cms.businesslogic.web.DocumentType docType = new umbraco.cms.businesslogic.web.DocumentType(carrier.DocumentTypeID); + var docType = new DocumentType(carrier.DocumentTypeID); if (docType == null) throw new Exception("DocumenttypeID " + carrier.DocumentTypeID + " not found"); // We create the document - Document newDoc = Document.MakeNew(carrier.Name, docType, user, carrier.ParentID); + var newDoc = Document.MakeNew(carrier.Name, docType, user, carrier.ParentID); newDoc.ReleaseDate = carrier.ReleaseDate; newDoc.ExpireDate = carrier.ExpireDate; // We iterate the properties in the carrier if (carrier.DocumentProperties != null) { - foreach (documentProperty updatedproperty in carrier.DocumentProperties) + foreach (var updatedproperty in carrier.DocumentProperties) { - umbraco.cms.businesslogic.property.Property property = newDoc.getProperty(updatedproperty.Key); + var property = newDoc.getProperty(updatedproperty.Key); if (property == null) throw new Exception("property " + updatedproperty.Key + " was not found"); property.Value = updatedproperty.PropertyValue; } } - // We check the publishaction and do the appropiate + // We check the publish action and do the appropiate handlePublishing(newDoc, carrier, user); // We return the ID of the document..65 @@ -244,31 +244,21 @@ namespace umbraco.webservices.documents switch (carrier.PublishAction) { case documentCarrier.EPublishAction.Publish: - if (doc.PublishWithResult(user)) - { - umbraco.library.UpdateDocumentCache(doc); - } + doc.SaveAndPublish(user); break; case documentCarrier.EPublishAction.Unpublish: - if (doc.PublishWithResult(user)) - { - umbraco.library.UnPublishSingleNode(doc); - } + doc.UnPublish(); + library.UnPublishSingleNode(doc); break; case documentCarrier.EPublishAction.Ignore: if (doc.Published) { - if (doc.PublishWithResult(user)) - { - umbraco.library.UpdateDocumentCache(doc); - } + doc.UnPublish(); + library.UnPublishSingleNode(doc); } else { - if (doc.PublishWithResult(user)) - { - umbraco.library.UpdateDocumentCache(doc); - } + doc.SaveAndPublish(user); } break; }