merge with 6.1.0
This commit is contained in:
@@ -58,9 +58,14 @@ namespace Umbraco.Core.Strings
|
||||
static void InitializeLegacyUrlReplaceCharacters()
|
||||
{
|
||||
var replaceChars = UmbracoSettings.UrlReplaceCharacters;
|
||||
foreach (var node in replaceChars.SelectNodes("char").Cast<System.Xml.XmlNode>())
|
||||
if (replaceChars == null) return;
|
||||
var nodes = replaceChars.SelectNodes("char");
|
||||
if (nodes == null) return;
|
||||
foreach (var node in nodes.Cast<System.Xml.XmlNode>())
|
||||
{
|
||||
var org = node.Attributes.GetNamedItem("org");
|
||||
var attributes = node.Attributes;
|
||||
if (attributes == null) continue;
|
||||
var org = attributes.GetNamedItem("org");
|
||||
if (org != null && org.Value != "")
|
||||
UrlReplaceCharacters[org.Value] = XmlHelper.GetNodeValue(node);
|
||||
}
|
||||
|
||||
217
src/Umbraco.Tests/CoreXml/FrameworkXmlTests.cs
Normal file
217
src/Umbraco.Tests/CoreXml/FrameworkXmlTests.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Umbraco.Tests.CoreXml
|
||||
{
|
||||
[TestFixture]
|
||||
public class FrameworkXmlTests
|
||||
{
|
||||
const string Xml1 = @"<root>
|
||||
<items>
|
||||
<item1 />
|
||||
<item2>
|
||||
<item21>text21</item21>
|
||||
</item2>
|
||||
<item3>
|
||||
<item31>text31</item31>
|
||||
</item3>
|
||||
<item4 />
|
||||
<item5 />
|
||||
<item6 />
|
||||
</items>
|
||||
</root>";
|
||||
|
||||
|
||||
// Umbraco : the following test shows that when legacy imports the whole tree in a
|
||||
// "contentAll" xslt macro parameter, the entire collection of nodes is cloned ie is
|
||||
// duplicated.
|
||||
//
|
||||
// What is the impact on memory?
|
||||
// What happens for non-xslt macros?
|
||||
|
||||
[Test]
|
||||
public void ImportNodeClonesImportedNode()
|
||||
{
|
||||
var doc1 = new XmlDocument();
|
||||
doc1.LoadXml(Xml1);
|
||||
|
||||
var node1 = doc1.SelectSingleNode("//item2");
|
||||
Assert.IsNotNull(node1);
|
||||
|
||||
var doc2 = new XmlDocument();
|
||||
doc2.LoadXml("<nodes />");
|
||||
var node2 = doc2.ImportNode(node1, true);
|
||||
var root2 = doc2.DocumentElement;
|
||||
Assert.IsNotNull(root2);
|
||||
root2.AppendChild(node2);
|
||||
|
||||
var node3 = doc2.SelectSingleNode("//item2");
|
||||
|
||||
Assert.AreNotSame(node1, node2); // has been cloned
|
||||
Assert.AreSame(node2, node3); // has been appended
|
||||
|
||||
Assert.AreNotSame(node1.FirstChild, node2.FirstChild); // deep clone
|
||||
}
|
||||
|
||||
|
||||
// Umbraco: the CanRemove...NodeAndNavigate tests shows that if the underlying XmlDocument
|
||||
// is modified while navigating, then strange situations can be created. For xslt macros,
|
||||
// the result depends on what the xslt engine is doing at the moment = unpredictable.
|
||||
//
|
||||
// What happens for non-xslt macros?
|
||||
|
||||
[Test]
|
||||
public void CanRemoveCurrentNodeAndNavigate()
|
||||
{
|
||||
var doc1 = new XmlDocument();
|
||||
doc1.LoadXml(Xml1);
|
||||
var nav1 = doc1.CreateNavigator();
|
||||
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("root", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("items", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("item1", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToNext());
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
|
||||
var node1 = doc1.SelectSingleNode("//item2");
|
||||
Assert.IsNotNull(node1);
|
||||
var parent1 = node1.ParentNode;
|
||||
Assert.IsNotNull(parent1);
|
||||
parent1.RemoveChild(node1);
|
||||
|
||||
// navigator now navigates on an isolated fragment
|
||||
// that is rooted on the node that was removed
|
||||
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
Assert.IsFalse(nav1.MoveToPrevious());
|
||||
Assert.IsFalse(nav1.MoveToNext());
|
||||
Assert.IsFalse(nav1.MoveToParent());
|
||||
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("item21", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToParent());
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
|
||||
nav1.MoveToRoot();
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRemovePathNodeAndNavigate()
|
||||
{
|
||||
var doc1 = new XmlDocument();
|
||||
doc1.LoadXml(Xml1);
|
||||
var nav1 = doc1.CreateNavigator();
|
||||
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("root", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("items", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("item1", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToNext());
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("item21", nav1.Name);
|
||||
|
||||
var node1 = doc1.SelectSingleNode("//item2");
|
||||
Assert.IsNotNull(node1);
|
||||
var parent1 = node1.ParentNode;
|
||||
Assert.IsNotNull(parent1);
|
||||
parent1.RemoveChild(node1);
|
||||
|
||||
// navigator now navigates on an isolated fragment
|
||||
// that is rooted on the node that was removed
|
||||
|
||||
Assert.AreEqual("item21", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToParent());
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
Assert.IsFalse(nav1.MoveToPrevious());
|
||||
Assert.IsFalse(nav1.MoveToNext());
|
||||
Assert.IsFalse(nav1.MoveToParent());
|
||||
|
||||
nav1.MoveToRoot();
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanRemoveOutOfPathNodeAndNavigate()
|
||||
{
|
||||
var doc1 = new XmlDocument();
|
||||
doc1.LoadXml(Xml1);
|
||||
var nav1 = doc1.CreateNavigator();
|
||||
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("root", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("items", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToFirstChild());
|
||||
Assert.AreEqual("item1", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToNext());
|
||||
Assert.AreEqual("item2", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToNext());
|
||||
Assert.AreEqual("item3", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToNext());
|
||||
Assert.AreEqual("item4", nav1.Name);
|
||||
|
||||
var node1 = doc1.SelectSingleNode("//item2");
|
||||
Assert.IsNotNull(node1);
|
||||
var parent1 = node1.ParentNode;
|
||||
Assert.IsNotNull(parent1);
|
||||
parent1.RemoveChild(node1);
|
||||
|
||||
// navigator sees the change
|
||||
|
||||
Assert.AreEqual("item4", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToPrevious());
|
||||
Assert.AreEqual("item3", nav1.Name);
|
||||
Assert.IsTrue(nav1.MoveToPrevious());
|
||||
Assert.AreEqual("item1", nav1.Name);
|
||||
}
|
||||
|
||||
// Umbraco: the following test shows that if the underlying XmlDocument is modified while
|
||||
// iterating, then strange situations can be created. For xslt macros, the result depends
|
||||
// on what the xslt engine is doing at the moment = unpredictable.
|
||||
//
|
||||
// What happens for non-xslt macros?
|
||||
|
||||
[Test]
|
||||
public void CanRemoveNodeAndIterate()
|
||||
{
|
||||
var doc1 = new XmlDocument();
|
||||
doc1.LoadXml(Xml1);
|
||||
var nav1 = doc1.CreateNavigator();
|
||||
|
||||
var iter1 = nav1.Select("//items/*");
|
||||
var iter2 = nav1.Select("//items/*");
|
||||
|
||||
Assert.AreEqual(6, iter1.Count);
|
||||
|
||||
var node1 = doc1.SelectSingleNode("//item2");
|
||||
Assert.IsNotNull(node1);
|
||||
var parent1 = node1.ParentNode;
|
||||
Assert.IsNotNull(parent1);
|
||||
parent1.RemoveChild(node1);
|
||||
|
||||
// iterator partially sees the change
|
||||
|
||||
Assert.AreEqual(6, iter1.Count); // has been cached, not updated
|
||||
Assert.AreEqual(5, iter2.Count); // not calculated yet, correct value
|
||||
|
||||
var count = 0;
|
||||
while (iter1.MoveNext())
|
||||
count++;
|
||||
|
||||
Assert.AreEqual(5, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,7 @@
|
||||
<Compile Include="CodeFirst\TopologicalSorter.cs" />
|
||||
<Compile Include="CodeFirst\TypeInheritanceTest.cs" />
|
||||
<Compile Include="Configurations\FileSystemProviderTests.cs" />
|
||||
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
|
||||
<Compile Include="PublishedCache\PublishedMediaCacheTests.cs" />
|
||||
<Compile Include="CoreStrings\CmsHelperCasingTests.cs" />
|
||||
<Compile Include="CoreStrings\ShortStringHelperResolverTest.cs" />
|
||||
|
||||
@@ -209,12 +209,15 @@ namespace Umbraco.Web.Cache
|
||||
if (payloads.Any(x => x.Type == typeof(IContentType).Name)
|
||||
&& !payloads.All(x => x.IsNew)) //if they are all new then don't proceed
|
||||
{
|
||||
//we need to clear the routes cache here!
|
||||
var contentCache = PublishedContentCacheResolver.Current.ContentCache as PublishedContentCache;
|
||||
// SD: we need to clear the routes cache here!
|
||||
//
|
||||
// zpqrtbnk: no, not here, in fact the caches should subsribe to refresh events else we
|
||||
// are creating a nasty dependency - but keep it like that for the time being while
|
||||
// SD is cleaning cache refreshers up.
|
||||
|
||||
var contentCache = PublishedCachesResolver.Current.Caches.ContentCache as PublishedContentCache;
|
||||
if (contentCache != null)
|
||||
{
|
||||
contentCache.RoutesCache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,16 @@ namespace Umbraco.Web.Cache
|
||||
private void ClearCache()
|
||||
{
|
||||
ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.DomainCacheKey);
|
||||
//we need to clear the routes cache here!
|
||||
|
||||
// SD: we need to clear the routes cache here!
|
||||
//
|
||||
// zpqrtbnk: no, not here, in fact the caches should subsribe to refresh events else we
|
||||
// are creating a nasty dependency - but keep it like that for the time being while
|
||||
// SD is cleaning cache refreshers up.
|
||||
|
||||
var contentCache = PublishedContentCacheResolver.Current.ContentCache as PublishedContentCache;
|
||||
if (contentCache != null)
|
||||
{
|
||||
contentCache.RoutesCache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,14 +87,16 @@ namespace Umbraco.Web.Routing
|
||||
if (_pcr.IsRedirect)
|
||||
return;
|
||||
|
||||
// safety
|
||||
if (!_pcr.HasPublishedContent)
|
||||
_pcr.Is404 = true;
|
||||
{
|
||||
// safety
|
||||
_pcr.Is404 = true;
|
||||
|
||||
// handle 404 : return
|
||||
// whoever called us is in charge of doing what's appropriate
|
||||
if (_pcr.Is404)
|
||||
return;
|
||||
// whoever called us is in charge of doing what's appropriate
|
||||
return;
|
||||
}
|
||||
|
||||
// we may be 404 _and_ have a content
|
||||
|
||||
// can't go beyond that point without a PublishedContent to render
|
||||
// it's ok not to have a template, in order to give MVC a chance to hijack routes
|
||||
|
||||
@@ -114,11 +114,13 @@ namespace Umbraco.Web
|
||||
/// <param name="applicationContext"> </param>
|
||||
/// <param name="contentCache">The published content cache.</param>
|
||||
/// <param name="mediaCache">The published media cache.</param>
|
||||
/// <param name="preview">An optional value overriding detection of preview mode.</param>
|
||||
internal UmbracoContext(
|
||||
HttpContextBase httpContext,
|
||||
ApplicationContext applicationContext,
|
||||
IPublishedContentCache contentCache,
|
||||
IPublishedMediaCache mediaCache)
|
||||
IPublishedMediaCache mediaCache,
|
||||
bool? preview = null)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
|
||||
@@ -131,6 +133,7 @@ namespace Umbraco.Web
|
||||
|
||||
ContentCache = new ContextualPublishedContentCache(contentCache, this);
|
||||
MediaCache = new ContextualPublishedMediaCache(mediaCache, this);
|
||||
InPreviewMode = preview ?? DetectInPreviewModeFromRequest();
|
||||
|
||||
// set the urls...
|
||||
//original request url
|
||||
@@ -319,22 +322,21 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Determines whether the current user is in a preview mode and browsing the site (ie. not in the admin UI)
|
||||
/// </summary>
|
||||
public bool InPreviewMode
|
||||
{
|
||||
get
|
||||
{
|
||||
var request = GetRequestFromContext();
|
||||
if (request == null || request.Url == null)
|
||||
return false;
|
||||
public bool InPreviewMode { get; private set; }
|
||||
|
||||
var currentUrl = request.Url.AbsolutePath;
|
||||
// zb-00004 #29956 : refactor cookies names & handling
|
||||
return
|
||||
StateHelper.Cookies.Preview.HasValue // has preview cookie
|
||||
&& UmbracoUser != null // has user
|
||||
&& !currentUrl.StartsWith(Umbraco.Core.IO.IOHelper.ResolveUrl(Umbraco.Core.IO.SystemDirectories.Umbraco)); // is not in admin UI
|
||||
}
|
||||
}
|
||||
private bool DetectInPreviewModeFromRequest()
|
||||
{
|
||||
var request = GetRequestFromContext();
|
||||
if (request == null || request.Url == null)
|
||||
return false;
|
||||
|
||||
var currentUrl = request.Url.AbsolutePath;
|
||||
// zb-00004 #29956 : refactor cookies names & handling
|
||||
return
|
||||
StateHelper.Cookies.Preview.HasValue // has preview cookie
|
||||
&& UmbracoUser != null // has user
|
||||
&& !currentUrl.StartsWith(Umbraco.Core.IO.IOHelper.ResolveUrl(Umbraco.Core.IO.SystemDirectories.Umbraco)); // is not in admin UI
|
||||
}
|
||||
|
||||
private HttpRequestBase GetRequestFromContext()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user