mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-07-16 15:25:12 +08:00
A little more Routable path & slug bug fixing and cleanup
--HG-- branch : dev
This commit is contained in:
parent
9c70163f67
commit
6c86c89414
@ -63,7 +63,7 @@ namespace Orchard.Core.Tests.Common.Services {
|
|||||||
t.Title = "Please do not use any of the following characters in your slugs: \":\", \"/\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\"";
|
t.Title = "Please do not use any of the following characters in your slugs: \":\", \"/\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\"";
|
||||||
});
|
});
|
||||||
|
|
||||||
_routableService.FillSlug(thing.As<RoutePart>());
|
_routableService.FillSlugFromTitle(thing.As<RoutePart>());
|
||||||
|
|
||||||
Assert.That(thing.Slug, Is.EqualTo("please-do-not-use-any-of-the-following-characters-in-your-slugs-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\""));
|
Assert.That(thing.Slug, Is.EqualTo("please-do-not-use-any-of-the-following-characters-in-your-slugs-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\""));
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ namespace Orchard.Core.Tests.Common.Services {
|
|||||||
veryVeryLongTitle += "aaaaaaaaaa";
|
veryVeryLongTitle += "aaaaaaaaaa";
|
||||||
|
|
||||||
var thing = CreateRoutePart(veryVeryLongTitle);
|
var thing = CreateRoutePart(veryVeryLongTitle);
|
||||||
_routableService.FillSlug(thing);
|
_routableService.FillSlugFromTitle(thing);
|
||||||
|
|
||||||
Assert.That(veryVeryLongTitle.Length, Is.AtLeast(1001));
|
Assert.That(veryVeryLongTitle.Length, Is.AtLeast(1001));
|
||||||
Assert.That(thing.Slug.Length, Is.EqualTo(1000));
|
Assert.That(thing.Slug.Length, Is.EqualTo(1000));
|
||||||
@ -139,7 +139,7 @@ namespace Orchard.Core.Tests.Common.Services {
|
|||||||
public void GeneratedSlugIsLowerCased() {
|
public void GeneratedSlugIsLowerCased() {
|
||||||
var thing = CreateRoutePart("This Is Some Interesting Title");
|
var thing = CreateRoutePart("This Is Some Interesting Title");
|
||||||
|
|
||||||
_routableService.FillSlug(thing);
|
_routableService.FillSlugFromTitle(thing);
|
||||||
|
|
||||||
Assert.That(thing.Slug, Is.EqualTo("this-is-some-interesting-title"));
|
Assert.That(thing.Slug, Is.EqualTo("this-is-some-interesting-title"));
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,6 @@ namespace Orchard.Core.Routable.Drivers {
|
|||||||
updater.TryUpdateModel(model, Prefix, null, null);
|
updater.TryUpdateModel(model, Prefix, null, null);
|
||||||
part.Title = model.Title;
|
part.Title = model.Title;
|
||||||
part.Slug = model.Slug;
|
part.Slug = model.Slug;
|
||||||
part.Path = part.GetPathFromSlug(model.Slug);
|
|
||||||
|
|
||||||
if (!_routableService.IsSlugValid(part.Slug)) {
|
if (!_routableService.IsSlugValid(part.Slug)) {
|
||||||
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead)."));
|
updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead)."));
|
||||||
@ -89,7 +88,7 @@ namespace Orchard.Core.Routable.Drivers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TEMP: path format patterns replaces this logic
|
// TEMP: path format patterns replaces this logic
|
||||||
part.Path = part.GetPathFromSlug(part.Slug);
|
part.Path = part.GetPathWithSlug(part.Slug);
|
||||||
|
|
||||||
if (part.ContentItem.Id != 0 && model.PromoteToHomePage && _routableHomePageProvider != null) {
|
if (part.ContentItem.Id != 0 && model.PromoteToHomePage && _routableHomePageProvider != null) {
|
||||||
CurrentSite.HomePage = _routableHomePageProvider.GetSettingValue(part.ContentItem.Id);
|
CurrentSite.HomePage = _routableHomePageProvider.GetSettingValue(part.ContentItem.Id);
|
||||||
|
@ -25,16 +25,13 @@ namespace Orchard.Core.Routable.Handlers {
|
|||||||
Action<RoutePart> processSlug = (
|
Action<RoutePart> processSlug = (
|
||||||
routable => {
|
routable => {
|
||||||
var originalSlug = routable.Slug;
|
var originalSlug = routable.Slug;
|
||||||
if (string.IsNullOrWhiteSpace(routable.Path))
|
|
||||||
routable.Path = routable.GetPathFromSlug(routable.Slug);
|
|
||||||
|
|
||||||
if (!_routableService.ProcessSlug(routable)) {
|
if (!_routableService.ProcessSlug(routable)) {
|
||||||
_services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created {2} so now it has the slug \"{1}\"",
|
_services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created {2} so now it has the slug \"{1}\"",
|
||||||
originalSlug, routable.Slug, routable.ContentItem.ContentType));
|
originalSlug, routable.Slug, routable.ContentItem.ContentType));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP: path format patterns replaces this logic
|
// TEMP: path format patterns replaces this logic
|
||||||
routable.Path = routable.GetPathFromSlug(routable.Slug);
|
routable.Path = routable.GetPathWithSlug(routable.Slug);
|
||||||
});
|
});
|
||||||
|
|
||||||
OnPublished<RoutePart>((context, routable) => {
|
OnPublished<RoutePart>((context, routable) => {
|
||||||
|
@ -29,7 +29,7 @@ namespace Orchard.Core.Routable.Models {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetPathFromSlug(string slug) {
|
public string GetPathWithSlug(string slug) {
|
||||||
// TEMP: path format patterns replaces this logic
|
// TEMP: path format patterns replaces this logic
|
||||||
var containerPath = GetContainerPath();
|
var containerPath = GetContainerPath();
|
||||||
if (string.IsNullOrEmpty(containerPath)) {
|
if (string.IsNullOrEmpty(containerPath)) {
|
||||||
|
@ -4,8 +4,7 @@ using Orchard.Core.Routable.Models;
|
|||||||
|
|
||||||
namespace Orchard.Core.Routable.Services {
|
namespace Orchard.Core.Routable.Services {
|
||||||
public interface IRoutableService : IDependency {
|
public interface IRoutableService : IDependency {
|
||||||
void FillSlug<TModel>(TModel model) where TModel : RoutePart;
|
void FillSlugFromTitle<TModel>(TModel model) where TModel : RoutePart;
|
||||||
void FillSlug<TModel>(TModel model, Func<string, string> generateSlug) where TModel : RoutePart;
|
|
||||||
string GenerateUniqueSlug(RoutePart part, IEnumerable<string> existingPaths);
|
string GenerateUniqueSlug(RoutePart part, IEnumerable<string> existingPaths);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -13,7 +13,7 @@ namespace Orchard.Core.Routable.Services {
|
|||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FillSlug<TModel>(TModel model) where TModel : RoutePart {
|
public void FillSlugFromTitle<TModel>(TModel model) where TModel : RoutePart {
|
||||||
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
|
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -29,13 +29,6 @@ namespace Orchard.Core.Routable.Services {
|
|||||||
model.Slug = slug.ToLowerInvariant();
|
model.Slug = slug.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FillSlug<TModel>(TModel model, Func<string, string> generateSlug) where TModel : RoutePart {
|
|
||||||
if (!string.IsNullOrEmpty(model.Slug) || string.IsNullOrEmpty(model.Title))
|
|
||||||
return;
|
|
||||||
|
|
||||||
model.Slug = generateSlug(model.Title).ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateUniqueSlug(RoutePart part, IEnumerable<string> existingPaths) {
|
public string GenerateUniqueSlug(RoutePart part, IEnumerable<string> existingPaths) {
|
||||||
var slugCandidate = part.Slug;
|
var slugCandidate = part.Slug;
|
||||||
if (existingPaths == null || !existingPaths.Contains(part.Path))
|
if (existingPaths == null || !existingPaths.Contains(part.Path))
|
||||||
@ -74,24 +67,21 @@ namespace Orchard.Core.Routable.Services {
|
|||||||
return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
|
return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ProcessSlug(RoutePart part)
|
public bool ProcessSlug(RoutePart part) {
|
||||||
{
|
FillSlugFromTitle(part);
|
||||||
FillSlug(part);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(part.Slug))
|
if (string.IsNullOrEmpty(part.Slug))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
|
part.Path = part.GetPathWithSlug(part.Slug);
|
||||||
var pathsLikeThis = GetSimilarPaths(part.Path);
|
var pathsLikeThis = GetSimilarPaths(part.Path);
|
||||||
|
|
||||||
// Don't include this part in the list
|
// Don't include *this* part in the list
|
||||||
// of slugs to consider for conflict detection
|
// of slugs to consider for conflict detection
|
||||||
pathsLikeThis = pathsLikeThis.Where(p => p.ContentItem.Id != part.ContentItem.Id);
|
pathsLikeThis = pathsLikeThis.Where(p => p.ContentItem.Id != part.ContentItem.Id);
|
||||||
|
|
||||||
//todo: (heskew) need better messages
|
//todo: (heskew) need better messages
|
||||||
if (pathsLikeThis.Count() > 0)
|
if (pathsLikeThis.Count() > 0) {
|
||||||
{
|
|
||||||
var originalSlug = part.Slug;
|
var originalSlug = part.Slug;
|
||||||
//todo: (heskew) make auto-uniqueness optional
|
//todo: (heskew) make auto-uniqueness optional
|
||||||
part.Slug = GenerateUniqueSlug(part, pathsLikeThis.Select(p => p.Path));
|
part.Slug = GenerateUniqueSlug(part, pathsLikeThis.Select(p => p.Path));
|
||||||
|
@ -100,7 +100,7 @@ namespace Orchard.Blogs.Commands {
|
|||||||
post.As<ICommonPart>().Container = blog;
|
post.As<ICommonPart>().Container = blog;
|
||||||
var slug = Slugify(postName);
|
var slug = Slugify(postName);
|
||||||
post.As<RoutePart>().Slug = slug;
|
post.As<RoutePart>().Slug = slug;
|
||||||
post.As<RoutePart>().Path = post.As<RoutePart>().GetPathFromSlug(slug);
|
post.As<RoutePart>().Path = post.As<RoutePart>().GetPathWithSlug(slug);
|
||||||
post.As<RoutePart>().Title = postName;
|
post.As<RoutePart>().Title = postName;
|
||||||
post.As<BodyPart>().Text = item.Element("description").Value;
|
post.As<BodyPart>().Text = item.Element("description").Value;
|
||||||
_contentManager.Create(post);
|
_contentManager.Create(post);
|
||||||
|
@ -182,8 +182,8 @@ namespace Orchard.Blogs.Services {
|
|||||||
if (blogPost.Is<RoutePart>()) {
|
if (blogPost.Is<RoutePart>()) {
|
||||||
blogPost.As<RoutePart>().Title = title;
|
blogPost.As<RoutePart>().Title = title;
|
||||||
blogPost.As<RoutePart>().Slug = slug;
|
blogPost.As<RoutePart>().Slug = slug;
|
||||||
_routableService.FillSlug(blogPost.As<RoutePart>());
|
_routableService.FillSlugFromTitle(blogPost.As<RoutePart>());
|
||||||
blogPost.As<RoutePart>().Path = blogPost.As<RoutePart>().GetPathFromSlug(blogPost.As<RoutePart>().Slug);
|
blogPost.As<RoutePart>().Path = blogPost.As<RoutePart>().GetPathWithSlug(blogPost.As<RoutePart>().Slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
_contentManager.Create(blogPost.ContentItem, VersionOptions.Draft);
|
_contentManager.Create(blogPost.ContentItem, VersionOptions.Draft);
|
||||||
|
Loading…
Reference in New Issue
Block a user