diff --git a/Orchard.proj b/Orchard.proj index 25004a059..34938468e 100644 --- a/Orchard.proj +++ b/Orchard.proj @@ -151,11 +151,12 @@ - - + + - + + diff --git a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs index 66852716f..eb2d53de6 100644 --- a/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs +++ b/src/Orchard.Web/Core/Common/Drivers/TextFieldDriver.cs @@ -84,8 +84,7 @@ namespace Orchard.Core.Common.Drivers { } protected override void Exporting(ContentPart part, TextField field, ExportContentContext context) { - if (!String.IsNullOrEmpty(field.Value)) - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Value); } protected override void Cloning(ContentPart part, TextField originalField, TextField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj b/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj index e3133ef21..6b2829aaa 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Orchard.DynamicForms.csproj @@ -118,6 +118,7 @@ + @@ -304,6 +305,7 @@ + @@ -549,6 +551,9 @@ + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Recipes/Builders/FormSubmissionsStep.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Recipes/Builders/FormSubmissionsStep.cs index 8a820dc05..206c15cf9 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Recipes/Builders/FormSubmissionsStep.cs +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Recipes/Builders/FormSubmissionsStep.cs @@ -3,12 +3,17 @@ using System.Xml.Linq; using Orchard.DynamicForms.Services; using Orchard.Localization; using Orchard.Recipes.Services; +using System.Collections.Generic; +using Orchard.ContentManagement; +using Orchard.DynamicForms.ViewModels; namespace Orchard.DynamicForms.Recipes.Builders { public class FormSubmissionsStep : RecipeBuilderStep { private readonly IFormService _formService; + public FormSubmissionsStep(IFormService formService) { _formService = formService; + SelectedForms = new List(); } public override string Name { @@ -23,29 +28,43 @@ namespace Orchard.DynamicForms.Recipes.Builders { get { return T("Exports submitted forms."); } } + public IList SelectedForms { get; set; } + public override dynamic BuildEditor(dynamic shapeFactory) { - // TODO: Implement an editor that enables the user to select which forms to export. - return null; + return UpdateEditor(shapeFactory, null); + } + + public override dynamic UpdateEditor(dynamic shapeFactory, IUpdateModel updater) { + List forms = new List(); + + if (updater != null && updater.TryUpdateModel(forms, Prefix, null, null)) { + SelectedForms = forms.Where(x => x.Export).Select(x => x.FormName).ToList(); + } + else { + forms = _formService.GetSubmissions().OrderBy(x => x.FormName).GroupBy(y => y.FormName) + .Select(x => new FormExportEntry { FormName = x.FirstOrDefault().FormName }) + .ToList(); + } + + return shapeFactory.EditorTemplate(TemplateName: "BuilderSteps/FormSubmissions", Model: forms, Prefix: Prefix); } public override void Build(BuildContext context) { - var submissions = _formService.GetSubmissions().ToArray(); + if (SelectedForms.Count() > 0) { + var root = new XElement("Forms"); + context.RecipeDocument.Element("Orchard").Add(root); - if (!submissions.Any()) { - return; - } - - var forms = submissions.GroupBy(x => x.FormName); - var root = new XElement("Forms"); - context.RecipeDocument.Element("Orchard").Add(root); - - foreach (var form in forms) { - root.Add(new XElement("Form", - new XAttribute("Name", form.Key), - new XElement("Submissions", form.Select(submission => - new XElement("Submission", - new XAttribute("CreatedUtc", submission.CreatedUtc), - new XCData(submission.FormData)))))); + foreach (var form in SelectedForms) { + var submissions = _formService.GetSubmissions(form); + if (submissions.Count() > 0) { + root.Add(new XElement("Form", + new XAttribute("Name", form), + new XElement("Submissions", submissions.Select(submission => + new XElement("Submission", + new XAttribute("CreatedUtc", submission.CreatedUtc), + new XCData(submission.FormData)))))); + } + } } } } diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Styles/recipebuilderstep-forms.css b/src/Orchard.Web/Modules/Orchard.DynamicForms/Styles/recipebuilderstep-forms.css new file mode 100644 index 000000000..660a1b012 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Styles/recipebuilderstep-forms.css @@ -0,0 +1,9 @@ +fieldset.recipe-builder-step-form-submissions table.items { + width: 500px; + margin: 0; +} + +fieldset.recipe-builder-step-form-submissions table.items td, +fieldset.recipe-builder-step-form-submissions table.items thead tr.sub th { + padding: 0 12px; +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/ViewModels/FormExportEntry.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/ViewModels/FormExportEntry.cs new file mode 100644 index 000000000..d3d1860d2 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/ViewModels/FormExportEntry.cs @@ -0,0 +1,6 @@ +namespace Orchard.DynamicForms.ViewModels { + public class FormExportEntry { + public string FormName { get; set; } + public bool Export { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/EditorTemplates/BuilderSteps/FormSubmissions.cshtml b/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/EditorTemplates/BuilderSteps/FormSubmissions.cshtml new file mode 100644 index 000000000..bfcb2c065 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/EditorTemplates/BuilderSteps/FormSubmissions.cshtml @@ -0,0 +1,35 @@ +@model List +@using Orchard.DynamicForms.ViewModels; + +@{ + Style.Include("recipebuilderstep-forms.css"); +} + +
+ + + + + + + + + + @for (int index = 0; index < Model.Count(); index++) { + var entry = Model.ElementAt(index); + + + + + + } + +
@T("Form") + + @T("Select All") +
@entry.FormName + + +
+ @Html.Hint(T("Choose the forms to include in the export file")) +
diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs index b126ceef4..4d55be49a 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/BooleanFieldDriver.cs @@ -62,8 +62,7 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, BooleanField field, ExportContentContext context) { - if (field.Value.HasValue) - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Cloning(ContentPart part, BooleanField originalField, BooleanField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs index 039bc6f07..e36b300ef 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/DateTimeFieldDriver.cs @@ -169,9 +169,7 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, DateTimeField field, ExportContentContext context) { - var value = field.Storage.Get(null); - if (value != DateTime.MinValue) - context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(value, XmlDateTimeSerializationMode.Utc)); + context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(field.Storage.Get(null), XmlDateTimeSerializationMode.Utc)); } protected override void Cloning(ContentPart part, DateTimeField originalField, DateTimeField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs index ed92d98df..2bbd1a903 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/EnumerationFieldDriver.cs @@ -63,8 +63,7 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, EnumerationField field, ExportContentContext context) { - if (!String.IsNullOrEmpty(field.Value)) - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Cloning(ContentPart part, EnumerationField originalField, EnumerationField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs index 625dba93a..8539daf63 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/InputFieldDriver.cs @@ -61,8 +61,7 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, InputField field, ExportContentContext context) { - if (!String.IsNullOrEmpty(field.Value)) - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value); } protected override void Cloning(ContentPart part, InputField originalField, InputField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs index 7298be8b8..2119023a6 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/LinkFieldDriver.cs @@ -75,11 +75,9 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, LinkField field, ExportContentContext context) { - if (!String.IsNullOrEmpty(field.Text) || !String.IsNullOrEmpty(field.Value) || !String.IsNullOrEmpty(field.Target)) { - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Text); - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Url", field.Value); - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Target", field.Target); - } + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Text); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Url", field.Value); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Target", field.Target); } protected override void Cloning(ContentPart part, LinkField originalField, LinkField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs index a8794abaf..85c7cff58 100644 --- a/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Fields/Drivers/NumericFieldDriver.cs @@ -106,8 +106,7 @@ namespace Orchard.Fields.Drivers { } protected override void Exporting(ContentPart part, NumericField field, ExportContentContext context) { - if (field.Value.HasValue) - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value.Value.ToString(CultureInfo.InvariantCulture)); + context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", !field.Value.HasValue ? String.Empty : field.Value.Value.ToString(CultureInfo.InvariantCulture)); } protected override void Cloning(ContentPart part, NumericField originalField, NumericField cloneField, CloneContentContext context) { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Harvesters/HarvestElementsContext.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Harvesters/HarvestElementsContext.cs index c8cc7c230..a30249306 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Harvesters/HarvestElementsContext.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Framework/Harvesters/HarvestElementsContext.cs @@ -3,5 +3,6 @@ namespace Orchard.Layouts.Framework.Harvesters { public class HarvestElementsContext { public IContent Content { get; set; } + public bool IsHarvesting { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/BlueprintElementHarvester.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/BlueprintElementHarvester.cs index 3ca89574b..9d76467cf 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Providers/BlueprintElementHarvester.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Providers/BlueprintElementHarvester.cs @@ -13,7 +13,6 @@ namespace Orchard.Layouts.Providers { public class BlueprintElementHarvester : Component, IElementHarvester { private readonly Work _elementBlueprintService; private readonly Work _elementManager; - private bool _isHarvesting; public BlueprintElementHarvester(Work elementBlueprintService, Work elementManager) { _elementBlueprintService = elementBlueprintService; @@ -21,15 +20,14 @@ namespace Orchard.Layouts.Providers { } public IEnumerable HarvestElements(HarvestElementsContext context) { - if (_isHarvesting) + if (context.IsHarvesting) return Enumerable.Empty(); - _isHarvesting = true; var blueprints = _elementBlueprintService.Value.GetBlueprints().ToArray(); var query = from blueprint in blueprints - let describeContext = new DescribeElementsContext {Content = context.Content, CacheVaryParam = "Blueprints"} + let describeContext = new DescribeElementsContext {Content = context.Content, CacheVaryParam = "Blueprints", IsHarvesting = true } let baseElementDescriptor = _elementManager.Value.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName) let baseElement = _elementManager.Value.ActivateElement(baseElementDescriptor) select new ElementDescriptor( @@ -48,9 +46,7 @@ namespace Orchard.Layouts.Providers { } }; - var descriptors = query.ToArray(); - _isHarvesting = false; - return descriptors; + return query.ToArray(); } private static string GetCategory(ElementBlueprint blueprint) { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/DescribeElementsContext.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/DescribeElementsContext.cs index 3a7f18f7a..42cb6fadf 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Services/DescribeElementsContext.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/DescribeElementsContext.cs @@ -4,6 +4,7 @@ namespace Orchard.Layouts.Services { public class DescribeElementsContext { public IContent Content { get; set; } public string CacheVaryParam { get; set; } + public bool IsHarvesting { get; set; } public static readonly DescribeElementsContext Empty = new DescribeElementsContext(); } diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs index 1281f5d85..5e0146250 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Services/ElementManager.cs @@ -40,7 +40,8 @@ namespace Orchard.Layouts.Services { var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam); return _cacheManager.Get(cacheKey, true, acquireContext => { var harvesterContext = new HarvestElementsContext { - Content = context.Content + Content = context.Content, + IsHarvesting = context.IsHarvesting }; var query = from harvester in _elementHarvesters.Value diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs index a4f6bcbab..20a7e9159 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Drivers/LocalizationPartDriver.cs @@ -21,35 +21,45 @@ namespace Orchard.Localization.Drivers { } protected override DriverResult Display(LocalizationPart part, string displayType, dynamic shapeHelper) { - var masterId = part.HasTranslationGroup - ? part.Record.MasterContentItemId - : part.Id; return Combined( ContentShape("Parts_Localization_ContentTranslations", - () => shapeHelper.Parts_Localization_ContentTranslations(Id: part.ContentItem.Id, MasterId: masterId, Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Published))), + () => shapeHelper.Parts_Localization_ContentTranslations(Id: part.ContentItem.Id, MasterId: ActualMasterId(part), Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Published))), ContentShape("Parts_Localization_ContentTranslations_Summary", - () => shapeHelper.Parts_Localization_ContentTranslations_Summary(Id: part.ContentItem.Id, MasterId: masterId, Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Published))), + () => shapeHelper.Parts_Localization_ContentTranslations_Summary(Id: part.ContentItem.Id, MasterId: ActualMasterId(part), Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Published))), ContentShape("Parts_Localization_ContentTranslations_SummaryAdmin", () => { var siteCultures = _cultureManager.ListCultures(); - return shapeHelper.Parts_Localization_ContentTranslations_SummaryAdmin(Id: part.ContentItem.Id, MasterId: masterId, Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Latest), SiteCultures: siteCultures); + return shapeHelper.Parts_Localization_ContentTranslations_SummaryAdmin(Id: part.ContentItem.Id, MasterId: ActualMasterId(part), Culture: GetCulture(part), Localizations: GetDisplayLocalizations(part, VersionOptions.Latest), SiteCultures: siteCultures); }) ); } + private int ActualMasterId(LocalizationPart part) { + var masterId = part.HasTranslationGroup + ? part.Record.MasterContentItemId + : part.Id; + if (_contentManager.Get(masterId, VersionOptions.Latest) == null) { + //the original MasterContentItem has been deleted + masterId = part.Id; + } + return masterId; + } + protected override DriverResult Editor(LocalizationPart part, dynamic shapeHelper) { var localizations = GetEditorLocalizations(part).ToList(); - var missingCultures = part.HasTranslationGroup ? - RetrieveMissingCultures(part.MasterContentItem.As(), true) : + var masterContentItem = _contentManager.Get(part.Record.MasterContentItemId, VersionOptions.Latest); + + var missingCultures = part.HasTranslationGroup && masterContentItem != null ? + RetrieveMissingCultures(masterContentItem.As(), true) : RetrieveMissingCultures(part, part.Culture != null); var model = new EditLocalizationViewModel { SelectedCulture = GetCulture(part), MissingCultures = missingCultures, ContentItem = part, - MasterContentItem = part.HasTranslationGroup ? part.MasterContentItem : null, + MasterContentItem = masterContentItem, ContentLocalizations = new ContentLocalizationsViewModel(part) { Localizations = localizations } }; @@ -70,7 +80,7 @@ namespace Orchard.Localization.Drivers { } private List RetrieveMissingCultures(LocalizationPart part, bool excludePartCulture) { - var editorLocalizations = GetEditorLocalizations(part); + var editorLocalizations = GetEditorLocalizations(part.MasterContentItem != null ? part.MasterContentItem.As() : part); var cultures = _cultureManager .ListCultures() diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Views/Parts/Localization.ContentTranslations.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Localization/Views/Parts/Localization.ContentTranslations.SummaryAdmin.cshtml index 5195066f8..f7db40dac 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Views/Parts/Localization.ContentTranslations.SummaryAdmin.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Localization/Views/Parts/Localization.ContentTranslations.SummaryAdmin.cshtml @@ -16,7 +16,7 @@ var localizationLinks = Html.UnorderedList(localizations, (c, i) => Html.ItemEdi } @if (Model.Culture != null && !((IEnumerable)Model.SiteCultures).All(c => c == Model.Culture || localizations.Any(l => c == l.Culture.Culture))) { -
@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.Id }, new { itemprop = "UnsafeUrl" })
+
@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.MasterId }, new { itemprop = "UnsafeUrl" })
} } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs index 0376feca3..2e73d8209 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs @@ -1,25 +1,40 @@ using System; -using Orchard.ContentManagement.Handlers; -using Orchard.Data; -using Orchard.MediaLibrary.Services; -using Orchard.MediaLibrary.Models; using System.IO; -using Orchard.FileSystems.Media; +using System.Linq; using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData; +using Orchard.Core.Title.Models; +using Orchard.Data; +using Orchard.FileSystems.Media; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Services; namespace Orchard.MediaLibrary.Handlers { public class MediaPartHandler : ContentHandler { private readonly IMediaLibraryService _mediaLibraryService; private readonly IStorageProvider _storageProvider; + private readonly IContentDefinitionManager _contentDefinitionManager; public MediaPartHandler( IStorageProvider storageProvider, IMediaLibraryService mediaLibraryService, - IRepository repository) { + IRepository repository, + IContentDefinitionManager contentDefinitionManager) { _storageProvider = storageProvider; _mediaLibraryService = mediaLibraryService; + _contentDefinitionManager = contentDefinitionManager; Filters.Add(StorageFilter.For(repository)); + Filters.Add(new ActivatingFilter(contentType => { + var typeDefinition = _contentDefinitionManager.GetTypeDefinition(contentType); + // To avoid NRE when the handler runs for ad-hoc content types, e.g. MediaLibraryExplorer. + return typeDefinition == null ? + false : + typeDefinition.Parts.Any(contentTypePartDefinition => + contentTypePartDefinition.PartDefinition.Name == typeof(MediaPart).Name); + })); + OnRemoving((context, part) => RemoveMedia(part)); OnLoaded((context, part) => { if (!String.IsNullOrEmpty(part.FileName)) { diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs index 38647a55c..b8cef2b4a 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Models/MediaPart.cs @@ -1,8 +1,10 @@ using System; using Orchard.ContentManagement; using Orchard.ContentManagement.FieldStorage.InfosetStorage; +using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.Utilities; using Orchard.Core.Title.Models; +using Orchard.MediaLibrary.Handlers; namespace Orchard.MediaLibrary.Models { public class MediaPart : ContentPart { @@ -11,6 +13,8 @@ namespace Orchard.MediaLibrary.Models { /// /// Gets or sets the title of the media. + /// This adds an implicit dependency on which will be resolved by an + /// in the . /// public string Title { get { return ContentItem.As().Title; } @@ -63,7 +67,7 @@ namespace Orchard.MediaLibrary.Models { /// Gets the public Url of the media if stored locally. /// public string MediaUrl { - get { return _publicUrl.Value; } + get { return _publicUrl.Value; } } /// diff --git a/src/Orchard.Web/Modules/Orchard.Redis/Caching/RedisCacheStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Redis/Caching/RedisCacheStorageProvider.cs index 38ba2134b..c85578cd8 100644 --- a/src/Orchard.Web/Modules/Orchard.Redis/Caching/RedisCacheStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Redis/Caching/RedisCacheStorageProvider.cs @@ -58,7 +58,7 @@ namespace Orchard.Redis.Caching { } public void Clear() { - Database.KeyDeleteWithPrefix(GetLocalizedKey("*")); + _connectionMultiplexer.KeyDeleteWithPrefix(GetLocalizedKey("*")); } private string GetLocalizedKey(string key) { diff --git a/src/Orchard.Web/Modules/Orchard.Redis/Extensions/RedisDatabaseExtensions.cs b/src/Orchard.Web/Modules/Orchard.Redis/Extensions/RedisDatabaseExtensions.cs deleted file mode 100644 index 2b223a064..000000000 --- a/src/Orchard.Web/Modules/Orchard.Redis/Extensions/RedisDatabaseExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using StackExchange.Redis; - -namespace Orchard.Redis.Extensions { - public static class RedisDatabaseExtensions { - - public static void KeyDeleteWithPrefix(this IDatabase database, string prefix) { - if (database == null) { - throw new ArgumentException("Database cannot be null", "database"); - } - - if (string.IsNullOrWhiteSpace(prefix)) { - throw new ArgumentException("Prefix cannot be empty", "database"); - } - - database.ScriptEvaluate(@" - local keys = redis.call('keys', ARGV[1]) - for i=1,#keys,5000 do - redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) - end", values: new RedisValue[] { prefix }); - } - - public static int KeyCount(this IDatabase database, string prefix) { - if (database == null) { - throw new ArgumentException("Database cannot be null", "database"); - } - - if (string.IsNullOrWhiteSpace(prefix)) { - throw new ArgumentException("Prefix cannot be empty", "database"); - } - - var retVal = database.ScriptEvaluate("return table.getn(redis.call('keys', ARGV[1]))", values: new RedisValue[] { prefix }); - - if (retVal.IsNull) { - return 0; - } - - return (int)retVal; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Redis/Orchard.Redis.csproj b/src/Orchard.Web/Modules/Orchard.Redis/Orchard.Redis.csproj index 891fb88bf..b050876b5 100644 --- a/src/Orchard.Web/Modules/Orchard.Redis/Orchard.Redis.csproj +++ b/src/Orchard.Web/Modules/Orchard.Redis/Orchard.Redis.csproj @@ -113,7 +113,7 @@ - + diff --git a/src/Orchard.Web/Modules/Orchard.Redis/OutputCache/RedisOutputCacheStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Redis/OutputCache/RedisOutputCacheStorageProvider.cs index c740bf294..ca8816b7e 100644 --- a/src/Orchard.Web/Modules/Orchard.Redis/OutputCache/RedisOutputCacheStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Redis/OutputCache/RedisOutputCacheStorageProvider.cs @@ -86,7 +86,7 @@ namespace Orchard.Redis.OutputCache { return; } - Database.KeyDeleteWithPrefix(GetLocalizedKey("*")); + Database.KeyDelete(GetPrefixedKeys().Select(key => (RedisKey)key).ToArray()); } public CacheItem GetCacheItem(string key) { @@ -126,7 +126,7 @@ namespace Orchard.Redis.OutputCache { return 0; } - return Database.KeyCount(GetLocalizedKey("*")); + return GetPrefixedKeys().Count(); } /// @@ -147,19 +147,19 @@ namespace Orchard.Redis.OutputCache { return new string[0]; } + var prefix = GetLocalizedKey(""); + return GetPrefixedKeys().Select(x => x.Substring(prefix.Length)); + } + + private IEnumerable GetPrefixedKeys() { // prevent the same request from computing the list twice (count + list) if (_keysCache == null) { _keysCache = new HashSet(); - var prefix = GetLocalizedKey(""); - - foreach (var endPoint in _connectionMultiplexer.GetEndPoints()) { - var server = _connectionMultiplexer.GetServer(endPoint); - foreach (var key in server.Keys(pattern: GetLocalizedKey("*"))) { - _keysCache.Add(key.ToString().Substring(prefix.Length)); - } + var keys = _connectionMultiplexer.GetKeys(GetLocalizedKey("*")); + foreach (var key in keys) { + _keysCache.Add(key); } } - return _keysCache; } diff --git a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs index 8e48ac6ba..396c7696b 100644 --- a/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Taxonomies/Drivers/TaxonomyFieldDriver.cs @@ -117,13 +117,10 @@ namespace Orchard.Taxonomies.Drivers { } protected override void Exporting(ContentPart part, TaxonomyField field, ExportContentContext context) { - var appliedTerms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name); - + var appliedTerms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name); // stores all content items associated to this field var termIdentities = appliedTerms.Select(x => Services.ContentManager.GetItemMetadata(x).Identity.ToString()).ToArray(); - - if (termIdentities.Any()) - context.Element(XmlConvert.EncodeLocalName(field.FieldDefinition.Name + "." + field.Name)).SetAttributeValue("Terms", String.Join(",", termIdentities)); + context.Element(XmlConvert.EncodeLocalName(field.FieldDefinition.Name + "." + field.Name)).SetAttributeValue("Terms", String.Join(",", termIdentities)); } protected override void Importing(ContentPart part, TaxonomyField field, ImportContentContext context) { diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeAttributeStrategy/ShapeAttributeBindingStrategy.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeAttributeStrategy/ShapeAttributeBindingStrategy.cs index 3dbe111e8..a98639fa3 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeAttributeStrategy/ShapeAttributeBindingStrategy.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeAttributeStrategy/ShapeAttributeBindingStrategy.cs @@ -70,7 +70,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy { catch(TargetInvocationException e) { // Throwing a TIE here will probably kill the web process // in Azure. For unknown reasons. - throw e.InnerException; + throw new Exception(string.Concat("TargetInvocationException ", methodInfo.Name), e.InnerException); } } diff --git a/src/Orchard/Mvc/Extensions/ControllerExtensions.cs b/src/Orchard/Mvc/Extensions/ControllerExtensions.cs index 904aae4d5..ddec70712 100644 --- a/src/Orchard/Mvc/Extensions/ControllerExtensions.cs +++ b/src/Orchard/Mvc/Extensions/ControllerExtensions.cs @@ -2,13 +2,15 @@ using System.Web; using System.Web.Mvc; using Orchard.Utility.Extensions; +using Orchard.Environment.Configuration; namespace Orchard.Mvc.Extensions { public static class ControllerExtensions { public static ActionResult RedirectLocal(this Controller controller, string redirectUrl, Func invalidUrlBehavior) { if (!string.IsNullOrWhiteSpace(redirectUrl) && controller.Request.IsLocalUrl(redirectUrl)) { - return new RedirectResult(redirectUrl); + return RedirectWithTenantPrefix(redirectUrl, controller); } + return invalidUrlBehavior != null ? invalidUrlBehavior() : null; } @@ -18,10 +20,25 @@ namespace Orchard.Mvc.Extensions { public static ActionResult RedirectLocal(this Controller controller, string redirectUrl, string defaultUrl) { if (controller.Request.IsLocalUrl(redirectUrl)) { - return new RedirectResult(redirectUrl); + return RedirectWithTenantPrefix(redirectUrl, controller); } - return new RedirectResult(defaultUrl ?? "~/"); + return RedirectWithTenantPrefix(defaultUrl ?? "~/", controller); + } + + private static ActionResult RedirectWithTenantPrefix(string redirectUrl, Controller controller) { + if (redirectUrl.StartsWith("~/")) { + ShellSettings settings; + var context = controller.ControllerContext.GetWorkContext(); + + if (context != null && + context.TryResolve(out settings) && + !string.IsNullOrWhiteSpace(settings.RequestUrlPrefix)) { + redirectUrl = VirtualPathUtility.ToAbsolute(redirectUrl, controller.Request.ApplicationPath.TrimEnd('/') + "/" + settings.RequestUrlPrefix); + } + } + + return new RedirectResult(redirectUrl); } } } diff --git a/src/Orchard/UI/Navigation/Pager.cs b/src/Orchard/UI/Navigation/Pager.cs index defcc539c..9fff3da35 100644 --- a/src/Orchard/UI/Navigation/Pager.cs +++ b/src/Orchard/UI/Navigation/Pager.cs @@ -23,10 +23,10 @@ namespace Orchard.UI.Navigation { /// The page parameter. /// The page size parameter. public Pager(ISite site, int? page, int? pageSize) { - Page = (int) (page != null ? (page > 0 ? page : PageDefault) : PageDefault); - PageSize = pageSize ?? site.PageSize; + Page = page == null || page == 0 ? PageDefault : page.Value; - if (site.MaxPageSize > 0 && PageSize > site.MaxPageSize) { + PageSize = pageSize ?? site.PageSize; + if (site.MaxPageSize > 0 && (PageSize == 0 || PageSize > site.MaxPageSize)) { PageSize = site.MaxPageSize; } } diff --git a/src/Rebracer.xml b/src/Rebracer.xml index ee2bf5fa9..ab7d68805 100644 --- a/src/Rebracer.xml +++ b/src/Rebracer.xml @@ -22,8 +22,8 @@ - 0 - 0 + 1 + 1 1 1 -1 @@ -141,10 +141,10 @@ false false false - false + true true false - false + true true true true