mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Updating Routable to fix the paths of contained items when a container's path changes
--HG-- branch : dev
This commit is contained in:
@@ -33,11 +33,27 @@ namespace Orchard.Core.Routable.Handlers {
|
||||
OnGetEditorShape<RoutePart>(SetModelProperties);
|
||||
OnUpdateEditorShape<RoutePart>(SetModelProperties);
|
||||
|
||||
OnPublishing<RoutePart>((context, routable) => {
|
||||
OnPublished<RoutePart>((context, route) => {
|
||||
var path = route.Path;
|
||||
route.Path = route.GetPathWithSlug(route.Slug);
|
||||
|
||||
if (context.PublishingItemVersionRecord != null)
|
||||
processSlug(routable);
|
||||
if (!string.IsNullOrEmpty(routable.Path))
|
||||
_routablePathConstraint.AddPath(routable.Path);
|
||||
processSlug(route);
|
||||
|
||||
// if the path has changed by having the slug changed on the way in (e.g. user input) or to avoid conflict
|
||||
// then update and publish all contained items
|
||||
if (path != route.Path) {
|
||||
_routablePathConstraint.RemovePath(path);
|
||||
_routableService.FixContainedPaths(route);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(route.Path))
|
||||
_routablePathConstraint.AddPath(route.Path);
|
||||
});
|
||||
|
||||
OnRemoved<RoutePart>((context, route) => {
|
||||
if (!string.IsNullOrWhiteSpace(route.Path))
|
||||
_routablePathConstraint.RemovePath(route.Path);
|
||||
});
|
||||
|
||||
OnIndexing<RoutePart>((context, part) => context.DocumentIndex.Add("title", part.Record.Title).RemoveTags().Analyze());
|
||||
|
@@ -1,9 +1,15 @@
|
||||
<Placement>
|
||||
<!-- available display shapes -->
|
||||
<!--
|
||||
Parts_RoutableTitle
|
||||
Parts_RoutableTitle_Summary
|
||||
Parts_RoutableTitle_SummaryAdmin
|
||||
-->
|
||||
<Place Parts_Routable_Edit="Content:before.5"/>
|
||||
<Match DisplayType="Detail">
|
||||
<Place Parts_RoutableTitle="Header:5"/>
|
||||
</Match>
|
||||
<Match DisplayType="Summary">
|
||||
<Place Parts_RoutableTitle="Header:5"/>
|
||||
<Place Parts_RoutableTitle_Summary="Header:5"/>
|
||||
</Match>
|
||||
</Placement>
|
@@ -22,5 +22,9 @@ namespace Orchard.Core.Routable.Services {
|
||||
/// <returns>True if the slug has been created, False if a conflict occured</returns>
|
||||
bool ProcessSlug(IRoutableAspect part);
|
||||
|
||||
/// <summary>
|
||||
/// Updated the paths of all contained items to reflect the current path of this item
|
||||
/// </summary>
|
||||
void FixContainedPaths(IRoutableAspect part);
|
||||
}
|
||||
}
|
@@ -45,7 +45,8 @@ namespace Orchard.Core.Routable.Services {
|
||||
|
||||
public void RemovePath(string path) {
|
||||
lock (_syncLock) {
|
||||
_paths.Remove(path);
|
||||
if (path != null && _paths.ContainsKey(path))
|
||||
_paths.Remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Routable.Models;
|
||||
|
||||
namespace Orchard.Core.Routable.Services {
|
||||
@@ -14,6 +15,18 @@ namespace Orchard.Core.Routable.Services {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public void FixContainedPaths(IRoutableAspect part) {
|
||||
var items = _contentManager.Query(VersionOptions.Published)
|
||||
.Join<CommonPartRecord>().Where(cr => cr.Container.Id == part.Id)
|
||||
.List()
|
||||
.Select(item => item.As<IRoutableAspect>()).Where(item => item != null);
|
||||
|
||||
foreach (var itemRoute in items) {
|
||||
itemRoute.ContentItem.VersionRecord.Published = false; // <- to force a republish
|
||||
_contentManager.Publish(itemRoute.ContentItem);
|
||||
}
|
||||
}
|
||||
|
||||
public void FillSlugFromTitle<TModel>(TModel model) where TModel : IRoutableAspect {
|
||||
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
|
||||
return;
|
||||
@@ -86,6 +99,7 @@ namespace Orchard.Core.Routable.Services {
|
||||
var originalSlug = part.Slug;
|
||||
var newSlug = GenerateUniqueSlug(part, pathsLikeThis.Select(p => p.Path));
|
||||
part.Path = part.GetPathWithSlug(newSlug);
|
||||
part.Slug = newSlug;
|
||||
|
||||
if (originalSlug != newSlug)
|
||||
return false;
|
||||
|
@@ -1,6 +1 @@
|
||||
@{
|
||||
Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;
|
||||
string title = Model.Title.ToString();
|
||||
}
|
||||
|
||||
<h1>@Html.ItemDisplayLink(title, contentItem)</h1>
|
||||
<h1>@Model.Title</h1>
|
@@ -73,17 +73,16 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
_contentManager.Publish(blog.ContentItem);
|
||||
_blogSlugConstraint.AddSlug(blog.As<IRoutableAspect>().GetEffectiveSlug());
|
||||
|
||||
var slug = blog.As<IRoutableAspect>().GetEffectiveSlug();
|
||||
_blogSlugConstraint.AddSlug(slug);
|
||||
return Redirect(Url.BlogForAdmin(blog));
|
||||
}
|
||||
|
||||
public ActionResult Edit(string blogSlug) {
|
||||
public ActionResult Edit(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to edit blog")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var blog = _blogService.Get(blogSlug);
|
||||
var blog = _blogService.Get(id, VersionOptions.Latest);
|
||||
if (blog == null)
|
||||
return HttpNotFound();
|
||||
|
||||
@@ -92,20 +91,24 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("Edit")]
|
||||
public ActionResult EditPOST(string blogSlug) {
|
||||
public ActionResult EditPOST(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't edit blog")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var blog = _blogService.Get(blogSlug);
|
||||
var blog = _blogService.Get(id, VersionOptions.DraftRequired);
|
||||
if (blog == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var model = Services.ContentManager.UpdateEditor(blog, this);
|
||||
if (!ModelState.IsValid)
|
||||
if (!ModelState.IsValid) {
|
||||
Services.TransactionManager.Cancel();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
_contentManager.Publish(blog);
|
||||
_blogSlugConstraint.AddSlug(blog.As<IRoutableAspect>().GetEffectiveSlug());
|
||||
Services.Notifier.Information(T("Blog information updated"));
|
||||
|
||||
return Redirect(Url.BlogsForAdmin());
|
||||
}
|
||||
|
||||
|
@@ -132,6 +132,8 @@ namespace Orchard.Blogs.Controllers {
|
||||
return View(model);
|
||||
}
|
||||
|
||||
conditionallyPublish(blogPost.ContentItem);
|
||||
|
||||
Services.Notifier.Information(T("Your {0} has been saved.", blogPost.TypeDefinition.DisplayName));
|
||||
|
||||
if (!String.IsNullOrEmpty(returnUrl))
|
||||
|
@@ -48,11 +48,11 @@ namespace Orchard.Blogs.Extensions {
|
||||
}
|
||||
|
||||
public static string BlogEdit(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
return urlHelper.Action("Edit", "BlogAdmin", new { blogSlug = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("Edit", "BlogAdmin", new { blogPart.Id, area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogRemove(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
return urlHelper.Action("Remove", "BlogAdmin", new { blogSlug = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("Remove", "BlogAdmin", new { blogPart.Id, area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogPostCreate(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
|
@@ -35,15 +35,13 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs/{blogSlug}/Edit",
|
||||
"Admin/Blogs/{id}/Edit",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogAdmin"},
|
||||
{"action", "Edit"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint}
|
||||
},
|
||||
new RouteValueDictionary (),
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
},
|
||||
@@ -51,15 +49,13 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"Admin/Blogs/{blogSlug}/Remove",
|
||||
"Admin/Blogs/{id}/Remove",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogAdmin"},
|
||||
{"action", "Remove"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint}
|
||||
},
|
||||
new RouteValueDictionary (),
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
},
|
||||
|
@@ -24,6 +24,10 @@ namespace Orchard.Blogs.Services {
|
||||
.List().FirstOrDefault();
|
||||
}
|
||||
|
||||
public ContentItem Get(int id, VersionOptions versionOptions) {
|
||||
return _contentManager.Get(id, versionOptions);
|
||||
}
|
||||
|
||||
public IEnumerable<BlogPart> Get() {
|
||||
return _contentManager.Query<BlogPart, BlogPartRecord>()
|
||||
.Join<RoutePartRecord>()
|
||||
|
@@ -1,9 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.ContentManagement;
|
||||
|
||||
namespace Orchard.Blogs.Services {
|
||||
public interface IBlogService : IDependency {
|
||||
BlogPart Get(string slug);
|
||||
ContentItem Get(int id, VersionOptions versionOptions);
|
||||
IEnumerable<BlogPart> Get();
|
||||
void Delete(BlogPart blogPart);
|
||||
}
|
||||
|
Reference in New Issue
Block a user