using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.Drivers; using Orchard.Core.Common.Models; using Orchard.Core.Routable.Models; using Orchard.Core.Routable.Services; using Orchard.Core.Routable.ViewModels; using Orchard.Localization; using Orchard.UI.Notify; namespace Orchard.Core.Routable.Drivers { public class RoutableDriver : ContentPartDriver { private readonly IOrchardServices _services; private readonly IRoutableService _routableService; public RoutableDriver(IOrchardServices services, IRoutableService routableService) { _services = services; _routableService = routableService; T = NullLocalizer.Instance; } private const string TemplateName = "Parts/Routable.IsRoutable"; public Localizer T { get; set; } protected override string Prefix { get { return "Routable"; } } int? GetContainerId(IContent item) { var commonAspect = item.As(); if (commonAspect != null && commonAspect.Container != null) { return commonAspect.Container.ContentItem.Id; } return null; } string GetContainerSlug(IContent item) { var commonAspect = item.As(); if (commonAspect != null && commonAspect.Container != null) { var routable = commonAspect.Container.As(); if (routable != null) { return routable.Slug; } } return null; } protected override DriverResult Editor(IsRoutable part) { var model = new RoutableEditorViewModel { ContentType = part.ContentItem.ContentType, Id = part.ContentItem.Id, Slug = part.Slug, Title = part.Title, ContainerId = GetContainerId(part), }; // TEMP: path format patterns replaces this logic var path = part.Record.Path; if (path.EndsWith(part.Slug)) { model.DisplayLeadingPath = path.Substring(0, path.Length - part.Slug.Length); } return ContentPartTemplate(model, TemplateName, Prefix).Location("primary", "before.5"); } protected override DriverResult Editor(IsRoutable part, IUpdateModel updater) { var model = new RoutableEditorViewModel(); updater.TryUpdateModel(model, Prefix, null, null); part.Title = model.Title; part.Slug = model.Slug; // TEMP: path format patterns replaces this logic var containerSlug = GetContainerSlug(part); if (string.IsNullOrEmpty(containerSlug)) { part.Record.Path = model.Slug; } else { part.Record.Path = containerSlug + "/" + model.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).")); } string originalSlug = part.Slug; if (!_routableService.ProcessSlug(part)) { _services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created {2} so now it has the slug \"{1}\"", originalSlug, part.Slug, part.ContentItem.ContentType)); } return Editor(part); } } }