Corrected slugs validation and added unit tests

This commit is contained in:
Sebastien Ros
2010-04-21 10:01:57 -07:00
parent 2647c1f8d4
commit 3604a52d74
3 changed files with 21 additions and 49 deletions

View File

@@ -52,6 +52,24 @@ namespace Orchard.Core.Tests.Common.Services {
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-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\"-\""));
} }
[Test]
public void EmptySlugsShouldBeConsideredValid() {
// so that automatic generation on Publish occurs
Assert.That(_routableService.IsSlugValid(null), Is.True);
Assert.That(_routableService.IsSlugValid(String.Empty), Is.True);
Assert.That(_routableService.IsSlugValid(" "), Is.True);
}
[Test]
public void InvalidCharacterShouldBeRefusedInSlugs() {
Assert.That(_routableService.IsSlugValid("aaaa-_aaaa"), Is.True);
foreach (var c in @"/:?#[]@!$&'()*+,;= ") {
Assert.That(_routableService.IsSlugValid("a" + c + "b"), Is.False);
}
}
[Test] [Test]
public void VeryLongStringTruncatedTo1000Chars() { public void VeryLongStringTruncatedTo1000Chars() {
var contentManager = _container.Resolve<IContentManager>(); var contentManager = _container.Resolve<IContentManager>();

View File

@@ -74,7 +74,8 @@ namespace Orchard.Core.Common.Services {
} }
public bool IsSlugValid(string slug) { public bool IsSlugValid(string slug) {
return slug == null || String.IsNullOrEmpty(slug.Trim()) || !Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$"); // see http://tools.ietf.org/html/rfc3987 for prohibited chars
return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
} }
public bool ProcessSlug(RoutableAspect part) public bool ProcessSlug(RoutableAspect part)

View File

@@ -1,16 +1,12 @@
using System; using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Routing; using System.Web.Routing;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.Blogs.Models; using Orchard.Blogs.Models;
using Orchard.Blogs.Services; using Orchard.Blogs.Services;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services; using Orchard.Core.Common.Services;
using Orchard.Localization; using Orchard.Localization;
using Orchard.UI.Notify;
namespace Orchard.Blogs.Drivers { namespace Orchard.Blogs.Drivers {
[UsedImplicitly] [UsedImplicitly]
@@ -78,54 +74,11 @@ namespace Orchard.Blogs.Drivers {
protected override DriverResult Editor(BlogPost post, IUpdateModel updater) { protected override DriverResult Editor(BlogPost post, IUpdateModel updater) {
updater.TryUpdateModel(post, Prefix, null, null); updater.TryUpdateModel(post, Prefix, null, null);
//todo: (heskew) something better needs to be done with this...still feels shoehorned in here
ProcessSlug(post, updater);
DateTime scheduled; DateTime scheduled;
if (DateTime.TryParse(string.Format("{0} {1}", post.ScheduledPublishUtcDate, post.ScheduledPublishUtcTime), out scheduled)) if (DateTime.TryParse(string.Format("{0} {1}", post.ScheduledPublishUtcDate, post.ScheduledPublishUtcTime), out scheduled))
post.ScheduledPublishUtc = scheduled; post.ScheduledPublishUtc = scheduled;
return Editor(post); return Editor(post);
} }
private void ProcessSlug(BlogPost post, IUpdateModel updater) {
_routableService.FillSlug(post.As<RoutableAspect>());
if (string.IsNullOrEmpty(post.Slug)) {
return;
// OR
//updater.AddModelError("Routable.Slug", T("The slug is required.").ToString());
//return;
}
if (!Regex.IsMatch(post.Slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$")) {
//todo: (heskew) get rid of the hard-coded prefix
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).").ToString());
return;
}
var slugsLikeThis = _blogPostService.Get(post.Blog, VersionOptions.Published).Where(
p => p.Slug.StartsWith(post.Slug, StringComparison.OrdinalIgnoreCase) &&
p.Id != post.Id).Select(p => p.Slug);
//todo: (heskew) need better messages
if (slugsLikeThis.Count() > 0) {
//todo: (heskew) need better messages
Services.Notifier.Warning(T("A different blog post is already published with this same slug."));
if (post.ContentItem.VersionRecord == null || post.ContentItem.VersionRecord.Published)
{
var originalSlug = post.Slug;
//todo: (heskew) make auto-uniqueness optional
post.Slug = _routableService.GenerateUniqueSlug(post.Slug, slugsLikeThis);
if (originalSlug != post.Slug)
Services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created blog post so this post now has the slug \"{1}\"",
originalSlug, post.Slug));
}
}
}
} }
} }