Merge branch '1.10.x' into 1.10.2

This commit is contained in:
Sebastien Ros
2017-03-27 15:39:59 -07:00
45 changed files with 470 additions and 107 deletions

View File

@@ -14,7 +14,6 @@ using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Data;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
@@ -69,6 +68,7 @@ namespace Orchard.Tests.Modules.Indexing {
builder.RegisterType<IndexingTaskManager>().As<IIndexingTaskManager>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
builder.RegisterType<Signals>().As<ISignals>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(_contentDefinitionManager.Object);

View File

@@ -9,6 +9,7 @@ using Orchard.Environment.Configuration;
using Orchard.FileSystems.AppData;
using Orchard.Indexing;
using Orchard.Tests.FileSystems.AppData;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.Modules.Indexing {
public class LuceneIndexProviderTests {
@@ -35,6 +36,7 @@ namespace Orchard.Tests.Modules.Indexing {
_appDataFolder = AppDataFolderTests.CreateAppDataFolder(_basePath);
var builder = new ContainerBuilder();
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
builder.RegisterType<DefaultLuceneAnalyzerProvider>().As<ILuceneAnalyzerProvider>();
builder.RegisterType<DefaultLuceneAnalyzerSelector>().As<ILuceneAnalyzerSelector>();
builder.RegisterType<LuceneIndexProvider>().As<IIndexProvider>();

View File

@@ -8,6 +8,7 @@ using Orchard.Environment.Configuration;
using Orchard.FileSystems.AppData;
using Orchard.Indexing;
using Orchard.Tests.FileSystems.AppData;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.Modules.Indexing {
public class LuceneSearchBuilderTests {
@@ -34,6 +35,7 @@ namespace Orchard.Tests.Modules.Indexing {
_appDataFolder = AppDataFolderTests.CreateAppDataFolder(_basePath);
var builder = new ContainerBuilder();
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
builder.RegisterType<DefaultLuceneAnalyzerProvider>().As<ILuceneAnalyzerProvider>();
builder.RegisterType<DefaultLuceneAnalyzerSelector>().As<ILuceneAnalyzerSelector>();
builder.RegisterType<LuceneIndexProvider>().As<IIndexProvider>();

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -189,7 +189,7 @@ namespace Orchard.Core.Settings.Metadata {
private void Apply(ContentTypeDefinition model, ContentTypeDefinitionRecord record) {
record.DisplayName = model.DisplayName;
record.Settings = _settingsFormatter.Map(model.Settings).ToString();
record.Settings = Compose(_settingsFormatter.Map(model.Settings));
var toRemove = record.ContentTypePartDefinitionRecords
.Where(partDefinitionRecord => model.Parts.All(part => partDefinitionRecord.ContentPartDefinitionRecord.Name != part.PartDefinition.Name))
@@ -215,7 +215,7 @@ namespace Orchard.Core.Settings.Metadata {
}
private void Apply(ContentPartDefinition model, ContentPartDefinitionRecord record) {
record.Settings = _settingsFormatter.Map(model.Settings).ToString();
record.Settings = Compose(_settingsFormatter.Map(model.Settings));
var toRemove = record.ContentPartFieldDefinitionRecords
.Where(partFieldDefinitionRecord => model.Fields.All(partField => partFieldDefinitionRecord.Name != partField.Name))

View File

@@ -0,0 +1,69 @@
using Lucene.Models;
using Lucene.Services;
using Lucene.ViewModels;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Indexing;
using Orchard.Localization;
using Orchard.UI.Notify;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Lucene.Drivers {
public class LuceneSettingsPartDriver : ContentPartDriver<LuceneSettingsPart> {
private readonly IIndexManager _indexManager;
private readonly IEnumerable<ILuceneAnalyzerSelector> _analyzerSelectors;
private readonly INotifier _notifier;
public Localizer T { get; set; }
public LuceneSettingsPartDriver(IIndexManager indexManager, IEnumerable<ILuceneAnalyzerSelector> analyzerSelectors, INotifier notifier) {
_indexManager = indexManager;
_analyzerSelectors = analyzerSelectors;
_notifier = notifier;
T = NullLocalizer.Instance;
}
protected override DriverResult Editor(LuceneSettingsPart part, dynamic shapeHelper) {
return ContentShape("Parts_LuceneSettings_Edit", () => {
MaintainMappings(part);
return shapeHelper.EditorTemplate(
TemplateName: "Parts.LuceneSettings",
Model: new LuceneSettingsPartEditViewModel {
LuceneAnalyzerSelectorMappings = part.LuceneAnalyzerSelectorMappings.ToArray(),
LuceneAnalyzerSelectors = _analyzerSelectors.Select(analyzerSelector =>
new SelectListItem { Text = T(analyzerSelector.Name).Text, Value = analyzerSelector.Name })
},
Prefix: Prefix);
});
}
protected override DriverResult Editor(LuceneSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
var viewModel = new LuceneSettingsPartEditViewModel();
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
_notifier.Warning(T("Don't forget to rebuild your index in case you have changed its analyzer."));
part.LuceneAnalyzerSelectorMappings = viewModel.LuceneAnalyzerSelectorMappings;
MaintainMappings(part);
}
return Editor(part, shapeHelper);
}
private void MaintainMappings(LuceneSettingsPart part) {
var analyzerProviderNames = _analyzerSelectors.Select(analyzerProvider => analyzerProvider.Name);
var indexNames = _indexManager.GetSearchIndexProvider().List();
var maintainedMappings = part.LuceneAnalyzerSelectorMappings.ToList();
// Removing mappings which contain a removed/invalid index or analyzer provider.
maintainedMappings.RemoveAll(mapping => !indexNames.Contains(mapping.IndexName) || !analyzerProviderNames.Contains(mapping.AnalyzerName));
// Adding new mappings for the new indexes.
foreach (var indexName in indexNames) {
if (!maintainedMappings.Any(mapping => mapping.IndexName == indexName)) {
maintainedMappings.Add(new LuceneAnalyzerSelectorMapping { IndexName = indexName, AnalyzerName = "Default" });
}
}
part.LuceneAnalyzerSelectorMappings = maintainedMappings;
}
}
}

View File

@@ -0,0 +1,39 @@
using Lucene.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Localization;
using Orchard.Services;
using System.Collections.Generic;
namespace Lucene.Handlers {
public class LuceneSettingsPartHandler : ContentHandler {
public Localizer T { get; set; }
public LuceneSettingsPartHandler(IJsonConverter jsonConverter) {
T = NullLocalizer.Instance;
Filters.Add(new ActivatingFilter<LuceneSettingsPart>("Site"));
OnActivated<LuceneSettingsPart>((context, part) => {
part.LuceneAnalyzerSelectorMappingsField.Loader(() => {
return string.IsNullOrEmpty(part.LuceneAnalyzerSelectorMappingsSerialized)
? new List<LuceneAnalyzerSelectorMapping>()
: jsonConverter.Deserialize<List<LuceneAnalyzerSelectorMapping>>(part.LuceneAnalyzerSelectorMappingsSerialized);
});
part.LuceneAnalyzerSelectorMappingsField.Setter((value) => {
part.LuceneAnalyzerSelectorMappingsSerialized = value == null ? "[]" : jsonConverter.Serialize(value);
return value;
});
});
}
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
if (context.ContentItem.ContentType != "Site") return;
base.GetItemMetadata(context);
context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Lucene Settings")) { Id = "LuceneSettings" });
}
}
}

View File

@@ -97,8 +97,12 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="Drivers\LuceneSettingsPartDriver.cs" />
<Compile Include="Handlers\LuceneSettingsPartHandler.cs" />
<Compile Include="Models\LuceneAnalyzerSelectorMapping.cs" />
<Compile Include="Models\LuceneDocumentIndex.cs" />
<Compile Include="Models\LuceneSearchHit.cs" />
<Compile Include="Models\LuceneSettingsPart.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\DefaultLuceneAnalyzerSelector.cs" />
<Compile Include="Services\DefaultLuceneAnalyzerProvider.cs" />
@@ -108,6 +112,7 @@
<Compile Include="Services\LuceneIndexProvider.cs" />
<Compile Include="Services\LuceneSearchBuilder.cs" />
<Compile Include="Services\SearchBits.cs" />
<Compile Include="ViewModels\LuceneSettingsPartEditViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
@@ -127,6 +132,13 @@
<ItemGroup>
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Placement.info" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\EditorTemplates\Parts.LuceneSettings.cshtml" />
</ItemGroup>
<ItemGroup />
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1,6 @@
namespace Lucene.Models {
public class LuceneAnalyzerSelectorMapping {
public string IndexName { get; set; }
public string AnalyzerName { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using Lucene.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities;
using System.Collections.Generic;
namespace Lucene.Models {
public class LuceneSettingsPart : ContentPart {
public string LuceneAnalyzerSelectorMappingsSerialized {
get { return this.Retrieve(x => x.LuceneAnalyzerSelectorMappingsSerialized); }
set { this.Store(x => x.LuceneAnalyzerSelectorMappingsSerialized, value); }
}
private readonly LazyField<IEnumerable<LuceneAnalyzerSelectorMapping>> _luceneAnalyzerSelectorMappings = new LazyField<IEnumerable<LuceneAnalyzerSelectorMapping>>();
internal LazyField<IEnumerable<LuceneAnalyzerSelectorMapping>> LuceneAnalyzerSelectorMappingsField { get { return _luceneAnalyzerSelectorMappings; }
}
public IEnumerable<LuceneAnalyzerSelectorMapping> LuceneAnalyzerSelectorMappings {
get { return _luceneAnalyzerSelectorMappings.Value; }
set { _luceneAnalyzerSelectorMappings.Value = value; }
}
}
}

View File

@@ -0,0 +1,5 @@
<Placement>
<Match ContentType="Site">
<Place Parts_LuceneSettings_Edit="Content: 1@LuceneSettings" />
</Match>
</Placement>

View File

@@ -1,34 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lucene.Models;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Orchard;
using Orchard.ContentManagement;
using System.Collections.Generic;
using System.Linq;
namespace Lucene.Services {
public class DefaultLuceneAnalyzerProvider : ILuceneAnalyzerProvider {
private readonly IWorkContextAccessor _wca;
private IEnumerable<ILuceneAnalyzerSelector> _analyzerSelectors;
public DefaultLuceneAnalyzerProvider(IEnumerable<ILuceneAnalyzerSelector> analyzerSelectors) {
public DefaultLuceneAnalyzerProvider(IEnumerable<ILuceneAnalyzerSelector> analyzerSelectors, IWorkContextAccessor wca) {
_analyzerSelectors = analyzerSelectors;
_wca = wca;
}
public Analyzer GetAnalyzer(string indexName) {
var luceneSettingsPart = _wca
.GetContext()
.CurrentSite
.As<LuceneSettingsPart>();
if (luceneSettingsPart == null) {
return new StandardAnalyzer(LuceneIndexProvider.LuceneVersion);
}
var currentIndexMapping = luceneSettingsPart
.LuceneAnalyzerSelectorMappings
.FirstOrDefault(mapping => mapping.IndexName == indexName);
if (currentIndexMapping == null) {
return new StandardAnalyzer(LuceneIndexProvider.LuceneVersion);
}
var analyzer = _analyzerSelectors
.Where(x => x.Name == currentIndexMapping.AnalyzerName)
.Select(x => x.GetLuceneAnalyzer(indexName))
.Where(x => x != null)
.OrderByDescending(x => x.Priority)
.Select(x => x.Analyzer)
.FirstOrDefault();
if (analyzer != null) {
return analyzer;
}
return new StandardAnalyzer(LuceneIndexProvider.LuceneVersion);
return analyzer != null ? analyzer : new StandardAnalyzer(LuceneIndexProvider.LuceneVersion);
}
}
}

View File

@@ -12,5 +12,7 @@ namespace Lucene.Services {
Analyzer = new StandardAnalyzer(LuceneIndexProvider.LuceneVersion)
};
}
public string Name { get { return "Default"; } }
}
}

View File

@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard;
using Orchard;
namespace Lucene.Services {
public interface ILuceneAnalyzerSelector : IDependency {
LuceneAnalyzerSelectorResult GetLuceneAnalyzer(string indexName);
string Name { get; }
}
}

View File

@@ -0,0 +1,14 @@
using Lucene.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Lucene.ViewModels {
public class LuceneSettingsPartEditViewModel {
public LuceneAnalyzerSelectorMapping[] LuceneAnalyzerSelectorMappings { get; set; }
public IEnumerable<SelectListItem> LuceneAnalyzerSelectors { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
@model Lucene.ViewModels.LuceneSettingsPartEditViewModel
@using System.Linq
<fieldset>
<legend>@T("Lucene Settings")</legend>
@if (!Model.LuceneAnalyzerSelectorMappings.Any()) {
@T("There is currently no mapping. Create an index first.")
}
else {
<ul>
@for (int i = 0; i < Model.LuceneAnalyzerSelectorMappings.Length; i++) {
<li>
@Html.HiddenFor(m => Model.LuceneAnalyzerSelectorMappings[i].IndexName)
@Html.LabelFor(m => Model.LuceneAnalyzerSelectorMappings[i].AnalyzerName, T("Analyzer name for the \"{0}\" index", Model.LuceneAnalyzerSelectorMappings[i].IndexName))
@Html.DropDownListFor(m => Model.LuceneAnalyzerSelectorMappings[i].AnalyzerName, new SelectList(
Model.LuceneAnalyzerSelectors,
"Text",
"Value",
Model.LuceneAnalyzerSelectorMappings[i].AnalyzerName
))
</li>
}
</ul>
}
</fieldset>

View File

@@ -22,7 +22,7 @@ namespace Orchard.ContentTypes {
return 1;
}
public int UpgradeFrom1() {
public int UpdateFrom1() {
foreach (var typeDefinition in _contentDefinitionManager.ListTypeDefinitions()) {
if (typeDefinition.Settings.ContainsKey("ContentTypeSettings.Creatable") && Convert.ToBoolean(typeDefinition.Settings["ContentTypeSettings.Creatable"], CultureInfo.InvariantCulture)) {
typeDefinition.Settings["ContentTypeSettings.Securable"] = "True";

View File

@@ -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>

View File

@@ -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))))));
}
}
}
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.DynamicForms.ViewModels {
public class FormExportEntry {
public string FormName { get; set; }
public bool Export { get; set; }
}
}

View File

@@ -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>

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -165,9 +165,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 Describe(DescribeMembersContext context) {

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -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 Describe(DescribeMembersContext context) {

View File

@@ -3,5 +3,6 @@
namespace Orchard.Layouts.Framework.Harvesters {
public class HarvestElementsContext {
public IContent Content { get; set; }
public bool IsHarvesting { get; set; }
}
}

View File

@@ -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) {

View File

@@ -125,6 +125,7 @@ namespace Orchard.Layouts.Providers {
var shape = (dynamic)_shapeFactory.Value.Create(shapeType);
shape.Element = context.Element;
shape.SnippetDescriptor = snippetDescriptor;
if (snippetDescriptor != null) {
foreach (var fieldDescriptor in snippetDescriptor.Fields) {

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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)) {

View File

@@ -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>

View File

@@ -11,6 +11,7 @@ using Orchard.PublishLater.Models;
using Orchard.PublishLater.Services;
using Orchard.PublishLater.ViewModels;
using Orchard.Services;
using Orchard.Tasks.Scheduling;
namespace Orchard.PublishLater.Drivers {
public class PublishLaterPartDriver : ContentPartDriver<PublishLaterPart> {
@@ -19,19 +20,22 @@ namespace Orchard.PublishLater.Drivers {
private readonly IPublishLaterService _publishLaterService;
private readonly IClock _clock;
private readonly IDateLocalizationServices _dateLocalizationServices;
private readonly IPublishingTaskManager _publishingTaskManager;
public PublishLaterPartDriver(
IOrchardServices services,
IHttpContextAccessor httpContextAccessor,
IPublishLaterService publishLaterService,
IClock clock,
IDateLocalizationServices dateLocalizationServices) {
IDateLocalizationServices dateLocalizationServices,
IPublishingTaskManager publishingTaskManager) {
_httpContextAccessor = httpContextAccessor;
_publishLaterService = publishLaterService;
_clock = clock;
_dateLocalizationServices = dateLocalizationServices;
T = NullLocalizer.Instance;
Services = services;
_publishingTaskManager = publishingTaskManager;
}
public Localizer T {
@@ -105,6 +109,9 @@ namespace Orchard.PublishLater.Drivers {
}
}
if (httpContext.Request.Form["submit.Save"] == "submit.CancelPublishLaterTasks") {
_publishingTaskManager.DeleteTasks(model.ContentItem);
}
return ContentShape("Parts_PublishLater_Edit",
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: model, Prefix: Prefix));
}

View File

@@ -41,6 +41,9 @@
@Html.HiddenFor(m => m.Editor.ShowTime)
@Html.EditorFor(m => m.Editor)
<button type="submit" name="submit.Save" value="submit.PublishLater">@T("Publish Later")</button>
@if (!string.IsNullOrEmpty(Model.Editor.Date)) {
<button type="submit" name="submit.Save" value="submit.CancelPublishLaterTasks">@T("Cancel Publish Later")</button>
}
</fieldset>
using (Script.Foot()) {

View File

@@ -36,6 +36,13 @@ namespace Orchard.Tags {
return 2;
}
public int UpdateFrom2() {
SchemaBuilder.AlterTable("ContentTagRecord", table => table
.CreateIndex("IDX_TagsPartRecord_Id", "TagsPartRecord_Id")
);
return 3;
}
}
[OrchardFeature("Orchard.Tags.TagCloud")]

View File

@@ -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) {

View File

@@ -1,11 +1,19 @@
<div class="sections">
<div class="primary">
@Display(Model.Content)
<div class="edit-item">
<div class="edit-item-primary">
@if (Model.Content != null) {
<div class="edit-item-content">
@Display(Model.Content)
</div>
}
</div>
<div class="secondary">
@Display(Model.Sidebar)
<div class="edit-item-secondary group">
@if (Model.Sidebar != null) {
<div class="edit-item-sidebar group">
@Display(Model.Sidebar)
</div>
}
</div>
</div>
@if (!String.IsNullOrWhiteSpace(Request.QueryString["returnUrl"])) {
@Html.Hidden("returnUrl", Request.QueryString["returnUrl"])
}
}

View File

@@ -405,7 +405,7 @@ namespace Orchard.Data.Migration.Interpreters {
if ( value == null ) {
return "null";
}
TypeCode typeCode = Type.GetTypeCode(value.GetType());
switch (typeCode) {
case TypeCode.Empty:
@@ -428,7 +428,7 @@ namespace Orchard.Data.Migration.Interpreters {
case TypeCode.Decimal:
return Convert.ToString(value, CultureInfo.InvariantCulture);
case TypeCode.DateTime:
return String.Concat("'", Convert.ToString(value, CultureInfo.InvariantCulture), "'");
return String.Concat("'", ((DateTime)value).ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture), "'");
}
return "null";

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using NHibernate.Dialect;
using Orchard.Data.Migration.Schema;
@@ -8,12 +9,14 @@ using Orchard.Environment.Configuration;
using Orchard.Localization;
namespace Orchard.Data.Migration.Interpreters {
public class MySqlCommandInterpreter : ICommandInterpreter<AlterColumnCommand> {
public class MySqlCommandInterpreter : ICommandInterpreter<AlterColumnCommand>, ICommandInterpreter<AddIndexCommand> {
private readonly Lazy<Dialect> _dialectLazy;
private readonly ShellSettings _shellSettings;
private readonly ITransactionManager _transactionManager;
private readonly DefaultDataMigrationInterpreter _dataMigrationInterpreter;
public MySqlCommandInterpreter(DefaultDataMigrationInterpreter dataMigrationInterpreter) {
public MySqlCommandInterpreter(DefaultDataMigrationInterpreter dataMigrationInterpreter, ITransactionManager transactionManager) {
_transactionManager = transactionManager;
_dataMigrationInterpreter = dataMigrationInterpreter;
T = NullLocalizer.Instance;
}
@@ -26,14 +29,16 @@ namespace Orchard.Data.Migration.Interpreters {
public MySqlCommandInterpreter(
ShellSettings shellSettings,
ISessionFactoryHolder sessionFactoryHolder) {
_shellSettings = shellSettings;
_dialectLazy = new Lazy<Dialect>(() => Dialect.GetDialect(sessionFactoryHolder.GetConfiguration().Properties));
ISessionFactoryHolder sessionFactoryHolder,
ITransactionManager transactionManager) {
_shellSettings = shellSettings;
_transactionManager = transactionManager;
_dialectLazy = new Lazy<Dialect>(() => Dialect.GetDialect(sessionFactoryHolder.GetConfiguration().Properties));
}
public string[] CreateStatements(AlterColumnCommand command) {
var builder = new StringBuilder();
builder.AppendFormat("alter table {0} modify column {1} ",
_dialectLazy.Value.QuoteForTableName(PrefixTableName(command.TableName)),
_dialectLazy.Value.QuoteForColumnName(command.ColumnName));
@@ -42,8 +47,7 @@ namespace Orchard.Data.Migration.Interpreters {
// type
if (command.DbType != DbType.Object) {
builder.Append(DefaultDataMigrationInterpreter.GetTypeName(_dialectLazy.Value, command.DbType, command.Length, command.Precision, command.Scale));
}
else {
} else {
if (command.Length > 0 || command.Precision > 0 || command.Scale > 0) {
throw new OrchardException(T("Error while executing data migration: you need to specify the field's type in order to change its properties"));
}
@@ -56,7 +60,7 @@ namespace Orchard.Data.Migration.Interpreters {
_dialectLazy.Value.QuoteForTableName(PrefixTableName(command.TableName)),
_dialectLazy.Value.QuoteForColumnName(command.ColumnName));
var initLength2 = builder2.Length;
if (command.Default != null) {
builder2.Append(" set default ").Append(_dataMigrationInterpreter.ConvertToSqlValue(command.Default)).Append(" ");
}
@@ -64,13 +68,11 @@ namespace Orchard.Data.Migration.Interpreters {
// result
var result = new List<string>();
if (builder.Length > initLength)
{
if (builder.Length > initLength) {
result.Add(builder.ToString());
}
if (builder2.Length > initLength2)
{
if (builder2.Length > initLength2) {
result.Add(builder2.ToString());
}
@@ -82,5 +84,36 @@ namespace Orchard.Data.Migration.Interpreters {
return tableName;
return _shellSettings.DataTablePrefix + "_" + tableName;
}
public string[] CreateStatements(AddIndexCommand command) {
var session = _transactionManager.GetSession();
using (var sqlCommand = session.Connection.CreateCommand()) {
var columnNames = String.Join(", ", command.ColumnNames.Select(c => string.Format("'{0}'", c)));
var tableName = PrefixTableName(command.TableName);
// check whether the index contains big nvarchar columns or text fields
string sql = @"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{1}' AND COLUMN_NAME in ({0}) AND TABLE_SCHEMA = '{2}' AND
((Data_type = 'varchar' and CHARACTER_MAXIMUM_LENGTH > 767) OR data_type= 'text');";
sql = string.Format(sql, columnNames, tableName, session.Connection.Database);
sqlCommand.CommandText = sql;
var columnList = command.ColumnNames.ToList();
using (var reader = sqlCommand.ExecuteReader()) {
// Provide prefix for string columns with length longer than 767
while (reader.Read()) {
var columnName = reader.GetString(0);
columnList[columnList.IndexOf(columnName)] = string.Format("{0}(767)", columnName);
}
}
return new[] {string.Format("create index {1} on {0} ({2}) ",
_dialectLazy.Value.QuoteForTableName(tableName),
_dialectLazy.Value.QuoteForTableName(PrefixTableName(command.IndexName)),
String.Join(", ", columnList))};
}
}
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}