Changed blog constraint to be a singleton like page constraint and made them consistent

--HG--
branch : dev
rename : src/Orchard.Web/Modules/Orchard.Blogs/Routing/IsBlogConstraint.cs => src/Orchard.Web/Modules/Orchard.Blogs/Routing/BlogSlugConstraint.cs
rename : src/Orchard.Web/Modules/Orchard.Pages/Routing/ISlugConstraint.cs => src/Orchard.Web/Modules/Orchard.Pages/Routing/IPageSlugConstraint.cs
rename : src/Orchard.Web/Modules/Orchard.Pages/Routing/SlugConstraint.cs => src/Orchard.Web/Modules/Orchard.Pages/Routing/PageSlugConstraint.cs
rename : src/Orchard.Web/Modules/Orchard.Pages/Routing/SlugConstraintUpdator.cs => src/Orchard.Web/Modules/Orchard.Pages/Routing/PageSlugConstraintUpdator.cs
This commit is contained in:
Erik Porter
2010-03-05 00:24:53 -08:00
parent 43eeb4e7d7
commit 554d279795
22 changed files with 279 additions and 178 deletions

View File

@@ -37,8 +37,7 @@ namespace Orchard.Blogs.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to create blogs")))
return new HttpUnauthorizedResult();
Blog blog = Services.ContentManager.New<Blog>(BlogDriver.ContentType.Name);
var blog = Services.ContentManager.New<Blog>(BlogDriver.ContentType.Name);
if (blog == null)
return new NotFoundResult();
@@ -60,12 +59,9 @@ namespace Orchard.Blogs.Controllers {
if (!ModelState.IsValid)
return View(model);
Services.ContentManager.Create(model.Blog.Item.ContentItem);
_blogService.Create(model.Blog.Item);
//TEMP: (erikpo) ensure information has committed for this record
Services.ContentManager.Flush();
return Redirect(Url.BlogForAdmin(model.Blog.Item.As<RoutableAspect>().Slug));
return Redirect(Url.BlogForAdmin(model.Blog.Item.Slug));
}
public ActionResult Edit(string blogSlug) {
@@ -74,8 +70,7 @@ namespace Orchard.Blogs.Controllers {
return new HttpUnauthorizedResult();
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
var blog = _blogService.Get(blogSlug);
if (blog == null)
return new NotFoundResult();
@@ -92,8 +87,7 @@ namespace Orchard.Blogs.Controllers {
return new HttpUnauthorizedResult();
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
Blog blog = _blogService.Get(blogSlug);
var blog = _blogService.Get(blogSlug);
if (blog == null)
return new NotFoundResult();
@@ -109,6 +103,8 @@ namespace Orchard.Blogs.Controllers {
CurrentSite.HomePage = "BlogHomePageProvider;" + model.Blog.Item.Id;
}
_blogService.Edit(model.Blog.Item);
Services.Notifier.Information(T("Blog information updated"));
return Redirect(Url.BlogsForAdmin());

View File

@@ -5,6 +5,7 @@ using System.Web.Routing;
using System.Xml.Linq;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Models;
using Orchard.Blogs.Routing;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
using Orchard.Core.Feeds;
@@ -15,16 +16,14 @@ namespace Orchard.Blogs.Controllers {
public class BlogController : Controller {
private readonly IOrchardServices _services;
private readonly IBlogService _blogService;
private readonly IBlogSlugConstraint _blogSlugConstraint;
private readonly IFeedManager _feedManager;
private readonly RouteCollection _routeCollection;
public BlogController(
IOrchardServices services,
IBlogService blogService,
IFeedManager feedManager,
RouteCollection routeCollection) {
public BlogController(IOrchardServices services, IBlogService blogService, IBlogSlugConstraint blogSlugConstraint, IFeedManager feedManager, RouteCollection routeCollection) {
_services = services;
_blogService = blogService;
_blogSlugConstraint = blogSlugConstraint;
_feedManager = feedManager;
_routeCollection = routeCollection;
Logger = NullLogger.Instance;
@@ -42,8 +41,11 @@ namespace Orchard.Blogs.Controllers {
//TODO: (erikpo) Should move the slug parameter and get call and null check up into a model binder
public ActionResult Item(string blogSlug) {
Blog blog = _blogService.Get(blogSlug);
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
if (correctedSlug == null)
return new NotFoundResult();
var blog = _blogService.Get(correctedSlug);
if (blog == null)
return new NotFoundResult();

View File

@@ -31,14 +31,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=1.4.4.561, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="Autofac.Integration.Web, Version=1.4.4.561, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">
@@ -83,8 +75,10 @@
<Compile Include="Handlers\BlogArchiveHandler.cs" />
<Compile Include="Models\BlogArchiveRecord.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Routing\IBlogSlugConstraint.cs" />
<Compile Include="Routing\IsArchiveConstraint.cs" />
<Compile Include="Routing\IsBlogConstraint.cs" />
<Compile Include="Routing\BlogSlugConstraint.cs" />
<Compile Include="Routing\BlogSlugConstraintUpdator.cs" />
<Compile Include="Services\BlogHomePageProvider.cs" />
<Compile Include="Services\BlogService.cs" />
<Compile Include="Controllers\BlogController.cs" />
@@ -180,10 +174,6 @@
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Users\Orchard.Users.csproj">
<Project>{79AED36E-ABD0-4747-93D3-8722B042454B}</Project>
<Name>Orchard.Users</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -1,17 +1,15 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac.Integration.Web;
using Orchard.Blogs.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Blogs {
public class Routes : IRouteProvider
{
private readonly IContainerProvider _containerProvider;
public class Routes : IRouteProvider {
private readonly IBlogSlugConstraint _blogSlugConstraint;
public Routes(IContainerProvider containerProvider) {
_containerProvider = containerProvider;
public Routes(IBlogSlugConstraint blogSlugConstraint) {
_blogSlugConstraint = blogSlugConstraint;
}
public void GetRoutes(ICollection<RouteDescriptor> routes) {
@@ -44,7 +42,7 @@ namespace Orchard.Blogs {
{"action", "Edit"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -60,7 +58,7 @@ namespace Orchard.Blogs {
{"action", "Delete"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -76,7 +74,7 @@ namespace Orchard.Blogs {
{"action", "Item"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -92,7 +90,7 @@ namespace Orchard.Blogs {
{"action", "Create"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -108,7 +106,7 @@ namespace Orchard.Blogs {
{"action", "Edit"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -124,7 +122,7 @@ namespace Orchard.Blogs {
{"action", "Delete"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -140,7 +138,7 @@ namespace Orchard.Blogs {
{"action", "Publish"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -156,7 +154,7 @@ namespace Orchard.Blogs {
{"action", "Unpublish"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -200,7 +198,7 @@ namespace Orchard.Blogs {
{"action", "ListByArchive"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)},
{"blogSlug", _blogSlugConstraint},
{"archiveData", new IsArchiveConstraint()}
},
new RouteValueDictionary {
@@ -217,7 +215,7 @@ namespace Orchard.Blogs {
{"action", "LiveWriterManifest"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -233,7 +231,7 @@ namespace Orchard.Blogs {
{"action", "Rsd"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -249,7 +247,7 @@ namespace Orchard.Blogs {
{"action", "Item"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}
@@ -265,7 +263,7 @@ namespace Orchard.Blogs {
{"action", "Item"}
},
new RouteValueDictionary {
{"blogSlug", new IsBlogConstraint(_containerProvider)}
{"blogSlug", _blogSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Blogs"}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using JetBrains.Annotations;
using Orchard.Logging;
namespace Orchard.Blogs.Routing {
[UsedImplicitly]
public class BlogSlugConstraint : IBlogSlugConstraint {
/// <summary>
/// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary.
/// </summary>
private readonly object _syncLock = new object();
private IDictionary<string, string> _slugs = new Dictionary<string, string>();
public BlogSlugConstraint() {
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void SetSlugs(IEnumerable<string> slugs) {
// Make a copy to avoid performing potential lazy computation inside the lock
var slugsArray = slugs.ToArray();
lock (_syncLock) {
_slugs = slugsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
}
Logger.Debug("Blog slugs: {0}", string.Join(", ", slugsArray));
}
public string FindSlug(string slug) {
lock (_syncLock) {
string actual;
return _slugs.TryGetValue(slug, out actual) ? actual : slug;
}
}
public void AddSlug(string slug) {
lock (_syncLock) {
_slugs[slug] = slug;
}
}
public void RemoveSlug(string slug) {
lock (_syncLock) {
_slugs.Remove(slug);
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
object value;
if (values.TryGetValue(parameterName, out value)) {
var parameterValue = Convert.ToString(value);
lock (_syncLock) {
return _slugs.ContainsKey(parameterValue);
}
}
return false;
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Linq;
using JetBrains.Annotations;
using Orchard.Blogs.Services;
using Orchard.Extensions;
using Orchard.Tasks;
namespace Orchard.Blogs.Routing {
[UsedImplicitly]
public class BlogSlugConstraintUpdator : ExtensionManagerEvents, IBackgroundTask {
private readonly IBlogSlugConstraint _blogSlugConstraint;
private readonly IBlogService _blogService;
public BlogSlugConstraintUpdator(IBlogSlugConstraint blogSlugConstraint, IBlogService blogService) {
_blogSlugConstraint = blogSlugConstraint;
_blogService = blogService;
}
public override void Activated(ExtensionEventContext context) {
if (context.Extension.Descriptor.Name == "Orchard.Blogs") {
Refresh();
}
}
public void Sweep() {
Refresh();
}
private void Refresh() {
_blogSlugConstraint.SetSlugs(_blogService.Get().Select(b => b.Slug));
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using System.Web.Routing;
namespace Orchard.Blogs.Routing {
public interface IBlogSlugConstraint : IRouteConstraint, ISingletonDependency {
void SetSlugs(IEnumerable<string> slugs);
string FindSlug(string slug);
void AddSlug(string slug);
void RemoveSlug(string slug);
}
}

View File

@@ -1,18 +0,0 @@
using System.Web;
using System.Web.Routing;
using Autofac.Integration.Web;
using Orchard.Blogs.Services;
namespace Orchard.Blogs.Routing {
public class IsBlogConstraint : IRouteConstraint {
private readonly IContainerProvider _containerProvider;
public IsBlogConstraint(IContainerProvider containerProvider) {
_containerProvider = containerProvider;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
return _containerProvider.RequestContainer.Resolve<IBlogService>().Get(values[parameterName].ToString()) != null;
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Routing;
using Orchard.Blogs.ViewModels;
using Orchard.Mvc.Results;
using Orchard.Services;
@@ -11,12 +12,14 @@ namespace Orchard.Blogs.Services {
[UsedImplicitly]
public class BlogHomePageProvider : IHomePageProvider {
private readonly IBlogService _blogService;
private readonly IBlogSlugConstraint _blogSlugConstraint;
private readonly IFeedManager _feedManager;
public BlogHomePageProvider(IOrchardServices services, IBlogService blogService, IFeedManager feedManager) {
public BlogHomePageProvider(IOrchardServices services, IBlogService blogService, IBlogSlugConstraint blogSlugConstraint, IFeedManager feedManager) {
Services = services;
_feedManager = feedManager;
_blogService = blogService;
_blogSlugConstraint = blogSlugConstraint;
_feedManager = feedManager;
}
public IOrchardServices Services { get; private set; }
@@ -30,6 +33,14 @@ namespace Orchard.Blogs.Services {
if (blog == null)
return new NotFoundResult();
var correctedSlug = _blogSlugConstraint.FindSlug(blog.Slug);
if (correctedSlug == null)
return new NotFoundResult();
blog = _blogService.Get(correctedSlug);
if (blog == null)
return new NotFoundResult();
var model = new BlogViewModel {
Blog = Services.ContentManager.BuildDisplayModel(blog, "Detail")
};

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Orchard.Blogs.Models;
using Orchard.Blogs.Routing;
using Orchard.Core.Common.Models;
using Orchard.ContentManagement;
@@ -9,9 +10,11 @@ namespace Orchard.Blogs.Services {
[UsedImplicitly]
public class BlogService : IBlogService {
private readonly IContentManager _contentManager;
private readonly IBlogSlugConstraint _blogSlugConstraint;
public BlogService(IContentManager contentManager) {
public BlogService(IContentManager contentManager, IBlogSlugConstraint blogSlugConstraint) {
_contentManager = contentManager;
_blogSlugConstraint = blogSlugConstraint;
}
public Blog Get(string slug) {
@@ -27,8 +30,18 @@ namespace Orchard.Blogs.Services {
.List();
}
public void Create(Blog blog) {
_contentManager.Create(blog.ContentItem);
_blogSlugConstraint.AddSlug(blog.Slug);
}
public void Edit(Blog blog) {
_blogSlugConstraint.AddSlug(blog.Slug);
}
public void Delete(Blog blog) {
_contentManager.Remove(blog.ContentItem);
_blogSlugConstraint.RemoveSlug(blog.Slug);
}
}
}

View File

@@ -5,6 +5,8 @@ namespace Orchard.Blogs.Services {
public interface IBlogService : IDependency {
Blog Get(string slug);
IEnumerable<Blog> Get();
void Create(Blog blog);
void Edit(Blog blog);
void Delete(Blog blog);
}
}

View File

@@ -110,10 +110,10 @@ namespace Orchard.Pages.Controllers {
if (!Services.Authorizer.Authorize(Permissions.EditPages, T("Not allowed to create a page")))
return new HttpUnauthorizedResult();
var page = Services.ContentManager.BuildEditorModel(Services.ContentManager.New<Page>(PageDriver.ContentType.Name));
var page = Services.ContentManager.New<Page>(PageDriver.ContentType.Name);
var model = new PageCreateViewModel {
Page = page
Page = Services.ContentManager.BuildEditorModel(page)
};
return View(model);

View File

@@ -10,12 +10,12 @@ namespace Orchard.Pages.Controllers {
[ValidateInput(false)]
public class PageController : Controller {
private readonly IPageService _pageService;
private readonly ISlugConstraint _slugConstraint;
private readonly IPageSlugConstraint _pageSlugConstraint;
public PageController(IOrchardServices services, IPageService pageService, ISlugConstraint slugConstraint) {
public PageController(IOrchardServices services, IPageService pageService, IPageSlugConstraint pageSlugConstraint) {
Services = services;
_pageService = pageService;
_slugConstraint = slugConstraint;
_pageSlugConstraint = pageSlugConstraint;
T = NullLocalizer.Instance;
}
@@ -26,7 +26,7 @@ namespace Orchard.Pages.Controllers {
if (!Services.Authorizer.Authorize(StandardPermissions.AccessFrontEnd, T("Couldn't view page")))
return new HttpUnauthorizedResult();
var correctedSlug = _slugConstraint.LookupPublishedSlug(slug);
var correctedSlug = _pageSlugConstraint.FindSlug(slug);
if (correctedSlug == null)
return new NotFoundResult();

View File

@@ -76,13 +76,13 @@
<Compile Include="Routes.cs" />
<Compile Include="Security\Authorization.cs" />
<Compile Include="Services\IPageService.cs" />
<Compile Include="Routing\ISlugConstraint.cs" />
<Compile Include="Routing\IPageSlugConstraint.cs" />
<Compile Include="Services\PageService.cs" />
<Compile Include="Services\PageHomePageProvider.cs" />
<Compile Include="Routing\SlugConstraint.cs">
<Compile Include="Routing\PageSlugConstraint.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Routing\SlugConstraintUpdator.cs" />
<Compile Include="Routing\PageSlugConstraintUpdator.cs" />
<Compile Include="ViewModels\PageCreateViewModel.cs" />
<Compile Include="ViewModels\PageEditViewModel.cs" />
<Compile Include="ViewModels\PagesViewModel.cs" />

View File

@@ -6,10 +6,10 @@ using Orchard.Pages.Routing;
namespace Orchard.Pages {
public class Routes : IRouteProvider {
private readonly ISlugConstraint _slugConstraint;
private readonly IPageSlugConstraint _pageSlugConstraint;
public Routes(ISlugConstraint slugConstraint) {
_slugConstraint = slugConstraint;
public Routes(IPageSlugConstraint pageSlugConstraint) {
_pageSlugConstraint = pageSlugConstraint;
}
public void GetRoutes(ICollection<RouteDescriptor> routes) {
@@ -29,7 +29,7 @@ namespace Orchard.Pages {
{"action", "item"}
},
new RouteValueDictionary {
{"slug", _slugConstraint}
{"slug", _pageSlugConstraint}
},
new RouteValueDictionary {
{"area", "Orchard.Pages"}
@@ -38,6 +38,5 @@ namespace Orchard.Pages {
}
};
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using System.Web.Routing;
namespace Orchard.Pages.Routing {
public interface IPageSlugConstraint : IRouteConstraint, ISingletonDependency {
void SetSlugs(IEnumerable<string> slugs);
string FindSlug(string slug);
void AddSlug(string slug);
void RemoveSlug(string slug);
}
}

View File

@@ -1,11 +0,0 @@
using System.Collections.Generic;
using System.Web.Routing;
namespace Orchard.Pages.Routing {
public interface ISlugConstraint : IRouteConstraint, ISingletonDependency {
void SetCurrentlyPublishedSlugs(IEnumerable<string> slugs);
string LookupPublishedSlug(string slug);
void AddPublishedSlug(string slug);
void RemovePublishedSlug(string slug);
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using JetBrains.Annotations;
using Orchard.Logging;
namespace Orchard.Pages.Routing {
[UsedImplicitly]
public class PageSlugConstraint : IPageSlugConstraint {
/// <summary>
/// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary.
/// </summary>
private readonly object _syncLock = new object();
private IDictionary<string, string> _slugs = new Dictionary<string, string>();
public PageSlugConstraint() {
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void SetSlugs(IEnumerable<string> slugs) {
// Make a copy to avoid performing potential lazy computation inside the lock
var slugsArray = slugs.ToArray();
lock (_syncLock) {
_slugs = slugsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
}
Logger.Debug("Page slugs: {0}", string.Join(", ", slugsArray));
}
public string FindSlug(string slug) {
lock (_syncLock) {
string actual;
return _slugs.TryGetValue(slug, out actual) ? actual : slug;
}
}
public void AddSlug(string slug) {
lock (_syncLock) {
_slugs[slug] = slug;
}
}
public void RemoveSlug(string slug) {
lock (_syncLock) {
_slugs.Remove(slug);
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
object value;
if (values.TryGetValue(parameterName, out value)) {
var parameterValue = Convert.ToString(value);
lock (_syncLock) {
return _slugs.ContainsKey(parameterValue);
}
}
return false;
}
}
}

View File

@@ -6,12 +6,12 @@ using Orchard.Tasks;
namespace Orchard.Pages.Routing {
[UsedImplicitly]
public class SlugConstraintUpdator : ExtensionManagerEvents, IBackgroundTask {
private readonly ISlugConstraint _slugConstraint;
public class PageSlugConstraintUpdator : ExtensionManagerEvents, IBackgroundTask {
private readonly IPageSlugConstraint _pageSlugConstraint;
private readonly IPageService _pageService;
public SlugConstraintUpdator(ISlugConstraint slugConstraint, IPageService pageService) {
_slugConstraint = slugConstraint;
public PageSlugConstraintUpdator(IPageSlugConstraint pageSlugConstraint, IPageService pageService) {
_pageSlugConstraint = pageSlugConstraint;
_pageService = pageService;
}
@@ -26,7 +26,7 @@ namespace Orchard.Pages.Routing {
}
private void Refresh() {
_slugConstraint.SetCurrentlyPublishedSlugs(_pageService.Get(PageStatus.Published).Select(page => page.Slug));
_pageSlugConstraint.SetSlugs(_pageService.Get(PageStatus.Published).Select(p => p.Slug));
}
}
}

View File

@@ -1,69 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using Orchard.Logging;
namespace Orchard.Pages.Routing {
public class SlugConstraint : ISlugConstraint {
/// <summary>
/// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the
/// dictionary.
/// </summary>
private readonly object _syncLock = new object();
private IDictionary<string, string> _currentlyPublishedSlugs = new Dictionary<string, string>();
public SlugConstraint() {
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void SetCurrentlyPublishedSlugs(IEnumerable<string> values) {
// Make a copy to avoid performing potential lazy computation inside the lock
string[] valuesArray = values.ToArray();
lock (_syncLock) {
_currentlyPublishedSlugs = valuesArray
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
}
Logger.Debug("Publishing slugs: {0}", string.Join(", ", valuesArray));
}
public string LookupPublishedSlug(string slug) {
lock (_syncLock) {
string actual;
if (_currentlyPublishedSlugs.TryGetValue(slug, out actual))
return actual;
return slug;
}
}
public void AddPublishedSlug(string slug) {
lock (_syncLock) {
_currentlyPublishedSlugs[slug] = slug;
}
}
public void RemovePublishedSlug(string slug) {
lock (_syncLock) {
_currentlyPublishedSlugs.Remove(slug);
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
object value;
if (values.TryGetValue(parameterName, out value)) {
var parameterValue = Convert.ToString(value);
lock (_syncLock) {
return _currentlyPublishedSlugs.ContainsKey(parameterValue);
}
}
return false;
}
}
}

View File

@@ -10,11 +10,11 @@ namespace Orchard.Pages.Services {
[UsedImplicitly]
public class PageHomePageProvider : IHomePageProvider {
private readonly IPageService _pageService;
private readonly ISlugConstraint _slugConstraint;
private readonly IPageSlugConstraint _pageSlugConstraint;
public PageHomePageProvider(IOrchardServices services, IPageService pageService, ISlugConstraint slugConstraint) {
public PageHomePageProvider(IOrchardServices services, IPageService pageService, IPageSlugConstraint pageSlugConstraint) {
Services = services;
_slugConstraint = slugConstraint;
_pageSlugConstraint = pageSlugConstraint;
_pageService = pageService;
T = NullLocalizer.Instance;
}
@@ -31,7 +31,7 @@ namespace Orchard.Pages.Services {
if (page == null)
return new NotFoundResult();
var correctedSlug = _slugConstraint.LookupPublishedSlug(page.Slug);
var correctedSlug = _pageSlugConstraint.FindSlug(page.Slug);
if (correctedSlug == null)
return new NotFoundResult();

View File

@@ -15,12 +15,12 @@ namespace Orchard.Pages.Services {
public class PageService : IPageService {
private readonly IContentManager _contentManager;
private readonly IPublishingTaskManager _publishingTaskManager;
private readonly ISlugConstraint _slugConstraint;
private readonly IPageSlugConstraint _pageSlugConstraint;
public PageService(IContentManager contentManager, IPublishingTaskManager publishingTaskManager, ISlugConstraint slugConstraint) {
public PageService(IContentManager contentManager, IPublishingTaskManager publishingTaskManager, IPageSlugConstraint pageSlugConstraint) {
_contentManager = contentManager;
_publishingTaskManager = publishingTaskManager;
_slugConstraint = slugConstraint;
_pageSlugConstraint = pageSlugConstraint;
}
public int GetCount() {
@@ -82,7 +82,7 @@ namespace Orchard.Pages.Services {
public void Publish(Page page) {
_publishingTaskManager.DeleteTasks(page.ContentItem);
_contentManager.Publish(page.ContentItem);
_slugConstraint.AddPublishedSlug(page.Slug);
_pageSlugConstraint.AddSlug(page.Slug);
}
public void Publish(Page page, DateTime scheduledPublishUtc) {
@@ -91,7 +91,7 @@ namespace Orchard.Pages.Services {
public void Unpublish(Page page) {
_contentManager.Unpublish(page.ContentItem);
_slugConstraint.RemovePublishedSlug(page.Slug);
_pageSlugConstraint.RemoveSlug(page.Slug);
}
public DateTime? GetScheduledPublishUtc(Page page) {