diff --git a/src/Orchard.Tests.Modules/Warmup/WebDownloaderTests.cs b/src/Orchard.Tests.Modules/Warmup/WebDownloaderTests.cs index 66fbd993b..2edd5a72a 100644 --- a/src/Orchard.Tests.Modules/Warmup/WebDownloaderTests.cs +++ b/src/Orchard.Tests.Modules/Warmup/WebDownloaderTests.cs @@ -20,7 +20,7 @@ namespace Orchard.Tests.Modules.Warmup { [Test] public void StatusCodeShouldBe404ForUnexistingResources() { - var download = _webDownloader.Download("http://www.microsoft.com/yepyep"); + var download = _webDownloader.Download("http://orchardproject.net/yepyep"); Assert.That(download, Is.Not.Null); Assert.That(download.StatusCode, Is.EqualTo(HttpStatusCode.NotFound)); Assert.That(download.Content, Is.Null); @@ -28,7 +28,7 @@ namespace Orchard.Tests.Modules.Warmup { [Test] public void StatusCodeShouldBe200ForValidRequests() { - var download = _webDownloader.Download("http://www.microsoft.com/"); + var download = _webDownloader.Download("http://orchardproject.net/"); Assert.That(download, Is.Not.Null); Assert.That(download.StatusCode, Is.EqualTo(HttpStatusCode.OK)); Assert.That(download.Content, Is.Not.Empty); diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 388226cdb..a702e9c99 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -121,7 +121,10 @@ namespace Orchard.Core.Contents.Controllers { } private IEnumerable GetCreatableTypes(bool andContainable) { - return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Settings.GetModel().Creatable && (!andContainable || ctd.Parts.Any(p => p.PartDefinition.Name == "ContainablePart"))); + return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => + Services.Authorizer.Authorize(Permissions.EditContent, _contentManager.New(ctd.Name)) && + ctd.Settings.GetModel().Creatable && + (!andContainable || ctd.Parts.Any(p => p.PartDefinition.Name == "ContainablePart"))); } [HttpPost, ActionName("List")] diff --git a/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml b/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml index b5ef9118a..21830c122 100644 --- a/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Core/Navigation/Views/Admin/Index.cshtml @@ -6,9 +6,9 @@ Layout.Title = T("Navigation").ToString(); Style.Include("navigation-admin.css"); - Script.Require("jQueryUI_Sortable"); - Script.Include("jquery.mjs.nestedSortable.js"); - Script.Include("navigation-admin.js"); + Script.Require("jQueryUI_Sortable").AtFoot(); + Script.Include("jquery.mjs.nestedSortable.js").AtFoot(); + Script.Include("navigation-admin.js").AtFoot(); }
@T("You need to hit \"Save All\" in order to save your changes.")
diff --git a/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml b/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml index 090d37073..aeb02b44a 100644 --- a/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml +++ b/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml @@ -5,12 +5,14 @@ }
@Html.EditorFor(m => m.OnAdminMenu) - -
- + +
+ @Html.TextBoxFor(m => m.AdminMenuText, new { @class = "text single-line" }) + @T("The text that should appear in the menu.") - - @Html.TextBoxFor(m => m.AdminMenuPosition, new { @class = "text single-line" }) + + @Html.TextBoxFor(m => m.AdminMenuPosition, new { @class = "text small" }) + @T("The position in the menu.")
diff --git a/src/Orchard.Web/Core/Shapes/CoreShapes.cs b/src/Orchard.Web/Core/Shapes/CoreShapes.cs index f81be0d1c..03b4a42f5 100644 --- a/src/Orchard.Web/Core/Shapes/CoreShapes.cs +++ b/src/Orchard.Web/Core/Shapes/CoreShapes.cs @@ -263,26 +263,24 @@ namespace Orchard.Core.Shapes { IDictionary attributes = Shape.Attributes; var zoneWrapper = GetTagBuilder("div", id, classes, attributes); Output.Write(zoneWrapper.ToString(TagRenderMode.StartTag)); - foreach (var item in ordered_hack(Shape)) + foreach (var item in Order(Shape)) Output.Write(Display(item)); Output.Write(zoneWrapper.ToString(TagRenderMode.EndTag)); } [Shape] public void ContentZone(dynamic Display, dynamic Shape, TextWriter Output) { - foreach (var item in ordered_hack(Shape)) + foreach (var item in Order(Shape)) Output.Write(Display(item)); } [Shape] public void DocumentZone(dynamic Display, dynamic Shape, TextWriter Output) { - foreach (var item in ordered_hack(Shape)) + foreach (var item in Order(Shape)) Output.Write(Display(item)); } - #region ordered_hack - - private static IEnumerable ordered_hack(dynamic shape) { + public static IEnumerable Order(dynamic shape) { IEnumerable unordered = shape; if (unordered == null || unordered.Count() < 2) return shape; @@ -317,8 +315,6 @@ namespace Orchard.Core.Shapes { return ordering.Select(ordered => ordered.item).ToList(); } - #endregion - [Shape] public void HeadScripts(dynamic Display, TextWriter Output) { WriteResources(Display, Output, "script", ResourceLocation.Head, null); @@ -618,7 +614,7 @@ namespace Orchard.Core.Shapes { IEnumerable classes = Shape.Classes; IDictionary attributes = Shape.Attributes; - attributes.Add("href", action); + attributes["href"] = action; string id = Shape.Id; var tag = GetTagBuilder("a", id, classes, attributes); tag.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString(); diff --git a/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs b/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs index 7228539db..3b018e9af 100644 --- a/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs +++ b/src/Orchard.Web/Modules/Lucene/Models/LuceneDocumentIndex.cs @@ -100,7 +100,7 @@ namespace Lucene.Models { switch(_typeCode) { case TypeCode.String: if(_removeTags) { - _stringValue = _stringValue.RemoveTags(); + _stringValue = _stringValue.RemoveTags(true); } Fields.Add(new Field(_name, _stringValue ?? String.Empty, _store ? Field.Store.YES : Field.Store.NO, diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/Drivers/ReCaptchaPartDriver.cs b/src/Orchard.Web/Modules/Orchard.AntiSpam/Drivers/ReCaptchaPartDriver.cs index 5b5300669..569d55722 100644 --- a/src/Orchard.Web/Modules/Orchard.AntiSpam/Drivers/ReCaptchaPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/Drivers/ReCaptchaPartDriver.cs @@ -9,6 +9,7 @@ using Orchard.AntiSpam.ViewModels; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.Localization; +using Orchard.Logging; using Orchard.UI.Admin; using Orchard.UI.Notify; @@ -25,10 +26,11 @@ namespace Orchard.AntiSpam.Drivers { _notifier = notifier; _workContextAccessor = workContextAccessor; T = NullLocalizer.Instance; + Logger = NullLogger.Instance; } public Localizer T { get; set; } - + public ILogger Logger { get; set; } protected override DriverResult Editor(ReCaptchaPart part, dynamic shapeHelper) { var workContext = _workContextAccessor.GetContext(); @@ -70,16 +72,22 @@ namespace Orchard.AntiSpam.Drivers { if(updater.TryUpdateModel(submitViewModel, String.Empty, null, null)) { var context = workContext.HttpContext; - var result = ExecuteValidateRequest( - settings.PrivateKey, - context.Request.ServerVariables["REMOTE_ADDR"], - submitViewModel.recaptcha_challenge_field, - submitViewModel.recaptcha_response_field - ); + try { + var result = ExecuteValidateRequest( + settings.PrivateKey, + context.Request.ServerVariables["REMOTE_ADDR"], + submitViewModel.recaptcha_challenge_field, + submitViewModel.recaptcha_response_field + ); - if(!HandleValidateResponse(context, result)) { - _notifier.Error(T("The text you entered in the Captcha field does not match the image")); - updater.AddModelError("", T("The text you entered in the Captcha field does not match the image")); + if (!HandleValidateResponse(context, result)) { + _notifier.Error(T("The text you entered in the Captcha field does not match the image")); + updater.AddModelError("", T("The text you entered in the Captcha field does not match the image")); + } + } + catch(Exception e) { + Logger.Error(e, "An unexcepted error occured while submitting a reCaptcha"); + updater.AddModelError("Parts_ReCaptcha_Fields", T("There was an error while validating the Captcha image")); } } diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureOutputCacheStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureOutputCacheStorageProvider.cs index 736aa25ca..c1414b8a0 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureOutputCacheStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Caching/Output/AzureOutputCacheStorageProvider.cs @@ -48,6 +48,10 @@ namespace Orchard.Azure.Services.Caching.Output { } public void Set(string key, CacheItem cacheItem) { + if (cacheItem.ValidFor <= 0) { + return; + } + Logger.Debug("Set() invoked with key='{0}' in region '{1}'.", key, _regionAlphaNumeric); _cache.Put(key, cacheItem, TimeSpan.FromSeconds(cacheItem.ValidFor), _regionAlphaNumeric); } diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs index b037114b6..f299d7440 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs @@ -108,11 +108,15 @@ namespace Orchard.Comments.Controllers { // if the user who submitted the comment has the right to moderate, don't make this comment moderated if (Services.Authorizer.Authorize(Permissions.ManageComments)) { commentPart.Status = CommentStatus.Approved; + Services.Notifier.Information(T("Your comment has been posted.")); } else { Services.Notifier.Information(T("Your comment will appear after the site administrator approves it.")); } } + else { + Services.Notifier.Information(T("Your comment has been posted.")); + } } else { Services.TransactionManager.Cancel(); diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml index 2c13da45b..da4a48ac0 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/EditPlacement.cshtml @@ -52,12 +52,32 @@ (function ($) { var assignPositions = function () { - var position = 1; - $('.position').each(function() { - $(this).val(position++); + var position = 0; + $('.type').each(function () { + var input = $(this); + reAssignIdName(input, position); // type + + input = input.next(); + reAssignIdName(input, position); // differentiator + + input = input.next(); + reAssignIdName(input, position); // zone + + input = input.next(); + reAssignIdName(input, position); // position + + input.val(++position); }); }; + var reAssignIdName = function (input, pos) { + var name = input.attr('name'); + input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + pos + ']')); + + var id = input.attr('id'); + input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + pos + '__')); + }; + assignPositions(); var startPos; diff --git a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs index 9d1672bd9..c481be81a 100644 --- a/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs +++ b/src/Orchard.Web/Modules/Orchard.ImportExport/Services/ImportExportService.cs @@ -5,6 +5,7 @@ using System.Xml; using System.Xml.Linq; using JetBrains.Annotations; using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.MetaData; using Orchard.Environment.Descriptor; using Orchard.FileSystems.AppData; @@ -139,33 +140,50 @@ namespace Orchard.ImportExport.Services { } private XElement ExportSiteSettings() { - var settings = new XElement("Settings"); - var hasSetting = false; + var siteContentItem = _orchardServices.WorkContext.CurrentSite.ContentItem; + var exportedElements = ExportContentItem(siteContentItem).Elements().ToList(); + + foreach (var contentPart in siteContentItem.Parts) { + var exportedElement = exportedElements.FirstOrDefault(element => element.Name == contentPart.PartDefinition.Name); - foreach (var sitePart in _orchardServices.WorkContext.CurrentSite.ContentItem.Parts) { - var setting = new XElement(sitePart.PartDefinition.Name); + //Get all simple attributes if exported element is null + //Get exclude the simple attributes that already exist if element is not null + var simpleAttributes = + ExportSettingsPartAttributes(contentPart) + .Where(attribute => exportedElement == null || exportedElement.Attributes().All(xAttribute => xAttribute.Name != attribute.Name)) + .ToList(); - foreach (var property in sitePart.GetType().GetProperties()) { - var propertyType = property.PropertyType; - // Supported types (we also know they are not indexed properties). - if (propertyType == typeof(string) || propertyType == typeof(bool) || propertyType == typeof(int)) { - // Exclude read-only properties. - if (property.GetSetMethod() != null) { - setting.SetAttributeValue(property.Name, property.GetValue(sitePart, null)); - hasSetting = true; - } + if (simpleAttributes.Any()) { + if (exportedElement == null) { + exportedElement = new XElement(contentPart.PartDefinition.Name); + exportedElements.Add(exportedElement); } - } - if (hasSetting) { - settings.Add(setting); - hasSetting = false; + exportedElement.Add(simpleAttributes); } } - return settings; + return new XElement("Settings", exportedElements); } + private IEnumerable ExportSettingsPartAttributes(ContentPart sitePart) { + foreach (var property in sitePart.GetType().GetProperties()) { + var propertyType = property.PropertyType; + + // Supported types (we also know they are not indexed properties). + if (propertyType == typeof(string) || propertyType == typeof(bool) || propertyType == typeof(int)) { + // Exclude read-only properties. + if (property.GetSetMethod() != null) { + var value = property.GetValue(sitePart, null); + if (value == null) + continue; + + yield return new XAttribute(property.Name, value); + } + } + } + } + private XElement ExportData(IEnumerable contentTypes, IEnumerable contentItems, int? batchSize) { var data = new XElement("Data"); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs index 8b0dfdc94..f6686ad2e 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/AdminController.cs @@ -39,7 +39,9 @@ namespace Orchard.MediaLibrary.Controllers { public ILogger Logger { get; set; } public ActionResult Index(string folderPath = "", bool dialog = false) { - + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + return new HttpUnauthorizedResult(); + // let other modules enhance the ui by providing custom navigation and actions var explorer = Services.ContentManager.New("MediaLibraryExplorer"); explorer.Weld(new MediaLibraryExplorerPart()); @@ -67,6 +69,8 @@ namespace Orchard.MediaLibrary.Controllers { } public ActionResult Import(string folderPath) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot import media"))) + return new HttpUnauthorizedResult(); var mediaProviderMenu = _navigationManager.BuildMenu("mediaproviders"); var imageSets = _navigationManager.BuildImageSets("mediaproviders"); @@ -83,8 +87,11 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "") { - var mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType, VersionOptions.Latest); - var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType, VersionOptions.Latest); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + return new HttpUnauthorizedResult(); + + var mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType); + var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType); var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel { MediaPart = x, @@ -115,8 +122,12 @@ namespace Orchard.MediaLibrary.Controllers { [Themed(false)] public ActionResult RecentMediaItems(int skip = 0, int count = 0, string order = "created", string mediaType = "") { - var mediaParts = _mediaLibraryService.GetMediaContentItems(skip, count, order, mediaType, VersionOptions.Latest); - var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(mediaType, VersionOptions.Latest); + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media"))) + return new HttpUnauthorizedResult(); + + var mediaParts = _mediaLibraryService.GetMediaContentItems(skip, count, order, mediaType); + var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(mediaType); + var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel { MediaPart = x, @@ -138,7 +149,7 @@ namespace Orchard.MediaLibrary.Controllers { if (contentItem == null) return HttpNotFound(); - if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot edit media"))) + if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot view media"))) return new HttpUnauthorizedResult(); dynamic model = Services.ContentManager.BuildDisplay(contentItem, displayType); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/ModalAdminFilter.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/ModalAdminFilter.cs index b177cd410..cd47539f2 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/ModalAdminFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/ModalAdminFilter.cs @@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary { if (!(filterContext.Result is ViewResult) || !UI.Admin.AdminFilter.IsApplied(filterContext.RequestContext)) return; _resourceManager.Include("stylesheet", "~/Modules/Orchard.MediaLibrary/Styles/dialog-mode.css", null); - _resourceManager.Include("script", "~/Modules/Orchard.MediaLibrary/Scripts/modal-window.js", null); + _resourceManager.Include("script", "~/Modules/Orchard.MediaLibrary/Scripts/modal-window.js", null).AtFoot(); } public void OnResultExecuted(ResultExecutedContext filterContext) { diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml index a63739d98..eaac1450a 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml @@ -3,13 +3,13 @@ @{ var viewModel = Model; - Script.Require("ShapesBase"); + Script.Require("ShapesBase").AtFoot(); Style.Require("MediaManagerAdmin"); - Script.Require("jQuery"); - Script.Require("jQueryUI_Droppable"); - Script.Include("knockout-2.3.0.js"); - Script.Include("history.js"); - Script.Include("media-library.js"); + Script.Require("jQuery").AtFoot(); + Script.Require("jQueryUI_Droppable").AtFoot(); + Script.Include("knockout-2.3.0.js").AtFoot(); + Script.Include("history.js").AtFoot(); + Script.Include("media-library.js").AtFoot(); Style.Require("FontAwesome"); Layout.Title = T("Media Library"); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml index 5420fe349..533b70f31 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/ClientStorage/Index.cshtml @@ -4,15 +4,15 @@ @{ - Script.Require("jQuery"); - Script.Require("jQueryUI"); + Script.Require("jQuery").AtFoot(); + Script.Require("jQueryUI").AtFoot(); Style.Include("orchard-medialibrary-admin.css"); Style.Include("orchard-mediaproviders-admin.css"); Style.Include("orchard-clientstorage-admin.css"); - Script.Require("jQueryFileUpload"); - Script.Include("knockout-2.3.0.js"); + Script.Require("jQueryFileUpload").AtFoot(); + Script.Include("knockout-2.3.0.js").AtFoot(); } @Display.Metas() diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml index 189914a34..d99186a77 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/EditorTemplates/Fields/MediaLibraryPicker.Edit.cshtml @@ -7,7 +7,7 @@ Script.Require("jQueryUI_Sortable").AtFoot(); Style.Include("media-library-picker-admin.css"); - Script.Require("jQueryColorBox"); + Script.Require("jQueryColorBox").AtFoot(); Style.Require("jQueryColorBox"); var settings = Model.Field.PartFieldDefinition.Settings.GetModel(); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml index 1fc436d13..2bcca378a 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Media.SummaryAdmin.cshtml @@ -4,19 +4,19 @@ MediaPart mediaPart = Model.ContentItem.MediaPart; var contentTypeClassName = mediaPart.ContentItem.ContentType.HtmlClassify(); } -
+
@Display(Model.Header) @if (Model.Meta != null) {
- @Display(Model.Meta) + @Display(Model.Meta)
}
@Display(Model.Content) - @if(Model.Footer != null) { -
- @Display(Model.Footer) -
+ @if (Model.Footer != null) { +
+ @Display(Model.Footer) +
}
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/OEmbed/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/OEmbed/Index.cshtml index 1569efb97..7504fb0e9 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/OEmbed/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/OEmbed/Index.cshtml @@ -4,8 +4,8 @@ @{ - Script.Require("jQuery"); - Script.Require("jQueryUI"); + Script.Require("jQuery").AtFoot(); + Script.Require("jQueryUI").AtFoot(); Style.Include("orchard-medialibrary-admin.css"); Style.Include("orchard-mediaproviders-admin.css"); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml index 0b0251555..6d3356405 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/WebSearch/Index.cshtml @@ -8,8 +8,8 @@ @{ - Script.Require("jQuery"); - Script.Include("knockout-2.3.0.js"); + Script.Require("jQuery").AtFoot(); + Script.Include("knockout-2.3.0.js").AtFoot(); Style.Include("orchard-mediaproviders-admin.css"); Style.Include("orchard-websearch-admin.css"); diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml index 9324bfcae..42a05916a 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.cshtml @@ -8,7 +8,7 @@ @{ Style.Require("ModulesAdmin"); Style.Require("Switchable"); - Script.Require("Switchable"); + Script.Require("Switchable").AtFoot(); Script.Include("features.admin.js", "features.admin.min.js").AtFoot(); Layout.Title = T("Modules").ToString(); diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index 0684a7477..4beb676ec 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Linq; @@ -38,8 +37,6 @@ namespace Orchard.OutputCache.Filters { private readonly ICacheControlStrategy _cacheControlStrategy; private Stream _previousFilter; - private const string RefreshKey = "__r"; - public OutputCacheFilter( ICacheManager cacheManager, IOutputCacheStorageProvider cacheStorageProvider, @@ -51,7 +48,8 @@ namespace Orchard.OutputCache.Filters { ICacheService cacheService, ISignals signals, ShellSettings shellSettings, - ICacheControlStrategy cacheControlStrategy) { + ICacheControlStrategy cacheControlStrategy + ) { _cacheManager = cacheManager; _cacheStorageProvider = cacheStorageProvider; _tagCache = tagCache; @@ -74,11 +72,10 @@ namespace Orchard.OutputCache.Filters { private bool _applyCulture; private string _cacheKey; private string _invariantCacheKey; - private string _actionName; private DateTime _now; private string[] _varyQueryStringParameters; private ISet _varyRequestHeaders; - + private bool _transformRedirect; private WorkContext _workContext; private CapturingResponseFilter _filter; @@ -88,8 +85,6 @@ namespace Orchard.OutputCache.Filters { public ILogger Logger { get; set; } public void OnActionExecuting(ActionExecutingContext filterContext) { - // use the action in the cacheKey so that the same route can't return cache for different actions - _actionName = filterContext.ActionDescriptor.ActionName; // apply OutputCacheAttribute logic if defined var actionAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true); @@ -285,12 +280,12 @@ namespace Orchard.OutputCache.Filters { // no cache content available, intercept the execution results for caching _previousFilter = response.Filter; - response.Filter = _filter = new CapturingResponseFilter(response.Filter); + response.Filter = _filter = new CapturingResponseFilter(); } public void OnActionExecuted(ActionExecutedContext filterContext) { // handle redirections - TransformRedirect(filterContext); + _transformRedirect = TransformRedirect(filterContext); } public void OnResultExecuted(ResultExecutedContext filterContext) { @@ -343,7 +338,7 @@ namespace Orchard.OutputCache.Filters { } return; } - + // save the result only if the content can be intercepted if (_filter == null) return; @@ -359,8 +354,7 @@ namespace Orchard.OutputCache.Filters { response.Filter = null; response.Write(output); - - + // check if there is a specific rule not to cache the whole route var configurations = _cacheService.GetRouteConfigurations(); var route = filterContext.Controller.ControllerContext.RouteData.Route; @@ -373,12 +367,32 @@ namespace Orchard.OutputCache.Filters { return; } + // don't cache the result of a POST redirection as it could contain notifications + if (_transformRedirect) { + return; + } + + // don't cache the result if there were some notifications + var messagesZone = _workContextAccessor.GetContext(filterContext).Layout.Zones["Messages"]; + var hasNotifications = messagesZone != null && ((IEnumerable)messagesZone).Any(); + if (hasNotifications) { + return; + } + // default duration of specific one ? var cacheDuration = configuration != null && configuration.Duration.HasValue ? configuration.Duration.Value : _cacheDuration; + if (cacheDuration <= 0) { + return; + } + // include each of the content item ids as tags for the cache entry var contentItemIds = _displayedContentItemHandler.GetDisplayed().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray(); + if (filterContext.HttpContext.Request.Url == null) { + return; + } + _cacheItem.ContentType = response.ContentType; _cacheItem.StatusCode = response.StatusCode; _cacheItem.CachedOnUtc = _now; @@ -408,6 +422,8 @@ namespace Orchard.OutputCache.Filters { private bool TransformRedirect(ActionExecutedContext filterContext) { + // removes the target of the redirection from cache after a POST + if (filterContext.Result == null) { throw new ArgumentNullException(); } @@ -439,26 +455,6 @@ namespace Orchard.OutputCache.Filters { _cacheService.RemoveByTag(invariantCacheKey); - // adding a refresh key so that the next request will not be cached - var epIndex = redirectUrl.IndexOf('?'); - var qs = new NameValueCollection(); - if (epIndex > 0) { - qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex)); - } - - var refresh = _now.Ticks; - qs.Remove(RefreshKey); - - qs.Add(RefreshKey, refresh.ToString("x")); - var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k])))); - - if (epIndex > 0) { - redirectUrl = redirectUrl.Substring(0, epIndex) + querystring; - } - else { - redirectUrl = redirectUrl + querystring; - } - filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult) filterContext.Result).Permanent); filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); @@ -539,9 +535,6 @@ namespace Orchard.OutputCache.Filters { // include the theme in the cache key keyBuilder.Append("theme=").Append(theme.ToLowerInvariant()).Append(";"); - // include the theme in the cache key - keyBuilder.Append("action=").Append(_actionName.ToLowerInvariant()).Append(";"); - if (parameters != null) { foreach (var pair in parameters) { keyBuilder.AppendFormat("{0}={1};", pair.Key.ToLowerInvariant(), Convert.ToString(pair.Value).ToLowerInvariant()); @@ -598,11 +591,9 @@ namespace Orchard.OutputCache.Filters { /// Captures the response stream while writing to it /// public class CapturingResponseFilter : Stream { - // private readonly Stream _sink; private readonly MemoryStream _mem; - public CapturingResponseFilter(Stream sink) { - // _sink = sink; + public CapturingResponseFilter() { _mem = new MemoryStream(); } @@ -630,27 +621,21 @@ namespace Orchard.OutputCache.Filters { } public override void SetLength(long length) { - // _sink.SetLength(length); } public override void Close() { - // _sink.Close(); _mem.Close(); } public override void Flush() { - // _sink.Flush(); } public override int Read(byte[] buffer, int offset, int count) { - // return _sink.Read(buffer, offset, count); return count; } // Override the Write method to filter Response to a file. public override void Write(byte[] buffer, int offset, int count) { - //Here we will not write to the sink b/c we want to capture - // _sink.Write(buffer, offset, count); //Write out the response to the file. _mem.Write(buffer, 0, count); diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultCacheStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultCacheStorageProvider.cs index ddda8e781..dbda6d6e2 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultCacheStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Services/DefaultCacheStorageProvider.cs @@ -3,9 +3,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using Orchard.OutputCache.Models; -using Orchard; using Orchard.Environment.Configuration; -using Orchard.Services; namespace Orchard.OutputCache.Services { public class DefaultCacheStorageProvider : IOutputCacheStorageProvider { diff --git a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs index 6a559ab06..782622d3c 100644 --- a/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs +++ b/src/Orchard.Web/Modules/Orchard.Packaging/Controllers/GalleryUpdatesController.cs @@ -31,11 +31,8 @@ namespace Orchard.Packaging.Controllers { ShellSettings shellSettings, IOrchardServices services, IPackagingSourceManager packagingSourceManager, - INotifier notifier, IPackageUpdateService packageUpdateService, IBackgroundPackageUpdateStatus backgroundPackageUpdateStatus, - IReportsCoordinator reportsCoordinator, - IReportsManager reportsManager, IShapeFactory shapeFactory) { _shellSettings = shellSettings; @@ -45,7 +42,6 @@ namespace Orchard.Packaging.Controllers { Services = services; Shape = shapeFactory; - PackageUpdateService = packageUpdateService; T = NullLocalizer.Instance; Logger = NullLogger.Instance; @@ -55,7 +51,6 @@ namespace Orchard.Packaging.Controllers { public Localizer T { get; set; } public ILogger Logger { get; set; } public dynamic Shape { get; set; } - public IPackageUpdateService PackageUpdateService { get; set; } public ActionResult ThemesUpdates(int? reportId, PagerParameters pagerParameters) { return PackageUpdate("ThemesUpdates", DefaultExtensionTypes.Theme, reportId, pagerParameters); diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs index f20940a12..207e10649 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs @@ -311,8 +311,8 @@ namespace Orchard.Projections.Drivers { int layoutIndexValue; if (layoutIndex != null && Int32.TryParse(layoutIndex, out layoutIndexValue) - && layoutIndexValue != -1 - && part.Record.QueryPartRecord.Layouts.Count >= layoutIndexValue + 1) + && layoutIndexValue >= 0 + && part.Record.QueryPartRecord.Layouts.Count > layoutIndexValue) { part.Record.LayoutRecord = part.Record.QueryPartRecord.Layouts[Int32.Parse(layoutIndex)]; } diff --git a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/SettingsRecipeHandler.cs b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/SettingsRecipeHandler.cs index e0e0366b3..1bf4e6548 100644 --- a/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/SettingsRecipeHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Recipes/RecipeHandlers/SettingsRecipeHandler.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; +using System.Security.Policy; using System.Xml; using System.Xml.Linq; using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; using Orchard.Localization; using Orchard.Logging; using Orchard.Recipes.Models; @@ -11,15 +14,20 @@ using Orchard.Settings; namespace Orchard.Recipes.RecipeHandlers { public class SettingsRecipeHandler : IRecipeHandler { private readonly ISiteService _siteService; + private readonly IContentManager _contentManager; + private readonly Lazy> _handlers; - public SettingsRecipeHandler(ISiteService siteService) { + public SettingsRecipeHandler(ISiteService siteService, IContentManager contentManager, Lazy> handlers) { _siteService = siteService; + _contentManager = contentManager; + _handlers = handlers; Logger = NullLogger.Instance; T = NullLocalizer.Instance; } public Localizer T { get; set; } public ILogger Logger { get; set; } + private IEnumerable Handlers { get { return _handlers.Value; } } /* @@ -33,41 +41,52 @@ namespace Orchard.Recipes.RecipeHandlers { return; } - var site = _siteService.GetSiteSettings(); - foreach (var element in recipeContext.RecipeStep.Step.Elements()) { - var partName = XmlConvert.DecodeName(element.Name.LocalName); - foreach (var contentPart in site.ContentItem.Parts) { - if (!String.Equals(contentPart.PartDefinition.Name, partName, StringComparison.OrdinalIgnoreCase)) { - continue; - } - foreach (var attribute in element.Attributes()) { - SetSetting(attribute, contentPart); - } + var siteContentItem = _siteService.GetSiteSettings().ContentItem; + + var importContentSession = new ImportContentSession(_contentManager); + + var context = new ImportContentContext(siteContentItem, recipeContext.RecipeStep.Step, importContentSession); + foreach (var contentHandler in Handlers) { + contentHandler.Importing(context); + } + + foreach (var contentPart in siteContentItem.Parts) { + var partElement = context.Data.Element(contentPart.PartDefinition.Name); + if (partElement == null) { + continue; } + + ImportSettingPart(contentPart, partElement); + } + + foreach (var contentHandler in Handlers) { + contentHandler.Imported(context); } recipeContext.Executed = true; } - private static void SetSetting(XAttribute attribute, ContentPart contentPart) { - var attributeName = attribute.Name.LocalName; - var attributeValue = attribute.Value; - var property = contentPart.GetType().GetProperty(attributeName); - if (property == null) { - throw new InvalidOperationException(string.Format("Could set setting {0} for part {1} because it was not found.", attributeName, contentPart.PartDefinition.Name)); - } - var propertyType = property.PropertyType; - if (propertyType == typeof(string)) { - property.SetValue(contentPart, attributeValue, null); - } - else if (propertyType == typeof(bool)) { - property.SetValue(contentPart, Boolean.Parse(attributeValue), null); - } - else if (propertyType == typeof(int)) { - property.SetValue(contentPart, Int32.Parse(attributeValue), null); - } - else { - throw new InvalidOperationException(string.Format("Could set setting {0} for part {1} because its type is not supported. Settings should be integer,boolean or string.", attributeName, contentPart.PartDefinition.Name)); + private void ImportSettingPart(ContentPart sitePart, XElement element) { + + foreach (var attribute in element.Attributes()) { + var attributeName = attribute.Name.LocalName; + var attributeValue = attribute.Value; + + var property = sitePart.GetType().GetProperty(attributeName); + if (property == null) { + throw new InvalidOperationException(string.Format("Could set setting {0} for part {1} because it was not found.", attributeName, sitePart.PartDefinition.Name)); + } + + var propertyType = property.PropertyType; + if (propertyType == typeof(string)) { + property.SetValue(sitePart, attributeValue, null); + } + else if (propertyType == typeof(bool)) { + property.SetValue(sitePart, Boolean.Parse(attributeValue), null); + } + else if (propertyType == typeof(int)) { + property.SetValue(sitePart, Int32.Parse(attributeValue), null); + } } } } diff --git a/src/Orchard.Web/Modules/Orchard.Search/Drivers/SearchSettingsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Search/Drivers/SearchSettingsPartDriver.cs index 20e2512c7..9e35a324b 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Drivers/SearchSettingsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Search/Drivers/SearchSettingsPartDriver.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Xml.Linq; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.Indexing; using Orchard.Localization; using Orchard.Search.Models; @@ -61,5 +63,19 @@ namespace Orchard.Search.Drivers { return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings", Model: model, Prefix: Prefix); }).OnGroup("search"); } + + protected override void Exporting(SearchSettingsPart part, ExportContentContext context) { + context.Element(part.PartDefinition.Name).Add(new XAttribute("SearchedFields", string.Join(",", part.SearchedFields))); + } + + protected override void Importing(SearchSettingsPart part, ImportContentContext context) { + var xElement = context.Data.Element(part.PartDefinition.Name); + if (xElement == null) return; + + var searchedFields = xElement.Attribute("SearchedFields"); + searchedFields.Remove(); + + part.SearchedFields = searchedFields.Value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj b/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj index 604a48aab..b56de30c1 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj +++ b/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj @@ -60,6 +60,7 @@ ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs index 856833efa..fe4d0ff62 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Models/SslSettingsPart.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using Orchard.ContentManagement; using Orchard.ContentManagement.FieldStorage.InfosetStorage; @@ -45,11 +46,13 @@ namespace Orchard.SecureSocketsLayer.Models { set { this.As().Set("CustomEnabled", value.ToString()); } } + [Required] public string SecureHostName { get { return this.As().Get("SecureHostName"); } set { this.As().Set("SecureHostName", value); } } + [Required] public string InsecureHostName { get { return this.As().Get("InsecureHostName"); } set { this.As().Set("InsecureHostName", value); } diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/SecureSocketsLayerService.cs b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/SecureSocketsLayerService.cs index aa4627683..358e05e0b 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/SecureSocketsLayerService.cs +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Services/SecureSocketsLayerService.cs @@ -99,6 +99,10 @@ namespace Orchard.SecureSocketsLayer.Services { var urlHelper = new UrlHelper(requestContext); var url = urlHelper.Action(actionName, controllerName, requestContext.RouteData); + if (String.IsNullOrWhiteSpace(url)) { + return false; + } + return IsRequestProtected( url, requestContext.HttpContext.Request.ApplicationPath, settings); } diff --git a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml index 7ced91c1c..9879a163e 100644 --- a/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.SecureSocketsLayer/Views/EditorTemplates/Parts/SecureSocketsLayer.Settings.cshtml @@ -8,6 +8,16 @@ @Html.ValidationMessage("Enabled", "*")
+
+ + @Html.TextBoxFor(m => m.SecureHostName, new { @class = "textMedium" }) + @T("(Mandatory) The host name secured traffic should be redirected to (e.g. localhost:44300, secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333).") +
+
+ + @Html.TextBoxFor(m => m.InsecureHostName, new { @class = "textMedium" }) + @T("(Mandatory) The host name non-secured traffic should be redirected to (e.g. localhost:30321, mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333).") +
@Html.EditorFor(m => m.SecureEverything) @@ -29,16 +39,6 @@
-
- - @Html.TextBoxFor(m => m.SecureHostName, new { @class = "textMedium" }) - @T("Provide the host name secure traffic should be redirected to (e.g. secure.mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. secure.127-0-0-1.org.uk:4333).") -
-
- - @Html.TextBoxFor(m => m.InsecureHostName, new { @class = "textMedium" }) - @T("Provide the host name non-secured traffic should be redirected to (e.g. mydomain.com). Don't include the protocol or anything else than the host name. A port can be specified after a colon if necessary (e.g. dev.127-0-0-1.org.uk:4333).") -
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml index 8251a9191..bb544387b 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/blog.recipe.xml @@ -59,7 +59,8 @@ site setting set baseurl theme activate "The Theme Machine" menu create /MenuName:"Main Menu" - blog create /Title:"Blog" /Homepage:true /Description:"This is your Orchard Blog." /MenuText:"Home" /MenuName:"Main Menu" + blog create /Title:"Blog" /Homepage:true /Description:"This is your Orchard Blog." + menuitem create /MenuPosition:"0" /MenuText:"Home" /Url:"~/" /MenuName:"Main Menu" widget create MenuWidget /Title:"Main Menu" /RenderTitle:false /Zone:"Navigation" /Position:"1" /Layer:"Default" /Identity:"MenuWidget1" /MenuName:"Main Menu" diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml index ec13aa0a1..701adb648 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/core.recipe.xml @@ -26,6 +26,8 @@ - page create /Slug:"welcome-to-orchard" /Title:"Welcome to Orchard!" /Path:"welcome-to-orchard" /Homepage:true /Publish:true /Text:"Welcome To Orchard!" /MenuText:"Home" /MenuName:"Main Menu" + menu create /MenuName:"Main Menu" + page create /Slug:"welcome-to-orchard" /Title:"Welcome to Orchard!" /Path:"welcome-to-orchard" /Homepage:true /Publish:true /Text:"Welcome To Orchard!" + menuitem create /MenuPosition:"0" /MenuText:"Home" /Url:"~/" /MenuName:"Main Menu" diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml index a354cc377..9c62a0ed8 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Recipes/default.recipe.xml @@ -53,7 +53,8 @@ widget create HtmlWidget /Title:"Third Leader Aside" /Zone:"TripelThird" /Position:"5" /Layer:"TheHomepage" /Identity:"SetupHtmlWidget3" /UseLoremIpsumText:true site setting set baseurl menu create /MenuName:"Main Menu" - page create /Slug:"welcome-to-orchard" /Title:"Welcome to Orchard!" /Path:"welcome-to-orchard" /Homepage:true /Publish:true /UseWelcomeText:true /MenuText:"Home" /MenuName:"Main Menu" + page create /Slug:"welcome-to-orchard" /Title:"Welcome to Orchard!" /Path:"welcome-to-orchard" /Homepage:true /Publish:true /UseWelcomeText:true + menuitem create /MenuPosition:"0" /MenuText:"Home" /Url:"~/" /MenuName:"Main Menu" widget create MenuWidget /Title:"Main Menu" /RenderTitle:false /Zone:"Navigation" /Position:"1" /Layer:"Default" /Identity:"MenuWidget1" /MenuName:"Main Menu" theme activate "The Theme Machine" diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TermAdminController.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TermAdminController.cs index be8e65be1..923f6d775 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TermAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Controllers/TermAdminController.cs @@ -167,6 +167,9 @@ namespace Orchard.Taxonomies.Controllers { var term = _taxonomyService.NewTerm(taxonomy); term.Container = parentTerm == null ? taxonomy.ContentItem : parentTerm.ContentItem; + // Create content item before updating so attached fields save correctly + Services.ContentManager.Create(term, VersionOptions.Draft); + var model = Services.ContentManager.UpdateEditor(term, this); if (!ModelState.IsValid) { @@ -175,7 +178,7 @@ namespace Orchard.Taxonomies.Controllers { } _taxonomyService.ProcessPath(term); - Services.ContentManager.Create(term, VersionOptions.Published); + Services.ContentManager.Publish(term.ContentItem); Services.Notifier.Information(T("The {0} term has been created.", term.Name)); return RedirectToAction("Index", "TermAdmin", new { taxonomyId }); diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs index abf8a3ace..3b2a9edc2 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Tokens/TaxonomyTokens.cs @@ -32,7 +32,10 @@ namespace Orchard.Taxonomies.Tokens { context.For("TaxonomyField") .Token("Terms", field => String.Join(", ", field.Terms.Select(t => t.Name).ToArray())) .Token( - token => token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Terms:".Length) : null, + token => { + var index = 0; + return (token.StartsWith("Terms:", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring("Terms:".Length), out index)) ? index.ToString() : null; + }, (token, t) => { var index = Convert.ToInt32(token); return index + 1 > t.Terms.Count() ? null : t.Terms.ElementAt(index).Name; diff --git a/src/Orchard.Web/Modules/Orchard.Users/Commands/UserCommands.cs b/src/Orchard.Web/Modules/Orchard.Users/Commands/UserCommands.cs index 3922251c3..c09e5d36e 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Commands/UserCommands.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Commands/UserCommands.cs @@ -30,6 +30,11 @@ namespace Orchard.Users.Commands { [CommandHelp("user create /UserName: /Password: /Email:\r\n\t" + "Creates a new User")] [OrchardSwitches("UserName,Password,Email")] public void Create() { + if (string.IsNullOrWhiteSpace(UserName)) { + Context.Output.WriteLine(T("Username cannot be empty.")); + return; + } + if (!_userService.VerifyUserUnicity(UserName, Email)) { Context.Output.WriteLine(T("User with that username and/or email already exists.")); return; diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs index b96fbb7a5..f5b3af46a 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs @@ -121,7 +121,7 @@ namespace Orchard.Users.Controllers { [HttpPost] [AlwaysAccessible] [ValidateInput(false)] - public ActionResult Register(string userName, string email, string password, string confirmPassword) { + public ActionResult Register(string userName, string email, string password, string confirmPassword, string returnUrl = null) { // ensure users can register var registrationSettings = _orchardServices.WorkContext.CurrentSite.As(); if ( !registrationSettings.UsersCanRegister ) { @@ -153,7 +153,7 @@ namespace Orchard.Users.Controllers { } _authenticationService.SignIn(user, false /* createPersistentCookie */); - return Redirect("~/"); + return this.RedirectLocal(returnUrl); } ModelState.AddModelError("_FORM", T(ErrorCodeToString(/*createStatus*/MembershipCreateStatus.ProviderError))); @@ -197,7 +197,7 @@ namespace Orchard.Users.Controllers { _userService.SendLostPasswordEmail(username, nonce => Url.MakeAbsolute(Url.Action("LostPassword", "Account", new { Area = "Orchard.Users", nonce = nonce }), siteUrl)); _orchardServices.Notifier.Information(T("Check your e-mail for the confirmation link.")); - + return RedirectToAction("LogOn"); } diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/LogOn.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/LogOn.cshtml index 03a64e6ab..6b0f6c15e 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/LogOn.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/LogOn.cshtml @@ -8,7 +8,7 @@

@Html.TitleForPage((string)Model.Title)

@T("Please enter your username and password.") - @if(userCanRegister) { @Html.ActionLink(T("Register").Text, "Register") @T(" if you don't have an account.") } + @if(userCanRegister) { @Html.ActionLink(T("Register").Text, "Register", new { ReturnUrl = Request.QueryString["ReturnUrl"] }) @T(" if you don't have an account.") } @if(enableLostPassword) { @Html.ActionLink(T("Lost your Password?").Text, "RequestLostPassword") }

@Html.ValidationSummary(T("Login was unsuccessful. Please correct the errors and try again.").ToString()) diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/Register.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/Register.cshtml index a349f1a0f..9a7a71eaf 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/Register.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/Register.cshtml @@ -2,7 +2,7 @@

@T("Use the form below to create a new account.")

@T("Passwords are required to be a minimum of {0} characters in length.", ViewData["PasswordLength"])

@Html.ValidationSummary(T("Account creation was unsuccessful. Please correct the errors and try again.").ToString()) -@using (Html.BeginFormAntiForgeryPost()) { +@using (Html.BeginFormAntiForgeryPost(Url.Action("Register", new { ReturnUrl = Request.QueryString["ReturnUrl"] }))) {
@T("Account Information")
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/WidgetLayersControl.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/WidgetLayersControl.cshtml index a29d421d7..e5413e3d2 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Views/WidgetLayersControl.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/WidgetLayersControl.cshtml @@ -2,7 +2,7 @@ @using Orchard.Widgets.Models; @{ Style.Require("WidgetsAdmin"); - Script.Require("Switchable"); + Script.Require("Switchable").AtFoot(); Style.Require("Switchable"); IEnumerable layers = Model.Layers; var returnUrl = Request.RawUrl; diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml index 36bd59648..fdaf466b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/Edit.cshtml @@ -7,7 +7,7 @@ Style.Require("WorkflowsAdmin"); Style.Require("WorkflowsActivities"); Style.Require("jQueryUI_Orchard"); - Script.Require("jsPlumb"); + Script.Require("jsPlumb").AtFoot(); Script.Include("orchard-workflows-serialize.js").AtFoot(); Script.Include("orchard-workflows.js").AtFoot(); } diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/EditActivity.cshtml b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/EditActivity.cshtml index 6c6646250..755331785 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/EditActivity.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Views/Admin/EditActivity.cshtml @@ -1,6 +1,6 @@ @{ Layout.Title = @T("Edit Activity"); - Script.Include("orchard-workflows-serialize.js"); + Script.Include("orchard-workflows-serialize.js").AtFoot(); } @Html.ValidationSummary() diff --git a/src/Orchard.Web/Themes/TheAdmin/Scripts/admin.js b/src/Orchard.Web/Themes/TheAdmin/Scripts/admin.js index 653313c41..39eca3ac1 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Scripts/admin.js +++ b/src/Orchard.Web/Themes/TheAdmin/Scripts/admin.js @@ -72,7 +72,7 @@ }); $(".check-all").change(function () { - $(this).parents("table.items").find(":checkbox").prop('checked', $(this).prop("checked")); + $(this).parents("table.items").find(":checkbox:not(:disabled)").prop('checked', $(this).prop("checked")); }); })(jQuery); diff --git a/src/Orchard.Web/Themes/TheAdmin/Views/Layout.cshtml b/src/Orchard.Web/Themes/TheAdmin/Views/Layout.cshtml index b9df1a943..954bc51f8 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Views/Layout.cshtml +++ b/src/Orchard.Web/Themes/TheAdmin/Views/Layout.cshtml @@ -11,9 +11,9 @@ Style.Include("ie.css").UseCondition("gte IE 9").SetAttribute("media", "screen, projection"); Style.Include("ie8.css").UseCondition("IE 8").SetAttribute("media", "screen, projection"); Style.Include("ie7.css").UseCondition("lte IE 7").SetAttribute("media", "screen, projection"); - Script.Require("jQuery"); - Script.Require("ShapesBase"); - Script.Include("admin.js"); + Script.Require("jQuery").AtFoot(); + Script.Require("ShapesBase").AtFoot(); + Script.Include("admin.js").AtFoot(); /* Some useful shortcuts or settings ***************************************************************/ diff --git a/src/Orchard.Web/Themes/TheAdmin/Views/Menu.cshtml b/src/Orchard.Web/Themes/TheAdmin/Views/Menu.cshtml index 83df54787..594d855f7 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Views/Menu.cshtml +++ b/src/Orchard.Web/Themes/TheAdmin/Views/Menu.cshtml @@ -1,7 +1,7 @@ @using Orchard.Utility.Extensions; @{ Script.Require("jQuery"); - Script.Include("admin.js"); + Script.Include("admin.js").AtFoot(); IEnumerable firstLevelMenuItems = Model; if (Model.ImageSets != null) { diff --git a/src/Orchard/ContentManagement/DefaultHqlQuery.cs b/src/Orchard/ContentManagement/DefaultHqlQuery.cs index 5ffffb40e..59583999e 100644 --- a/src/Orchard/ContentManagement/DefaultHqlQuery.cs +++ b/src/Orchard/ContentManagement/DefaultHqlQuery.cs @@ -52,17 +52,17 @@ namespace Orchard.ContentManagement { return tuple == null ? null : tuple.Item2; } - internal IAlias BindCriteriaByPath(IAlias alias, string path) { - return BindCriteriaByAlias(alias, path, PathToAlias(path)); + internal IAlias BindCriteriaByPath(IAlias alias, string path, string type = null, Action withPredicate = null) { + return BindCriteriaByAlias(alias, path, PathToAlias(path), type, withPredicate); } - internal IAlias BindCriteriaByAlias(IAlias alias, string path, string aliasName) { + internal IAlias BindCriteriaByAlias(IAlias alias, string path, string aliasName, string type = null, Action withPredicate = null) { // is this Join already existing (based on aliasName) Join join = BindNamedAlias(aliasName); if (join == null) { - join = new Join(path, aliasName); + join = new Join(path, aliasName, type, withPredicate); _joins.Add(new Tuple(alias, join)); } @@ -88,19 +88,19 @@ namespace Orchard.ContentManagement { return _from; } - internal IAlias BindPartCriteria() where TRecord : ContentPartRecord { - return BindPartCriteria(typeof(TRecord)); + internal IAlias BindPartCriteria(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord { + return BindPartCriteria(typeof(TRecord), type, withPredicate); } - internal IAlias BindPartCriteria(Type contentPartRecordType) { + internal IAlias BindPartCriteria(Type contentPartRecordType, string type = null, Action withPredicate = null) { if (!contentPartRecordType.IsSubclassOf(typeof(ContentPartRecord))) { throw new ArgumentException("The type must inherit from ContentPartRecord", "contentPartRecordType"); } if (contentPartRecordType.IsSubclassOf(typeof(ContentPartVersionRecord))) { - return BindCriteriaByPath(BindItemVersionCriteria(), contentPartRecordType.Name); + return BindCriteriaByPath(BindItemVersionCriteria(), contentPartRecordType.Name, type, withPredicate); } - return BindCriteriaByPath(BindItemCriteria(), contentPartRecordType.Name); + return BindCriteriaByPath(BindItemCriteria(), contentPartRecordType.Name, type, withPredicate); } internal void Where(IAlias alias, Action predicate) { @@ -246,7 +246,16 @@ namespace Orchard.ContentManagement { sb.Append("from ").Append(_from.TableName).Append(" as ").Append(_from.Name).AppendLine(); foreach (var join in _joins) { - sb.Append(join.Item2.Type).Append(" ").Append(join.Item1.Name + "." + join.Item2.TableName).Append(" as ").Append(join.Item2.Name).AppendLine(); + sb.Append(join.Item2.Type + " " + + join.Item1.Name + "." + join.Item2.TableName + + " as " + join.Item2.Name); + if (join.Item2.WithPredicate != null) { + var predicate = join.Item2.WithPredicate; + var expressionFactory = new DefaultHqlExpressionFactory(); + predicate(expressionFactory); + sb.Append(" with " + expressionFactory.Criterion.ToHql(join.Item2)); + } + sb.AppendLine(); } // generating where clause @@ -378,6 +387,7 @@ namespace Orchard.ContentManagement { public interface IJoin : IAlias { string TableName { get; set; } string Type { get; set; } + Action WithPredicate { get; set; } } public class Sort { @@ -396,20 +406,26 @@ namespace Orchard.ContentManagement { public class Join : Alias, IJoin { public Join(string tableName, string alias) - : this(tableName, alias, "join") {} + : this(tableName, alias, "join", null) {} public Join(string tableName, string alias, string type) + : this(tableName, alias, type, null) { + } + + public Join(string tableName, string alias, string type, Action withPredicate) : base(alias) { if (String.IsNullOrEmpty(tableName)) { throw new ArgumentException("Table Name can't be empty"); } TableName = tableName; - Type = type; + Type = type ?? "join"; + WithPredicate = withPredicate; } public string TableName { get; set; } public string Type { get; set; } + public Action WithPredicate { get; set; } } public class DefaultHqlSortFactory : IHqlSortFactory @@ -442,17 +458,17 @@ namespace Orchard.ContentManagement { Current = _query.BindItemCriteria(); } - public IAliasFactory ContentPartRecord() where TRecord : ContentPartRecord { - Current = _query.BindPartCriteria(); + public IAliasFactory ContentPartRecord(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord { + Current = _query.BindPartCriteria(type, withPredicate); return this; } - public IAliasFactory ContentPartRecord(Type contentPartRecord) { + public IAliasFactory ContentPartRecord(Type contentPartRecord, string type = null, Action withPredicate = null) { if(!contentPartRecord.IsSubclassOf(typeof(ContentPartRecord))) { throw new ArgumentException("Type must inherit from ContentPartRecord", "contentPartRecord"); } - Current = _query.BindPartCriteria(contentPartRecord); + Current = _query.BindPartCriteria(contentPartRecord, type, withPredicate); return this; } diff --git a/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs b/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs index e4865014b..bb09e4bae 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentShapeResult.cs @@ -30,6 +30,15 @@ namespace Orchard.ContentManagement.Drivers { if (string.IsNullOrEmpty(placement.Location) || placement.Location == "-") return; + // parse group placement + var group = placement.GetGroup(); + if (!String.IsNullOrEmpty(group)) { + _groupId = group; + } + + if (!string.Equals(context.GroupId ?? "", _groupId ?? "", StringComparison.OrdinalIgnoreCase)) + return; + dynamic parentShape = context.Shape; context.ContentPart = ContentPart; @@ -62,15 +71,6 @@ namespace Orchard.ContentManagement.Drivers { newShapeMetadata.Wrappers.Clear(); } - // parse group placement - var group = placement.GetGroup(); - if (!String.IsNullOrEmpty(group)) { - _groupId = group; - } - - if (!string.Equals(context.GroupId ?? "", _groupId ?? "", StringComparison.OrdinalIgnoreCase)) - return; - foreach (var alternate in placement.Alternates) { newShapeMetadata.Alternates.Add(alternate); } diff --git a/src/Orchard/ContentManagement/IHqlQuery.cs b/src/Orchard/ContentManagement/IHqlQuery.cs index 553ad363a..829f5fc8d 100644 --- a/src/Orchard/ContentManagement/IHqlQuery.cs +++ b/src/Orchard/ContentManagement/IHqlQuery.cs @@ -133,13 +133,18 @@ namespace Orchard.ContentManagement { public interface IAliasFactory { /// /// Creates a join on a content part record or returns it if it already exists. + /// The type of join, e.g. "left outer join" + /// An expression for an additional constraint on the join /// - IAliasFactory ContentPartRecord() where TRecord : ContentPartRecord; + IAliasFactory ContentPartRecord(string type = null, Action withPredicate = null) where TRecord : ContentPartRecord; /// /// Creates a join on a content part record or returns it if it already exists. + /// The type of the part to join + /// The type of join, e.g. "left outer join" + /// An expression for an additional constraint on the join /// - IAliasFactory ContentPartRecord(Type contentPartRecord); + IAliasFactory ContentPartRecord(Type contentPartRecord, string type = null, Action withPredicate = null); /// /// Creates a join based on a property, or returns it if it already exists. diff --git a/src/Orchard/Reports/ReportExtentions.cs b/src/Orchard/Reports/ReportExtentions.cs index 05b898058..2ebb2ff01 100644 --- a/src/Orchard/Reports/ReportExtentions.cs +++ b/src/Orchard/Reports/ReportExtentions.cs @@ -2,12 +2,32 @@ using Orchard.Reports.Services; public static class ReportExtentions { + /// + /// Adds a new report entry of type information to a report that was previously registered. + /// + /// + /// Key, i.e. technical name of the report. Should be the same as the one used when registering the report. + /// The message to include in the entry. public static void Information(this IReportsCoordinator reportCoordinator, string reportKey, string message) { reportCoordinator.Add(reportKey, ReportEntryType.Information, message); } + + /// + /// Adds a new report entry of type warning to a report that was previously registered. + /// + /// + /// Key, i.e. technical name of the report. Should be the same as the one used when registering the report. + /// The message to include in the entry. public static void Warning(this IReportsCoordinator reportCoordinator, string reportKey, string message) { reportCoordinator.Add(reportKey, ReportEntryType.Warning, message); } + + /// + /// Adds a new report entry of type error to a report that was previously registered. + /// + /// + /// Key, i.e. technical name of the report. Should be the same as the one used when registering the report. + /// The message to include in the entry. public static void Error(this IReportsCoordinator reportCoordinator, string reportKey, string message) { reportCoordinator.Add(reportKey, ReportEntryType.Error, message); } diff --git a/src/Orchard/Reports/Services/IReportsCoordinator.cs b/src/Orchard/Reports/Services/IReportsCoordinator.cs index d8104b89b..659f86f91 100644 --- a/src/Orchard/Reports/Services/IReportsCoordinator.cs +++ b/src/Orchard/Reports/Services/IReportsCoordinator.cs @@ -1,6 +1,30 @@ namespace Orchard.Reports.Services { + /// + /// Exposes a simplified interface for creating reports. Reports provide user-accessible log-like functionality. + /// + /// + /// can be used too to create reports directly. + /// public interface IReportsCoordinator : IDependency { + /// + /// Adds a new report entry to a report that was previously registered. + /// + /// + /// Entries can be only added to a report that was previously registered through Register(). + /// + /// + /// Key, i.e. technical name of the report. Should be the same as the one used when registering the report. + /// Type of the entry. + /// The message to include in the entry. void Add(string reportKey, ReportEntryType type, string message); + + /// + /// Registers a new report so entries can be added to it. + /// + /// Key, i.e. technical name of the report. + /// Name of the activity the report is about (e.g. "Upgrade"). + /// A title better describing what the report is about (e.g. "Migrating routes of Pages, Blog Posts"). + /// The report's numerical ID. int Register(string reportKey, string activityName, string title); } } diff --git a/src/Orchard/Reports/Services/IReportsManager.cs b/src/Orchard/Reports/Services/IReportsManager.cs index 36ff65038..f2006adf4 100644 --- a/src/Orchard/Reports/Services/IReportsManager.cs +++ b/src/Orchard/Reports/Services/IReportsManager.cs @@ -1,6 +1,12 @@ using System.Collections.Generic; namespace Orchard.Reports.Services { + /// + /// Service for handling reports. Reports provide user-accessible log-like functionality. + /// + /// + /// You can use to create reports through a simplified interface. + /// public interface IReportsManager : ISingletonDependency { void Add(int reportId, ReportEntryType type, string message); int CreateReport(string title, string activityName); diff --git a/src/Orchard/Reports/Services/IReportsPersister.cs b/src/Orchard/Reports/Services/IReportsPersister.cs index d1dd3238f..b79cd9e3b 100644 --- a/src/Orchard/Reports/Services/IReportsPersister.cs +++ b/src/Orchard/Reports/Services/IReportsPersister.cs @@ -1,6 +1,12 @@ using System.Collections.Generic; namespace Orchard.Reports.Services { + /// + /// Defines a service that can be used to persist reports. + /// + /// + /// Implementations of this interface are commonly used from implementations. + /// public interface IReportsPersister : IDependency { IEnumerable Fetch(); void Save(IEnumerable reports); diff --git a/src/Orchard/Utility/Extensions/StringExtensions.cs b/src/Orchard/Utility/Extensions/StringExtensions.cs index 0779de543..7fe13c987 100644 --- a/src/Orchard/Utility/Extensions/StringExtensions.cs +++ b/src/Orchard/Utility/Extensions/StringExtensions.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using Orchard.Localization; +using System.Web; namespace Orchard.Utility.Extensions { public static class StringExtensions { @@ -89,7 +90,7 @@ namespace Orchard.Utility.Extensions { : new LocalizedString(text); } - public static string RemoveTags(this string html) { + public static string RemoveTags(this string html, bool htmlDecode = false) { if (String.IsNullOrEmpty(html)) { return String.Empty; } @@ -115,7 +116,13 @@ namespace Orchard.Utility.Extensions { } } - return new string(result, 0, cursor); + var stringResult = new string(result, 0, cursor); + + if (htmlDecode) { + stringResult = HttpUtility.HtmlDecode(stringResult); + } + + return stringResult; } // not accounting for only \r (e.g. Apple OS 9 carriage return only new lines) @@ -167,9 +174,7 @@ namespace Orchard.Utility.Extensions { name = RemoveDiacritics(name); name = name.Strip(c => - c != '_' - && c != '-' - && !c.IsLetter() + !c.IsLetter() && !Char.IsDigit(c) );