diff --git a/src/Umbraco.Core/EventArgs.cs b/src/Umbraco.Core/EventArgs.cs
index 2d5fee1bcd..4b6a3fb2e3 100644
--- a/src/Umbraco.Core/EventArgs.cs
+++ b/src/Umbraco.Core/EventArgs.cs
@@ -1,9 +1,10 @@
-using Umbraco.Core.Models;
-
-namespace Umbraco.Core
+namespace Umbraco.Core
{
//Publishing Events
- public class PublishingEventArgs : System.ComponentModel.CancelEventArgs { }
+ public class PublishingEventArgs : System.ComponentModel.CancelEventArgs
+ {
+ public bool IsAllRepublished { get; set; }
+ }
public class SendToPublishEventArgs : System.ComponentModel.CancelEventArgs { }
//Moving object Events
diff --git a/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs b/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs
index e413732278..36656e5e27 100644
--- a/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs
+++ b/src/Umbraco.Core/Publishing/BasePublishingStrategy.cs
@@ -114,7 +114,8 @@ namespace Umbraco.Core.Publishing
/// Call to fire event that updating the published content has finalized.
///
/// An enumerable list of thats being published
- public abstract void PublishingFinalized(IEnumerable content);
+ /// Boolean indicating whether its all content that is republished
+ public abstract void PublishingFinalized(IEnumerable content, bool isAllRepublished);
///
/// Call to fire event that updating the unpublished content has finalized.
diff --git a/src/Umbraco.Core/Publishing/IPublishingStrategy.cs b/src/Umbraco.Core/Publishing/IPublishingStrategy.cs
index 4535e896cd..0408409488 100644
--- a/src/Umbraco.Core/Publishing/IPublishingStrategy.cs
+++ b/src/Umbraco.Core/Publishing/IPublishingStrategy.cs
@@ -54,7 +54,8 @@ namespace Umbraco.Core.Publishing
/// Call to fire event that updating the published content has finalized.
///
/// An enumerable list of thats being published
- void PublishingFinalized(IEnumerable content);
+ /// Boolean indicating whether its all content that is republished
+ void PublishingFinalized(IEnumerable content, bool isAllRepublished);
///
/// Call to fire event that updating the unpublished content has finalized.
diff --git a/src/Umbraco.Core/Publishing/PublishingStrategy.cs b/src/Umbraco.Core/Publishing/PublishingStrategy.cs
index 165a2339db..8b3bc8821a 100644
--- a/src/Umbraco.Core/Publishing/PublishingStrategy.cs
+++ b/src/Umbraco.Core/Publishing/PublishingStrategy.cs
@@ -252,9 +252,10 @@ namespace Umbraco.Core.Publishing
/// Call to fire event that updating the published content has finalized.
///
/// An enumerable list of thats being published
- public override void PublishingFinalized(IEnumerable content)
+ /// Boolean indicating whether its all content that is republished
+ public override void PublishingFinalized(IEnumerable content, bool isAllRepublished)
{
- OnPublished(content, new PublishingEventArgs());
+ OnPublished(content, new PublishingEventArgs{ IsAllRepublished = isAllRepublished});
}
///
diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index fe25a8f58f..6a3e670fab 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -362,7 +362,7 @@ namespace Umbraco.Core.Services
_unitOfWork.Commit();
//Updating content to published state is finished, so we fire event through PublishingStrategy to have cache updated
- _publishingStrategy.PublishingFinalized(updated);
+ _publishingStrategy.PublishingFinalized(updated, true);
Audit.Add(AuditTypes.Publish, "RePublish All performed by user", userId == -1 ? 0 : userId, -1);
}
@@ -433,7 +433,7 @@ namespace Umbraco.Core.Services
_unitOfWork.Commit();
//Save xml to db and call following method to fire event:
- _publishingStrategy.PublishingFinalized(updated);
+ _publishingStrategy.PublishingFinalized(updated, false);
Audit.Add(AuditTypes.Publish, "Publish with Children performed by user", userId == -1 ? 0 : userId, content.Id);
}
diff --git a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
index 9e6ea58ed8..ec2fff63a7 100644
--- a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
+++ b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
@@ -1,7 +1,5 @@
using System;
using System.IO;
-using System.Web;
-using System.Xml;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Configuration;
@@ -11,7 +9,6 @@ using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
-using Umbraco.Web.Strategies;
using umbraco.editorControls.tinyMCE3;
using umbraco.interfaces;
@@ -66,25 +63,7 @@ namespace Umbraco.Tests.Publishing
[Test]
public void Can_Publish_And_Update_Xml_Cache()
{
- // Arrange
- var httpContext = base.GetUmbracoContext("/test", 1234).HttpContext;
- var updateContentCache = new UpdateContentCache(httpContext);
- var contentService = ServiceContext.ContentService;
- var content = contentService.GetById(1046);
-
- // Act
- bool published = contentService.Publish(content, 0);
-
- // Assert
- Assert.That(published, Is.True);
- Assert.That(content.Published, Is.True);
- Assert.IsTrue(httpContext.Items.Contains("UmbracoXmlContextContent"));
-
- var document = httpContext.Items["UmbracoXmlContextContent"] as XmlDocument;
- Console.Write(document.OuterXml);
- document.Save("umbraco.config");
-
- updateContentCache.Unsubscribe();
+ //TODO Make new test
}
public void CreateTestData()
diff --git a/src/Umbraco.Web/Strategies/UpdateCacheAfterPublish.cs b/src/Umbraco.Web/Strategies/UpdateCacheAfterPublish.cs
new file mode 100644
index 0000000000..52bd6da466
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/UpdateCacheAfterPublish.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Umbraco.Core.Models;
+using Umbraco.Core.Publishing;
+using umbraco;
+using umbraco.cms.businesslogic.web;
+using umbraco.interfaces;
+using umbraco.presentation.cache;
+
+namespace Umbraco.Web.Strategies
+{
+ ///
+ /// Represents the UpdateCacheAfterPublish class, which subscribes to the Published event
+ /// of the class and is responsible for doing the actual
+ /// cache refresh after a content item has been published.
+ ///
+ ///
+ /// This implementation is meant as a seperation of the cache refresh from the ContentService
+ /// and PublishingStrategy.
+ ///
+ public class UpdateCacheAfterPublish : IApplicationStartupHandler
+ {
+ public UpdateCacheAfterPublish()
+ {
+ PublishingStrategy.Published += PublishingStrategy_Published;
+ }
+
+ void PublishingStrategy_Published(object sender, Core.PublishingEventArgs e)
+ {
+ if (sender is IContent)
+ {
+ var content = sender as IContent;
+ UpdateSingleContentCache(content);
+ }
+ else if (sender is IEnumerable)
+ {
+ if (e.IsAllRepublished)
+ {
+ var content = sender as IEnumerable;
+ UpdateMultipleContentCache(content);
+ }
+ else
+ {
+ UpdateEntireCache();
+ }
+ }
+ }
+
+ ///
+ /// Refreshes the xml cache for all nodes
+ ///
+ private void UpdateEntireCache()
+ {
+ if (UmbracoSettings.UseDistributedCalls)
+ {
+ dispatcher.RefreshAll(new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"));
+ }
+ else
+ {
+ content.Instance.RefreshContentFromDatabaseAsync();
+ }
+ }
+
+ ///
+ /// Refreshes the xml cache for nodes in list
+ ///
+ private void UpdateMultipleContentCache(IEnumerable content)
+ {
+ if (UmbracoSettings.UseDistributedCalls)
+ {
+ foreach (var c in content)
+ {
+ dispatcher.Refresh(new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"), c.Id);
+ }
+ }
+ else
+ {
+ var documents = content.Select(x => new Document(x)).ToList();
+ global::umbraco.content.Instance.UpdateDocumentCache(documents);
+ }
+ }
+
+ ///
+ /// Refreshes the xml cache for a single node
+ ///
+ private void UpdateSingleContentCache(IContent content)
+ {
+ if (UmbracoSettings.UseDistributedCalls)
+ {
+ dispatcher.Refresh(new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"), content.Id);
+ }
+ else
+ {
+ var doc = new Document(content);
+ global::umbraco.content.Instance.UpdateDocumentCache(doc);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/UpdateCacheAfterUnPublish.cs b/src/Umbraco.Web/Strategies/UpdateCacheAfterUnPublish.cs
new file mode 100644
index 0000000000..22eefc70af
--- /dev/null
+++ b/src/Umbraco.Web/Strategies/UpdateCacheAfterUnPublish.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using Umbraco.Core.Models;
+using Umbraco.Core.Publishing;
+using umbraco;
+using umbraco.interfaces;
+using umbraco.presentation.cache;
+
+namespace Umbraco.Web.Strategies
+{
+ ///
+ /// Represents the UpdateCacheAfterUnPublish class, which subscribes to the UnPublished event
+ /// of the class and is responsible for doing the actual
+ /// cache refresh after a content item has been unpublished.
+ ///
+ ///
+ /// This implementation is meant as a seperation of the cache refresh from the ContentService
+ /// and PublishingStrategy.
+ ///
+ public class UpdateCacheAfterUnPublish : IApplicationStartupHandler
+ {
+ public UpdateCacheAfterUnPublish()
+ {
+ PublishingStrategy.UnPublished += PublishingStrategy_UnPublished;
+ }
+
+ void PublishingStrategy_UnPublished(object sender, Core.PublishingEventArgs e)
+ {
+ if (sender is IContent)
+ {
+ var content = sender as IContent;
+ UnPublishSingle(content);
+ }
+ else if (sender is IEnumerable)
+ {
+ var content = sender as IEnumerable;
+ foreach (var c in content)
+ {
+ UnPublishSingle(c);
+ }
+ }
+ }
+
+ ///
+ /// Refreshes the xml cache for a single node by removing it
+ ///
+ private void UnPublishSingle(IContent content)
+ {
+ if (UmbracoSettings.UseDistributedCalls)
+ {
+ dispatcher.Remove(new Guid("27ab3022-3dfa-47b6-9119-5945bc88fd66"), content.Id);
+ }
+ else
+ {
+ global::umbraco.content.Instance.ClearDocumentCache(content.Id);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/UpdateContentCache.cs b/src/Umbraco.Web/Strategies/UpdateContentCache.cs
deleted file mode 100644
index 4dc81a5576..0000000000
--- a/src/Umbraco.Web/Strategies/UpdateContentCache.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Web;
-using System.Web.Caching;
-using System.Xml;
-using Umbraco.Core;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Models;
-using Umbraco.Core.Publishing;
-using Umbraco.Core.Services;
-using umbraco.interfaces;
-using umbraco.presentation.nodeFactory;
-using Node = umbraco.NodeFactory.Node;
-
-namespace Umbraco.Web.Strategies
-{
- internal class UpdateContentCache : IApplicationStartupHandler
- {
- // Sync access to internal cache
- private static readonly object XmlContentInternalSyncLock = new object();
- private const string XmlContextContentItemKey = "UmbracoXmlContextContent";
- private readonly HttpContextBase _httpContext;
- private readonly ServiceContext _serviceContext;
-
- public UpdateContentCache()
- {
- _httpContext = new HttpContextWrapper(HttpContext.Current);
- _serviceContext = ServiceContext.Current;
-
- PublishingStrategy.Published += PublishingStrategy_Published;
- }
-
- public UpdateContentCache(HttpContextBase httpContext)
- {
- _httpContext = httpContext;
- _serviceContext = ServiceContext.Current;
-
- PublishingStrategy.Published += PublishingStrategy_Published;
- }
-
- void PublishingStrategy_Published(object sender, PublishingEventArgs e)
- {
- if((sender is IContent) == false) return;
-
- //var e = new DocumentCacheEventArgs();
- //FireBeforeUpdateDocumentCache(d, e);
-
- var content = sender as IContent;
-
- // lock the xml cache so no other thread can write to it at the same time
- // note that some threads could read from it while we hold the lock, though
- lock (XmlContentInternalSyncLock)
- {
- XmlDocument wip = XmlContent;
-
- ClearContextCache();
-
- XmlContent = UpdateXmlAndSitemap(content, wip, false);//Update sitemap is usually set to true
- }
-
- // clear cached field values
- if (_httpContext != null)
- {
- Cache httpCache = _httpContext.Cache;
- string cachedFieldKeyStart = String.Format("contentItem{0}_", content.Id);
- var foundKeys = new List();
- foreach (DictionaryEntry cacheItem in httpCache)
- {
- string key = cacheItem.Key.ToString();
- if (key.StartsWith(cachedFieldKeyStart))
- foundKeys.Add(key);
- }
- foreach (string foundKey in foundKeys)
- {
- httpCache.Remove(foundKey);
- }
- }
-
- //Action.RunActionHandlers(d, ActionPublish.Instance);
- //FireAfterUpdateDocumentCache(d, e);
- }
-
- private XmlDocument UpdateXmlAndSitemap(IContent content, XmlDocument xmlContentCopy, bool updateSitemapProvider)
- {
- // check if document *is* published, it could be unpublished by an event
- if (content.Published)
- {
- int parentId = content.Level == 1 ? -1 : content.ParentId;
- var contentXmlNode = content.ToXml(false).GetXmlNode();
- var xmlNode = xmlContentCopy.ImportNode(contentXmlNode, true);
- xmlContentCopy = AppendContentXml(content.Id, content.Level, parentId, xmlNode, xmlContentCopy);
-
- // update sitemapprovider
- if (updateSitemapProvider && SiteMap.Provider is UmbracoSiteMapProvider)
- {
- try
- {
- var prov = (UmbracoSiteMapProvider)SiteMap.Provider;
- var n = new Node(content.Id, true);
- if (!String.IsNullOrEmpty(n.Url) && n.Url != "/#")
- {
- prov.UpdateNode(n);
- }
- else
- {
- //Log.Add(LogTypes.Error, content.Id, "Can't update Sitemap Provider due to empty Url in node");
- }
- }
- catch (Exception ee)
- {
- //Log.Add(LogTypes.Error, content.Id, string.Format("Error adding node to Sitemap Provider in PublishNodeDo(): {0}", ee));
- }
- }
- }
-
- return xmlContentCopy;
- }
-
- private XmlDocument AppendContentXml(int id, int level, int parentId, XmlNode docNode, XmlDocument xmlContentCopy)
- {
- // Find the document in the xml cache
- XmlNode x = xmlContentCopy.GetElementById(id.ToString());
-
- // if the document is not there already then it's a new document
- // we must make sure that its document type exists in the schema
- var xmlContentCopy2 = xmlContentCopy;
- if (x == null && UmbracoSettings.UseLegacyXmlSchema == false)
- {
- //TODO Look into the validate schema method - seems a bit odd
- //Move to Contract ?
- xmlContentCopy = ValidateSchema(docNode.Name, xmlContentCopy);
- if (xmlContentCopy != xmlContentCopy2)
- docNode = xmlContentCopy.ImportNode(docNode, true);
- }
-
- // Find the parent (used for sortering and maybe creation of new node)
- XmlNode parentNode;
- if (level == 1)
- parentNode = xmlContentCopy.DocumentElement;
- else
- parentNode = xmlContentCopy.GetElementById(parentId.ToString());
-
- if (parentNode != null)
- {
- if (x == null)
- {
- x = docNode;
- parentNode.AppendChild(x);
- }
- else
- {
- //TODO
- //TransferValuesFromDocumentXmlToPublishedXml(docNode, x);
- }
-
- // TODO: Update with new schema!
- string xpath = UmbracoSettings.UseLegacyXmlSchema ? "./node" : "./* [@id]";
- XmlNodeList childNodes = parentNode.SelectNodes(xpath);
-
- // Maybe sort the nodes if the added node has a lower sortorder than the last
- if (childNodes.Count > 0)
- {
- int siblingSortOrder =
- int.Parse(childNodes[childNodes.Count - 1].Attributes.GetNamedItem("sortOrder").Value);
- int currentSortOrder = int.Parse(x.Attributes.GetNamedItem("sortOrder").Value);
- if (childNodes.Count > 1 && siblingSortOrder > currentSortOrder)
- {
- //SortNodes(ref parentNode);
- }
- }
- }
-
- return xmlContentCopy;
- }
-
- ///
- /// Clear HTTPContext cache if any
- ///
- private void ClearContextCache()
- {
- // If running in a context very important to reset context cache or else new nodes are missing
- if (_httpContext != null && _httpContext.Items.Contains(XmlContextContentItemKey))
- _httpContext.Items.Remove(XmlContextContentItemKey);
- }
-
- private XmlDocument ValidateSchema(string docTypeAlias, XmlDocument xmlDoc)
- {
- // check if doctype is defined in schema else add it
- // can't edit the doctype of an xml document, must create a new document
-
- var doctype = xmlDoc.DocumentType;
- var subset = doctype.InternalSubset;
- if (!subset.Contains(string.Format("", docTypeAlias)))
- {
- subset = string.Format("\r\n\r\n{1}", docTypeAlias, subset);
- var xmlDoc2 = new XmlDocument();
- doctype = xmlDoc2.CreateDocumentType("root", null, null, subset);
- xmlDoc2.AppendChild(doctype);
- var root = xmlDoc2.ImportNode(xmlDoc.DocumentElement, true);
- xmlDoc2.AppendChild(root);
-
- // apply
- xmlDoc = xmlDoc2;
- }
-
- return xmlDoc;
- }
-
- private XmlDocument XmlContent
- {
- get
- {
- var content = _httpContext.Items[XmlContextContentItemKey] as XmlDocument;
- if (content == null)
- {
- //content = global::umbraco.content.Instance.XmlContent;
- var dtd = _serviceContext.ContentTypeService.GetDtd();
-
- content = new XmlDocument();
- content.LoadXml(
- String.Format("{0}{1}{0}",
- Environment.NewLine,
- dtd));
-
- _httpContext.Items[XmlContextContentItemKey] = content;
- }
- return content;
- }
- set { _httpContext.Items[XmlContextContentItemKey] = value; }
- }
-
- internal void Unsubscribe()
- {
- PublishingStrategy.Published -= PublishingStrategy_Published;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/UpdateMultipleContentCache.cs b/src/Umbraco.Web/Strategies/UpdateMultipleContentCache.cs
deleted file mode 100644
index fa06e82927..0000000000
--- a/src/Umbraco.Web/Strategies/UpdateMultipleContentCache.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using Umbraco.Core.Models;
-using Umbraco.Core.Publishing;
-
-namespace Umbraco.Web.Strategies
-{
- public class UpdateMultipleContentCache
- {
- public UpdateMultipleContentCache()
- {
- PublishingStrategy.Published += PublishingStrategy_Published;
- }
-
- void PublishingStrategy_Published(object sender, Core.PublishingEventArgs e)
- {
- if ((sender is IEnumerable) == false) return;
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index b46e7337e5..399a2e15bc 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -327,9 +327,9 @@
+
+
-
-
ASPXCodeBehind