Created an ContentStoreResolver so we can specify a custom ContentStore which means we can return a custom

IDocument. This now means we've opened up the possibility of an abstracted routing lookup system to map to a Document
stored anywhere. By default this is obviously Xml but could theoretically be anything, still internal until more review
of the API is done.
This commit is contained in:
shannon@ShandemVaio
2012-08-10 13:38:02 +06:00
parent a858712bcc
commit c522ad6e30
15 changed files with 105 additions and 64 deletions

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Tests
{
private FakeHttpContextFactory _httpContextFactory;
private UmbracoContext _umbracoContext;
private ContentStore _contentStore;
private XmlContentStore _contentStore;
[SetUp]
public void SetUp()
@@ -56,7 +56,7 @@ namespace Umbraco.Tests
return xDoc;
};
_contentStore = new ContentStore(_umbracoContext);
_contentStore = new XmlContentStore();
}
@@ -74,7 +74,7 @@ namespace Umbraco.Tests
[TestCase("/home/Sub1", 1173)] //test different cases
public void Get_Node_By_Route(string route, int nodeId)
{
var result = _contentStore.GetDocumentByRoute(route, false);
var result = _contentStore.GetDocumentByRoute(_umbracoContext, route, false);
Assert.IsNotNull(result);
Assert.AreEqual(nodeId, result.Id);
}
@@ -84,7 +84,7 @@ namespace Umbraco.Tests
[TestCase("/Sub1", 1173)]
public void Get_Node_By_Route_Hiding_Top_Level_Nodes(string route, int nodeId)
{
var result = _contentStore.GetDocumentByRoute(route, true);
var result = _contentStore.GetDocumentByRoute(_umbracoContext, route, true);
Assert.IsNotNull(result);
Assert.AreEqual(nodeId, result.Id);
}

View File

