diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj
index c06905952..0c9308d99 100644
--- a/src/Orchard.Web/Core/Orchard.Core.csproj
+++ b/src/Orchard.Web/Core/Orchard.Core.csproj
@@ -104,6 +104,7 @@
+
diff --git a/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs b/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs
new file mode 100644
index 000000000..a178aed71
--- /dev/null
+++ b/src/Orchard.Web/Core/Routable/Events/ISlugEventHandler.cs
@@ -0,0 +1,17 @@
+using Orchard.Events;
+
+namespace Orchard.Core.Routable.Events {
+ public interface ISlugEventHandler : IEventHandler {
+ void FillingSlugFromTitle(FillSlugContext context);
+ void FilledSlugFromTitle(FillSlugContext context);
+ }
+
+ public class FillSlugContext {
+ public FillSlugContext(string slug) {
+ Slug = slug;
+ }
+
+ public string Slug { get; set; }
+ public bool Adjusted { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs
index 68dc30218..889720db9 100644
--- a/src/Orchard.Web/Core/Routable/Services/RoutableService.cs
+++ b/src/Orchard.Web/Core/Routable/Services/RoutableService.cs
@@ -7,14 +7,17 @@ using System.Text.RegularExpressions;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Common.Models;
+using Orchard.Core.Routable.Events;
using Orchard.Core.Routable.Models;
namespace Orchard.Core.Routable.Services {
public class RoutableService : IRoutableService {
private readonly IContentManager _contentManager;
+ private readonly IEnumerable _slugEventHandlers;
- public RoutableService(IContentManager contentManager) {
+ public RoutableService(IContentManager contentManager, IEnumerable slugEventHandlers) {
_contentManager = contentManager;
+ _slugEventHandlers = slugEventHandlers;
}
public void FixContainedPaths(IRoutableAspect part) {
@@ -47,18 +50,29 @@ namespace Orchard.Core.Routable.Services {
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
return;
- var slug = model.Title;
- var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>]+");
+ FillSlugContext slugContext = new FillSlugContext(model.Title);
- slug = disallowed.Replace(slug, "-");
- slug = slug.Trim('-');
+ foreach(ISlugEventHandler slugEventHandler in _slugEventHandlers) {
+ slugEventHandler.FillingSlugFromTitle(slugContext);
+ }
- if (slug.Length > 1000)
- slug = slug.Substring(0, 1000);
+ if (!slugContext.Adjusted) {
+ var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>]+");
- // dots are not allowed at the begin and the end of routes
- slug = slug.Trim('.');
- model.Slug = RemoveDiacritics(slug.ToLower());
+ slugContext.Slug = disallowed.Replace(slugContext.Slug, "-").Trim('-');
+
+ if (slugContext.Slug.Length > 1000)
+ slugContext.Slug = slugContext.Slug.Substring(0, 1000);
+
+ // dots are not allowed at the begin and the end of routes
+ slugContext.Slug = RemoveDiacritics(slugContext.Slug.Trim('.').ToLower());
+ }
+
+ foreach (ISlugEventHandler slugEventHandler in _slugEventHandlers) {
+ slugEventHandler.FilledSlugFromTitle(slugContext);
+ }
+
+ model.Slug = slugContext.Slug;
}
public string GenerateUniqueSlug(IRoutableAspect part, IEnumerable existingPaths) {