mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-19 18:27:55 +08:00

committed by
Sébastien Ros

parent
38bf36075a
commit
a5605b7fbd
@@ -320,6 +320,7 @@
|
|||||||
<Compile Include="Localization\DateTimePartsTests.cs" />
|
<Compile Include="Localization\DateTimePartsTests.cs" />
|
||||||
<Compile Include="Localization\DefaultDateLocalizationServicesTests.cs" />
|
<Compile Include="Localization\DefaultDateLocalizationServicesTests.cs" />
|
||||||
<Compile Include="Localization\DefaultDateFormatterTests.cs" />
|
<Compile Include="Localization\DefaultDateFormatterTests.cs" />
|
||||||
|
<Compile Include="Services\YamlParserTests.cs" />
|
||||||
<Compile Include="Stubs\StubApplicationEnvironment.cs" />
|
<Compile Include="Stubs\StubApplicationEnvironment.cs" />
|
||||||
<Compile Include="Stubs\StubCultureSelector.cs" />
|
<Compile Include="Stubs\StubCultureSelector.cs" />
|
||||||
<Compile Include="Localization\TestHelpers.cs" />
|
<Compile Include="Localization\TestHelpers.cs" />
|
||||||
|
70
src/Orchard.Tests/Services/YamlParserTests.cs
Normal file
70
src/Orchard.Tests/Services/YamlParserTests.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Orchard.Services;
|
||||||
|
|
||||||
|
namespace Orchard.Tests.Services {
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class YamlParserTests {
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldConvertYamlToWellknowType() {
|
||||||
|
var parser = new YamlParser();
|
||||||
|
var yaml = SampleYamlDocument;
|
||||||
|
|
||||||
|
var order = parser.Deserialize<Order>(yaml);
|
||||||
|
|
||||||
|
Assert.AreEqual("Nikola", order.Customer.FirstName);
|
||||||
|
Assert.AreEqual(2, order.Items.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldConvertYamlToDynamic()
|
||||||
|
{
|
||||||
|
var parser = new YamlParser();
|
||||||
|
var yaml = SampleYamlDocument;
|
||||||
|
|
||||||
|
var order = parser.Deserialize(yaml);
|
||||||
|
|
||||||
|
Assert.AreEqual("Nikola", (string)order.Customer.FirstName);
|
||||||
|
Assert.AreEqual(2, (int)order.Items.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public Customer Customer { get; set; }
|
||||||
|
public IList<OrderItem> Items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OrderItem {
|
||||||
|
public string Product { get; set; }
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Customer {
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string SampleYamlDocument =
|
||||||
|
@"
|
||||||
|
Date: 1916-04-01
|
||||||
|
Customer:
|
||||||
|
FirstName: Nikola
|
||||||
|
LastName: Tesla
|
||||||
|
Items:
|
||||||
|
- Product: Bulb
|
||||||
|
Quantity: 1
|
||||||
|
Price: 1.46
|
||||||
|
|
||||||
|
- Product: Wire
|
||||||
|
Quantity: 1
|
||||||
|
Price: 0.32
|
||||||
|
";
|
||||||
|
}
|
||||||
|
}
|
@@ -17,13 +17,14 @@ using Orchard.Layouts.Services;
|
|||||||
using Orchard.Layouts.Shapes;
|
using Orchard.Layouts.Shapes;
|
||||||
using Orchard.Layouts.ViewModels;
|
using Orchard.Layouts.ViewModels;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
|
using Orchard.Services;
|
||||||
using Orchard.Themes.Services;
|
using Orchard.Themes.Services;
|
||||||
using Orchard.Tokens;
|
using Orchard.Tokens;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
namespace Orchard.Layouts.Providers {
|
namespace Orchard.Layouts.Providers {
|
||||||
[OrchardFeature("Orchard.Layouts.Snippets")]
|
[OrchardFeature("Orchard.Layouts.Snippets")]
|
||||||
public class SnippetElementHarvester : Component, IElementHarvester {
|
public class SnippetElementHarvester : IElementHarvester {
|
||||||
private const string SnippetShapeSuffix = "Snippet";
|
private const string SnippetShapeSuffix = "Snippet";
|
||||||
private readonly Work<IShapeFactory> _shapeFactory;
|
private readonly Work<IShapeFactory> _shapeFactory;
|
||||||
private readonly Work<ISiteThemeService> _siteThemeService;
|
private readonly Work<ISiteThemeService> _siteThemeService;
|
||||||
@@ -33,6 +34,7 @@ namespace Orchard.Layouts.Providers {
|
|||||||
private readonly Work<ICurrentThemeShapeBindingResolver> _currentThemeShapeBindingResolver;
|
private readonly Work<ICurrentThemeShapeBindingResolver> _currentThemeShapeBindingResolver;
|
||||||
private readonly Work<ITokenizer> _tokenizer;
|
private readonly Work<ITokenizer> _tokenizer;
|
||||||
private readonly IWorkContextAccessor _wca;
|
private readonly IWorkContextAccessor _wca;
|
||||||
|
private readonly Work<IYamlParser> _yamlParser;
|
||||||
|
|
||||||
public SnippetElementHarvester(
|
public SnippetElementHarvester(
|
||||||
IWorkContextAccessor workContextAccessor,
|
IWorkContextAccessor workContextAccessor,
|
||||||
@@ -42,7 +44,8 @@ namespace Orchard.Layouts.Providers {
|
|||||||
Work<IElementFactory> elementFactory,
|
Work<IElementFactory> elementFactory,
|
||||||
Work<IShapeDisplay> shapeDisplay,
|
Work<IShapeDisplay> shapeDisplay,
|
||||||
Work<ITokenizer> tokenizer,
|
Work<ITokenizer> tokenizer,
|
||||||
Work<ICurrentThemeShapeBindingResolver> currentThemeShapeBindingResolver) {
|
Work<ICurrentThemeShapeBindingResolver> currentThemeShapeBindingResolver,
|
||||||
|
Work<IYamlParser> yamlParser) {
|
||||||
|
|
||||||
_shapeFactory = shapeFactory;
|
_shapeFactory = shapeFactory;
|
||||||
_siteThemeService = siteThemeService;
|
_siteThemeService = siteThemeService;
|
||||||
@@ -51,6 +54,7 @@ namespace Orchard.Layouts.Providers {
|
|||||||
_shapeDisplay = shapeDisplay;
|
_shapeDisplay = shapeDisplay;
|
||||||
_tokenizer = tokenizer;
|
_tokenizer = tokenizer;
|
||||||
_currentThemeShapeBindingResolver = currentThemeShapeBindingResolver;
|
_currentThemeShapeBindingResolver = currentThemeShapeBindingResolver;
|
||||||
|
_yamlParser = yamlParser;
|
||||||
_wca = workContextAccessor;
|
_wca = workContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +69,13 @@ namespace Orchard.Layouts.Providers {
|
|||||||
var shapeType = shapeDescriptor.Value.ShapeType;
|
var shapeType = shapeDescriptor.Value.ShapeType;
|
||||||
var elementName = GetDisplayName(shapeDescriptor.Value.BindingSource);
|
var elementName = GetDisplayName(shapeDescriptor.Value.BindingSource);
|
||||||
var closureDescriptor = shapeDescriptor;
|
var closureDescriptor = shapeDescriptor;
|
||||||
yield return new ElementDescriptor(elementType, shapeType, T(elementName), T("An element that renders the {0} shape.", shapeType), snippetElement.Category) {
|
var snippetDescriptor = ParseSnippetDescriptor(shapeDescriptor.Value.BindingSource);
|
||||||
Displaying = displayContext => Displaying(displayContext, closureDescriptor.Value),
|
yield return new ElementDescriptor(elementType, shapeType, new LocalizedString(elementName), new LocalizedString(String.Format("An element that renders the {0} shape.", shapeType)), snippetElement.Category) {
|
||||||
|
Displaying = displayContext => Displaying(displayContext, closureDescriptor.Value, snippetDescriptor),
|
||||||
ToolboxIcon = "\uf10c",
|
ToolboxIcon = "\uf10c",
|
||||||
EnableEditorDialog = HasSnippetFields(shapeDescriptor.Value),
|
EnableEditorDialog = snippetDescriptor != null || HasSnippetFields(shapeDescriptor.Value),
|
||||||
Editor = ctx => Editor(DescribeSnippet(shapeType, snippetElement), ctx),
|
Editor = ctx => Editor(snippetDescriptor ?? DescribeSnippet(shapeType, snippetElement), ctx),
|
||||||
UpdateEditor = ctx => UpdateEditor(DescribeSnippet(shapeType, snippetElement), ctx)
|
UpdateEditor = ctx => UpdateEditor(snippetDescriptor ?? DescribeSnippet(shapeType, snippetElement), ctx)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,22 +118,53 @@ namespace Orchard.Layouts.Providers {
|
|||||||
context.EditorResult.Add(snippetEditorShape);
|
context.EditorResult.Add(snippetEditorShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Displaying(ElementDisplayingContext context, ShapeDescriptor shapeDescriptor) {
|
private void Displaying(ElementDisplayingContext context, ShapeDescriptor shapeDescriptor, SnippetDescriptor snippetDescriptor) {
|
||||||
var shapeType = shapeDescriptor.ShapeType;
|
var shapeType = shapeDescriptor.ShapeType;
|
||||||
var shape = (dynamic)_shapeFactory.Value.Create(shapeType);
|
var shape = (dynamic)_shapeFactory.Value.Create(shapeType);
|
||||||
|
|
||||||
shape.Element = context.Element;
|
shape.Element = context.Element;
|
||||||
|
|
||||||
|
if (snippetDescriptor != null) {
|
||||||
|
foreach (var fieldDescriptor in snippetDescriptor.Fields) {
|
||||||
|
var value = context.Element.Data.Get(fieldDescriptor.Name);
|
||||||
|
shape.Properties[fieldDescriptor.Name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ElementShapes.AddTokenizers(shape, _tokenizer.Value);
|
ElementShapes.AddTokenizers(shape, _tokenizer.Value);
|
||||||
context.ElementShape.Snippet = shape;
|
context.ElementShape.Snippet = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetDisplayName(string bindingSource) {
|
private string GetDisplayName(string bindingSource) {
|
||||||
var fileName = Path.GetFileNameWithoutExtension(bindingSource);
|
var fileName = Path.GetFileNameWithoutExtension(bindingSource) ?? "";
|
||||||
var lastIndex = fileName.IndexOf(SnippetShapeSuffix, StringComparison.OrdinalIgnoreCase);
|
var lastIndex = fileName.IndexOf(SnippetShapeSuffix, StringComparison.OrdinalIgnoreCase);
|
||||||
return fileName.Substring(0, lastIndex).CamelFriendly();
|
return fileName.Substring(0, lastIndex).CamelFriendly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SnippetDescriptor ParseSnippetDescriptor(string bindingSource) {
|
||||||
|
var physicalSourcePath = _wca.GetContext().HttpContext.Server.MapPath(bindingSource);
|
||||||
|
var paramsFileName = Path.Combine(Path.GetDirectoryName(physicalSourcePath) ?? "", Path.GetFileNameWithoutExtension(physicalSourcePath) + ".txt");
|
||||||
|
|
||||||
|
if (!File.Exists(paramsFileName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var yaml = File.ReadAllText(paramsFileName);
|
||||||
|
var snippetConfig = _yamlParser.Value.Deserialize(yaml);
|
||||||
|
var fieldsConfig = snippetConfig.Fields != null ? snippetConfig.Fields.Children : new dynamic[0];
|
||||||
|
var descriptor = new SnippetDescriptor();
|
||||||
|
|
||||||
|
foreach (var fieldConfig in fieldsConfig) {
|
||||||
|
descriptor.Fields.Add(new SnippetFieldDescriptor {
|
||||||
|
Name = (string)fieldConfig.Name,
|
||||||
|
Type = (string)fieldConfig.Type,
|
||||||
|
DisplayName = new LocalizedString((string)fieldConfig.DisplayName),
|
||||||
|
Description = new LocalizedString((string)fieldConfig.Description)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
private SnippetDescriptor DescribeSnippet(string shapeType, Snippet element) {
|
private SnippetDescriptor DescribeSnippet(string shapeType, Snippet element) {
|
||||||
var shape = (dynamic)_shapeFactory.Value.Create(shapeType);
|
var shape = (dynamic)_shapeFactory.Value.Create(shapeType);
|
||||||
shape.Element = element;
|
shape.Element = element;
|
||||||
|
@@ -225,7 +225,11 @@
|
|||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Iesi.Collections" publicKeyToken="aa95f207798dfdb4" culture="neutral" />
|
<assemblyIdentity name="Iesi.Collections" publicKeyToken="aa95f207798dfdb4" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@@ -166,6 +166,14 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="YamlDotNet, Version=3.8.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\YamlDotNet.3.8.0\lib\net35\YamlDotNet.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="YamlDotNet.Dynamic, Version=3.2.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\YamlDotNet.Dynamic.3.2.3\lib\net40\YamlDotNet.Dynamic.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ContentManagement\Extensions\DriverResultExtensions.cs" />
|
<Compile Include="ContentManagement\Extensions\DriverResultExtensions.cs" />
|
||||||
@@ -419,7 +427,9 @@
|
|||||||
<Compile Include="Services\ClientHostAddressAccessor.cs" />
|
<Compile Include="Services\ClientHostAddressAccessor.cs" />
|
||||||
<Compile Include="Services\DefaultJsonConverter.cs" />
|
<Compile Include="Services\DefaultJsonConverter.cs" />
|
||||||
<Compile Include="Services\IClientHostAddressAccessor.cs" />
|
<Compile Include="Services\IClientHostAddressAccessor.cs" />
|
||||||
|
<Compile Include="Services\IYamlParser.cs" />
|
||||||
<Compile Include="Services\IJsonConverter.cs" />
|
<Compile Include="Services\IJsonConverter.cs" />
|
||||||
|
<Compile Include="Services\YamlParser.cs" />
|
||||||
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
<Compile Include="Settings\CurrentSiteWorkContext.cs" />
|
||||||
<Compile Include="Settings\ResourceDebugMode.cs" />
|
<Compile Include="Settings\ResourceDebugMode.cs" />
|
||||||
<Compile Include="Tasks\Locking\Services\DistributedLockSchemaBuilder.cs" />
|
<Compile Include="Tasks\Locking\Services\DistributedLockSchemaBuilder.cs" />
|
||||||
|
21
src/Orchard/Services/IYamlParser.cs
Normal file
21
src/Orchard/Services/IYamlParser.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Orchard.Services {
|
||||||
|
/// <summary>
|
||||||
|
/// Provides methods to deserialize objects from YAML documents.
|
||||||
|
/// </summary>
|
||||||
|
public interface IYamlParser : IDependency {
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes a YAML document to a dynamic object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="yaml">The YAML document to deserialize.</param>
|
||||||
|
/// <returns>The deserialized object.</returns>
|
||||||
|
dynamic Deserialize(string yaml);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes a YAML document to a specific object.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
|
||||||
|
/// <param name="yaml">The YAML document to deserialize.</param>
|
||||||
|
/// <returns>The deserialized object.</returns>
|
||||||
|
T Deserialize<T>(string yaml);
|
||||||
|
}
|
||||||
|
}
|
19
src/Orchard/Services/YamlParser.cs
Normal file
19
src/Orchard/Services/YamlParser.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.IO;
|
||||||
|
using YamlDotNet.Dynamic;
|
||||||
|
using YamlDotNet.Serialization;
|
||||||
|
using YamlDotNet.Serialization.NamingConventions;
|
||||||
|
|
||||||
|
namespace Orchard.Services {
|
||||||
|
public class YamlParser : IYamlParser {
|
||||||
|
public dynamic Deserialize(string yaml) {
|
||||||
|
return new DynamicYaml(yaml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Deserialize<T>(string yaml) {
|
||||||
|
var deserializer = new Deserializer(namingConvention: new PascalCaseNamingConvention(), ignoreUnmatched: true);
|
||||||
|
using (var reader = new StringReader(yaml)) {
|
||||||
|
return deserializer.Deserialize<T>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,4 +17,6 @@
|
|||||||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net452" />
|
||||||
<package id="NHibernate" version="4.0.1.4000" targetFramework="net452" />
|
<package id="NHibernate" version="4.0.1.4000" targetFramework="net452" />
|
||||||
<package id="Owin" version="1.0" targetFramework="net452" />
|
<package id="Owin" version="1.0" targetFramework="net452" />
|
||||||
|
<package id="YamlDotNet" version="3.8.0" targetFramework="net452" />
|
||||||
|
<package id="YamlDotNet.Dynamic" version="3.2.3" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
Reference in New Issue
Block a user