using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Xml; using JetBrains.Annotations; using Orchard.Comments.Models; using Orchard.Comments.Settings; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Aspects; using Orchard.Security; using Orchard.Services; using Orchard.Localization; using Orchard.Comments.Services; using Orchard.UI.Notify; namespace Orchard.Comments.Drivers { [UsedImplicitly] public class CommentPartDriver : ContentPartDriver { private readonly IContentManager _contentManager; private readonly IWorkContextAccessor _workContextAccessor; private readonly IClock _clock; private readonly ICommentService _commentService; private readonly IEnumerable _htmlFilters; private readonly IOrchardServices _orchardServices; protected override string Prefix { get { return "Comments"; } } public Localizer T { get; set; } public CommentPartDriver( IContentManager contentManager, IWorkContextAccessor workContextAccessor, IClock clock, ICommentService commentService, IEnumerable htmlFilters, IOrchardServices orchardServices) { _contentManager = contentManager; _workContextAccessor = workContextAccessor; _clock = clock; _commentService = commentService; _htmlFilters = htmlFilters; _orchardServices = orchardServices; T = NullLocalizer.Instance; } protected override DriverResult Display(CommentPart part, string displayType, dynamic shapeHelper) { var formattedText = new Lazy(() => { var commentsPart = _contentManager.Get(part.CommentedOn); var settings = commentsPart.TypePartDefinition.Settings.GetModel(); var formatted = _htmlFilters.Where(x => x.GetType().Name.Equals(settings.HtmlFilter, StringComparison.OrdinalIgnoreCase)).Aggregate(part.CommentText, (text, filter) => filter.ProcessContent(text)); return formatted; }); return Combined( ContentShape("Parts_Comment_SummaryAdmin", () => shapeHelper.Parts_Comment_SummaryAdmin(FormattedText: formattedText.Value)) ); } // GET protected override DriverResult Editor(CommentPart part, dynamic shapeHelper) { if (UI.Admin.AdminFilter.IsApplied(_workContextAccessor.GetContext().HttpContext.Request.RequestContext)) { return ContentShape("Parts_Comment_AdminEdit", () => shapeHelper.EditorTemplate(TemplateName: "Parts.Comment.AdminEdit", Model: part, Prefix: Prefix)); } else { return ContentShape("Parts_Comment_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts.Comment", Model: part, Prefix: Prefix)); } } // POST protected override DriverResult Editor(CommentPart part, IUpdateModel updater, dynamic shapeHelper) { updater.TryUpdateModel(part, Prefix, null, null); var workContext = _workContextAccessor.GetContext(); // applying moderate/approve actions var httpContext = workContext.HttpContext; var name = httpContext.Request.Form["submit.Save"]; if (!string.IsNullOrEmpty(name) && String.Equals(name, "moderate", StringComparison.OrdinalIgnoreCase)) { if (_orchardServices.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't moderate comment"))) { _commentService.UnapproveComment(part.Id); _orchardServices.Notifier.Information(T("Comment successfully moderated.")); return Editor(part, shapeHelper); } } if (!string.IsNullOrEmpty(name) && String.Equals(name, "approve", StringComparison.OrdinalIgnoreCase)) { if (_orchardServices.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't approve comment"))) { _commentService.ApproveComment(part.Id); _orchardServices.Notifier.Information(T("Comment approved.")); return Editor(part, shapeHelper); } } if (!string.IsNullOrEmpty(name) && String.Equals(name, "delete", StringComparison.OrdinalIgnoreCase)) { if (_orchardServices.Authorizer.Authorize(Permissions.ManageComments, T("Couldn't delete comment"))) { _commentService.DeleteComment(part.Id); _orchardServices.Notifier.Information(T("Comment successfully deleted.")); return Editor(part, shapeHelper); } } // if editing from the admin, don't update the owner or the status if (!string.IsNullOrEmpty(name) && String.Equals(name, "save", StringComparison.OrdinalIgnoreCase)) { _orchardServices.Notifier.Information(T("Comment saved.")); return Editor(part, shapeHelper); } part.CommentDateUtc = _clock.UtcNow; if (!String.IsNullOrEmpty(part.SiteName) && !part.SiteName.StartsWith("http://") && !part.SiteName.StartsWith("https://")) { part.SiteName = "http://" + part.SiteName; } var currentUser = workContext.CurrentUser; part.UserName = (currentUser != null ? currentUser.UserName : null); if (currentUser != null) part.Author = currentUser.UserName; if (String.IsNullOrEmpty(part.Author)) updater.AddModelError("NameMissing", T("You didn't specify your name.")); var moderateComments = workContext.CurrentSite.As().Record.ModerateComments; part.Status = moderateComments ? CommentStatus.Pending : CommentStatus.Approved; var commentedOn = _contentManager.Get(part.CommentedOn); // prevent users from commenting on a closed thread by hijacking the commentedOn property var commentsPart = commentedOn.As(); if (!commentsPart.CommentsActive) { _orchardServices.TransactionManager.Cancel(); return Editor(part, shapeHelper); } if (commentedOn != null && commentedOn.Container != null) { part.CommentedOnContainer = commentedOn.Container.ContentItem.Id; } commentsPart.Record.CommentPartRecords.Add(part.Record); return Editor(part, shapeHelper); } protected override void Importing(CommentPart part, ContentManagement.Handlers.ImportContentContext context) { var author = context.Attribute(part.PartDefinition.Name, "Author"); if (author != null) { part.Record.Author = author; } var siteName = context.Attribute(part.PartDefinition.Name, "SiteName"); if (siteName != null) { part.Record.SiteName = siteName; } var userName = context.Attribute(part.PartDefinition.Name, "UserName"); if (userName != null) { part.Record.UserName = userName; } var email = context.Attribute(part.PartDefinition.Name, "Email"); if (email != null) { part.Record.Email = email; } var position = context.Attribute(part.PartDefinition.Name, "Position"); if (position != null) { part.Record.Position = decimal.Parse(position, CultureInfo.InvariantCulture); } var status = context.Attribute(part.PartDefinition.Name, "Status"); if (status != null) { part.Record.Status = (CommentStatus)Enum.Parse(typeof(CommentStatus), status); } var commentDate = context.Attribute(part.PartDefinition.Name, "CommentDateUtc"); if (commentDate != null) { part.Record.CommentDateUtc = XmlConvert.ToDateTime(commentDate, XmlDateTimeSerializationMode.Utc); } var text = context.Attribute(part.PartDefinition.Name, "CommentText"); if (text != null) { part.Record.CommentText = text; } var commentedOn = context.Attribute(part.PartDefinition.Name, "CommentedOn"); if (commentedOn != null) { var contentItem = context.GetItemFromSession(commentedOn); if (contentItem != null) { part.Record.CommentedOn = contentItem.Id; } contentItem.As().Record.CommentPartRecords.Add(part.Record); } var repliedOn = context.Attribute(part.PartDefinition.Name, "RepliedOn"); if (repliedOn != null) { var contentItem = context.GetItemFromSession(repliedOn); if (contentItem != null) { part.Record.RepliedOn = contentItem.Id; } contentItem.As().Record.CommentPartRecords.Add(part.Record); } var commentedOnContainer = context.Attribute(part.PartDefinition.Name, "CommentedOnContainer"); if (commentedOnContainer != null) { var container = context.GetItemFromSession(commentedOnContainer); if (container != null) { part.Record.CommentedOnContainer = container.Id; } } } protected override void Exporting(CommentPart part, ContentManagement.Handlers.ExportContentContext context) { context.Element(part.PartDefinition.Name).SetAttributeValue("Author", part.Record.Author); context.Element(part.PartDefinition.Name).SetAttributeValue("SiteName", part.Record.SiteName); context.Element(part.PartDefinition.Name).SetAttributeValue("UserName", part.Record.UserName); context.Element(part.PartDefinition.Name).SetAttributeValue("Email", part.Record.Email); context.Element(part.PartDefinition.Name).SetAttributeValue("Position", part.Record.Position.ToString(CultureInfo.InvariantCulture)); context.Element(part.PartDefinition.Name).SetAttributeValue("Status", part.Record.Status.ToString()); if (part.Record.CommentDateUtc != null) { context.Element(part.PartDefinition.Name) .SetAttributeValue("CommentDateUtc", XmlConvert.ToString(part.Record.CommentDateUtc.Value, XmlDateTimeSerializationMode.Utc)); } context.Element(part.PartDefinition.Name).SetAttributeValue("CommentText", part.Record.CommentText); var commentedOn = _contentManager.Get(part.Record.CommentedOn); if (commentedOn != null) { var commentedOnIdentity = _contentManager.GetItemMetadata(commentedOn).Identity; context.Element(part.PartDefinition.Name).SetAttributeValue("CommentedOn", commentedOnIdentity.ToString()); } var commentedOnContainer = _contentManager.Get(part.Record.CommentedOnContainer); if (commentedOnContainer != null) { var commentedOnContainerIdentity = _contentManager.GetItemMetadata(commentedOnContainer).Identity; context.Element(part.PartDefinition.Name).SetAttributeValue("CommentedOnContainer", commentedOnContainerIdentity.ToString()); } if (part.Record.RepliedOn.HasValue) { var repliedOn = _contentManager.Get(part.Record.RepliedOn.Value); if (repliedOn != null) { var repliedOnIdentity = _contentManager.GetItemMetadata(repliedOn).Identity; context.Element(part.PartDefinition.Name).SetAttributeValue("RepliedOn", repliedOnIdentity.ToString()); } } } } }