--HG--
branch : 1.x
This commit is contained in:
Bertrand Le Roy
2013-02-05 10:42:18 -08:00
183 changed files with 6747 additions and 694 deletions

View File

@@ -3,6 +3,7 @@ using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Core.Title.Models;
using Orchard.Forms.Services;
using Orchard.Projections.Descriptors.Filter;
using Orchard.Projections.Descriptors.Layout;
using Orchard.Projections.Descriptors.SortCriterion;

View File

@@ -10,6 +10,7 @@ using Orchard.Core.Feeds;
using Orchard.Core.Title.Models;
using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;
using Orchard.Projections.Descriptors.Layout;
using Orchard.Projections.Descriptors.Property;

View File

@@ -21,6 +21,10 @@
</UpgradeBackupLocation>
<TargetFrameworkProfile />
<UseIISExpress>false</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -209,7 +213,6 @@
<Compile Include="Services\IPropertyService.cs" />
<Compile Include="Services\LayoutProvider.cs" />
<Compile Include="Services\ISortCriteriaProvider.cs" />
<Compile Include="Services\FormParametersHelper.cs" />
<Compile Include="Services\IFilterProvider.cs" />
<Compile Include="Services\IProjectionManager.cs" />
<Compile Include="Services\IQueryService.cs" />
@@ -217,16 +220,8 @@
<Compile Include="Services\PropertyShapes.cs" />
<Compile Include="Services\ProjectionManager.cs" />
<Compile Include="Services\QueryService.cs" />
<Compile Include="Settings\Serialization\XmlSettingsSerializer.cs" />
<Compile Include="Settings\Serialization\ISettingsSerializer.cs" />
<Compile Include="Services\FieldIndexService.cs" />
<Compile Include="Services\IFieldIndexService.cs" />
<Compile Include="Settings\SArray.cs" />
<Compile Include="Settings\SConvert.cs" />
<Compile Include="Settings\SItem.cs" />
<Compile Include="Settings\StateValueProvider.cs" />
<Compile Include="Settings\SValue.cs" />
<Compile Include="Settings\SObject.cs" />
<Compile Include="StandardQueries\QueryFeedQuery.cs" />
<Compile Include="ViewModels\BindingIndexViewModel.cs" />
<Compile Include="ViewModels\BindingSelectViewModel.cs" />

View File

