mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-26 12:03:16 +08:00
Merge branch '1.10.x' into dev
# Conflicts: # src/Orchard.Web/Core/Orchard.Core.csproj # src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs # src/Orchard.Web/Modules/Orchard.Localization/Views/Parts/Localization.ContentTranslations.SummaryAdmin.cshtml # src/Orchard.Web/Modules/Orchard.Redis/OutputCache/RedisOutputCacheStorageProvider.cs
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
<Content Include="Styles\DynamicForms.min.css" />
|
||||
<Content Include="Styles\menu.dynamicforms-admin.css" />
|
||||
<Content Include="Styles\menu.dynamicforms.png" />
|
||||
<Content Include="Styles\recipebuilderstep-forms.css" />
|
||||
<Content Include="Styles\workflows-activity-add-model-error.css" />
|
||||
<Content Include="Styles\workflows-activity-dynamic-form-submitted.css" />
|
||||
<Content Include="Styles\workflows-activity-dynamic-form-validating.css" />
|
||||
@@ -304,6 +305,7 @@
|
||||
<Compile Include="Validators\TextAreaValidator.cs" />
|
||||
<Compile Include="Validators\TextFieldValidator.cs" />
|
||||
<Compile Include="Validators\UrlFieldValidator.cs" />
|
||||
<Compile Include="ViewModels\FormExportEntry.cs" />
|
||||
<Compile Include="ViewModels\FieldValidationSettings.cs" />
|
||||
<Compile Include="ViewModels\FormBindingSettings.cs" />
|
||||
<Compile Include="Helpers\ContentTypeDefinitionExtensions.cs" />
|
||||
@@ -549,6 +551,9 @@
|
||||
<ItemGroup>
|
||||
<Content Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\BuilderSteps\FormSubmissions.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
||||
@@ -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<string>();
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
@@ -23,29 +28,43 @@ namespace Orchard.DynamicForms.Recipes.Builders {
|
||||
get { return T("Exports submitted forms."); }
|
||||
}
|
||||
|
||||
public IList<string> 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<FormExportEntry> forms = new List<FormExportEntry>();
|
||||
|
||||
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))))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.DynamicForms.ViewModels {
|
||||
public class FormExportEntry {
|
||||
public string FormName { get; set; }
|
||||
public bool Export { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
@model List<FormExportEntry>
|
||||
@using Orchard.DynamicForms.ViewModels;
|
||||
|
||||
@{
|
||||
Style.Include("recipebuilderstep-forms.css");
|
||||
}
|
||||
|
||||
<div>
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>@T("Form")</th>
|
||||
<th>
|
||||
<input type="checkbox" class="check-all-in-column" />
|
||||
@T("Select All")
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (int index = 0; index < Model.Count(); index++) {
|
||||
var entry = Model.ElementAt(index);
|
||||
<tr>
|
||||
<td>@entry.FormName</td>
|
||||
<td>
|
||||
<input type="hidden" name="@Html.NameFor(m => m[index].FormName)" value="@entry.FormName" />
|
||||
<input type="checkbox" class="check-data" name="@Html.NameFor(m => m[index].Export)" value="true" />
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@Html.Hint(T("Choose the forms to include in the export file"))
|
||||
</div>
|
||||
@@ -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) {
|
||||
|
||||
@@ -169,9 +169,7 @@ namespace Orchard.Fields.Drivers {
|
||||
}
|
||||
|
||||
protected override void Exporting(ContentPart part, DateTimeField field, ExportContentContext context) {
|
||||
var value = field.Storage.Get<DateTime>(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<DateTime>(null), XmlDateTimeSerializationMode.Utc));
|
||||
}
|
||||
|
||||
protected override void Cloning(ContentPart part, DateTimeField originalField, DateTimeField cloneField, CloneContentContext context) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
namespace Orchard.Layouts.Framework.Harvesters {
|
||||
public class HarvestElementsContext {
|
||||
public IContent Content { get; set; }
|
||||
public bool IsHarvesting { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ namespace Orchard.Layouts.Providers {
|
||||
public class BlueprintElementHarvester : Component, IElementHarvester {
|
||||
private readonly Work<IElementBlueprintService> _elementBlueprintService;
|
||||
private readonly Work<IElementManager> _elementManager;
|
||||
private bool _isHarvesting;
|
||||
|
||||
public BlueprintElementHarvester(Work<IElementBlueprintService> elementBlueprintService, Work<IElementManager> elementManager) {
|
||||
_elementBlueprintService = elementBlueprintService;
|
||||
@@ -21,15 +20,14 @@ namespace Orchard.Layouts.Providers {
|
||||
}
|
||||
|
||||
public IEnumerable<ElementDescriptor> HarvestElements(HarvestElementsContext context) {
|
||||
if (_isHarvesting)
|
||||
if (context.IsHarvesting)
|
||||
return Enumerable.Empty<ElementDescriptor>();
|
||||
|
||||
_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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<LocalizationPart>(), true) :
|
||||
var masterContentItem = _contentManager.Get(part.Record.MasterContentItemId, VersionOptions.Latest);
|
||||
|
||||
var missingCultures = part.HasTranslationGroup && masterContentItem != null ?
|
||||
RetrieveMissingCultures(masterContentItem.As<LocalizationPart>(), 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<string> RetrieveMissingCultures(LocalizationPart part, bool excludePartCulture) {
|
||||
var editorLocalizations = GetEditorLocalizations(part);
|
||||
var editorLocalizations = GetEditorLocalizations(part.MasterContentItem != null ? part.MasterContentItem.As<LocalizationPart>() : part);
|
||||
|
||||
var cultures = _cultureManager
|
||||
.ListCultures()
|
||||
|
||||
@@ -16,7 +16,7 @@ var localizationLinks = Html.UnorderedList(localizations, (c, i) => Html.ItemEdi
|
||||
}
|
||||
@if (Model.Culture != null && !((IEnumerable<string>)Model.SiteCultures).All(c => c == Model.Culture || localizations.Any(l => c == l.Culture.Culture)))
|
||||
{
|
||||
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.Id }, new { itemprop = "UnsafeUrl" })</div>
|
||||
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.MasterId }, new { itemprop = "UnsafeUrl" })</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@@ -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<MediaPartRecord> repository) {
|
||||
IRepository<MediaPartRecord> repository,
|
||||
IContentDefinitionManager contentDefinitionManager) {
|
||||
_storageProvider = storageProvider;
|
||||
_mediaLibraryService = mediaLibraryService;
|
||||
_contentDefinitionManager = contentDefinitionManager;
|
||||
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
Filters.Add(new ActivatingFilter<TitlePart>(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<MediaPart>((context, part) => RemoveMedia(part));
|
||||
OnLoaded<MediaPart>((context, part) => {
|
||||
if (!String.IsNullOrEmpty(part.FileName)) {
|
||||
|
||||
@@ -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<MediaPartRecord> {
|
||||
@@ -11,6 +13,8 @@ namespace Orchard.MediaLibrary.Models {
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title of the media.
|
||||
/// This adds an implicit dependency on <see cref="TitlePart"/> which will be resolved by an
|
||||
/// <see cref="ActivatingFilter{TPart}"/> in the <see cref="MediaPartHandler"/>.
|
||||
/// </summary>
|
||||
public string Title {
|
||||
get { return ContentItem.As<TitlePart>().Title; }
|
||||
@@ -63,7 +67,7 @@ namespace Orchard.MediaLibrary.Models {
|
||||
/// Gets the public Url of the media if stored locally.
|
||||
/// </summary>
|
||||
public string MediaUrl {
|
||||
get { return _publicUrl.Value; }
|
||||
get { return _publicUrl.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Orchard.Redis.Caching {
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
Database.KeyDeleteWithPrefix(GetLocalizedKey("*"));
|
||||
_connectionMultiplexer.KeyDeleteWithPrefix(GetLocalizedKey("*"));
|
||||
}
|
||||
|
||||
private string GetLocalizedKey(string key) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Caching\RedisCacheStorageProvider.cs" />
|
||||
<Compile Include="Extensions\RedisDatabaseExtensions.cs" />
|
||||
<Compile Include="Extensions\RedisConnectionExtensions.cs" />
|
||||
<Compile Include="Configuration\IRedisConnectionProvider.cs" />
|
||||
<Compile Include="Configuration\RedisConnectionProvider.cs" />
|
||||
<Compile Include="MessageBus\RedisMessageBusBroker.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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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<string> GetPrefixedKeys() {
|
||||
// prevent the same request from computing the list twice (count + list)
|
||||
if (_keysCache == null) {
|
||||
_keysCache = new HashSet<string>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ActionResult> 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<ShellSettings>(out settings) &&
|
||||
!string.IsNullOrWhiteSpace(settings.RequestUrlPrefix)) {
|
||||
redirectUrl = VirtualPathUtility.ToAbsolute(redirectUrl, controller.Request.ApplicationPath.TrimEnd('/') + "/" + settings.RequestUrlPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
return new RedirectResult(redirectUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ namespace Orchard.UI.Navigation {
|
||||
/// <param name="page">The page parameter.</param>
|
||||
/// <param name="pageSize">The page size parameter.</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
</ToolsOptionsCategory>
|
||||
<ToolsOptionsCategory name="TextEditor">
|
||||
<ToolsOptionsSubCategory name="CSharp-Specific">
|
||||
<PropertyValue name="AddImport_SuggestForTypesInNuGetPackages">0</PropertyValue>
|
||||
<PropertyValue name="AddImport_SuggestForTypesInReferenceAssemblies">0</PropertyValue>
|
||||
<PropertyValue name="AddImport_SuggestForTypesInNuGetPackages">1</PropertyValue>
|
||||
<PropertyValue name="AddImport_SuggestForTypesInReferenceAssemblies">1</PropertyValue>
|
||||
<PropertyValue name="AutoComment">1</PropertyValue>
|
||||
<PropertyValue name="AutoInsertAsteriskForNewLinesOfBlockComments">1</PropertyValue>
|
||||
<PropertyValue name="CSharpClosedFileDiagnostics">-1</PropertyValue>
|
||||
@@ -141,10 +141,10 @@
|
||||
<PropertyValue name="EnableExpandPrecedence">false</PropertyValue>
|
||||
<PropertyValue name="EnableExpandScopes">false</PropertyValue>
|
||||
<PropertyValue name="EnableExtractFunction">false</PropertyValue>
|
||||
<PropertyValue name="EnableSQLiteStoreEngine">false</PropertyValue>
|
||||
<PropertyValue name="EnableSQLiteStoreEngine">true</PropertyValue>
|
||||
<PropertyValue name="EnableSingleFileISense">true</PropertyValue>
|
||||
<PropertyValue name="EnableSingleFileISenseSquiggles">false</PropertyValue>
|
||||
<PropertyValue name="EnumerateCommentTasks">false</PropertyValue>
|
||||
<PropertyValue name="EnumerateCommentTasks">true</PropertyValue>
|
||||
<PropertyValue name="GroupBrackets">true</PropertyValue>
|
||||
<PropertyValue name="HideExperimentalAd">true</PropertyValue>
|
||||
<PropertyValue name="HighlightMatchingTokens">true</PropertyValue>
|
||||
|
||||
Reference in New Issue
Block a user