@@ -59,7 +59,7 @@ namespace Umbraco.Tests.DocumentLookups
protected RoutingContext GetRoutingContext(string url, Template template)
{
var umbracoContext = GetUmbracoContext(url, template);
var contentStore = new ContentStore(umbracoContext);
var contentStore = new XmlContentStore();
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
var routingRequest = new RoutingContext(
umbracoContext,

View File

@@ -0,0 +1,32 @@
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Web
{
/// <summary>
/// An object resolver to return the IContentStore
/// </summary>
internal class ContentStoreResolver : SingleObjectResolverBase<ContentStoreResolver, IContentStore>
{
internal ContentStoreResolver(IContentStore contentStore)
{
Value = contentStore;
}
/// <summary>
/// Can be used by developers at runtime to set their IContentStore at app startup
/// </summary>
/// <param name="contentStore"></param>
public void SetContentStore(IContentStore contentStore)
{
Value = contentStore;
}
/// <summary>
/// Returns the IContentStore
/// </summary>
public IContentStore ContentStore
{
get { return Value; }
}
}
}

View File

@@ -4,9 +4,9 @@ namespace Umbraco.Web
{
internal interface IContentStore
{
IDocument GetDocumentById(int nodeId);
IDocument GetDocumentByRoute(string route, bool? hideTopLevelNode = null);
IDocument GetDocumentByUrlAlias(int rootNodeId, string alias);
string GetDocumentProperty(IDocument node, string propertyAlias);
IDocument GetDocumentById(UmbracoContext umbracoContext, int nodeId);
IDocument GetDocumentByRoute(UmbracoContext umbracoContext, string route, bool? hideTopLevelNode = null);
IDocument GetDocumentByUrlAlias(UmbracoContext umbracoContext, int rootNodeId, string alias);
string GetDocumentProperty(UmbracoContext umbracoContext, IDocument node, string propertyAlias);
}
}

View File

@@ -44,7 +44,9 @@ namespace Umbraco.Web.Routing
if (handler.Execute(docRequest.Uri.AbsolutePath) && handler.redirectID > 0)
{
//currentPage = umbracoContent.GetElementById(handler.redirectID.ToString());
currentPage = docRequest.RoutingContext.ContentStore.GetDocumentById(handler.redirectID);
currentPage = docRequest.RoutingContext.ContentStore.GetDocumentById(
docRequest.RoutingContext.UmbracoContext,
handler.redirectID);
// FIXME - could it be null?

View File

@@ -183,7 +183,7 @@ namespace Umbraco.Web.Routing
throw new InvalidOperationException("There is no node.");
bool redirect = false;
string internalRedirect = _routingContext.ContentStore.GetDocumentProperty(_documentRequest.Node, "umbracoInternalRedirectId");
string internalRedirect = _routingContext.ContentStore.GetDocumentProperty(_umbracoContext, _documentRequest.Node, "umbracoInternalRedirectId");
if (!string.IsNullOrWhiteSpace(internalRedirect))
{
@@ -207,7 +207,10 @@ namespace Umbraco.Web.Routing
else
{
// redirect to another page
var node = _routingContext.ContentStore.GetDocumentById(internalRedirectId);
var node = _routingContext.ContentStore.GetDocumentById(
_umbracoContext,
internalRedirectId);
_documentRequest.Node = node;
if (node != null)
{
@@ -235,7 +238,7 @@ namespace Umbraco.Web.Routing
if (_documentRequest.Node == null)
throw new InvalidOperationException("There is no node.");
var path = _routingContext.ContentStore.GetDocumentProperty(_documentRequest.Node, "@path");
var path = _routingContext.ContentStore.GetDocumentProperty(_umbracoContext, _documentRequest.Node, "@path");
if (Access.IsProtected(_documentRequest.NodeId, path))
{
@@ -248,14 +251,18 @@ namespace Umbraco.Web.Routing
LogHelper.Debug<DocumentRequest>("{0}Not logged in, redirect to login page", () => tracePrefix);
var loginPageId = Access.GetLoginPage(path);
if (loginPageId != _documentRequest.NodeId)
_documentRequest.Node = _routingContext.ContentStore.GetDocumentById(loginPageId);
_documentRequest.Node = _routingContext.ContentStore.GetDocumentById(
_umbracoContext,
loginPageId);
}
else if (!Access.HasAccces(_documentRequest.NodeId, user.ProviderUserKey))
{
LogHelper.Debug<DocumentRequest>("{0}Current member has not access, redirect to error page", () => tracePrefix);
var errorPageId = Access.GetErrorPage(path);
if (errorPageId != _documentRequest.NodeId)
_documentRequest.Node = _routingContext.ContentStore.GetDocumentById(errorPageId);
_documentRequest.Node = _routingContext.ContentStore.GetDocumentById(
_umbracoContext,
errorPageId);
}
else
{
@@ -288,7 +295,7 @@ namespace Umbraco.Web.Routing
{
if (string.IsNullOrWhiteSpace(templateAlias))
{
templateAlias = _routingContext.ContentStore.GetDocumentProperty(_documentRequest.Node, "@template");
templateAlias = _routingContext.ContentStore.GetDocumentProperty(_umbracoContext, _documentRequest.Node, "@template");
LogHelper.Debug<DocumentRequest>("{0}Look for template id={1}", () => tracePrefix, () => templateAlias);
int templateId;
if (!int.TryParse(templateAlias, out templateId))
@@ -330,7 +337,7 @@ namespace Umbraco.Web.Routing
if (_documentRequest.HasNode)
{
int redirectId;
if (!int.TryParse(_routingContext.ContentStore.GetDocumentProperty(_documentRequest.Node, "umbracoRedirect"), out redirectId))
if (!int.TryParse(_routingContext.ContentStore.GetDocumentProperty(_umbracoContext, _documentRequest.Node, "umbracoRedirect"), out redirectId))
redirectId = -1;
string redirectUrl = "#";
if (redirectId > 0)

View File

@@ -28,7 +28,11 @@ namespace Umbraco.Web.Routing
if (docRequest.Uri.AbsolutePath != "/") // no alias if "/"
{
node = docRequest.RoutingContext.ContentStore.GetDocumentByUrlAlias(docRequest.HasDomain ? docRequest.Domain.RootNodeId : 0, docRequest.Uri.AbsolutePath);
node = docRequest.RoutingContext.ContentStore.GetDocumentByUrlAlias(
docRequest.RoutingContext.UmbracoContext,
docRequest.HasDomain ? docRequest.Domain.RootNodeId : 0,
docRequest.Uri.AbsolutePath);
if (node != null)
{
LogHelper.Debug<LookupByAlias>("Path \"{0}\" is an alias for id={1}", () => docRequest.Uri.AbsolutePath, () => docRequest.NodeId);

View File

@@ -36,7 +36,10 @@ namespace Umbraco.Web.Routing
if (nodeId > 0)
{
LogHelper.Debug<LookupById>("Id={0}", () => nodeId);
node = docRequest.RoutingContext.ContentStore.GetDocumentById(nodeId);
node = docRequest.RoutingContext.ContentStore.GetDocumentById(
docRequest.RoutingContext.UmbracoContext,
nodeId);
if (node != null)
{
docRequest.Node = node;

View File

@@ -51,7 +51,10 @@ namespace Umbraco.Web.Routing
IDocument node = null;
if (nodeId > 0)
{
node = docreq.RoutingContext.ContentStore.GetDocumentById(nodeId);
node = docreq.RoutingContext.ContentStore.GetDocumentById(
docreq.RoutingContext.UmbracoContext,
nodeId);
if (node != null)
{
docreq.Node = node;
@@ -66,7 +69,10 @@ namespace Umbraco.Web.Routing
if (node == null)
{
LogHelper.Debug<LookupByNiceUrl>("Cache miss, query");
node = docreq.RoutingContext.ContentStore.GetDocumentByRoute(route);
node = docreq.RoutingContext.ContentStore.GetDocumentByRoute(
docreq.RoutingContext.UmbracoContext,
route);
if (node != null)
{
docreq.Node = node;

View File

@@ -22,14 +22,14 @@ namespace Umbraco.Web.Routing
/// </summary>
/// <param name="contentStore">The content store.</param>
/// <param name="umbracoContext">The Umbraco context.</param>
public NiceUrlProvider(ContentStore contentStore, UmbracoContext umbracoContext)
public NiceUrlProvider(IContentStore contentStore, UmbracoContext umbracoContext)
{
_umbracoContext = umbracoContext;
_contentStore = contentStore;
}
private readonly UmbracoContext _umbracoContext;
private readonly ContentStore _contentStore;
private readonly IContentStore _contentStore;
// note: this could be a parameter...
const string UrlNameProperty = "@urlName";
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Routing
}
else
{
var node = _contentStore.GetDocumentById(nodeId);
var node = _contentStore.GetDocumentById(_umbracoContext, nodeId);
if (node == null)
return "#"; // legacy wrote to the log here...
@@ -95,9 +95,9 @@ namespace Umbraco.Web.Routing
domainUri = DomainUriAtNode(id, current);
while (domainUri == null && id > 0)
{
pathParts.Add(_contentStore.GetDocumentProperty(node, UrlNameProperty));
pathParts.Add(_contentStore.GetDocumentProperty(_umbracoContext, node, UrlNameProperty));
node = node.Parent; // set to parent node
id = int.Parse(_contentStore.GetDocumentProperty(node, "@id")); // will be -1 or 1234
id = int.Parse(_contentStore.GetDocumentProperty(_umbracoContext, node, "@id")); // will be -1 or 1234
domainUri = id > 0 ? DomainUriAtNode(id, current) : null;
}
@@ -146,7 +146,7 @@ namespace Umbraco.Web.Routing
}
else
{
var node = _contentStore.GetDocumentById(nodeId);
var node = _contentStore.GetDocumentById(_umbracoContext, nodeId);
if (node == null)
return new string[] { "#" }; // legacy wrote to the log here...
@@ -155,9 +155,9 @@ namespace Umbraco.Web.Routing
domainUris = DomainUrisAtNode(id, current);
while (!domainUris.Any() && id > 0)
{
pathParts.Add(_contentStore.GetDocumentProperty(node, UrlNameProperty));
pathParts.Add(_contentStore.GetDocumentProperty(_umbracoContext, node, UrlNameProperty));
node = node.Parent; //set to parent node
id = int.Parse(_contentStore.GetDocumentProperty(node, "@id")); // will be -1 or 1234
id = int.Parse(_contentStore.GetDocumentProperty(_umbracoContext, node, "@id")); // will be -1 or 1234
domainUris = id > 0 ? DomainUrisAtNode(id, current) : new Uri[] { };
}

View File

@@ -12,6 +12,7 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Initializes a new instance of the <see cref="RoutingContext"/> class.
/// </summary>
/// <param name="umbracoContext"> </param>
/// <param name="documentLookups">The document lookups resolver.</param>
/// <param name="documentLastChanceLookup"> </param>
/// <param name="contentStore">The content store.</param>
@@ -20,7 +21,7 @@ namespace Umbraco.Web.Routing
UmbracoContext umbracoContext,
IEnumerable<IDocumentLookup> documentLookups,
IDocumentLastChanceLookup documentLastChanceLookup,
ContentStore contentStore,
IContentStore contentStore,
NiceUrlProvider niceUrlResolver)
{
this.UmbracoContext = umbracoContext;
@@ -48,7 +49,7 @@ namespace Umbraco.Web.Routing
/// <summary>
/// Gets the content store.
/// </summary>
internal ContentStore ContentStore { get; private set; }
internal IContentStore ContentStore { get; private set; }
/// <summary>
/// Gets the nice urls provider.

View File

@@ -238,7 +238,8 @@
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>
</Compile>
<Compile Include="ContentStore.cs" />
<Compile Include="XmlContentStore.cs" />
<Compile Include="ContentStoreResolver.cs" />
<Compile Include="DocumentNotFoundHttpHandler.cs" />
<Compile Include="IContentStore.cs" />
<Compile Include="Models\XmlDocument.cs" />

View File

@@ -58,16 +58,14 @@ namespace Umbraco.Web
RoutesCacheResolver.Current.RoutesCache);
UmbracoContext.Current = umbracoContext;
//create a content store
var contentStore = new ContentStore(umbracoContext);
//create the nice urls
var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
var niceUrls = new NiceUrlProvider(ContentStoreResolver.Current.ContentStore, umbracoContext);
//create the RoutingContext
var routingContext = new RoutingContext(
umbracoContext,
DocumentLookupsResolver.Current.DocumentLookups,
LastChanceLookupResolver.Current.LastChanceLookup,
contentStore,
ContentStoreResolver.Current.ContentStore,
niceUrls);
//assign the routing context back to the umbraco context
umbracoContext.RoutingContext = routingContext;

View File

@@ -63,6 +63,8 @@ namespace Umbraco.Web
{
base.InitializeResolvers();
ContentStoreResolver.Current = new ContentStoreResolver(new XmlContentStore());
FilteredControllerFactoriesResolver.Current = new FilteredControllerFactoriesResolver(
//add all known factories, devs can then modify this list on application startup either by binding to events
//or in their own global.asax

View File

@@ -10,16 +10,11 @@ using umbraco.interfaces;
namespace Umbraco.Web
{
/// <summary>
/// Used for the new routing system
/// <summary>
/// An IContentStore which uses the Xml cache system to return data
/// </summary>
internal class ContentStore : IContentStore
internal class XmlContentStore : IContentStore
{
/// <summary>
/// Delegate to return the current UmbracoContext
/// </summary>
private readonly UmbracoContext _umbracoContext;
private IDocument ConvertToDocument(XmlNode xmlNode)
{
@@ -29,22 +24,12 @@ namespace Umbraco.Web
return new Models.XmlDocument(xmlNode);
}
/// <summary>
/// Constructor accepting a delegate to resolve the UmbracoContext
/// </summary>
/// <param name="umbracoContext"></param>
public ContentStore(UmbracoContext umbracoContext)
{
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
_umbracoContext = umbracoContext;
}
public IDocument GetDocumentById(int nodeId)
public IDocument GetDocumentById(UmbracoContext umbracoContext, int nodeId)
{
return ConvertToDocument(GetXml().GetElementById(nodeId.ToString()));
return ConvertToDocument(GetXml(umbracoContext).GetElementById(nodeId.ToString()));
}
public IDocument GetDocumentByRoute(string route, bool? hideTopLevelNode = null)
public IDocument GetDocumentByRoute(UmbracoContext umbracoContext, string route, bool? hideTopLevelNode = null)
{
//set the default to be what is in the settings
if (hideTopLevelNode == null)
@@ -67,10 +52,10 @@ namespace Umbraco.Web
var xpath = CreateXpathQuery(startNodeId, path, hideTopLevelNode.Value);
return ConvertToDocument(GetXml().SelectSingleNode(xpath));
return ConvertToDocument(GetXml(umbracoContext).SelectSingleNode(xpath));
}
public IDocument GetDocumentByUrlAlias(int rootNodeId, string alias)
public IDocument GetDocumentByUrlAlias(UmbracoContext umbracoContext, int rootNodeId, string alias)
{
// the alias may be "foo/bar" or "/foo/bar"
@@ -89,7 +74,7 @@ namespace Umbraco.Web
var xpath = xpathBuilder.ToString();
return ConvertToDocument(GetXml().SelectSingleNode(xpath));
return ConvertToDocument(GetXml(umbracoContext).SelectSingleNode(xpath));
}
//public IDocument GetNodeParent(IDocument node)
@@ -97,7 +82,7 @@ namespace Umbraco.Web
// return node.Parent;
//}
public string GetDocumentProperty(IDocument node, string propertyAlias)
public string GetDocumentProperty(UmbracoContext umbracoContext, IDocument node, string propertyAlias)
{
if (propertyAlias.StartsWith("@"))
{
@@ -120,9 +105,9 @@ namespace Umbraco.Web
}
}
XmlDocument GetXml()
XmlDocument GetXml(UmbracoContext umbracoContext)
{
return _umbracoContext.GetXml();
return umbracoContext.GetXml();
}
static readonly char[] SlashChar = new char[] { '/' };