@@ -42,14 +42,14 @@ namespace Orchard.Projections.Providers.SortCriteria {
public void ApplyFilter(SortCriterionContext context, PropertyInfo property) {
bool ascending = Convert.ToBoolean(context.State.Sort);
bool ascending = Boolean.Parse(Convert.ToString(context.State.Sort));
context.Query = ascending
? context.Query.OrderBy(alias => alias.ContentPartRecord(property.DeclaringType), x => x.Asc(property.Name))
: context.Query.OrderBy(alias => alias.ContentPartRecord(property.DeclaringType), x => x.Desc(property.Name));
}
public LocalizedString DisplaySortCriterion(SortCriterionContext context, string propertyName) {
bool ascending = Convert.ToBoolean(context.State.Sort);
bool ascending = Boolean.Parse(Convert.ToString(context.State.Sort));
if (ascending) {
return T("Ordered by {0}, ascending", propertyName);

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
using Orchard.Projections.Settings;
namespace Orchard.Projections.Services {
public static class FormParametersHelper {
public static string ToString(IDictionary<string, string> parameters) {
var doc = new XDocument();
doc.Add(new XElement("Form"));
var root = doc.Root;
if (root == null) {
return String.Empty;
}
foreach (var entry in parameters) {
root.Add(new XElement(XmlConvert.EncodeLocalName(entry.Key), entry.Value));
}
return doc.ToString(SaveOptions.DisableFormatting);
}
public static IDictionary<string, string> FromString(string parameters) {
var result = new Dictionary<string, string>();
if (String.IsNullOrEmpty(parameters)) {
return result;
}
var doc = XDocument.Parse(parameters);
if (doc.Root == null) {
return result;
}
foreach (var element in doc.Root.Elements()) {
result.Add(element.Name.LocalName, element.Value);
}
return result;
}
public static dynamic ToDynamic(string parameters) {
var result = SObject.New();
if (String.IsNullOrEmpty(parameters)) {
return result;
}
var doc = XDocument.Parse(parameters);
if (doc.Root == null) {
return result;
}
foreach (var element in doc.Root.Elements()) {
result[element.Name.LocalName] = element.Value;
}
return result;
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
using Orchard.Data;
using Orchard.Forms.Services;
using Orchard.Projections.Descriptors;
using Orchard.Localization;
using Orchard.Projections.Descriptors.Property;

View File

@@ -1,78 +0,0 @@
using System;
using System.Dynamic;
using System.Linq;
using System.Reflection;
namespace Orchard.Projections.Settings {
public class SArray : DynamicObject, ISItem {
public ISItem[] Values { get; private set; }
public SArray(Array array) {
Values = new ISItem[array.Length];
for (var i = 0; i < array.Length; i++) {
Values[i] = SConvert.ToSettings(array.GetValue(i));
}
}
// Set the property value by index.
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) {
if (typeof(long).IsAssignableFrom(indexes[0].GetType())) {
Values[(long)indexes[0]] = SConvert.ToSettings(value);
return true;
}
return false;
}
// Get the property value by index.
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
if (typeof(long).IsAssignableFrom(indexes[0].GetType())) {
result = SConvert.ToObject(Values[(long)indexes[0]]);
return true;
}
result = null;
return false;
}
// Forward any call to the internal array (Length, ...)
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
try {
result = typeof(Array).InvokeMember(
binder.Name,
BindingFlags.InvokeMethod |
BindingFlags.Public |
BindingFlags.Instance,
null, Values, args);
return true;
}
catch {
result = null;
return false;
}
}
#region ICloneable Members
public object Clone() {
return Values.Select(x => x.Clone()).Cast<ISItem>().ToArray();
}
#endregion
public static SArray operator &(SArray o1, SArray o2) {
// concatenate the value with the array
return new SArray(o1.Values.Union(o2.Values).ToArray());
}
public static SArray operator &(SArray o1, SValue o2) {
// concatenate the value with the array
return new SArray(o1.Values.Union(new[] { o1 }).ToArray());
}
public static SObject operator &(SArray o1, SObject o2) {
return o2;
}
}
}

View File

@@ -1,126 +0,0 @@
using System;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Globalization;
using System.Xml;
namespace Orchard.Projections.Settings {
public class SConvert {
public static ISItem ToSettings(object o) {
if (o is SValue) {
return (ISItem)o;
}
if (o is SObject) {
return (ISItem)o;
}
if (o is SArray) {
return (ISItem)o;
}
if (o is Array) {
return new SArray((Array)o);
}
if (IsAnonymousType(o.GetType())) {
dynamic grappe = new SObject();
foreach (var p in o.GetType().GetProperties()) {
grappe[p.Name] = p.GetValue(o, null);
}
return grappe;
}
return new SValue(o);
}
public static object ToObject(object s) {
if (s is SValue) {
return ((SValue)s).Value;
}
if (s is SArray) {
var array = (SArray)s;
var result = new object[array.Values.Length];
for (var i = 0; i < array.Values.Length; i++) {
result[i] = ToObject(array.Values[i]);
}
return result;
}
return s;
}
private static bool IsAnonymousType(Type type) {
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
public static string XmlEncode(object value) {
switch (Type.GetTypeCode(value.GetType())) {
case TypeCode.Boolean:
case TypeCode.Char:
case TypeCode.String:
return value.ToString();
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return Convert.ToDecimal(value).ToString(CultureInfo.InvariantCulture);
case TypeCode.DateTime:
return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Utc);
default:
throw new NotSupportedException("Could not encode member");
}
}
public static SValue XmlDecode(TypeCode typeCode, string value) {
switch (typeCode) {
case TypeCode.Boolean:
return new SValue(Boolean.Parse(value));
case TypeCode.Byte:
return new SValue(Byte.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Decimal:
return new SValue(Decimal.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Double:
return new SValue(Double.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Int16:
return new SValue(Int16.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Int32:
return new SValue(Int32.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Int64:
return new SValue(Int64.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.SByte:
return new SValue(SByte.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Single:
return new SValue(Single.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.UInt16:
return new SValue(UInt16.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.UInt32:
return new SValue(UInt32.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.UInt64:
return new SValue(UInt64.Parse(value, CultureInfo.InvariantCulture));
case TypeCode.Char:
return new SValue(value[1]);
case TypeCode.String:
return new SValue(value);
case TypeCode.DateTime:
return new SValue(XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.Utc));
default:
throw new NotSupportedException("Could not decode member");
}
}
}
}

View File

@@ -1,7 +0,0 @@
using System;
namespace Orchard.Projections.Settings {
public interface ISItem : ICloneable {
}
}

View File

@@ -1,114 +0,0 @@
using System.Collections.Generic;
using System.Dynamic;
namespace Orchard.Projections.Settings {
public class SObject : DynamicObject, IEnumerable<KeyValuePair<string, object>>, ISItem {
internal readonly Dictionary<string, ISItem> _properties = new Dictionary<string, ISItem>();
public static dynamic New() {
return new SObject();
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
return SetMember(binder.Name, value);
}
public bool SetMember(string name, object value) {
if (value == null && _properties.ContainsKey(name)) {
_properties.Remove(name);
}
else {
_properties[name] = SConvert.ToSettings(value);
}
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
return GetMember(binder.Name, out result);
}
public bool GetMember(string name, out object result) {
// if the property doesn't exist, return null
if (!_properties.ContainsKey(name)) {
result = null;
return true;
}
var value = _properties[name];
result = SConvert.ToObject(value);
return true;
}
// Set the property value by index.
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) {
return SetMember(indexes[0].ToString(), value);
}
// Get the property value by index.
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
return GetMember(indexes[0].ToString(), out result);
}
public static SObject operator &(SObject o1, SObject o2) {
if (o1 == null) {
return o2;
}
var clone = (SObject)o1.Clone();
dynamic dclone = clone;
foreach (var pair in o2._properties) {
if (clone._properties.ContainsKey(pair.Key)) {
if (pair.Value == null) {
// remove the left element
dclone[pair.Key] = null;
}
else {
dynamic d1 = clone._properties[pair.Key];
dclone[pair.Key] = d1 & (dynamic)pair.Value;
}
}
else {
if (pair.Value != null) {
dclone[pair.Key] = pair.Value;
}
}
}
return clone;
}
#region IEnumerable<KeyValuePair<string,object>> Members
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {
foreach (var key in _properties.Keys) {
object member;
if (GetMember(key, out member)) {
yield return new KeyValuePair<string, object>(key, member);
}
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region ICloneable Members
public object Clone() {
var o = New();
foreach (var pair in _properties) {
o[pair.Key] = pair.Value.Clone();
}
return o;
}
#endregion
}
}

View File

@@ -1,32 +0,0 @@
using System.Linq;
namespace Orchard.Projections.Settings {
public class SValue : ISItem {
public object Value { get; set; }
public SValue(object value) {
Value = value;
}
#region ICloneable Members
public object Clone() {
return new SValue(Value);
}
public static SValue operator &(SValue o1, SValue o2) {
return o2;
}
public static SArray operator &(SValue o1, SArray o2) {
// concatenate the value with the array
return new SArray(new[] { o1 }.Union(o2.Values).ToArray());
}
public static SObject operator &(SValue o1, SObject o2) {
return o2;
}
#endregion
}
}

View File

@@ -1,8 +0,0 @@
using System.IO;
namespace Orchard.Projections.Settings.Serialization {
public interface ISettingsSerializer : IDependency {
void Serialize(TextWriter tw, SObject o);
SObject Deserialize(TextReader tr);
}
}

View File

@@ -1,106 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace Orchard.Projections.Settings.Serialization {
public class XmlSettingsSerializer : ISettingsSerializer {
private const string Root = "SObject";
public void Serialize(TextWriter tw, SObject o) {
using (var writer = new XmlTextWriter(tw)) {
writer.WriteStartDocument();
writer.WriteStartElement(Root);
WriteGrappe(writer, o);
writer.WriteEndDocument();
}
}
public SObject Deserialize(TextReader tr) {
var reader = new XmlTextReader(tr);
var result = new SObject();
// ignore root element
while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == Root) {
reader.Read();
}
while (reader.MoveToContent() == XmlNodeType.Element) {
ReadElement(reader, result);
}
return result;
}
private void ReadElement(XmlReader reader, SObject parent) {
var name = XmlConvert.DecodeName(reader.LocalName);
var type = reader["type"];
// is it a value node ? i.e. type=""
if (type != null) {
if (type == "Array") {
// go to first item
parent.SetMember(name, ReadArray(reader));
reader.Read();
}
else {
var typeCode = (TypeCode)Enum.Parse(typeof(TypeCode), type);
var value = SConvert.XmlDecode(typeCode, reader.ReadElementString());
parent.SetMember(name, value);
}
}
else {
var grappe = new SObject();
reader.Read();
parent.SetMember(name, grappe);
while (reader.MoveToContent() == XmlNodeType.Element) {
ReadElement(reader, grappe);
}
reader.Read();
}
}
public SArray ReadArray(XmlReader reader) {
var list = new List<object>();
reader.Read();
while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Item") {
dynamic o = new SObject();
ReadElement(reader, o);
list.Add(o.Item);
}
return new SArray(list.ToArray());
}
private void WriteGrappe(XmlWriter writer, SObject grappe) {
foreach (var pair in grappe._properties) {
WriteAny(writer, pair.Key, pair.Value);
}
}
private void WriteAny(XmlWriter writer, string name, object value) {
if (value is SObject) {
writer.WriteStartElement(XmlConvert.EncodeLocalName(name));
WriteGrappe(writer, (SObject)value);
writer.WriteEndElement();
}
if (value is SArray) {
writer.WriteStartElement(XmlConvert.EncodeLocalName(name));
writer.WriteAttributeString("type", "Array");
foreach (var v in ((SArray)value).Values) {
WriteAny(writer, "Item", v);
}
writer.WriteEndElement();
}
else if (value is SValue) {
var sValue = (SValue)value;
writer.WriteStartElement(XmlConvert.EncodeLocalName(name));
writer.WriteAttributeString("type", Type.GetTypeCode(sValue.Value.GetType()).ToString());
writer.WriteString(SConvert.XmlEncode(sValue.Value));
writer.WriteEndElement();
}
}
}
}

View File

@@ -1,19 +0,0 @@
using System.Web.Mvc;
namespace Orchard.Projections.Settings {
public class SettingsValueProvider : IValueProvider {
private readonly dynamic _state;
public SettingsValueProvider(dynamic state) {
_state = state;
}
public bool ContainsPrefix(string prefix) {
return true;
}
public ValueProviderResult GetValue(string key) {
return _state[key];
}
}
}

View File

@@ -66,7 +66,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\FieldIndexServiceTests.cs" />
<Compile Include="Services\FieldIndexStorageTests.cs" />
<Compile Include="Settings\SettingsTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Orchard.Tests\Orchard.Framework.Tests.csproj">

View File

@@ -1,162 +0,0 @@
using NUnit.Framework;
using Orchard.Projections.Settings;
using System.Collections.Generic;
using System.IO;
using Orchard.Projections.Settings.Serialization;
namespace Orchard.Projections.Tests.Settings {
[TestFixture]
public class SettingsTests {
[Test]
public void ShouldRemoveMember() {
dynamic e = new SObject();
e.Foo = "Bar";
Assert.That(e, Is.Not.Empty);
Assert.That(e.Foo, Is.EqualTo("Bar"));
e.Foo = null;
Assert.That(e, Is.Empty);
}
[Test]
public void ShouldSupportFactoryInvocation() {
var e = SObject.New();
e.Foo = "Bar";
Assert.That(e["Foo"], Is.EqualTo("Bar"));
Assert.That(e.Foo, Is.EqualTo("Bar"));
}
[Test]
public void ShouldAddDynamicProperties() {
dynamic e = new SObject();
e.Foo = "Bar";
Assert.That(e["Foo"], Is.EqualTo("Bar"));
Assert.That(e.Foo, Is.EqualTo("Bar"));
}
[Test]
public void UnknownPropertiesShouldBeNull() {
dynamic e = new SObject();
Assert.That((object)e["Foo"], Is.EqualTo(null));
Assert.That((object)e.Foo, Is.EqualTo(null));
}
[Test]
public void ShouldAddDynamicObjects() {
dynamic e = new SObject();
e.Address = new SObject();
e.Address.Street = "One Microsoft Way";
Assert.That(e["Address"]["Street"], Is.EqualTo("One Microsoft Way"));
Assert.That(e.Address.Street, Is.EqualTo("One Microsoft Way"));
}
public void ShouldAddArraysOfAnonymousObject() {
dynamic e = new SObject();
e.Foos = new[] { new { Foo1 = "Bar1", Foo2 = "Bar2" } };
Assert.That(e.Foos[0].Foo1, Is.EqualTo("Bar1"));
Assert.That(e.Foos[0].Foo2, Is.EqualTo("Bar2"));
}
public void ShouldAddAnonymousObject() {
dynamic e = new SObject();
e.Foos = new { Foo1 = "Bar1", Foo2 = "Bar2" };
Assert.That(e.Foos.Foo1, Is.EqualTo("Bar1"));
Assert.That(e.Foos.Foo2, Is.EqualTo("Bar2"));
}
[Test]
public void ShouldAddArrays() {
dynamic e = new SObject();
e.Owners = new[] { "Steve", "Bill" };
Assert.That(e.Owners[0], Is.EqualTo("Steve"));
Assert.That(e.Owners[1], Is.EqualTo("Bill"));
}
[Test]
public void ShouldBeEnumerable() {
dynamic e = new SObject();
e.Address = new SObject();
e.Address.Street = "One Microsoft Way";
e.Foos = new[] { new { Foo1 = "Bar1", Foo2 = "Bar2" } };
e.Owners = new[] { "Steve", "Bill" };
// IEnumerable
Assert.That(e, Has.Some.Matches<KeyValuePair<string, object>>(x => x.Key == "Address"));
Assert.That(e, Has.Some.Matches<KeyValuePair<string, object>>(x => x.Key == "Owners"));
Assert.That(e, Has.Some.Matches<KeyValuePair<string, object>>(x => x.Key == "Foos"));
}
[Test]
public void ShouldSerializeAndDeserialize() {
dynamic e = new SObject();
e.Foo = "Bar";
e.Address = new SObject();
e.Address.Street = "One Microsoft Way";
e.Owners = new[] { "Steve", "Bill" };
e.Foos = new[] { new { Foo1 = "Bar1", Foo2 = "Bar2" } };
string xml1;
var serializer = new XmlSettingsSerializer();
using (var sw = new StringWriter()) {
serializer.Serialize(sw, e);
xml1 = sw.ToString();
}
dynamic clone;
using (var sr = new StringReader(xml1)) {
clone = serializer.Deserialize(sr);
}
string xml2;
using (var sw = new StringWriter()) {
serializer.Serialize(sw, clone);
xml2 = sw.ToString();
}
Assert.That(xml1, Is.EqualTo(xml2));
}
[Test]
public void MergeShouldOverwriteExistingProperties() {
var o1 = SObject.New();
o1.Foo = "Foo1";
o1.Bar = "Bar1";
var o2 = SObject.New();
o2.Foo = "Foo2";
o2.Baz = "Baz2";
var o3 = o1 & o2;
Assert.That(o3.Foo, Is.EqualTo("Foo2"));
Assert.That(o3.Bar, Is.EqualTo("Bar1"));
Assert.That(o3.Baz, Is.EqualTo("Baz2"));
}
[Test]
public void MergeShouldConcatenateArrays() {
var o1 = SObject.New();
o1.Foo = new[] { "a", "b" };
var o2 = SObject.New();
o2.Foo = new[] { "c", "d" };
var o3 = o1 & o2;
Assert.That(o3.Foo[0], Is.EqualTo("a"));
Assert.That(o3.Foo[1], Is.EqualTo("b"));
Assert.That(o3.Foo[2], Is.EqualTo("c"));
Assert.That(o3.Foo[3], Is.EqualTo("d"));
}
}
}