mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-26 12:03:16 +08:00
Merge branch '1.10.x' into 1.10.2
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Lucene.Models {
|
||||
public class LuceneAnalyzerSelectorMapping {
|
||||
public string IndexName { get; set; }
|
||||
public string AnalyzerName { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/Orchard.Web/Modules/Lucene/Models/LuceneSettingsPart.cs
Normal file
21
src/Orchard.Web/Modules/Lucene/Models/LuceneSettingsPart.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/Orchard.Web/Modules/Lucene/Placement.info
Normal file
5
src/Orchard.Web/Modules/Lucene/Placement.info
Normal file
@@ -0,0 +1,5 @@
|
||||
<Placement>
|
||||
<Match ContentType="Site">
|
||||
<Place Parts_LuceneSettings_Edit="Content: 1@LuceneSettings" />
|
||||
</Match>
|
||||
</Placement>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,7 @@ namespace Lucene.Services {
|
||||
Analyzer = new StandardAnalyzer(LuceneIndexProvider.LuceneVersion)
|
||||
};
|
||||
}
|
||||
|
||||
public string Name { get { return "Default"; } }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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";
|
||||
|
||||
@@ -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 Describe(DescribeMembersContext context) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"])
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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))};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user