diff --git a/AzurePackage.proj b/AzurePackage.proj
index 696168b1e..5ae8072d0 100644
--- a/AzurePackage.proj
+++ b/AzurePackage.proj
@@ -48,7 +48,8 @@
+ Properties="Configuration=Release;OutputPath=$(CompileFolder);PlatformTarget=x64;DefineConstants=AZURE"
+ />
YamlSerializer
-
+
- Converts various types to / from string.
- I don't remember why this class was needed....
+ Type 関連のユーティリティメソッド
- object obj = GetObjectToConvert();
+ Type type;
+ AttributeType attr = type.GetAttribute<AttributeType>();
- // Check if the type has [TypeConverter] attribute.
- if( EasyTypeConverter.IsTypeConverterSpecified(type) ) {
+ PropertyInfo propInfo;
+ AttributeType attr = propInfo.GetAttribute<AttributeType>();
- // Convert the object to string.
- string s = EasyTypeConverter.ConvertToString(obj);
+ string name;
+ Type type = TypeUtils.GetType(name); // search from all assembly loaded
- // Convert the string to an object of the spific type.
- object restored = EasyTypeConverter.ConvertFromString(s, type);
-
- Assert.AreEqual(obj, restored);
- }
+
+
+ Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す
+ 複数存在した場合には最後の値を返す
+ 存在しなければ null を返す
+
+ 取り出したい属性の型
+ 取り出した属性値
+
+
+
+ 現在ロードされているすべてのアセンブリから name という名の型を探して返す
+
+
+
+
+
+
+ Check if the type is a ValueType and does not contain any non ValueType members.
+
+
+
+
+
+
+ Returnes true if the specified is a struct type.
+
+ to be analyzed.
+ true if the specified is a struct type; otehrwise false.
+
+
+
+ Compare two objects to see if they are equal or not. Null is acceptable.
+
+
+
+
+
+
+
+ Return if an object is a numeric value.
+
+ Any object to be tested.
+ True if object is a numeric value.
+
+
+
+ Cast an object to a specified numeric type.
+
+ Any object
+ Numric type
+ Numeric value or null if the object is not a numeric value.
+
+
+
+ Cast boxed numeric value to double
+
+ boxed numeric value
+ Numeric value in double. Double.Nan if obj is not a numeric value.
+
+
+
+ Check if type is fully public or not.
+ Nested class is checked if all declared types are public.
+
+
+
+
+
+
+ Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values.
+
+
+
+
+
+ Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y).
+
+ The first object to compare.
+ The second object to compare.
+ true if the specified objects are equal; otherwise, false.
+
+
+
+ Serves as a hash function for the specified object for hashing algorithms and
+ data structures, such as a hash table.
+
+ The object for which to get a hash code.
+ A hash code for the specified object.
+ is null.
+
+
+
+ Returns a default equality comparer for the type specified by the generic argument.
+
+ The default instance of the System.Collections.Generic.EqualityComparer<T>
+ class for type T.
+
+
+
+
+ object に代入されたクラスや構造体のメンバーに、リフレクションを
+ 解して簡単にアクセスできるようにしたクラス
+
+ アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が
+ 期待できる
+
+
+
+
+ Caches ObjectMemberAccessor instances for reuse.
+
+
+
+
+
+ 指定した型へのアクセス方法を表すインスタンスを返す
+ キャッシュに存在すればそれを返す
+ キャッシュに存在しなければ新しく作って返す
+ 作った物はキャッシュされる
+
+ クラスまたは構造体を表す型情報
+
+
+
+
+ メンバ名と Accessor のペアを巡回する
+
+
+
+
+
+ メンバへの読み書きを行うことができる
+
+ オブジェクト
+ メンバの名前
+
+
+
+
+ class has instance methods and ,
+ with which C# native objects can be converted into / from YAML text without any preparations.
+
+ var serializer = new YamlSerializer();
+ object obj = GetObjectToSerialize();
+ string yaml = serializer.Serialize(obj);
+ object restored = serializer.Deserialize(yaml);
+ Assert.AreEqual(obj, restored);
+
+
+
+
+
What kind of objects can be serialized?
+
+ can serialize / deserialize native C# objects of primitive types
+ (bool, char, int,...), enums, built-in non-primitive types (string, decimal), structures,
+ classes and arrays of these types.
+
+
+ On the other hand, it does not deal with IntPtr (which is a primitive type, though) and
+ pointer types (void*, int*, ...) because these types are, by their nature, not persistent.
+
+
+
+ Classes without a default constructor can be deserialized only when the way of activating an instance
+ is explicitly specified by .
+
+
+
+ object obj = new object[]{
+ null,
+ "abc",
+ true,
+ 1,
+ (Byte)1,
+ 1.0,
+ "1",
+ new double[]{ 1.1, 2, -3 },
+ new string[]{ "def", "ghi", "1" },
+ new System.Drawing.Point(1,3),
+ new System.Drawing.SolidBrush(Color.Blue)
+ };
+
+ var serializer = new YamlSerializer();
+ string yaml = serializer.Serialize(obj);
+ // %YAML 1.2
+ // ---
+ // - null
+ // - abc
+ // - True
+ // - 1
+ // - !System.Byte 1
+ // - !!float 1
+ // - "1"
+ // - !<!System.Double[]%gt; [1.1, 2, -3]
+ // - !<!System.String[]%gt;
+ // - def
+ // - ghi
+ // - !System.Drawing.Point 1, 3
+ // - !System.Drawing.SolidBrush
+ // Color: Blue
+ // ...
+
+ object restored;
+ try {
+ restored = YamlSerializer.Deserialize(yaml)[0];
+ } catch(MissingMethodException) {
+ // default constructor is missing for SolidBrush
+ }
+
+ // Let the library know how to activate an instance of SolidBrush.
+ YamlNode.DefaultConfig.AddActivator<System.Drawing.SolidBrush>(
+ () => new System.Drawing.SolidBrush(Color.Black /* dummy */));
+
+ // Then, all the objects can be restored correctly.
+ restored = serializer.Deserialize(yaml)[0];
+
+
+ A YAML document generated by always have a %YAML directive and
+ explicit document start ("---") and end ("...") marks.
+ This allows several documents to be written in a single YAML stream.
+
+
+ var yaml = "";
+ var serializer = new YamlSerializer();
+ yaml += serializer.Serialize("a");
+ yaml += serializer.Serialize(1);
+ yaml += serializer.Serialize(1.1);
+ // %YAML 1.2
+ // ---
+ // a
+ // ...
+ // %YAML 1.2
+ // ---
+ // 1
+ // ...
+ // %YAML 1.2
+ // ---
+ // 1.1
+ // ...
+
+ object[] objects = serializer.Deserialize(yaml);
+ // objects[0] == "a"
+ // objects[1] == 1
+ // objects[2] == 1.1
+
+
+ Since a YAML stream can consist of multiple YAML documents as above,
+ returns an array of .
+
+
+
Serializing structures and classes
+
+ For structures and classes, by default, all public fields and public properties are
+ serialized. Note that protected / private members are always ignored.
+
+
Serialization methods
+
+ Readonly value-type members are also ignored because there is no way to
+ assign a new value to them on deserialization, while readonly class-type members
+ are serialized. When deserializing, instead of creating a new object and assigning it
+ to the member, the child members of such class instance are restored independently.
+ Such a deserializing method is refered to
+ YamlSerializeMethod.Content.
+
+
+ On the other hand, when writeable fields/properties are deserialized, new objects are
+ created by using the parameters in the YAML description and assiend to the fields/properties.
+ Such a deserializing method is refered to
+ YamlSerializeMethod.Assign. Writeable properties can be explicitly specified to use
+ YamlSerializeMethod.Content method for
+ deserialization, by adding to its definition.
+
+
+ Another type of serializing method is
+ YamlSerializeMethod.Binary.
+ This method is only applicable to an array-type field / property that contains
+ only value-type members.
+
+ If serializing method is specified,
+ the member is never serialized nor deserialized.
+
+
+ public class Test1
+ {
+ public int PublicProp { get; set; } // processed (by assign)
+ protected int ProtectedProp { get; set; } // Ignored
+ private int PrivateProp { get; set; } // Ignored
+ internal int InternalProp { get; set; } // Ignored
+
+ public int PublicField; // processed (by assign)
+ protected int ProtectedField; // Ignored
+ private int PrivateField; // Ignored
+ internal int InternalField; // Ignored
+
+ public List<string> ClassPropByAssign // processed (by assign)
+ { get; set; }
+
+ public int ReadOnlyValueProp { get; private set; } // Ignored
+ public List<string> ReadOnlyClassProp // processed (by content)
+ { get; private set; }
+
+ [YamlSerialize(YamlSerializeMethod.Content)]
+ public List<string> ClassPropByContent// processed (by content)
+ { get; set; }
+
+ public int[] IntArrayField = // processed (by assign)
+ new int[10];
+
+ [YamlSerialize(YamlSerializeMethod.Binary)]
+ public int[] IntArrayFieldBinary = // processed (as binary)
+ new int[100];
+
+ [YamlSerialize(YamlSerializeMethod.Never)]
+ public int PublicPropHidden; // Ignored
+
+ public Test1()
+ {
+ ClassPropByAssign = new List<string>();
+ ReadOnlyClassProp = new List<string>();
+ ClassPropByContent = new List<string>();
+ }
+ }
+
+ public void TestPropertiesAndFields1()
+ {
+ var test1 = new Test1();
+ test1.ClassPropByAssign.Add("abc");
+ test1.ReadOnlyClassProp.Add("def");
+ test1.ClassPropByContent.Add("ghi");
+ var rand = new Random(0);
+ for ( int i = 0; i < test1.IntArrayFieldBinary.Length; i++ )
+ test1.IntArrayFieldBinary[i] = rand.Next();
+
+ var serializer = new YamlSerializer();
+ string yaml = serializer.Serialize(test1);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test1
+ // PublicProp: 0
+ // ClassPropByAssign:
+ // Capacity: 4
+ // ICollection.Items:
+ // - abc
+ // ReadOnlyClassProp:
+ // Capacity: 4
+ // ICollection.Items:
+ // - def
+ // ClassPropByContent:
+ // Capacity: 4
+ // ICollection.Items:
+ // - ghi
+ // PublicField: 0
+ // IntArrayField: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ // IntArrayFieldBinary: |+2
+ // Gor1XAwenmhGkU5ib9NxR11LXxp1iYlH5LH4c9hImTitWSB9Z78II2UvXSXV99A79fj6UBn3GDzbIbd9
+ // yBDjAyslYm58iGd/NN+tVjuLRCg3cJBo+PWMbIWm9n4AEC0E7LKXWV5HXUNk7I13APEDWFMM/kWTz2EK
+ // s7LzFw2gBjpKugkmQJqIfinpQ1J1yqhhz/XjA3TBxDBsEuwrD+SNevQSqEC+/KRbwgE6D011ACMeyRt0
+ // BOG6ZesRKCtL0YU6tSnLEpgKVBz+R300qD3/W0aZVk+1vHU+auzyGCGUaHCGd6dpRoEhXoIg2m3+AwJX
+ // EJ37T+TA9BuEPJtyGoq+crQMFQtXj1Zriz3HFbReclLvDdVpZlcOHPga/3+3Y509EHZ7UyT7H1xGeJxn
+ // eXPrDDb0Ul04MfZb4UYREOfR3HNzNTUYGRsIPUvHOEW7AaoplIfkVQp19DvGBrBqlP2TZ9atlWUHVdth
+ // 7lIBeIh0wiXxoOpCbQ7qVP9GkioQUrMkOcAJaad3exyZaOsXxznFCA==
+ // ...
+ }
+
+
+
Default values of fields and properties
+
+ is aware of
+ System.ComponentModel.DefaultValueAttribute.
+ So, when a member of a structure / class instance has a value that equals to the default value,
+ the member will not be written in the YAML text.
+
+ It also checkes for the result of ShouldSerializeXXX method. For instance, just before serializing Font
+ property of some type, bool ShouldSerializeFont() method is called if exists. If the method returns false,
+ Font property will not be written in the YAML text. ShouldSerializeXXX method can be non-public.
+
+
+ using System.ComponentModel;
+
+ public class Test2
+ {
+ [DefaultValue(0)]
+ public int Default0 = 0;
+
+ [DefaultValue("a")]
+ public string Defaulta = "a";
+
+ public int DynamicDefault = 0;
+
+ bool ShouldSerializeDynamicDefault()
+ {
+ return Default0 != DynamicDefault;
+ }
+ }
+
+ public void TestDefaultValue()
+ {
+ var test2 = new Test2();
+ var serializer = new YamlSerializer();
+
+ // All properties have defalut values.
+ var yaml = serializer.Serialize(test2);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test2 {}
+ // ...
+
+ test2.Defaulta = "b";
+ yaml = serializer.Serialize(test2);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test2
+ // Defaulta: b
+ // ...
+
+ test2.Defaulta = "a";
+ var yaml = serializer.Serialize(test2);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test2 {}
+ // ...
+
+ test2.DynamicDefault = 1;
+ yaml = serializer.Serialize(test2);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test2
+ // DynamicDefault: 1
+ // ...
+
+ test2.Default0 = 1;
+ yaml = serializer.Serialize(test2);
+ // %YAML 1.2
+ // ---
+ // !YamlSerializerTest.Test2
+ // Default0: 1
+ // ...
+ }
+
+
+
Collection classes
+
+ If an object implements , or
+ the child objects are serialized as well its other public members.
+ Pseudproperty ICollection.Items or IDictionary.Entries appears to hold the child objects.
+
+
Multitime appearance of a same object
+
+ preserve C# objects' graph structure. Namely, when a same objects are refered to
+ from several points in the object graph, the structure is correctly described in YAML text and restored objects
+ preserve the structure. can safely manipulate directly / indirectly self refering
+ objects, too.
+
+
+ public class TestClass
+ {
+ public List<TestClass> list =
+ new List<TestClass>();
+ }
+
+ public class ChildClass: TestClass
+ {
+ }
+
+ void RecursiveObjectsTest()
+ {
+ var a = new TestClass();
+ var b = new ChildClass();
+ a.list.Add(a);
+ a.list.Add(a);
+ a.list.Add(b);
+ a.list.Add(a);
+ a.list.Add(b);
+ b.list.Add(a);
+ var serializer = new YamlSerializer();
+ string yaml = serializer.Serialize(a);
+ // %YAML 1.2
+ // ---
+ // &A !TestClass
+ // list:
+ // Capacity: 8
+ // ICollection.Items:
+ // - *A
+ // - *A
+ // - &B !ChildClass
+ // list:
+ // Capacity: 4
+ // ICollection.Items:
+ // - *A
+ // - *A
+ // - *B
+ // ...
+
+ var restored = (TestClass)serializer.Deserialize(yaml)[0];
+ Assert.IsTrue(restored == restored.list[0]);
+ Assert.IsTrue(restored == restored.list[1]);
+ Assert.IsTrue(restored == restored.list[3]);
+ Assert.IsTrue(restored == restored.list[5]);
+ Assert.IsTrue(restored.list[2] == restored.list[4]);
+ }
+
+
+ This is not the case if the object is . Same instances of
+ are repeatedly written in a YAML text and restored as different
+ instance of when deserialized, unless the content of the string
+ is extremely long (longer than 999 chars).
+
+
+ // 1000 chars
+ string long_str =
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
+ string short_str = "12345";
+ object obj = new object[] { long_str, long_str, short_str, short_str };
+ var serializer = new YamlSerializer();
+ string yaml = serializer.Serialize(obj);
+ // %YAML 1.2
+ // ---
+ // - &A 01234567890123456789012345678901234567890123456789 ... (snip) ... 789
+ // - *A
+ // - "12345"
+ // - "12345"
+ // ...
+
+
+
YAML text written / read by
+
+ When serializing, intelligently uses various YAML 1.2 styles,
+ namely the block style, flow style, explicit mapping and implicit mapping, to maximize readability
+ of the YAML stream.
+
+
+ [Flags]
+ enum TestEnum: uint
+ {
+ abc = 1,
+ あいう = 2
+ }
+
+ public void TestVariousFormats()
+ {
+ var dict = new Dictionary<object, object>();
+ dict.Add(new object[] { 1, "a" }, new object());
+ object obj = new object[]{
+ dict,
+ null,
+ "abc",
+ "1",
+ "a ",
+ "- a",
+ "abc\n",
+ "abc\ndef\n",
+ "abc\ndef\nghi",
+ new double[]{ 1.1, 2, -3, 3.12, 13.2 },
+ new int[,] { { 1, 3}, {4, 5}, {10, 1} },
+ new string[]{ "jkl", "mno\npqr" },
+ new System.Drawing.Point(1,3),
+ TestEnum.abc,
+ TestEnum.abc | TestEnum.あいう,
+ };
+ var config = new YamlConfig();
+ config.ExplicitlyPreserveLineBreaks = false;
+ var serializer = new YamlSerializer(config);
+ string yaml = serializer.Serialize(obj);
+
+ // %YAML 1.2
+ // ---
+ // - !<!System.Collections.Generic.Dictionary%602[[System.Object,...],[System.Object,...]]>
+ // Keys: {}
+ // Values: {}
+ // IDictionary.Entries:
+ // ? - 1
+ // - a
+ // : !System.Object {}
+ // - null
+ // - abc
+ // - "1"
+ // - "a "
+ // - "- a"
+ // - "abc\n"
+ // - |+2
+ // abc
+ // def
+ // - |-2
+ // abc
+ // def
+ // ghi
+ // - !<!System.Double[]> [1.1, 2, -3, 3.12, 13.2]
+ // - !<!System.Int32[,]> [[1, 3], [4, 5], [10, 1]]
+ // - !<!System.String[]>
+ // - jkl
+ // - |-2
+ // mno
+ // pqr
+ // - !System.Drawing.Point 1, 3
+ // - !TestEnum abc
+ // - !TestEnum abc, あいう
+ // ...
+ }
+
+
+ When deserializing, accepts any valid YAML 1.2 documents.
+ TAG directives, comments, flow / block styles, implicit / explicit mappings can be freely used
+ to express valid C# objects. Namely, the members of the array can be given eighter in a flow style
+ or in a block style.
+
+
+ By default, outputs a YAML stream with line break of "\r\n".
+ This can be customized either by setting YamlNode.DefaultConfig.LineBreakForOutput or
+ by giving an instance of to the
+ constructor.
+
+
+
+ var serializer = new YamlSerializer();
+ var yaml = serializer.Serialize("abc");
+ // %YAML 1.2\r\n // line breaks are explicitly shown in this example
+ // ---\r\n
+ // abc\r\n
+ // ...\r\n
+
+ var config = new YamlConfig();
+ config.LineBreakForOutput = "\n";
+ serializer = new YamlSerializer(config);
+ var yaml = serializer.Serialize("abc");
+ // %YAML 1.2\n
+ // ---\n
+ // abc\n
+ // ...\n
+
+ YamlNode.DefaultConfig.LineBreakForOutput = "\n";
+
+ var serializer = new YamlSerializer();
+ serializer = new YamlSerializer();
+ var yaml = serializer.Serialize("abc");
+ // %YAML 1.2\n
+ // ---\n
+ // abc\n
+ // ...\n
+
+
+
Line breaks in YAML text
+
+ By default, line breaks in multi line values are explicitly presented as escaped style.
+ Although, this makes the resulting YAML stream hard to read, it is necessary to preserve
+ the exact content of the string because the YAML specification requires that a YAML parser
+ must normalize evely line break that is not escaped in a YAML document to be a single line
+ feed "\n" when deserializing.
+
+ In order to have the YAML documents easy to be read, set
+ YamlConfig.ExplicitlyPreserveLineBreaks
+ false. Then, the multiline values of will be written in literal style.
+
+ Of course, it makes all the line breaks to be normalized into a single line feeds "\n".
+
+
+ var serializer = new YamlSerializer();
+ var text = "abc\r\n def\r\nghi\r\n";
+ // abc
+ // def
+ // ghi
+
+ // By default, line breaks explicitly appears in escaped form.
+ var yaml = serializer.Serialize(text);
+ // %YAML 1.2
+ // ---
+ // "abc\r\n\
+ // \ def\r\n\
+ // ghi\r\n"
+ // ...
+
+ // Original line breaks are preserved
+ var restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\r\n def\r\nghi\r\n"
+
+
+ YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false;
+
+ // Literal style is easier to be read.
+ var yaml = serializer.Serialize(text);
+ // %YAML 1.2
+ // ---
+ // |+2
+ // abc
+ // def
+ // ghi
+ // ...
+
+ // Original line breaks are lost.
+ var restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\n def\nghi\n"
+
+
+ This library offers two work arounds for this problem, although both of which
+ violates the official behavior of a YAML parser defined in the YAML specification.
+
+ One is to set YamlConfig.LineBreakForInput
+ to be "\r\n". Then, the YAML parser normalizes all line breaks into "\r\n" instead of "\n".
+
+ The other is to set YamlConfig.NormalizeLineBreaks
+ false. It disables the line break normalization both at output and at input. Namely, the line breaks are
+ written and read as-is when serialized / deserialized.
+
+
+ var serializer = new YamlSerializer();
+
+ // text with mixed line breaks
+ var text = "abc\r def\nghi\r\n";
+ // abc\r // line breaks are explicitly shown in this example
+ // def\n
+ // ghi\r\n
+
+ YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false;
+
+ // By default, all line breaks are normalized to "\r\n" when serialized.
+ var yaml = serializer.Serialize(text);
+ // %YAML 1.2\r\n
+ // ---\r\n
+ // |+2\r\n
+ // abc\r\n
+ // def\r\n
+ // ghi\r\n
+ // ...\r\n
+
+ // When deserialized, line breaks are normalized into "\n".
+ var restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\n def\nghi\n"
+
+ // Line breaks are normalized into "\r\n" instead of "\n".
+ YamlNode.DefaultConfig.LineBreakForInput = "\r\n";
+ restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\r\n def\r\nghi\r\n"
+
+ // Line breaks are written as is,
+ YamlNode.DefaultConfig.NormalizeLineBreaks = false;
+ var yaml = serializer.Serialize(text);
+ // %YAML 1.2\r\n
+ // ---\r\n
+ // |+2\r\n
+ // abc\r
+ // def\n
+ // ghi\r\n
+ // ...\r\n
+
+ // and are read as is.
+ restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\r def\nghi\r\n"
+
+ // Note that when the line breaks of YAML stream is changed
+ // between serialization and deserialization, the original
+ // line breaks are lost.
+ yaml = yaml.Replace("\r\n", "\n").Replace("\r", "\n");
+ restored = (string)serializer.Deserialize(yaml)[0];
+ // "abc\n def\nghi\n"
+
+
+ It is repeatedly stated that although these two options are useful in many situation,
+ they makes the YAML parser violate the YAML specification.
+
+
+
+
+
+ Initialize an instance of that obeys
+ .
+
+
+
+
+ Initialize an instance of with custom .
+
+ Custom to customize serialization.
+
+
+
+ Serialize C# object into YAML text.
+
+ Object to be serialized.
+ YAML text.
+
+
+
+ Serialize C# object into YAML text and write it into a .
+
+ A to which the YAML text is written.
+ Object to be serialized.
+
+
+
+ Serialize C# object into YAML text and write it into a .
+
+ A to which the YAML text is written.
+ Object to be serialized.
+
+
+
+ Serialize C# object into YAML text and save it into a file named as .
+
+ A file name to which the YAML text is written.
+ Object to be serialized.
+
+
+
+ Deserialize C# object(s) from a YAML text. Since a YAML text can contain multiple YAML documents, each of which
+ represents a C# object, the result is returned as an array of .
+
+ A YAML text from which C# objects are deserialized.
+ Expected type(s) of the root object(s) in the YAML stream.
+ C# object(s) deserialized from YAML text.
+
+
+
+ Deserialize C# object(s) from a YAML text in a .
+ Since a YAML text can contain multiple YAML documents, each of which
+ represents a C# object, the result is returned as an array of .
+
+ A that contains YAML text from which C# objects are deserialized.
+ Expected type(s) of the root object(s) in the YAML stream.
+ C# object(s) deserialized from YAML text.
+
+
+
+ Deserialize C# object(s) from a YAML text in a .
+ Since a YAML text can contain multiple YAML documents, each of which
+ represents a C# object, the result is returned as an array of .
+
+ A that contains YAML text from which C# objects are deserialized.
+ Expected type(s) of the root object(s) in the YAML stream.
+ C# object(s) deserialized from YAML text.
+
+
+
+ Deserialize C# object(s) from a YAML text in a file named as .
+ Since a YAML text can contain multiple YAML documents, each of which
+ represents a C# object, the result is returned as an array of .
+
+ The name of a file that contains YAML text from which C# objects are deserialized.
+ Expected type(s) of the root object(s) in the YAML stream.
+ C# object(s) deserialized from YAML text.
+
+
+
+ Add .DoFunction method to string
+
+
+
+
+ Short expression of string.Format(XXX, arg1, arg2, ...)
+
+
+
+
+
+
+
+ Specify the way to store a property or field of some class or structure.
+ See for detail.
+
+
+
+
+
+
+ The property / field will not be stored.
+
+
+
+
+ When restored, new object is created by using the parameters in
+ the YAML data and assigned to the property / field. When the
+ property / filed is writeable, this is the default.
+
+
+
+
+ Only valid for a property / field that has a class or struct type.
+ When restored, instead of recreating the whole class or struct,
+ the members are independently restored. When the property / field
+ is not writeable this is the default.
+
+
+
+
+ Only valid for a property / field that has an array type of a
+ some value type. The content of the array is stored in a binary
+ format encoded in base64 style.
+
+
+
+
+ Specify the way to store a property or field of some class or structure.
+
+ See for detail.
+
+
+
+
+
+
+ Specify the way to store a property or field of some class or structure.
+
+ See for detail.
+
+
+
+
+
+ - Never: The property / field will not be stored.
+
+
+ - Assign: When restored, new object is created by using the parameters in
+ the YAML data and assigned to the property / field. When the
+ property / filed is writeable, this is the default.
+
+
+ - Content: Only valid for a property / field that has a class or struct type.
+ When restored, instead of recreating the whole class or struct,
+ the members are independently restored. When the property / field
+ is not writeable this is the default.
+
+
+ - Binary: Only valid for a property / field that has an array type of a
+ some value type. The content of the array is stored in a binary
+ format encoded in base64 style.
+
+
+
Converts C# object to YamlNode
@@ -855,6 +1786,52 @@
Column in a text.
+
+
+ Converts various types to / from string.
+ I don't remember why this class was needed....
+
+
+
+ object obj = GetObjectToConvert();
+
+ // Check if the type has [TypeConverter] attribute.
+ if( EasyTypeConverter.IsTypeConverterSpecified(type) ) {
+
+ // Convert the object to string.
+ string s = EasyTypeConverter.ConvertToString(obj);
+
+ // Convert the string to an object of the spific type.
+ object restored = EasyTypeConverter.ConvertFromString(s, type);
+
+ Assert.AreEqual(obj, restored);
+
+ }
+
+
+
+
+
+ Construct YAML node tree that represents a given C# object.
+
+
+
+
+ Construct YAML node tree that represents a given C# object.
+
+ to be converted to C# object.
+ to customize serialization.
+
+
+
+
+ Construct YAML node tree that represents a given C# object.
+
+ to be converted to C# object.
+ Expected type for the root object.
+ to customize serialization.
+
+
Validates a text as a global tag in YAML.
@@ -874,74 +1851,6 @@
Not used in this parser
-
-
- Dictionary that automatically rehash when the content of a key is changed.
- Keys of this dictionary must implement .
- It also call back item addition and removal by and
- events.
-
- Type of key. Must implements .
- Type of value.
-
-
-
- A dictionary that returns or
- from hash code. This is the main repository that stores the pairs.
- If there are several entries that have same hash code for thir keys,
- a is stored to hold all those entries.
- Otherwise, a is stored.
-
-
-
-
- A dictionary that returns hash code from the key reference.
- The key must be the instance that
- to one exsisting in the dictionary.
-
-
- We store the hashes correspoinding to each key. So that when rehash,
- we can find old hash code to quickly find the entry for the key.
- It is also used to remember the number of keys exists in the dictionary.
-
-
-
-
- Recalc hash key of the .
-
- The key to be rehash. The key must be the instance that
- to one exsisting in the dictionary.
-
-
-
- Try to find entry for key (and value).
-
- key to find
- if true, value matters
- value to find
- key not found
- hash hit one entry and key found
- hash hit several entries and key found
-
-
-
- Try to find entry for key (and value).
-
- key to find
- if true, value matters
- value to find
- hash not found
- hash hit one entry but key not found
- hash hit one entry and key found
- hash hit several entries but key not found
- hash hit several entries and key found
-
-
-
- Collection that is readonly and invalidated when an item is
- added to or removed from the dictionary.
-
- A text parser for
@@ -1095,67 +2004,6 @@
[23]
-
-
- Construct YAML node tree that represents a given C# object.
-
-
-
-
- Construct YAML node tree that represents a given C# object.
-
- to be converted to C# object.
- to customize serialization.
-
-
-
-
- Construct YAML node tree that represents a given C# object.
-
- to be converted to C# object.
- Expected type for the root object.
- to customize serialization.
-
-
-
-
- Add string class two methods: .UriEscape(), .UriUnescape()
-
- Charset that is not escaped is represented NonUriChar member.
-
- NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&=$,\[\]]");
-
-
-
-
- Escape the string in URI encoding format.
-
- String to be escaped.
- Escaped string.
-
-
-
- Escape the string in URI encoding format.
-
- String to be escaped.
- Escaped string.
-
-
-
- Unescape the string escaped in URI encoding format.
-
- String to be unescape.
- Unescaped string.
-
-
-
- Escape / Unescape string in URI encoding format
-
- Charset that is not escaped is represented NonUriChar member.
-
- NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&=$,\[\]]");
-
-
Reset();
@@ -1164,62 +2012,6 @@
verbatim_tag = Resolve(tag_handle, tag_name);
-
-
- Converts YamlNode tree into yaml text.
-
-
-
- YamlNode node;
- YamlPresenter.ToYaml(node);
-
- YamlNode node1;
- YamlNode node2;
- YamlNode node3;
- YamlPresenter.ToYaml(node1, node2, node3);
-
-
-
-
-
-
- object に代入されたクラスや構造体のメンバーに、リフレクションを
- 解して簡単にアクセスできるようにしたクラス
-
- アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が
- 期待できる
-
-
-
-
- Caches ObjectMemberAccessor instances for reuse.
-
-
-
-
-
- 指定した型へのアクセス方法を表すインスタンスを返す
- キャッシュに存在すればそれを返す
- キャッシュに存在しなければ新しく作って返す
- 作った物はキャッシュされる
-
- クラスまたは構造体を表す型情報
-
-
-
-
- メンバ名と Accessor のペアを巡回する
-
-
-
-
-
- メンバへの読み書きを行うことができる
-
- オブジェクト
- メンバの名前
-
- Configuration to customize YAML serialization.
@@ -2720,937 +3512,6 @@
The number of child nodes of the sequence.
-
-
- class has instance methods and ,
- with which C# native objects can be converted into / from YAML text without any preparations.
-
- var serializer = new YamlSerializer();
- object obj = GetObjectToSerialize();
- string yaml = serializer.Serialize(obj);
- object restored = serializer.Deserialize(yaml);
- Assert.AreEqual(obj, restored);
-
-
-
-
-
What kind of objects can be serialized?
-
- can serialize / deserialize native C# objects of primitive types
- (bool, char, int,...), enums, built-in non-primitive types (string, decimal), structures,
- classes and arrays of these types.
-
-
- On the other hand, it does not deal with IntPtr (which is a primitive type, though) and
- pointer types (void*, int*, ...) because these types are, by their nature, not persistent.
-
-
-
- Classes without a default constructor can be deserialized only when the way of activating an instance
- is explicitly specified by .
-
-
-
- object obj = new object[]{
- null,
- "abc",
- true,
- 1,
- (Byte)1,
- 1.0,
- "1",
- new double[]{ 1.1, 2, -3 },
- new string[]{ "def", "ghi", "1" },
- new System.Drawing.Point(1,3),
- new System.Drawing.SolidBrush(Color.Blue)
- };
-
- var serializer = new YamlSerializer();
- string yaml = serializer.Serialize(obj);
- // %YAML 1.2
- // ---
- // - null
- // - abc
- // - True
- // - 1
- // - !System.Byte 1
- // - !!float 1
- // - "1"
- // - !<!System.Double[]%gt; [1.1, 2, -3]
- // - !<!System.String[]%gt;
- // - def
- // - ghi
- // - !System.Drawing.Point 1, 3
- // - !System.Drawing.SolidBrush
- // Color: Blue
- // ...
-
- object restored;
- try {
- restored = YamlSerializer.Deserialize(yaml)[0];
- } catch(MissingMethodException) {
- // default constructor is missing for SolidBrush
- }
-
- // Let the library know how to activate an instance of SolidBrush.
- YamlNode.DefaultConfig.AddActivator<System.Drawing.SolidBrush>(
- () => new System.Drawing.SolidBrush(Color.Black /* dummy */));
-
- // Then, all the objects can be restored correctly.
- restored = serializer.Deserialize(yaml)[0];
-
-
- A YAML document generated by always have a %YAML directive and
- explicit document start ("---") and end ("...") marks.
- This allows several documents to be written in a single YAML stream.
-
-
- var yaml = "";
- var serializer = new YamlSerializer();
- yaml += serializer.Serialize("a");
- yaml += serializer.Serialize(1);
- yaml += serializer.Serialize(1.1);
- // %YAML 1.2
- // ---
- // a
- // ...
- // %YAML 1.2
- // ---
- // 1
- // ...
- // %YAML 1.2
- // ---
- // 1.1
- // ...
-
- object[] objects = serializer.Deserialize(yaml);
- // objects[0] == "a"
- // objects[1] == 1
- // objects[2] == 1.1
-
-
- Since a YAML stream can consist of multiple YAML documents as above,
- returns an array of .
-
-
-
Serializing structures and classes
-
- For structures and classes, by default, all public fields and public properties are
- serialized. Note that protected / private members are always ignored.
-
-
Serialization methods
-
- Readonly value-type members are also ignored because there is no way to
- assign a new value to them on deserialization, while readonly class-type members
- are serialized. When deserializing, instead of creating a new object and assigning it
- to the member, the child members of such class instance are restored independently.
- Such a deserializing method is refered to
- YamlSerializeMethod.Content.
-
-
- On the other hand, when writeable fields/properties are deserialized, new objects are
- created by using the parameters in the YAML description and assiend to the fields/properties.
- Such a deserializing method is refered to
- YamlSerializeMethod.Assign. Writeable properties can be explicitly specified to use
- YamlSerializeMethod.Content method for
- deserialization, by adding to its definition.
-
-
- Another type of serializing method is
- YamlSerializeMethod.Binary.
- This method is only applicable to an array-type field / property that contains
- only value-type members.
-
- If serializing method is specified,
- the member is never serialized nor deserialized.
-
-
- public class Test1
- {
- public int PublicProp { get; set; } // processed (by assign)
- protected int ProtectedProp { get; set; } // Ignored
- private int PrivateProp { get; set; } // Ignored
- internal int InternalProp { get; set; } // Ignored
-
- public int PublicField; // processed (by assign)
- protected int ProtectedField; // Ignored
- private int PrivateField; // Ignored
- internal int InternalField; // Ignored
-
- public List<string> ClassPropByAssign // processed (by assign)
- { get; set; }
-
- public int ReadOnlyValueProp { get; private set; } // Ignored
- public List<string> ReadOnlyClassProp // processed (by content)
- { get; private set; }
-
- [YamlSerialize(YamlSerializeMethod.Content)]
- public List<string> ClassPropByContent// processed (by content)
- { get; set; }
-
- public int[] IntArrayField = // processed (by assign)
- new int[10];
-
- [YamlSerialize(YamlSerializeMethod.Binary)]
- public int[] IntArrayFieldBinary = // processed (as binary)
- new int[100];
-
- [YamlSerialize(YamlSerializeMethod.Never)]
- public int PublicPropHidden; // Ignored
-
- public Test1()
- {
- ClassPropByAssign = new List<string>();
- ReadOnlyClassProp = new List<string>();
- ClassPropByContent = new List<string>();
- }
- }
-
- public void TestPropertiesAndFields1()
- {
- var test1 = new Test1();
- test1.ClassPropByAssign.Add("abc");
- test1.ReadOnlyClassProp.Add("def");
- test1.ClassPropByContent.Add("ghi");
- var rand = new Random(0);
- for ( int i = 0; i < test1.IntArrayFieldBinary.Length; i++ )
- test1.IntArrayFieldBinary[i] = rand.Next();
-
- var serializer = new YamlSerializer();
- string yaml = serializer.Serialize(test1);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test1
- // PublicProp: 0
- // ClassPropByAssign:
- // Capacity: 4
- // ICollection.Items:
- // - abc
- // ReadOnlyClassProp:
- // Capacity: 4
- // ICollection.Items:
- // - def
- // ClassPropByContent:
- // Capacity: 4
- // ICollection.Items:
- // - ghi
- // PublicField: 0
- // IntArrayField: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- // IntArrayFieldBinary: |+2
- // Gor1XAwenmhGkU5ib9NxR11LXxp1iYlH5LH4c9hImTitWSB9Z78II2UvXSXV99A79fj6UBn3GDzbIbd9
- // yBDjAyslYm58iGd/NN+tVjuLRCg3cJBo+PWMbIWm9n4AEC0E7LKXWV5HXUNk7I13APEDWFMM/kWTz2EK
- // s7LzFw2gBjpKugkmQJqIfinpQ1J1yqhhz/XjA3TBxDBsEuwrD+SNevQSqEC+/KRbwgE6D011ACMeyRt0
- // BOG6ZesRKCtL0YU6tSnLEpgKVBz+R300qD3/W0aZVk+1vHU+auzyGCGUaHCGd6dpRoEhXoIg2m3+AwJX
- // EJ37T+TA9BuEPJtyGoq+crQMFQtXj1Zriz3HFbReclLvDdVpZlcOHPga/3+3Y509EHZ7UyT7H1xGeJxn
- // eXPrDDb0Ul04MfZb4UYREOfR3HNzNTUYGRsIPUvHOEW7AaoplIfkVQp19DvGBrBqlP2TZ9atlWUHVdth
- // 7lIBeIh0wiXxoOpCbQ7qVP9GkioQUrMkOcAJaad3exyZaOsXxznFCA==
- // ...
- }
-
-
-
Default values of fields and properties
-
- is aware of
- System.ComponentModel.DefaultValueAttribute.
- So, when a member of a structure / class instance has a value that equals to the default value,
- the member will not be written in the YAML text.
-
- It also checkes for the result of ShouldSerializeXXX method. For instance, just before serializing Font
- property of some type, bool ShouldSerializeFont() method is called if exists. If the method returns false,
- Font property will not be written in the YAML text. ShouldSerializeXXX method can be non-public.
-
-
- using System.ComponentModel;
-
- public class Test2
- {
- [DefaultValue(0)]
- public int Default0 = 0;
-
- [DefaultValue("a")]
- public string Defaulta = "a";
-
- public int DynamicDefault = 0;
-
- bool ShouldSerializeDynamicDefault()
- {
- return Default0 != DynamicDefault;
- }
- }
-
- public void TestDefaultValue()
- {
- var test2 = new Test2();
- var serializer = new YamlSerializer();
-
- // All properties have defalut values.
- var yaml = serializer.Serialize(test2);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test2 {}
- // ...
-
- test2.Defaulta = "b";
- yaml = serializer.Serialize(test2);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test2
- // Defaulta: b
- // ...
-
- test2.Defaulta = "a";
- var yaml = serializer.Serialize(test2);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test2 {}
- // ...
-
- test2.DynamicDefault = 1;
- yaml = serializer.Serialize(test2);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test2
- // DynamicDefault: 1
- // ...
-
- test2.Default0 = 1;
- yaml = serializer.Serialize(test2);
- // %YAML 1.2
- // ---
- // !YamlSerializerTest.Test2
- // Default0: 1
- // ...
- }
-
-
-
Collection classes
-
- If an object implements , or
- the child objects are serialized as well its other public members.
- Pseudproperty ICollection.Items or IDictionary.Entries appears to hold the child objects.
-
-
Multitime appearance of a same object
-
- preserve C# objects' graph structure. Namely, when a same objects are refered to
- from several points in the object graph, the structure is correctly described in YAML text and restored objects
- preserve the structure. can safely manipulate directly / indirectly self refering
- objects, too.
-
-
- public class TestClass
- {
- public List<TestClass> list =
- new List<TestClass>();
- }
-
- public class ChildClass: TestClass
- {
- }
-
- void RecursiveObjectsTest()
- {
- var a = new TestClass();
- var b = new ChildClass();
- a.list.Add(a);
- a.list.Add(a);
- a.list.Add(b);
- a.list.Add(a);
- a.list.Add(b);
- b.list.Add(a);
- var serializer = new YamlSerializer();
- string yaml = serializer.Serialize(a);
- // %YAML 1.2
- // ---
- // &A !TestClass
- // list:
- // Capacity: 8
- // ICollection.Items:
- // - *A
- // - *A
- // - &B !ChildClass
- // list:
- // Capacity: 4
- // ICollection.Items:
- // - *A
- // - *A
- // - *B
- // ...
-
- var restored = (TestClass)serializer.Deserialize(yaml)[0];
- Assert.IsTrue(restored == restored.list[0]);
- Assert.IsTrue(restored == restored.list[1]);
- Assert.IsTrue(restored == restored.list[3]);
- Assert.IsTrue(restored == restored.list[5]);
- Assert.IsTrue(restored.list[2] == restored.list[4]);
- }
-
-
- This is not the case if the object is . Same instances of
- are repeatedly written in a YAML text and restored as different
- instance of when deserialized, unless the content of the string
- is extremely long (longer than 999 chars).
-
-
- // 1000 chars
- string long_str =
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
- string short_str = "12345";
- object obj = new object[] { long_str, long_str, short_str, short_str };
- var serializer = new YamlSerializer();
- string yaml = serializer.Serialize(obj);
- // %YAML 1.2
- // ---
- // - &A 01234567890123456789012345678901234567890123456789 ... (snip) ... 789
- // - *A
- // - "12345"
- // - "12345"
- // ...
-
-
-
YAML text written / read by
-
- When serializing, intelligently uses various YAML 1.2 styles,
- namely the block style, flow style, explicit mapping and implicit mapping, to maximize readability
- of the YAML stream.
-
-
- [Flags]
- enum TestEnum: uint
- {
- abc = 1,
- あいう = 2
- }
-
- public void TestVariousFormats()
- {
- var dict = new Dictionary<object, object>();
- dict.Add(new object[] { 1, "a" }, new object());
- object obj = new object[]{
- dict,
- null,
- "abc",
- "1",
- "a ",
- "- a",
- "abc\n",
- "abc\ndef\n",
- "abc\ndef\nghi",
- new double[]{ 1.1, 2, -3, 3.12, 13.2 },
- new int[,] { { 1, 3}, {4, 5}, {10, 1} },
- new string[]{ "jkl", "mno\npqr" },
- new System.Drawing.Point(1,3),
- TestEnum.abc,
- TestEnum.abc | TestEnum.あいう,
- };
- var config = new YamlConfig();
- config.ExplicitlyPreserveLineBreaks = false;
- var serializer = new YamlSerializer(config);
- string yaml = serializer.Serialize(obj);
-
- // %YAML 1.2
- // ---
- // - !<!System.Collections.Generic.Dictionary%602[[System.Object,...],[System.Object,...]]>
- // Keys: {}
- // Values: {}
- // IDictionary.Entries:
- // ? - 1
- // - a
- // : !System.Object {}
- // - null
- // - abc
- // - "1"
- // - "a "
- // - "- a"
- // - "abc\n"
- // - |+2
- // abc
- // def
- // - |-2
- // abc
- // def
- // ghi
- // - !<!System.Double[]> [1.1, 2, -3, 3.12, 13.2]
- // - !<!System.Int32[,]> [[1, 3], [4, 5], [10, 1]]
- // - !<!System.String[]>
- // - jkl
- // - |-2
- // mno
- // pqr
- // - !System.Drawing.Point 1, 3
- // - !TestEnum abc
- // - !TestEnum abc, あいう
- // ...
- }
-
-
- When deserializing, accepts any valid YAML 1.2 documents.
- TAG directives, comments, flow / block styles, implicit / explicit mappings can be freely used
- to express valid C# objects. Namely, the members of the array can be given eighter in a flow style
- or in a block style.
-
-
- By default, outputs a YAML stream with line break of "\r\n".
- This can be customized either by setting YamlNode.DefaultConfig.LineBreakForOutput or
- by giving an instance of to the
- constructor.
-
-
-
- var serializer = new YamlSerializer();
- var yaml = serializer.Serialize("abc");
- // %YAML 1.2\r\n // line breaks are explicitly shown in this example
- // ---\r\n
- // abc\r\n
- // ...\r\n
-
- var config = new YamlConfig();
- config.LineBreakForOutput = "\n";
- serializer = new YamlSerializer(config);
- var yaml = serializer.Serialize("abc");
- // %YAML 1.2\n
- // ---\n
- // abc\n
- // ...\n
-
- YamlNode.DefaultConfig.LineBreakForOutput = "\n";
-
- var serializer = new YamlSerializer();
- serializer = new YamlSerializer();
- var yaml = serializer.Serialize("abc");
- // %YAML 1.2\n
- // ---\n
- // abc\n
- // ...\n
-
-
-
Line breaks in YAML text
-
- By default, line breaks in multi line values are explicitly presented as escaped style.
- Although, this makes the resulting YAML stream hard to read, it is necessary to preserve
- the exact content of the string because the YAML specification requires that a YAML parser
- must normalize evely line break that is not escaped in a YAML document to be a single line
- feed "\n" when deserializing.
-
- In order to have the YAML documents easy to be read, set
- YamlConfig.ExplicitlyPreserveLineBreaks
- false. Then, the multiline values of will be written in literal style.
-
- Of course, it makes all the line breaks to be normalized into a single line feeds "\n".
-
-
- var serializer = new YamlSerializer();
- var text = "abc\r\n def\r\nghi\r\n";
- // abc
- // def
- // ghi
-
- // By default, line breaks explicitly appears in escaped form.
- var yaml = serializer.Serialize(text);
- // %YAML 1.2
- // ---
- // "abc\r\n\
- // \ def\r\n\
- // ghi\r\n"
- // ...
-
- // Original line breaks are preserved
- var restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\r\n def\r\nghi\r\n"
-
-
- YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false;
-
- // Literal style is easier to be read.
- var yaml = serializer.Serialize(text);
- // %YAML 1.2
- // ---
- // |+2
- // abc
- // def
- // ghi
- // ...
-
- // Original line breaks are lost.
- var restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\n def\nghi\n"
-
-
- This library offers two work arounds for this problem, although both of which
- violates the official behavior of a YAML parser defined in the YAML specification.
-
- One is to set YamlConfig.LineBreakForInput
- to be "\r\n". Then, the YAML parser normalizes all line breaks into "\r\n" instead of "\n".
-
- The other is to set YamlConfig.NormalizeLineBreaks
- false. It disables the line break normalization both at output and at input. Namely, the line breaks are
- written and read as-is when serialized / deserialized.
-
-
- var serializer = new YamlSerializer();
-
- // text with mixed line breaks
- var text = "abc\r def\nghi\r\n";
- // abc\r // line breaks are explicitly shown in this example
- // def\n
- // ghi\r\n
-
- YamlNode.DefaultConfig.ExplicitlyPreserveLineBreaks = false;
-
- // By default, all line breaks are normalized to "\r\n" when serialized.
- var yaml = serializer.Serialize(text);
- // %YAML 1.2\r\n
- // ---\r\n
- // |+2\r\n
- // abc\r\n
- // def\r\n
- // ghi\r\n
- // ...\r\n
-
- // When deserialized, line breaks are normalized into "\n".
- var restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\n def\nghi\n"
-
- // Line breaks are normalized into "\r\n" instead of "\n".
- YamlNode.DefaultConfig.LineBreakForInput = "\r\n";
- restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\r\n def\r\nghi\r\n"
-
- // Line breaks are written as is,
- YamlNode.DefaultConfig.NormalizeLineBreaks = false;
- var yaml = serializer.Serialize(text);
- // %YAML 1.2\r\n
- // ---\r\n
- // |+2\r\n
- // abc\r
- // def\n
- // ghi\r\n
- // ...\r\n
-
- // and are read as is.
- restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\r def\nghi\r\n"
-
- // Note that when the line breaks of YAML stream is changed
- // between serialization and deserialization, the original
- // line breaks are lost.
- yaml = yaml.Replace("\r\n", "\n").Replace("\r", "\n");
- restored = (string)serializer.Deserialize(yaml)[0];
- // "abc\n def\nghi\n"
-
-
- It is repeatedly stated that although these two options are useful in many situation,
- they makes the YAML parser violate the YAML specification.
-
-
-
-
-
- Initialize an instance of that obeys
- .
-
-
-
-
- Initialize an instance of with custom .
-
- Custom to customize serialization.
-
-
-
- Serialize C# object into YAML text.
-
- Object to be serialized.
- YAML text.
-
-
-
- Serialize C# object into YAML text and write it into a .
-
- A to which the YAML text is written.
- Object to be serialized.
-
-
-
- Serialize C# object into YAML text and write it into a .
-
- A to which the YAML text is written.
- Object to be serialized.
-
-
-
- Serialize C# object into YAML text and save it into a file named as .
-
- A file name to which the YAML text is written.
- Object to be serialized.
-
-
-
- Deserialize C# object(s) from a YAML text. Since a YAML text can contain multiple YAML documents, each of which
- represents a C# object, the result is returned as an array of .
-
- A YAML text from which C# objects are deserialized.
- Expected type(s) of the root object(s) in the YAML stream.
- C# object(s) deserialized from YAML text.
-
-
-
- Deserialize C# object(s) from a YAML text in a .
- Since a YAML text can contain multiple YAML documents, each of which
- represents a C# object, the result is returned as an array of .
-
- A that contains YAML text from which C# objects are deserialized.
- Expected type(s) of the root object(s) in the YAML stream.
- C# object(s) deserialized from YAML text.
-
-
-
- Deserialize C# object(s) from a YAML text in a .
- Since a YAML text can contain multiple YAML documents, each of which
- represents a C# object, the result is returned as an array of .
-
- A that contains YAML text from which C# objects are deserialized.
- Expected type(s) of the root object(s) in the YAML stream.
- C# object(s) deserialized from YAML text.
-
-
-
- Deserialize C# object(s) from a YAML text in a file named as .
- Since a YAML text can contain multiple YAML documents, each of which
- represents a C# object, the result is returned as an array of .
-
- The name of a file that contains YAML text from which C# objects are deserialized.
- Expected type(s) of the root object(s) in the YAML stream.
- C# object(s) deserialized from YAML text.
-
-
-
- Add .DoFunction method to string
-
-
-
-
- Short expression of string.Format(XXX, arg1, arg2, ...)
-
-
-
-
-
-
-
- Specify the way to store a property or field of some class or structure.
- See for detail.
-
-
-
-
-
-
- The property / field will not be stored.
-
-
-
-
- When restored, new object is created by using the parameters in
- the YAML data and assigned to the property / field. When the
- property / filed is writeable, this is the default.
-
-
-
-
- Only valid for a property / field that has a class or struct type.
- When restored, instead of recreating the whole class or struct,
- the members are independently restored. When the property / field
- is not writeable this is the default.
-
-
-
-
- Only valid for a property / field that has an array type of a
- some value type. The content of the array is stored in a binary
- format encoded in base64 style.
-
-
-
-
- Specify the way to store a property or field of some class or structure.
-
- See for detail.
-
-
-
-
-
-
- Specify the way to store a property or field of some class or structure.
-
- See for detail.
-
-
-
-
-
- - Never: The property / field will not be stored.
-
-
- - Assign: When restored, new object is created by using the parameters in
- the YAML data and assigned to the property / field. When the
- property / filed is writeable, this is the default.
-
-
- - Content: Only valid for a property / field that has a class or struct type.
- When restored, instead of recreating the whole class or struct,
- the members are independently restored. When the property / field
- is not writeable this is the default.
-
-
- - Binary: Only valid for a property / field that has an array type of a
- some value type. The content of the array is stored in a binary
- format encoded in base64 style.
-
-
-
-
-
- Type 関連のユーティリティメソッド
-
-
-
- Type type;
- AttributeType attr = type.GetAttribute<AttributeType>();
-
- PropertyInfo propInfo;
- AttributeType attr = propInfo.GetAttribute<AttributeType>();
-
- string name;
- Type type = TypeUtils.GetType(name); // search from all assembly loaded
-
-
-
-
-
-
-
- Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す
- 複数存在した場合には最後の値を返す
- 存在しなければ null を返す
-
- 取り出したい属性の型
- 取り出した属性値
-
-
-
- 現在ロードされているすべてのアセンブリから name という名の型を探して返す
-
-
-
-
-
-
- Check if the type is a ValueType and does not contain any non ValueType members.
-
-
-
-
-
-
- Returnes true if the specified is a struct type.
-
- to be analyzed.
- true if the specified is a struct type; otehrwise false.
-
-
-
- Compare two objects to see if they are equal or not. Null is acceptable.
-
-
-
-
-
-
-
- Return if an object is a numeric value.
-
- Any object to be tested.
- True if object is a numeric value.
-
-
-
- Cast an object to a specified numeric type.
-
- Any object
- Numric type
- Numeric value or null if the object is not a numeric value.
-
-
-
- Cast boxed numeric value to double
-
- boxed numeric value
- Numeric value in double. Double.Nan if obj is not a numeric value.
-
-
-
- Check if type is fully public or not.
- Nested class is checked if all declared types are public.
-
-
-
-
-
-
- Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values.
-
-
-
-
-
- Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y).
-
- The first object to compare.
- The second object to compare.
- true if the specified objects are equal; otherwise, false.
-
-
-
- Serves as a hash function for the specified object for hashing algorithms and
- data structures, such as a hash table.
-
- The object for which to get a hash code.
- A hash code for the specified object.
- is null.
-
-
-
- Returns a default equality comparer for the type specified by the generic argument.
-
- The default instance of the System.Collections.Generic.EqualityComparer<T>
- class for type T.
-
-
-
- Calculate hash code by reference.
-
-
-
-
-
- Initializes a new instance of the HashCodeByRef<T> class.
-
-
-
-
- Calculate hash code by reference.
-
-
Represents the way to automatically resolve Tag from the Value of a YamlScalar.
@@ -3727,6 +3588,22 @@
Decoded value.
True if decoded successfully.
+
+
+ Converts YamlNode tree into yaml text.
+
+
+
+ YamlNode node;
+ YamlPresenter.ToYaml(node);
+
+ YamlNode node1;
+ YamlNode node2;
+ YamlNode node3;
+ YamlPresenter.ToYaml(node1, node2, node3);
+
+
+
Extend string object to have .DoubleQuoteEscape() / .DoubleQuoteUnescape().
@@ -3766,5 +3643,112 @@
Unescape control codes, double quotations, backslashes escape in the YAML double quoted string format
+
+
+ Add string class two methods: .UriEscape(), .UriUnescape()
+
+ Charset that is not escaped is represented NonUriChar member.
+
+ NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&=$,\[\]]");
+
+
+
+
+ Escape the string in URI encoding format.
+
+ String to be escaped.
+ Escaped string.
+
+
+
+ Escape the string in URI encoding format.
+
+ String to be escaped.
+ Escaped string.
+
+
+
+ Unescape the string escaped in URI encoding format.
+
+ String to be unescape.
+ Unescaped string.
+
+
+
+ Escape / Unescape string in URI encoding format
+
+ Charset that is not escaped is represented NonUriChar member.
+
+ NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&=$,\[\]]");
+
+
+
+
+ Dictionary that automatically rehash when the content of a key is changed.
+ Keys of this dictionary must implement .
+ It also call back item addition and removal by and
+ events.
+
+ Type of key. Must implements .
+ Type of value.
+
+
+
+ A dictionary that returns or
+ from hash code. This is the main repository that stores the pairs.
+ If there are several entries that have same hash code for thir keys,
+ a is stored to hold all those entries.
+ Otherwise, a is stored.
+
+
+
+
+ A dictionary that returns hash code from the key reference.
+ The key must be the instance that
+ to one exsisting in the dictionary.
+
+
+ We store the hashes correspoinding to each key. So that when rehash,
+ we can find old hash code to quickly find the entry for the key.
+ It is also used to remember the number of keys exists in the dictionary.
+
+
+
+
+ Recalc hash key of the .
+
+ The key to be rehash. The key must be the instance that
+ to one exsisting in the dictionary.
+
+
+
+ Try to find entry for key (and value).
+
+ key to find
+ if true, value matters
+ value to find
+ key not found
+ hash hit one entry and key found
+ hash hit several entries and key found
+
+
+
+ Try to find entry for key (and value).
+
+ key to find
+ if true, value matters
+ value to find
+ hash not found
+ hash hit one entry but key not found
+ hash hit one entry and key found
+ hash hit several entries but key not found
+ hash hit several entries and key found
+
+
+
+ Collection that is readonly and invalidated when an item is
+ added to or removed from the dictionary.
+
+
diff --git a/lib/yaml/YamlSerializer.dll b/lib/yaml/YamlSerializer.dll
index 057f2c4e6..74fec4710 100644
Binary files a/lib/yaml/YamlSerializer.dll and b/lib/yaml/YamlSerializer.dll differ
diff --git a/src/Orchard.Azure.Tests/FileSystems/Media/AzureBlobStorageProviderTests.cs b/src/Orchard.Azure.Tests/FileSystems/Media/AzureBlobStorageProviderTests.cs
index 2b2c5baab..e6c948032 100644
--- a/src/Orchard.Azure.Tests/FileSystems/Media/AzureBlobStorageProviderTests.cs
+++ b/src/Orchard.Azure.Tests/FileSystems/Media/AzureBlobStorageProviderTests.cs
@@ -50,7 +50,7 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
Assert.AreEqual(".txt", storageFile.GetFileType());
Assert.AreEqual("foo.txt", storageFile.GetName());
- Assert.That(storageFile.GetPath().EndsWith("/default/foo.txt"), Is.True);
+ Assert.AreEqual("foo.txt", storageFile.GetPath());
Assert.AreEqual(0, storageFile.GetSize());
}
@@ -71,7 +71,8 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
var files = _azureBlobStorageProvider.ListFiles("");
Assert.AreEqual(1, files.Count());
- Assert.That(files.First().GetPath().EndsWith("foo2.txt"), Is.True);
+ Assert.That(files.First().GetPath().Equals("foo2.txt"), Is.True);
+ Assert.That(files.First().GetName().Equals("foo2.txt"), Is.True);
}
[Test]
@@ -82,17 +83,28 @@ namespace Orchard.Azure.Tests.FileSystems.Media {
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("").Count());
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("folder").Count());
+ Assert.AreEqual("folder/foo.txt", _azureBlobStorageProvider.ListFiles("folder").First().GetPath());
+ Assert.AreEqual("foo.txt", _azureBlobStorageProvider.ListFiles("folder").First().GetName());
Assert.AreEqual(1, _azureBlobStorageProvider.ListFiles("folder/folder").Count());
+ Assert.AreEqual("folder/folder/foo.txt", _azureBlobStorageProvider.ListFiles("folder/folder").First().GetPath());
+ Assert.AreEqual("foo.txt", _azureBlobStorageProvider.ListFiles("folder/folder").First().GetName());
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void CreateFolderThatExistsShouldThrow() {
- // sebros: In Azure, the folder concept is just about checking files prefix. So until a file exists, a folder is nothing
_azureBlobStorageProvider.CreateFile("folder/foo.txt");
_azureBlobStorageProvider.CreateFolder("folder");
}
+ [Test]
+ public void ListFolderShouldAcceptNullPath() {
+ _azureBlobStorageProvider.CreateFolder("folder");
+ Assert.AreEqual(1, _azureBlobStorageProvider.ListFolders(null).Count());
+ Assert.AreEqual("folder", _azureBlobStorageProvider.ListFolders(null).First().GetName());
+ Assert.AreEqual("folder", _azureBlobStorageProvider.ListFolders(null).First().GetPath());
+ }
+
[Test]
public void DeleteFolderShouldDeleteFilesAlso() {
_azureBlobStorageProvider.CreateFile("folder/foo1.txt");
diff --git a/src/Orchard.Azure/AzureFileSystem.cs b/src/Orchard.Azure/AzureFileSystem.cs
index 6de706353..598974b68 100644
--- a/src/Orchard.Azure/AzureFileSystem.cs
+++ b/src/Orchard.Azure/AzureFileSystem.cs
@@ -8,11 +8,15 @@ using Microsoft.WindowsAzure.StorageClient;
using Orchard.FileSystems.Media;
namespace Orchard.Azure {
- public class AzureFileSystem {
+ public class AzureFileSystem
+ {
+ private const string FolderEntry = "$$$ORCHARD$$$.$$$";
+
public string ContainerName { get; protected set; }
private readonly CloudStorageAccount _storageAccount;
private readonly string _root;
+ private readonly string _absoluteRoot;
public CloudBlobClient BlobClient { get; private set; }
public CloudBlobContainer Container { get; private set; }
@@ -25,6 +29,7 @@ namespace Orchard.Azure {
_storageAccount = storageAccount;
ContainerName = containerName;
_root = String.IsNullOrEmpty(root) || root == "/" ? String.Empty : root + "/";
+ _absoluteRoot = _storageAccount.BlobEndpoint.AbsoluteUri + containerName + "/" + root + "/";
using ( new HttpContextWeaver() ) {
@@ -46,66 +51,65 @@ namespace Orchard.Azure {
}
private static void EnsurePathIsRelative(string path) {
- if ( path.StartsWith("/") || path.StartsWith("http://"))
+ if (path.StartsWith("/") || path.StartsWith("http://"))
throw new ArgumentException("Path must be relative");
}
public IStorageFile GetFile(string path) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- using ( new HttpContextWeaver() )
- {
- Container.EnsureBlobExists(path);
- return new AzureBlobFileStorage(Container.GetBlockBlobReference(path));
+ using ( new HttpContextWeaver() ) {
+ Container.EnsureBlobExists(String.Concat(_root, path));
+ return new AzureBlobFileStorage(Container.GetBlockBlobReference(path), _absoluteRoot);
}
}
public bool FileExists(string path) {
- using ( new HttpContextWeaver() )
- {
- path = String.Concat(_root, path);
- return Container.BlobExists(path);
+ using ( new HttpContextWeaver() ) {
+ return Container.BlobExists(String.Concat(_root, path));
}
}
public IEnumerable ListFiles(string path) {
+ path = path ?? String.Empty;
+
EnsurePathIsRelative(path);
string prefix = String.Concat(Container.Name, "/", _root, path);
+
if ( !prefix.EndsWith("/") )
prefix += "/";
- using ( new HttpContextWeaver() )
- {
- foreach (var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType())
- {
- yield return new AzureBlobFileStorage(blobItem);
+
+ using ( new HttpContextWeaver() ) {
+ foreach (var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType()) {
+ // ignore directory entries
+ if(blobItem.Uri.AbsoluteUri.EndsWith(FolderEntry))
+ continue;
+
+ yield return new AzureBlobFileStorage(blobItem, _absoluteRoot);
}
}
}
public IEnumerable ListFolders(string path) {
+ path = path ?? String.Empty;
+
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- using ( new HttpContextWeaver() )
- {
- if (!Container.DirectoryExists(path))
- {
- try
- {
- CreateFolder(path);
+ using ( new HttpContextWeaver() ) {
+ if ( !Container.DirectoryExists(String.Concat(_root, path)) ) {
+ try {
+ CreateFolder(String.Concat(_root, path));
}
- catch (Exception ex)
- {
+ catch ( Exception ex ) {
throw new ArgumentException(string.Format("The folder could not be created at path: {0}. {1}",
path, ex));
}
}
- return Container.GetDirectoryReference(path)
+ return Container.GetDirectoryReference(String.Concat(_root, path))
.ListBlobs()
.OfType()
- .Select(d => new AzureBlobFolderStorage(d))
+ .Select(d => new AzureBlobFolderStorage(d, _absoluteRoot))
.ToList();
}
}
@@ -113,23 +117,20 @@ namespace Orchard.Azure {
public void CreateFolder(string path)
{
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- using (new HttpContextWeaver())
- {
- Container.EnsureDirectoryDoesNotExist(path);
- Container.GetDirectoryReference(path);
+ using (new HttpContextWeaver()) {
+ Container.EnsureDirectoryDoesNotExist(String.Concat(_root, path));
+
+ // Creating a virtually hidden file to make the directory an existing concept
+ CreateFile(path + "/" + FolderEntry);
}
}
public void DeleteFolder(string path) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- using ( new HttpContextWeaver() )
- {
- Container.EnsureDirectoryExists(path);
- foreach (var blob in Container.GetDirectoryReference(path).ListBlobs())
- {
+ using ( new HttpContextWeaver() ) {
+ Container.EnsureDirectoryExists(String.Concat(_root, path));
+ foreach ( var blob in Container.GetDirectoryReference(String.Concat(_root, path)).ListBlobs() ) {
if (blob is CloudBlob)
((CloudBlob) blob).Delete();
@@ -141,7 +142,6 @@ namespace Orchard.Azure {
public void RenameFolder(string path, string newPath) {
EnsurePathIsRelative(path);
-
EnsurePathIsRelative(newPath);
if ( !path.EndsWith("/") )
@@ -149,20 +149,16 @@ namespace Orchard.Azure {
if ( !newPath.EndsWith("/") )
newPath += "/";
- using ( new HttpContextWeaver() )
- {
- foreach (var blob in Container.GetDirectoryReference(_root + path).ListBlobs())
- {
- if (blob is CloudBlob)
- {
+ using ( new HttpContextWeaver() ) {
+ foreach (var blob in Container.GetDirectoryReference(_root + path).ListBlobs()) {
+ if (blob is CloudBlob) {
string filename = Path.GetFileName(blob.Uri.ToString());
string source = String.Concat(path, filename);
string destination = String.Concat(newPath, filename);
RenameFile(source, destination);
}
- if (blob is CloudBlobDirectory)
- {
+ if (blob is CloudBlobDirectory) {
string foldername = blob.Uri.Segments.Last();
string source = String.Concat(path, foldername);
string destination = String.Concat(newPath, foldername);
@@ -174,29 +170,24 @@ namespace Orchard.Azure {
public void DeleteFile(string path) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
-
- using ( new HttpContextWeaver() )
- {
+
+ using ( new HttpContextWeaver() ) {
Container.EnsureBlobExists(path);
- var blob = Container.GetBlockBlobReference(path);
+ var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
blob.Delete();
}
}
public void RenameFile(string path, string newPath) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
-
EnsurePathIsRelative(newPath);
- newPath = String.Concat(_root, newPath);
- using ( new HttpContextWeaver() )
- {
- Container.EnsureBlobExists(path);
- Container.EnsureBlobDoesNotExist(newPath);
- var blob = Container.GetBlockBlobReference(path);
- var newBlob = Container.GetBlockBlobReference(newPath);
+ using ( new HttpContextWeaver() ) {
+ Container.EnsureBlobExists(String.Concat(_root, path));
+ Container.EnsureBlobDoesNotExist(String.Concat(_root, newPath));
+
+ var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
+ var newBlob = Container.GetBlockBlobReference(String.Concat(_root, newPath));
newBlob.CopyFromBlob(blob);
blob.Delete();
}
@@ -204,36 +195,36 @@ namespace Orchard.Azure {
public IStorageFile CreateFile(string path) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- if ( Container.BlobExists(path) ) {
+ if ( Container.BlobExists(String.Concat(_root, path)) ) {
throw new ArgumentException("File " + path + " already exists");
}
- var blob = Container.GetBlockBlobReference(path);
+ var blob = Container.GetBlockBlobReference(String.Concat(_root, path));
blob.OpenWrite().Dispose(); // force file creation
- return new AzureBlobFileStorage(blob);
+ return new AzureBlobFileStorage(blob, _absoluteRoot);
}
public string GetPublicUrl(string path) {
EnsurePathIsRelative(path);
- path = String.Concat(_root, path);
- using ( new HttpContextWeaver() )
- {
- Container.EnsureBlobExists(path);
- return Container.GetBlockBlobReference(path).Uri.ToString();
+
+ using ( new HttpContextWeaver() ) {
+ Container.EnsureBlobExists(String.Concat(_root, path));
+ return Container.GetBlockBlobReference(String.Concat(_root, path)).Uri.ToString();
}
}
private class AzureBlobFileStorage : IStorageFile {
private readonly CloudBlockBlob _blob;
+ private readonly string _rootPath;
- public AzureBlobFileStorage(CloudBlockBlob blob) {
+ public AzureBlobFileStorage(CloudBlockBlob blob, string rootPath) {
_blob = blob;
+ _rootPath = rootPath;
}
public string GetPath() {
- return _blob.Uri.ToString();
+ return _blob.Uri.ToString().Substring(_rootPath.Length+1);
}
public string GetName() {
@@ -264,17 +255,19 @@ namespace Orchard.Azure {
private class AzureBlobFolderStorage : IStorageFolder {
private readonly CloudBlobDirectory _blob;
+ private readonly string _rootPath;
- public AzureBlobFolderStorage(CloudBlobDirectory blob) {
+ public AzureBlobFolderStorage(CloudBlobDirectory blob, string rootPath) {
_blob = blob;
+ _rootPath = rootPath;
}
public string GetName() {
- return Path.GetDirectoryName(_blob.Uri.ToString());
+ return Path.GetDirectoryName(GetPath() + "/");
}
public string GetPath() {
- return _blob.Uri.ToString();
+ return _blob.Uri.ToString().Substring(_rootPath.Length + 1).TrimEnd('/');
}
public long GetSize() {
@@ -287,7 +280,7 @@ namespace Orchard.Azure {
public IStorageFolder GetParent() {
if ( _blob.Parent != null ) {
- return new AzureBlobFolderStorage(_blob.Parent);
+ return new AzureBlobFolderStorage(_blob.Parent, _rootPath);
}
throw new ArgumentException("Directory " + _blob.Uri + " does not have a parent directory");
}
diff --git a/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs b/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs
index 832917606..ad0306387 100644
--- a/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs
+++ b/src/Orchard.Azure/Orchard.Azure.Web/WebRole.cs
@@ -8,6 +8,11 @@ namespace Orchard.Azure.Web {
public override bool OnStart() {
DiagnosticMonitor.Start("DiagnosticsConnectionString");
+ CloudStorageAccount.SetConfigurationSettingPublisher(
+ (configName, configSetter) =>
+ configSetter(RoleEnvironment.GetConfigurationSettingValue(configName))
+ );
+
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
RoleEnvironment.Changing += RoleEnvironmentChanging;
diff --git a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs
index ae9e5661b..ad47314a4 100644
--- a/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs
+++ b/src/Orchard.Core.Tests/Routable/Services/RoutableServiceTests.cs
@@ -21,6 +21,7 @@ using Orchard.DisplayManagement.Descriptors;
using Orchard.DisplayManagement.Implementation;
using Orchard.Environment;
using Orchard.Environment.Extensions;
+using Orchard.Mvc;
using Orchard.Security;
using Orchard.Tests.Modules;
using System.Web.Mvc;
@@ -45,6 +46,8 @@ namespace Orchard.Core.Tests.Routable.Services {
builder.RegisterInstance(new Mock().Object);
builder.RegisterInstance(new Mock().Object);
builder.RegisterInstance(new Mock().Object);
+ builder.RegisterType().As();
+ builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
diff --git a/src/Orchard.Specs/Hosting/Orchard.Web/Themes/Web.config b/src/Orchard.Specs/Hosting/Orchard.Web/Themes/Web.config
index f2f307586..dd900f1a0 100644
--- a/src/Orchard.Specs/Hosting/Orchard.Web/Themes/Web.config
+++ b/src/Orchard.Specs/Hosting/Orchard.Web/Themes/Web.config
@@ -2,9 +2,6 @@
-
-
-
+
+
+
diff --git a/src/Orchard.Web/Core/Contents/Settings/ContentTypeSettings.cs b/src/Orchard.Web/Core/Contents/Settings/ContentTypeSettings.cs
index e0d35b2e9..ed495eab7 100644
--- a/src/Orchard.Web/Core/Contents/Settings/ContentTypeSettings.cs
+++ b/src/Orchard.Web/Core/Contents/Settings/ContentTypeSettings.cs
@@ -1,8 +1,12 @@
namespace Orchard.Core.Contents.Settings {
public class ContentTypeSettings {
///
- /// This setting is used to display a Content Type in Content Management menu like
+ /// Used to determine if an instance of this content type can be created through the UI
///
public bool Creatable { get; set; }
+ ///
+ /// Used to determine if this content type supports draft versions
+ ///
+ public bool Draftable { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Core/Contents/Views/Content.PublishButton.cshtml b/src/Orchard.Web/Core/Contents/Views/Content.PublishButton.cshtml
new file mode 100644
index 000000000..b8f48a08f
--- /dev/null
+++ b/src/Orchard.Web/Core/Contents/Views/Content.PublishButton.cshtml
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/Orchard.Web/Core/Contents/Views/Content.SaveButton.cshtml b/src/Orchard.Web/Core/Contents/Views/Content.SaveButton.cshtml
new file mode 100644
index 000000000..cab18005a
--- /dev/null
+++ b/src/Orchard.Web/Core/Contents/Views/Content.SaveButton.cshtml
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml b/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml
index e0f0cd87b..534856f87 100644
--- a/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml
+++ b/src/Orchard.Web/Core/Contents/Views/Items/Content.Edit.cshtml
@@ -1,12 +1,21 @@
-
-
- @Display(Model.Content)
+
+
+ @if (Model.Content != null) {
+
+ @Display(Model.Content)
+
+ }
-
- @Display(Model.Sidebar)
- @* todo: (heskew) remove when the CommonPart is adding the save button *@
-
+
- @Display(Model.Sidebar)
- @* todo: (heskew) remove when the CommonPart is adding the save button *@
-
+
+ @if (Model.Actions != null) {
+
+ @Display(Model.Actions)
+
+ }
+ @if (Model.Sidebar != null) {
+
+ @Display(Model.Sidebar)
+
+ }
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-Blog.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-Blog.SummaryAdmin.cshtml
index 63bce04f0..021cd18a0 100644
--- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-Blog.SummaryAdmin.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-Blog.SummaryAdmin.cshtml
@@ -3,8 +3,9 @@
@using Orchard.ContentManagement;
@using Orchard.Utility.Extensions;
@{
- ContentItem contentItem = Model.ContentItem;
- var returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString();
+ Script.Require("ShapesBase");
+ ContentItem contentItem = Model.ContentItem;
+ var returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString();
}
diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-BlogPost.Editor.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-BlogPost.Editor.cshtml
deleted file mode 100644
index a73373f4f..000000000
--- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Items/Content-BlogPost.Editor.cshtml
+++ /dev/null
@@ -1,23 +0,0 @@
-@* todo: (heskew) remove - not being used but keeping around for the "remove draft" reminder *@
-
-@using Orchard.Blogs.Models;
-@{
- Html.AddTitleParts((string)Model.Title);
- BlogPostPart blogPost = Model.ContentItem.Get(typeof(BlogPostPart));
-}
-
-
- @Display(Model.Content)
-
-
- @Display(Model.Sidebar)
- @* todo: (heskew) remove when the CommonPart is adding the save button - also move the remove draft functionality to the CommonPart at that time *@
-
-
}
diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Views/Web.config b/src/Orchard.Web/Modules/Orchard.Themes/Views/Web.config
index bf2230060..dd900f1a0 100644
--- a/src/Orchard.Web/Modules/Orchard.Themes/Views/Web.config
+++ b/src/Orchard.Web/Modules/Orchard.Themes/Views/Web.config
@@ -2,8 +2,6 @@
-
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs
index beb07096a..e3c9ad8ca 100644
--- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs
@@ -10,8 +10,6 @@ using Orchard.Security;
using Orchard.Themes;
using Orchard.Users.Services;
using Orchard.Users.ViewModels;
-using Orchard.Settings;
-using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.Users.Models;
@@ -21,21 +19,23 @@ namespace Orchard.Users.Controllers {
private readonly IAuthenticationService _authenticationService;
private readonly IMembershipService _membershipService;
private readonly IUserService _userService;
+ private readonly IOrchardServices _orchardServices;
public AccountController(
IAuthenticationService authenticationService,
IMembershipService membershipService,
- IUserService userService) {
+ IUserService userService,
+ IOrchardServices orchardServices) {
_authenticationService = authenticationService;
_membershipService = membershipService;
_userService = userService;
+ _orchardServices = orchardServices;
Logger = NullLogger.Instance;
T = NullLocalizer.Instance;
}
public ILogger Logger { get; set; }
public Localizer T { get; set; }
- protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
public ActionResult AccessDenied() {
var returnUrl = Request.QueryString["ReturnUrl"];
@@ -93,7 +93,7 @@ namespace Orchard.Users.Controllers {
public ActionResult Register() {
// ensure users can register
- var registrationSettings = CurrentSite.As();
+ var registrationSettings = _orchardServices.WorkContext.CurrentSite.As();
if ( !registrationSettings.UsersCanRegister ) {
return HttpNotFound();
}
@@ -106,7 +106,7 @@ namespace Orchard.Users.Controllers {
[HttpPost]
public ActionResult Register(string userName, string email, string password, string confirmPassword) {
// ensure users can register
- var registrationSettings = CurrentSite.As();
+ var registrationSettings = _orchardServices.WorkContext.CurrentSite.As();
if ( !registrationSettings.UsersCanRegister ) {
return HttpNotFound();
}
@@ -125,6 +125,10 @@ namespace Orchard.Users.Controllers {
return RedirectToAction("ChallengeEmailSent");
}
+ if (user.As().RegistrationStatus == UserStatus.Pending) {
+ return RedirectToAction("RegistrationPending");
+ }
+
_authenticationService.SignIn(user, false /* createPersistentCookie */);
return Redirect("~/");
}
@@ -174,6 +178,10 @@ namespace Orchard.Users.Controllers {
}
}
+ public ActionResult RegistrationPending() {
+ return View();
+ }
+
public ActionResult ChangePasswordSuccess() {
return View();
}
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs
index d82a58a93..b7b0e3e55 100644
--- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs
@@ -1,11 +1,9 @@
using System.Linq;
using System.Web.Mvc;
-using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Security;
-using Orchard.Settings;
using Orchard.UI.Notify;
using Orchard.Users.Models;
using Orchard.Users.Services;
@@ -33,7 +31,6 @@ namespace Orchard.Users.Controllers {
dynamic Shape { get; set; }
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
- protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
public ActionResult Index() {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to list users")))
@@ -58,46 +55,52 @@ namespace Orchard.Users.Controllers {
return new HttpUnauthorizedResult();
var user = Services.ContentManager.New("User");
- var model = new UserCreateViewModel {
- User = Services.ContentManager.BuildEditor(user)
- };
+ var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Create", Model: new UserCreateViewModel(), Prefix: null);
+ editor.Metadata.Position = "2";
+ var model = Services.ContentManager.BuildEditor(user);
+ model.Content.Add(editor);
+
return View(model);
}
[HttpPost, ActionName("Create")]
- public ActionResult CreatePOST(UserCreateViewModel model) {
+ public ActionResult CreatePOST(UserCreateViewModel createModel) {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
return new HttpUnauthorizedResult();
- var user = Services.ContentManager.New("User");
- model.User = Services.ContentManager.UpdateEditor(user, this);
- if (!ModelState.IsValid) {
- Services.TransactionManager.Cancel();
- return View(model);
+ if (!string.IsNullOrEmpty(createModel.UserName)) {
+ string userExistsMessage = _userService.VerifyUserUnicity(createModel.UserName, createModel.Email);
+ if (userExistsMessage != null) {
+ AddModelError("NotUniqueUserName", T(userExistsMessage));
+ }
}
- string userExistsMessage = _userService.VerifyUserUnicity(model.UserName, model.Email);
- if (userExistsMessage != null) {
- AddModelError("NotUniqueUserName", T(userExistsMessage));
- }
-
- if (model.Password != model.ConfirmPassword) {
+ if (createModel.Password != createModel.ConfirmPassword) {
AddModelError("ConfirmPassword", T("Password confirmation must match"));
}
- user = _membershipService.CreateUser(new CreateUserParams(
- model.UserName,
- model.Password,
- model.Email,
- null, null, true));
+ var user = Services.ContentManager.New("User");
+ if (ModelState.IsValid) {
+ user = _membershipService.CreateUser(new CreateUserParams(
+ createModel.UserName,
+ createModel.Password,
+ createModel.Email,
+ null, null, true));
+ }
- model.User = Services.ContentManager.UpdateEditor(user, this);
+ var model = Services.ContentManager.UpdateEditor(user, this);
- if (ModelState.IsValid == false) {
+ if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
+
+ var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Create", Model: createModel, Prefix: null);
+ editor.Metadata.Position = "2";
+ model.Content.Add(editor);
+
return View(model);
}
+ Services.Notifier.Information(T("User created"));
return RedirectToAction("edit", new { user.Id });
}
@@ -106,10 +109,12 @@ namespace Orchard.Users.Controllers {
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get(id);
+ var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Edit", Model: new UserEditViewModel {User = user}, Prefix: null);
+ editor.Metadata.Position = "2";
+ var model = Services.ContentManager.BuildEditor(user);
+ model.Content.Add(editor);
- return View(new UserEditViewModel {
- User = Services.ContentManager.BuildEditor(user)
- });
+ return View(model);
}
[HttpPost, ActionName("Edit")]
@@ -118,26 +123,27 @@ namespace Orchard.Users.Controllers {
return new HttpUnauthorizedResult();
var user = Services.ContentManager.Get(id);
- var model = new UserEditViewModel {
- User = Services.ContentManager.UpdateEditor(user, this)
- };
+ var model = Services.ContentManager.UpdateEditor(user, this);
- TryUpdateModel(model);
+ var editModel = new UserEditViewModel {User = user};
+ TryUpdateModel(editModel);
- if (!ModelState.IsValid) {
- Services.TransactionManager.Cancel();
- return View(model);
- }
+ if (ModelState.IsValid) {
+ ((IContent)model.ContentItem).As().NormalizedUserName = editModel.UserName.ToLower();
- model.User.As().NormalizedUserName = model.UserName.ToLower();
-
- string userExistsMessage = _userService.VerifyUserUnicity(id, model.UserName, model.Email);
- if (userExistsMessage != null) {
- AddModelError("NotUniqueUserName", T(userExistsMessage));
+ string userExistsMessage = _userService.VerifyUserUnicity(id, editModel.UserName, editModel.Email);
+ if (userExistsMessage != null) {
+ AddModelError("NotUniqueUserName", T(userExistsMessage));
+ }
}
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
+
+ var editor = Shape.EditorTemplate(TemplateName: "Parts/User.Edit", Model: editModel, Prefix: null);
+ editor.Metadata.Position = "2";
+ model.Content.Add(editor);
+
return View(model);
}
@@ -192,7 +198,7 @@ namespace Orchard.Users.Controllers {
var user = Services.ContentManager.Get(id);
if ( user != null ) {
- if ( CurrentSite.SuperUser.Equals(user.As().UserName) ) {
+ if (Services.WorkContext.CurrentSite.SuperUser.Equals(user.As().UserName) ) {
Services.Notifier.Error(T("Super user can't be moderated"));
}
else {
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj
index e78ca1397..0e6484899 100644
--- a/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj
+++ b/src/Orchard.Web/Modules/Orchard.Users/Orchard.Users.csproj
@@ -109,7 +109,6 @@
-
@@ -123,6 +122,16 @@
Designer
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs
index 83da257c0..835c371c5 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs
@@ -7,7 +7,6 @@ using Orchard.Core.Contents.Controllers;
using Orchard.Localization;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
-using Orchard.UI.Widgets;
using Orchard.Widgets.Models;
using Orchard.Widgets.Services;
using Orchard.Widgets.ViewModels;
@@ -20,16 +19,13 @@ namespace Orchard.Widgets.Controllers {
private const string NotAuthorizedManageWidgetsLabel = "Not authorized to manage widgets";
private readonly IWidgetsService _widgetsService;
- private readonly IRuleManager _ruleManager;
public AdminController(
IOrchardServices services,
- IWidgetsService widgetsService,
- IRuleManager ruleManager) {
+ IWidgetsService widgetsService) {
Services = services;
_widgetsService = widgetsService;
- _ruleManager = ruleManager;
T = NullLocalizer.Instance;
}
@@ -179,8 +175,6 @@ namespace Orchard.Widgets.Controllers {
var model = Services.ContentManager.UpdateEditor(layerPart, this);
- ValidateLayer(layerPart);
-
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
return View(model);
@@ -227,8 +221,6 @@ namespace Orchard.Widgets.Controllers {
var model = Services.ContentManager.UpdateEditor(layerPart, this);
- ValidateLayer(layerPart);
-
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
return View(model);
@@ -339,27 +331,6 @@ namespace Orchard.Widgets.Controllers {
RedirectToAction("Index");
}
- public bool ValidateLayer(LayerPart layer) {
- if ( String.IsNullOrWhiteSpace(layer.LayerRule) ) {
- layer.LayerRule = "true";
- }
-
- if(_widgetsService.GetLayers().Count(l => String.Equals(l.Name, layer.Name, StringComparison.InvariantCultureIgnoreCase)) > 1) { // the current layer counts for 1
- ModelState.AddModelError("Name", T("A Layer with the same name already exists").Text);
- return false;
- }
-
- try {
- _ruleManager.Matches(layer.LayerRule);
- }
- catch ( Exception e ) {
- ModelState.AddModelError("Description", T("The rule is not valid: {0}", e.Message).Text);
- return false;
- }
-
- return true;
- }
-
bool IUpdateModel.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return base.TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs
index a37cfd2f6..e4d3c7b5d 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs
@@ -1,12 +1,31 @@
-using JetBrains.Annotations;
+using System;
+using System.Linq;
+using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
+using Orchard.Localization;
+using Orchard.UI.Widgets;
using Orchard.Widgets.Models;
+using Orchard.Widgets.Services;
namespace Orchard.Widgets.Drivers {
[UsedImplicitly]
public class LayerPartDriver : ContentPartDriver {
+ private readonly IRuleManager _ruleManager;
+ private readonly IWidgetsService _widgetsService;
+
+ public LayerPartDriver(
+ IRuleManager ruleManager,
+ IWidgetsService widgetsService) {
+
+ _ruleManager = ruleManager;
+ _widgetsService = widgetsService;
+
+ T = NullLocalizer.Instance;
+ }
+
+ public Localizer T { get; set; }
protected override DriverResult Editor(LayerPart layerPart, dynamic shapeHelper) {
return ContentShape("Parts_Widgets_LayerPart",
@@ -14,7 +33,23 @@ namespace Orchard.Widgets.Drivers {
}
protected override DriverResult Editor(LayerPart layerPart, IUpdateModel updater, dynamic shapeHelper) {
- updater.TryUpdateModel(layerPart, Prefix, null, null);
+ if(updater.TryUpdateModel(layerPart, Prefix, null, null)) {
+ if ( String.IsNullOrWhiteSpace(layerPart.LayerRule) ) {
+ layerPart.LayerRule = "true";
+ }
+
+ if ( _widgetsService.GetLayers().Any(l => String.Equals(l.Name, layerPart.Name, StringComparison.InvariantCultureIgnoreCase))) {
+ updater.AddModelError("Name", T("A Layer with the same name already exists"));
+ }
+
+ try {
+ _ruleManager.Matches(layerPart.LayerRule);
+ }
+ catch ( Exception e ) {
+ updater.AddModelError("Description", T("The rule is not valid: {0}", e.Message));
+ }
+ }
+
return Editor(layerPart, shapeHelper);
}
}
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs
index bc0e46f69..b971b1659 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs
@@ -47,9 +47,8 @@ namespace Orchard.Widgets.Filters {
IEnumerable widgetParts = _contentManager.Query().List();
IEnumerable activeLayers = _contentManager.Query().List();
- List activeLayerIds = new List();
+ var activeLayerIds = new List();
foreach (var activeLayer in activeLayers) {
- var context = workContext.HttpContext;
// ignore the rule if it fails to execute
try {
if (_ruleManager.Matches(activeLayer.Record.LayerRule)) {
@@ -57,7 +56,7 @@ namespace Orchard.Widgets.Filters {
}
}
catch(Exception e) {
- Logger.Debug(e, T("An error occured during layer evaluation on: {0}", activeLayer.Name).Text);
+ Logger.Warning(e, T("An error occured during layer evaluation on: {0}", activeLayer.Name).Text);
}
}
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
index ea6196de0..24e6924a6 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
@@ -38,6 +38,10 @@
..\..\..\..\lib\claysharp\ClaySharp.dll
+
+ False
+ ..\..\..\..\lib\dlr\Microsoft.Scripting.dll
+
@@ -94,7 +98,6 @@
-
@@ -127,6 +130,16 @@
+
+
+ Designer
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css b/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css
index 2c44a98d0..14438b614 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css
@@ -27,7 +27,6 @@ h4.widgets-layer-header {
.widgets-availableWidgets table.items th
{
background: #f1f1f1;
- font-size:1.6em;
padding:.5em 0 .3em .2em;
}
@@ -39,7 +38,6 @@ h4.widgets-layer-header {
}
.widgets-layerZones {
- font-size: 1.4em;
float: left;
float: right;
width: 60%;
@@ -76,7 +74,6 @@ h4.widgets-layer-header {
}
.widgets-layers {
- font-size: 1.4em;
border:1px solid #ccc;
border-right:none;
}
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml
index 87aa30d15..d5292641b 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml
@@ -4,6 +4,6 @@
@Display(Model)
-
+
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml
index 8d7f36a5c..a3b6aacf1 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml
@@ -4,6 +4,7 @@
@Display(Model)
-
+
+
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Items/Widget.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Items/Widget.Edit.cshtml
index 696503b21..ee08a573d 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Items/Widget.Edit.cshtml
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Items/Widget.Edit.cshtml
@@ -4,9 +4,5 @@
@Display(Model.Sidebar)
- @* todo: (heskew) remove when the CommonPart is adding the save button *@
-
\ No newline at end of file
+ @Display(Model.Footer)
+
\ No newline at end of file
diff --git a/src/Orchard.Web/Themes/TheAdmin/Views/OrchardVersion.cshtml b/src/Orchard.Web/Themes/TheAdmin/Views/OrchardVersion.cshtml
new file mode 100644
index 000000000..9b04becea
--- /dev/null
+++ b/src/Orchard.Web/Themes/TheAdmin/Views/OrchardVersion.cshtml
@@ -0,0 +1,4 @@
+@{
+ var version = new System.Reflection.AssemblyName(typeof(Orchard.ContentManagement.ContentItem).Assembly.FullName).Version.ToString();
+}
+
@T("Orchard v.{0}", version)
\ No newline at end of file
diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Styles/Web.config b/src/Orchard.Web/Themes/TheThemeMachine/Styles/Web.config
new file mode 100644
index 000000000..b4210f3e0
--- /dev/null
+++ b/src/Orchard.Web/Themes/TheThemeMachine/Styles/Web.config
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.Web/Themes/Themes.csproj b/src/Orchard.Web/Themes/Themes.csproj
index 7d12ed2ce..c7adcbe36 100644
--- a/src/Orchard.Web/Themes/Themes.csproj
+++ b/src/Orchard.Web/Themes/Themes.csproj
@@ -49,6 +49,10 @@
+
+
+
+
@@ -58,9 +62,17 @@
-
+ Designer
+
+ Designer
+
+
+
+
+ Designer
+
@@ -94,7 +106,19 @@
-
+
+ Designer
+
+
+
+
+ Designer
+
+
+
+
+ Designer
+
diff --git a/src/Orchard.Web/Themes/Web.config b/src/Orchard.Web/Themes/Web.config
index ae3d47d77..a2d69a7b9 100644
--- a/src/Orchard.Web/Themes/Web.config
+++ b/src/Orchard.Web/Themes/Web.config
@@ -2,13 +2,9 @@
-
-
-
-
-
+
+
-
+
diff --git a/src/Orchard.Web/Web.config b/src/Orchard.Web/Web.config
index be12b290a..05dce1250 100644
--- a/src/Orchard.Web/Web.config
+++ b/src/Orchard.Web/Web.config
@@ -66,6 +66,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Orchard.sln b/src/Orchard.sln
index 2f7139dc3..839c5af7c 100644
--- a/src/Orchard.sln
+++ b/src/Orchard.sln
@@ -1,4 +1,3 @@
-
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}"
@@ -93,7 +92,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Themes", "Orchard.Web\Theme
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.PublishLater", "Orchard.Web\Modules\Orchard.PublishLater\Orchard.PublishLater.csproj", "{C889167C-E52C-4A65-A419-224B3D1B957D}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.ContentQueries", "Orchard.Web\Modules\Orchard.ContentQueries\Orchard.ContentQueries.csproj", "{848126A0-9C88-415A-868F-F5F03449D0B6}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Lists", "Orchard.Web\Modules\Orchard.Lists\Orchard.Lists.csproj", "{137906EA-15FE-4AD8-A6A0-27528F0477D6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -494,16 +493,13 @@ Global
{C889167C-E52C-4A65-A419-224B3D1B957D}.FxCop|Any CPU.Build.0 = Release|Any CPU
{C889167C-E52C-4A65-A419-224B3D1B957D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C889167C-E52C-4A65-A419-224B3D1B957D}.Release|Any CPU.Build.0 = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Coverage|Any CPU.Build.0 = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.FxCop|Any CPU.Build.0 = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {848126A0-9C88-415A-868F-F5F03449D0B6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -533,7 +529,7 @@ Global
{AB3C207C-0126-4143-8D62-1119DF80D366} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{EA4F1DA7-F2AB-4384-9AA4-9B756E2026B1} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{C889167C-E52C-4A65-A419-224B3D1B957D} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
- {848126A0-9C88-415A-868F-F5F03449D0B6} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
+ {137906EA-15FE-4AD8-A6A0-27528F0477D6} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
{ABC826D4-2FA1-4F2F-87DE-E6095F653810} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{F112851D-B023-4746-B6B1-8D2E5AD8F7AA} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{6CB3EB30-F725-45C0-9742-42599BA8E8D2} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
diff --git a/src/Orchard/Caching/Weak.cs b/src/Orchard/Caching/Weak.cs
index ce8ba0c61..fbab6c623 100644
--- a/src/Orchard/Caching/Weak.cs
+++ b/src/Orchard/Caching/Weak.cs
@@ -1,23 +1,20 @@
using System;
-using System.Runtime.Serialization;
namespace Orchard.Caching {
- public class Weak : WeakReference {
- public Weak(T target)
- : base(target) {
+ public class Weak {
+ private readonly WeakReference _target;
+
+ public Weak(T target) {
+ _target = new WeakReference(target);
}
- public Weak(T target, bool trackResurrection)
- : base(target, trackResurrection) {
+ public Weak(T target, bool trackResurrection) {
+ _target = new WeakReference(target, trackResurrection);
}
- protected Weak(SerializationInfo info, StreamingContext context)
- : base(info, context) {
- }
-
- public new T Target {
- get { return (T)base.Target; }
- set { base.Target = value; }
+ public T Target {
+ get { return (T)_target.Target; }
+ set { _target.Target = value; }
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Orchard/Commands/CommandModule.cs b/src/Orchard/Commands/CommandModule.cs
index c857232b5..fb9c192e1 100644
--- a/src/Orchard/Commands/CommandModule.cs
+++ b/src/Orchard/Commands/CommandModule.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Linq;
using Autofac;
using Autofac.Core;
diff --git a/src/Orchard/ContentManagement/DefaultContentDisplay.cs b/src/Orchard/ContentManagement/DefaultContentDisplay.cs
index 554e1e2a2..19a2b2c7c 100644
--- a/src/Orchard/ContentManagement/DefaultContentDisplay.cs
+++ b/src/Orchard/ContentManagement/DefaultContentDisplay.cs
@@ -1,16 +1,11 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Web.Routing;
-using ClaySharp;
using ClaySharp.Implementation;
-using Microsoft.CSharp.RuntimeBinder;
using Orchard.ContentManagement.Handlers;
using Orchard.DisplayManagement;
using Orchard.DisplayManagement.Descriptors;
using Orchard.Logging;
-using Orchard.Mvc;
using Orchard.Themes;
using Orchard.UI.Zones;
@@ -19,24 +14,18 @@ namespace Orchard.ContentManagement {
private readonly Lazy> _handlers;
private readonly IShapeFactory _shapeFactory;
private readonly IShapeTableManager _shapeTableManager;
- private readonly IWorkContextAccessor _workContextAccessor;
- private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly Lazy _themeService;
+ private readonly Lazy _themeService;
private readonly RequestContext _requestContext;
public DefaultContentDisplay(
Lazy> handlers,
IShapeFactory shapeFactory,
IShapeTableManager shapeTableManager,
- IWorkContextAccessor workContextAccessor,
- IHttpContextAccessor httpContextAccessor,
- Lazy themeService,
+ Lazy themeService,
RequestContext requestContext) {
_handlers = handlers;
_shapeFactory = shapeFactory;
_shapeTableManager = shapeTableManager;
- _workContextAccessor = workContextAccessor;
- _httpContextAccessor = httpContextAccessor;
_themeService = themeService;
_requestContext = requestContext;
Logger = NullLogger.Instance;
@@ -44,14 +33,6 @@ namespace Orchard.ContentManagement {
public ILogger Logger { get; set; }
- static readonly CallSiteCollection _shapeHelperCalls = new CallSiteCollection(shapeTypeName => Binder.InvokeMember(
- CSharpBinderFlags.None,
- shapeTypeName,
- Enumerable.Empty(),
- null,
- new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
-
-
public dynamic BuildDisplay(IContent content, string displayType) {
var contentTypeDefinition = content.ContentItem.TypeDefinition;
string stereotype;
@@ -118,7 +99,7 @@ namespace Orchard.ContentManagement {
//var workContext = _workContextAccessor.GetContext();
//var theme = workContext.CurrentTheme;
var theme = _themeService.Value.GetRequestTheme(_requestContext);
- var shapeTable = _shapeTableManager.GetShapeTable(theme.ThemeName);
+ var shapeTable = _shapeTableManager.GetShapeTable(theme.Name);
ShapeDescriptor descriptor;
if (shapeTable.Descriptors.TryGetValue(partShapeType, out descriptor)) {
var placementContext = new ShapePlacementContext {
diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs
index 4ddf0ba2d..8d1adebac 100644
--- a/src/Orchard/Data/Migration/DataMigrationManager.cs
+++ b/src/Orchard/Data/Migration/DataMigrationManager.cs
@@ -86,8 +86,7 @@ namespace Orchard.Data.Migration {
Logger.Information("Updating feature: {0}", feature);
// proceed with dependent features first, whatever the module it's in
- var dependencies = ShellStateCoordinator.OrderByDependencies(_extensionManager.AvailableExtensions()
- .SelectMany(ext => ext.Features))
+ var dependencies = _extensionManager.AvailableFeatures()
.Where(f => String.Equals(f.Name, feature, StringComparison.OrdinalIgnoreCase))
.Where(f => f.Dependencies != null)
.SelectMany( f => f.Dependencies )
@@ -189,7 +188,7 @@ namespace Orchard.Data.Migration {
.ToList();
foreach (var migration in migrations.OfType()) {
- migration.SchemaBuilder = new SchemaBuilder(_interpreter, migration.Feature.Descriptor.Name.Replace(".", "_") + "_");
+ migration.SchemaBuilder = new SchemaBuilder(_interpreter, migration.Feature.Descriptor.Name, (s) => s.Replace(".", "_") + "_");
migration.ContentDefinitionManager = _contentDefinitionManager;
}
diff --git a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs
index 0744e6d3c..ea2fa5c26 100644
--- a/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs
+++ b/src/Orchard/Data/Migration/Generator/SchemaCommandGenerator.cs
@@ -41,8 +41,7 @@ namespace Orchard.Data.Migration.Generator {
/// Generates SchemaCommand instances in order to create the schema for a specific feature
///
public IEnumerable GetCreateFeatureCommands(string feature, bool drop) {
- var dependencies = ShellStateCoordinator.OrderByDependencies(_extensionManager.AvailableExtensions()
- .SelectMany(ext => ext.Features))
+ var dependencies = _extensionManager.AvailableFeatures()
.Where(f => String.Equals(f.Name, feature, StringComparison.OrdinalIgnoreCase))
.Where(f => f.Dependencies != null)
.SelectMany(f => f.Dependencies)
diff --git a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs
index cfe318267..af73145b8 100644
--- a/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs
+++ b/src/Orchard/Data/Migration/Schema/SchemaBuilder.cs
@@ -5,28 +5,30 @@ namespace Orchard.Data.Migration.Schema {
public class SchemaBuilder {
private readonly IDataMigrationInterpreter _interpreter;
private readonly string _featurePrefix;
+ private readonly Func _formatPrefix;
- public SchemaBuilder(IDataMigrationInterpreter interpreter, string featurePrefix = null) {
+ public SchemaBuilder(IDataMigrationInterpreter interpreter, string featurePrefix = null, Func formatPrefix = null) {
_interpreter = interpreter;
- _featurePrefix = featurePrefix;
+ _featurePrefix = featurePrefix ?? String.Empty;
+ _formatPrefix = formatPrefix ?? (s => s ?? String.Empty);
}
public SchemaBuilder CreateTable(string name, Action table) {
- var createTable = new CreateTableCommand(String.Concat(_featurePrefix, name));
+ var createTable = new CreateTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
table(createTable);
Run(createTable);
return this;
}
public SchemaBuilder AlterTable(string name, Action table) {
- var alterTable = new AlterTableCommand(String.Concat(_featurePrefix, name));
+ var alterTable = new AlterTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
table(alterTable);
Run(alterTable);
return this;
}
public SchemaBuilder DropTable(string name) {
- var deleteTable = new DropTableCommand(String.Concat(_featurePrefix, name));
+ var deleteTable = new DropTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
Run(deleteTable);
return this;
}
@@ -45,13 +47,37 @@ namespace Orchard.Data.Migration.Schema {
}
public SchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destTable, string[] destColumns) {
- var command = new CreateForeignKeyCommand(name, String.Concat(_featurePrefix, srcTable), srcColumns, String.Concat(_featurePrefix, destTable), destColumns);
+ var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns);
+ Run(command);
+ return this;
+ }
+
+ public SchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destTable, string[] destColumns) {
+ var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns);
+ Run(command);
+ return this;
+ }
+
+ public SchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns) {
+ var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns);
+ Run(command);
+ return this;
+ }
+
+ public SchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns) {
+ var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns);
Run(command);
return this;
}
public SchemaBuilder DropForeignKey(string srcTable, string name) {
- var command = new DropForeignKeyCommand(String.Concat(_featurePrefix, srcTable), name);
+ var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(_featurePrefix), srcTable), name);
+ Run(command);
+ return this;
+ }
+
+ public SchemaBuilder DropForeignKey(string srcModule, string srcTable, string name) {
+ var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(srcModule), srcTable), name);
Run(command);
return this;
}
diff --git a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs
index c2f68fc30..b10395cdb 100644
--- a/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs
+++ b/src/Orchard/DisplayManagement/Descriptors/DefaultShapeTableManager.cs
@@ -9,16 +9,12 @@ using Orchard.Utility;
namespace Orchard.DisplayManagement.Descriptors {
- public interface IFeatureMetadata {
- Feature Feature { get; }
- }
-
public class DefaultShapeTableManager : IShapeTableManager {
- private readonly IEnumerable> _bindingStrategies;
+ private readonly IEnumerable> _bindingStrategies;
private readonly IExtensionManager _extensionManager;
public DefaultShapeTableManager(
- IEnumerable> bindingStrategies,
+ IEnumerable> bindingStrategies,
IExtensionManager extensionManager) {
_extensionManager = extensionManager;
_bindingStrategies = bindingStrategies;
@@ -30,7 +26,10 @@ namespace Orchard.DisplayManagement.Descriptors {
return _tables.GetOrAdd(themeName ?? "", x => {
var builderFactory = new ShapeTableBuilderFactory();
foreach (var bindingStrategy in _bindingStrategies) {
- var strategyDefaultFeature = bindingStrategy.Metadata.Feature;
+ Feature strategyDefaultFeature = bindingStrategy.Metadata.ContainsKey("Feature") ?
+ (Feature) bindingStrategy.Metadata["Feature"] :
+ null;
+
var builder = builderFactory.CreateTableBuilder(strategyDefaultFeature);
bindingStrategy.Value.Discover(builder);
}
diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs
index 4ca7fba14..6f87b85bd 100644
--- a/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs
+++ b/src/Orchard/DisplayManagement/Implementation/DefaultDisplayManager.cs
@@ -53,7 +53,7 @@ namespace Orchard.DisplayManagement.Implementation {
return CoerceHtmlString(context.Value);
var workContext = _workContextAccessor.GetContext(context.ViewContext);
- var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.ThemeName);
+ var shapeTable = _shapeTableManager.GetShapeTable(workContext.CurrentTheme.Name);
var displayingContext = new ShapeDisplayingContext {
Shape = shape,
diff --git a/src/Orchard/Environment/AutofacUtil/DynamicProxy2/ConstructorFinderWrapper.cs b/src/Orchard/Environment/AutofacUtil/DynamicProxy2/ConstructorFinderWrapper.cs
index a4f37df3a..38d365fac 100644
--- a/src/Orchard/Environment/AutofacUtil/DynamicProxy2/ConstructorFinderWrapper.cs
+++ b/src/Orchard/Environment/AutofacUtil/DynamicProxy2/ConstructorFinderWrapper.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Reflection;
using Autofac.Core.Activators.Reflection;
diff --git a/src/Orchard/Environment/AutofacUtil/LifetimeScopeContainer.cs b/src/Orchard/Environment/AutofacUtil/LifetimeScopeContainer.cs
index 1d9ffe0e6..bd6a96e08 100644
--- a/src/Orchard/Environment/AutofacUtil/LifetimeScopeContainer.cs
+++ b/src/Orchard/Environment/AutofacUtil/LifetimeScopeContainer.cs
@@ -19,7 +19,7 @@ namespace Orchard.Environment.AutofacUtil {
get { return _lifetimeScope.ComponentRegistry; }
}
- public void Dispose() {
+ public void Dispose() {
}
public ILifetimeScope BeginLifetimeScope() {
diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs
index 07fbcd8e7..7d5f0b5d1 100644
--- a/src/Orchard/Environment/DefaultOrchardHost.cs
+++ b/src/Orchard/Environment/DefaultOrchardHost.cs
@@ -1,6 +1,5 @@
using System.Linq;
using System.Threading;
-using System.Web.Mvc;
using System.Collections.Generic;
using Orchard.Caching;
using Orchard.Environment.Configuration;
@@ -11,10 +10,7 @@ using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Localization;
using Orchard.Logging;
-using Orchard.Mvc;
-using Orchard.Mvc.ViewEngines;
using Orchard.Utility.Extensions;
-using Autofac;
namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost, IShellSettingsManagerEventHandler, IShellDescriptorManagerEventHandler {
@@ -62,7 +58,7 @@ namespace Orchard.Environment {
}
void IOrchardHost.ReloadExtensions() {
- _current = null;
+ DisposeShellContext();
}
void IOrchardHost.BeginRequest() {
@@ -145,11 +141,20 @@ namespace Orchard.Environment {
ctx => {
_extensionLoaderCoordinator.MonitorExtensions(ctx.Monitor);
_hostLocalRestart.Monitor(ctx.Monitor);
- _current = null;
+ DisposeShellContext();
return "";
});
}
+ private void DisposeShellContext() {
+ if (_current != null) {
+ foreach (var shellContext in _current) {
+ shellContext.Shell.Terminate();
+ }
+ _current = null;
+ }
+ }
+
protected virtual void BeginRequest() {
MonitorExtensions();
BuildCurrent();
@@ -176,11 +181,11 @@ namespace Orchard.Environment {
}
void IShellSettingsManagerEventHandler.Saved(ShellSettings settings) {
- _current = null;
+ DisposeShellContext();
}
void IShellDescriptorManagerEventHandler.Changed(ShellDescriptor descriptor) {
- _current = null;
+ DisposeShellContext();
}
}
}
diff --git a/src/Orchard/Environment/DefaultOrchardShell.cs b/src/Orchard/Environment/DefaultOrchardShell.cs
index b263f909b..df740d677 100644
--- a/src/Orchard/Environment/DefaultOrchardShell.cs
+++ b/src/Orchard/Environment/DefaultOrchardShell.cs
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using System.Web.Mvc;
using Autofac.Features.OwnedInstances;
-using Orchard.Environment.Extensions.Models;
using Orchard.Logging;
using Orchard.Mvc.ModelBinders;
using Orchard.Mvc.Routes;
@@ -17,21 +14,18 @@ namespace Orchard.Environment {
private readonly IRoutePublisher _routePublisher;
private readonly IEnumerable _modelBinderProviders;
private readonly IModelBinderPublisher _modelBinderPublisher;
- private readonly ViewEngineCollection _viewEngines;
public DefaultOrchardShell(
Func> eventsFactory,
IEnumerable routeProviders,
IRoutePublisher routePublisher,
IEnumerable modelBinderProviders,
- IModelBinderPublisher modelBinderPublisher,
- ViewEngineCollection viewEngines) {
+ IModelBinderPublisher modelBinderPublisher) {
_eventsFactory = eventsFactory;
_routeProviders = routeProviders;
_routePublisher = routePublisher;
_modelBinderProviders = modelBinderProviders;
_modelBinderPublisher = modelBinderPublisher;
- _viewEngines = viewEngines;
Logger = NullLogger.Instance;
}
@@ -42,8 +36,6 @@ namespace Orchard.Environment {
_routePublisher.Publish(_routeProviders.SelectMany(provider => provider.GetRoutes()));
_modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders()));
- //AddOrchardLocationsFormats();
-
using (var events = _eventsFactory()) {
events.Value.Activated();
}
@@ -54,62 +46,5 @@ namespace Orchard.Environment {
events.Value.Terminating();
}
}
-
- ///
- /// Adds view locations formats for non-themed views in custom orchard modules.
- ///
- private void AddOrchardLocationsFormats() {
-
- IEnumerable orchardMasterLocationFormats = new[] {
- "~/Modules/{2}/Views/{1}/{0}.master",
- "~/Modules/{2}/Views/Shared/{0}.master",
- "~/Themes/{2}/Views/{1}/{0}.master",
- "~/Themes/{2}/Views/Shared/{0}.master",
- "~/Core/{2}/Views/{1}/{0}.master",
- "~/Core/{2}/Views/Shared/{0}.master",
- "~/Areas/{2}/Views/{1}/{0}.master",
- "~/Areas/{2}/Views/Shared/{0}.master",
- };
-
- IEnumerable orchardLocationFormats = new[] {
- "~/Modules/{2}/Views/{1}/{0}.aspx",
- "~/Modules/{2}/Views/{1}/{0}.ascx",
- "~/Modules/{2}/Views/Shared/{0}.aspx",
- "~/Modules/{2}/Views/Shared/{0}.ascx",
- "~/Themes/{2}/Views/{1}/{0}.aspx",
- "~/Themes/{2}/Views/{1}/{0}.ascx",
- "~/Themes/{2}/Views/Shared/{0}.aspx",
- "~/Themes/{2}/Views/Shared/{0}.ascx",
- "~/Core/{2}/Views/{1}/{0}.aspx",
- "~/Core/{2}/Views/{1}/{0}.ascx",
- "~/Core/{2}/Views/Shared/{0}.aspx",
- "~/Core/{2}/Views/Shared/{0}.ascx",
- "~/Areas/{2}/Views/{1}/{0}.aspx",
- "~/Areas/{2}/Views/{1}/{0}.ascx",
- "~/Areas/{2}/Views/Shared/{0}.aspx",
- "~/Areas/{2}/Views/Shared/{0}.ascx",
- };
-
- var viewEngine = _viewEngines.OfType().Single();
- viewEngine.AreaMasterLocationFormats = orchardMasterLocationFormats
- .Concat(viewEngine.AreaMasterLocationFormats)
- .Distinct()
- .ToArray();
- viewEngine.AreaViewLocationFormats = orchardLocationFormats
- .Concat(viewEngine.AreaViewLocationFormats)
- .Distinct()
- .ToArray();
- viewEngine.AreaPartialViewLocationFormats = orchardLocationFormats
- .Concat(viewEngine.AreaPartialViewLocationFormats)
- .Distinct()
- .ToArray();
- }
-
- private static string ModelsLocationFormat(ExtensionDescriptor descriptor) {
- return Path.Combine(Path.Combine(descriptor.Location, descriptor.Name), "Views/Shared/{0}.ascx");
- }
-
-
-
}
}
diff --git a/src/Orchard/Environment/Extensions/ExtensionManager.cs b/src/Orchard/Environment/Extensions/ExtensionManager.cs
index f8a51dad2..1560913ce 100644
--- a/src/Orchard/Environment/Extensions/ExtensionManager.cs
+++ b/src/Orchard/Environment/Extensions/ExtensionManager.cs
@@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Web;
-using ICSharpCode.SharpZipLib.Zip;
-using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions.Folders;
-using Orchard.Environment.Extensions.Helpers;
using Orchard.Environment.Extensions.Loaders;
using Orchard.Environment.Extensions.Models;
using Orchard.Localization;
@@ -18,6 +14,7 @@ namespace Orchard.Environment.Extensions {
public class ExtensionManager : IExtensionManager {
private readonly IEnumerable _folders;
private readonly IEnumerable _loaders;
+ private IEnumerable _featureDescriptors;
public Localizer T { get; set; }
public ILogger Logger { get; set; }
@@ -31,14 +28,20 @@ namespace Orchard.Environment.Extensions {
// This method does not load extension types, simply parses extension manifests from
// the filesystem.
+ public ExtensionDescriptor GetExtension(string name) {
+ return AvailableExtensions().FirstOrDefault(x => x.Name == name);
+ }
+
public IEnumerable AvailableExtensions() {
return _folders.SelectMany(folder => folder.AvailableExtensions());
}
public IEnumerable AvailableFeatures() {
- var featureDescriptors = AvailableExtensions().SelectMany(ext => ext.Features);
- var featureDescriptorsOrdered = featureDescriptors.OrderByDependencies(HasDependency);
- return featureDescriptorsOrdered.ToReadOnlyCollection();
+ if (_featureDescriptors == null || _featureDescriptors.Count() == 0) {
+ _featureDescriptors = AvailableExtensions().SelectMany(ext => ext.Features).OrderByDependencies(HasDependency).ToReadOnlyCollection();
+ return _featureDescriptors;
+ }
+ return _featureDescriptors;
}
///
@@ -65,7 +68,7 @@ namespace Orchard.Environment.Extensions {
}
private IEnumerable LoadedExtensions() {
- foreach ( var descriptor in AvailableExtensions() ) {
+ foreach (var descriptor in AvailableExtensions()) {
ExtensionEntry entry = null;
try {
entry = BuildEntry(descriptor);
@@ -138,65 +141,6 @@ namespace Orchard.Environment.Extensions {
return null;
}
- public void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle) {
- if (String.IsNullOrEmpty(extensionType)) {
- throw new ArgumentException(T("extensionType was null or empty").ToString());
- }
- string targetFolder;
- if (String.Equals(extensionType, "Theme", StringComparison.OrdinalIgnoreCase)) {
- targetFolder = PathHelpers.GetPhysicalPath("~/Themes");
- }
- else if (String.Equals(extensionType, "Module", StringComparison.OrdinalIgnoreCase)) {
- targetFolder = PathHelpers.GetPhysicalPath("~/Modules");
- }
- else {
- throw new ArgumentException(T("extensionType was not recognized").ToString());
- }
- int postedFileLength = extensionBundle.ContentLength;
- Stream postedFileStream = extensionBundle.InputStream;
- byte[] postedFileData = new byte[postedFileLength];
- postedFileStream.Read(postedFileData, 0, postedFileLength);
-
- using (var memoryStream = new MemoryStream(postedFileData)) {
- var fileInflater = new ZipInputStream(memoryStream);
- ZipEntry entry;
- while ((entry = fileInflater.GetNextEntry()) != null) {
- string directoryName = Path.GetDirectoryName(entry.Name);
- if (!Directory.Exists(Path.Combine(targetFolder, directoryName))) {
- Directory.CreateDirectory(Path.Combine(targetFolder, directoryName));
- }
-
- if (!entry.IsDirectory && entry.Name.Length > 0) {
- var len = Convert.ToInt32(entry.Size);
- var extractedBytes = new byte[len];
- fileInflater.Read(extractedBytes, 0, len);
- File.WriteAllBytes(Path.Combine(targetFolder, entry.Name), extractedBytes);
- }
- }
- }
- }
-
- public void UninstallExtension(string extensionType, string extensionName) {
- if (String.IsNullOrEmpty(extensionType)) {
- throw new ArgumentException(T("extensionType was null or empty").ToString());
- }
- string targetFolder;
- if (String.Equals(extensionType, "Theme", StringComparison.OrdinalIgnoreCase)) {
- targetFolder = PathHelpers.GetPhysicalPath("~/Themes");
- }
- else if (String.Equals(extensionType, "Module", StringComparison.OrdinalIgnoreCase)) {
- targetFolder = PathHelpers.GetPhysicalPath("~/Modules");
- }
- else {
- throw new ArgumentException(T("extensionType was not recognized").ToString());
- }
- targetFolder = Path.Combine(targetFolder, extensionName);
- if (!Directory.Exists(targetFolder)) {
- throw new ArgumentException(T("extension was not found").ToString());
- }
- Directory.Delete(targetFolder, true);
- }
-
private ExtensionEntry BuildEntry(ExtensionDescriptor descriptor) {
foreach (var loader in _loaders) {
ExtensionEntry entry = loader.Load(descriptor);
diff --git a/src/Orchard/Environment/Extensions/IExtensionManager.cs b/src/Orchard/Environment/Extensions/IExtensionManager.cs
index b4917f132..d12f4a1ab 100644
--- a/src/Orchard/Environment/Extensions/IExtensionManager.cs
+++ b/src/Orchard/Environment/Extensions/IExtensionManager.cs
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
-using System.Web;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions.Models;
@@ -8,10 +7,10 @@ namespace Orchard.Environment.Extensions {
public interface IExtensionManager {
IEnumerable AvailableExtensions();
IEnumerable AvailableFeatures();
- IEnumerable LoadFeatures(IEnumerable featureDescriptors);
- void InstallExtension(string extensionType, HttpPostedFileBase extensionBundle);
- void UninstallExtension(string extensionType, string extensionName);
+ ExtensionDescriptor GetExtension(string name);
+
+ IEnumerable LoadFeatures(IEnumerable featureDescriptors);
}
public static class ExtensionManagerExtensions {
diff --git a/src/Orchard/Environment/Extensions/Models/Extension.cs b/src/Orchard/Environment/Extensions/Models/Extension.cs
deleted file mode 100644
index 3043c42e3..000000000
--- a/src/Orchard/Environment/Extensions/Models/Extension.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace Orchard.Environment.Extensions.Models {
- public class Extension {
- }
-}
\ No newline at end of file
diff --git a/src/Orchard/Environment/Extensions/Models/ExtensionDescriptor.cs b/src/Orchard/Environment/Extensions/Models/ExtensionDescriptor.cs
index 667b8ab1e..ba2452a2f 100644
--- a/src/Orchard/Environment/Extensions/Models/ExtensionDescriptor.cs
+++ b/src/Orchard/Environment/Extensions/Models/ExtensionDescriptor.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
namespace Orchard.Environment.Extensions.Models {
public class ExtensionDescriptor {
@@ -26,7 +27,7 @@ namespace Orchard.Environment.Extensions.Models {
public string WebSite { get; set; }
public string Tags { get; set; }
public string AntiForgery { get; set; }
- public string Zones { get; set; }
+ public string Zones { get; set; }
public string BaseTheme { get; set; }
public IEnumerable Features { get; set; }
diff --git a/src/Orchard/Environment/Extensions/Models/FeatureDescriptor.cs b/src/Orchard/Environment/Extensions/Models/FeatureDescriptor.cs
index 6f25ea09d..7f67705f7 100644
--- a/src/Orchard/Environment/Extensions/Models/FeatureDescriptor.cs
+++ b/src/Orchard/Environment/Extensions/Models/FeatureDescriptor.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
namespace Orchard.Environment.Extensions.Models {
diff --git a/src/Orchard/Environment/Features/FeatureManager.cs b/src/Orchard/Environment/Features/FeatureManager.cs
new file mode 100644
index 000000000..b4f347f71
--- /dev/null
+++ b/src/Orchard/Environment/Features/FeatureManager.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Orchard.Environment.Descriptor;
+using Orchard.Environment.Descriptor.Models;
+using Orchard.Environment.Extensions;
+using Orchard.Environment.Extensions.Models;
+
+namespace Orchard.Environment.Features {
+ public interface IFeatureManager : IDependency {
+ IEnumerable GetAvailableFeatures();
+ IEnumerable GetEnabledFeatures();
+
+ void EnableFeatures(IEnumerable featureNames);
+ void DisableFeatures(IEnumerable featureNames);
+ }
+
+ public class FeatureManager : IFeatureManager {
+ private readonly IExtensionManager _extensionManager;
+ private readonly ShellDescriptor _shellDescriptor;
+ private readonly IShellDescriptorManager _shellDescriptorManager;
+
+ public FeatureManager(
+ IExtensionManager extensionManager,
+ ShellDescriptor shellDescriptor,
+ IShellDescriptorManager shellDescriptorManager) {
+ _extensionManager = extensionManager;
+ _shellDescriptor = shellDescriptor;
+ _shellDescriptorManager = shellDescriptorManager;
+ }
+
+ public IEnumerable GetAvailableFeatures() {
+ return _extensionManager.AvailableFeatures();
+ }
+
+ public IEnumerable GetEnabledFeatures() {
+ throw new NotImplementedException();
+ }
+
+ public void EnableFeatures(IEnumerable featureNames) {
+ var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
+
+ var updatedFeatures = currentShellDescriptor.Features
+ .Union(featureNames
+ .Where(name => !currentShellDescriptor.Features.Any(sf => sf.Name == name))
+ .Select(name => new ShellFeature {Name = name}));
+
+ _shellDescriptorManager.UpdateShellDescriptor(
+ currentShellDescriptor.SerialNumber,
+ updatedFeatures,
+ currentShellDescriptor.Parameters);
+ }
+
+ public void DisableFeatures(IEnumerable featureNames) {
+ var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
+
+ var updatedFeatures = currentShellDescriptor.Features
+ .Where(sf => !featureNames.Contains(sf.Name));
+
+ _shellDescriptorManager.UpdateShellDescriptor(
+ currentShellDescriptor.SerialNumber,
+ updatedFeatures,
+ currentShellDescriptor.Parameters);
+ }
+
+
+ //private void DisableThemeFeatures(string themeName) {
+ // var themes = new Queue();
+ // while (themeName != null) {
+ // if (themes.Contains(themeName))
+ // throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features disabled.", themeName).Text);
+ // var theme = GetThemeByName(themeName);
+ // if (theme == null)
+ // break;
+ // themes.Enqueue(themeName);
+
+ // themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
+ // ? theme.BaseTheme
+ // : null;
+
+ // }
+
+ // while (themes.Count > 0)
+ // _moduleService.DisableFeatures(new[] { themes.Dequeue() });
+ //}
+
+ //private void EnableThemeFeatures(string themeName) {
+ // var themes = new Stack();
+ // while (themeName != null) {
+ // if (themes.Contains(themeName))
+ // throw new InvalidOperationException(T("The theme \"{0}\" is already in the stack of themes that need features enabled.", themeName).Text);
+ // themes.Push(themeName);
+
+ // var theme = GetThemeByName(themeName);
+ // themeName = !string.IsNullOrWhiteSpace(theme.BaseTheme)
+ // ? theme.BaseTheme
+ // : null;
+ // }
+
+ // while (themes.Count > 0)
+ // _moduleService.EnableFeatures(new[] { themes.Pop() });
+ //}
+
+ //private bool DoEnableTheme(string themeName) {
+ // if (string.IsNullOrWhiteSpace(themeName))
+ // return false;
+
+ // //todo: (heskew) need messages given in addition to all of these early returns so something meaningful can be presented to the user
+ // var themeToEnable = GetThemeByName(themeName);
+ // if (themeToEnable == null)
+ // return false;
+
+ // // ensure all base themes down the line are present and accounted for
+ // //todo: (heskew) dito on the need of a meaningful message
+ // if (!AllBaseThemesAreInstalled(themeToEnable.BaseTheme))
+ // return false;
+
+ // // enable all theme features
+ // EnableThemeFeatures(themeToEnable.Name);
+ // return true;
+ //}
+
+ }
+}
diff --git a/src/Orchard/Environment/IHostEnvironment.cs b/src/Orchard/Environment/IHostEnvironment.cs
index 772ef04fa..c1cba668a 100644
--- a/src/Orchard/Environment/IHostEnvironment.cs
+++ b/src/Orchard/Environment/IHostEnvironment.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Web;
using System.Web.Hosting;
using Orchard.Services;
@@ -36,7 +37,7 @@ namespace Orchard.Environment {
}
public bool IsAssemblyLoaded(string name) {
- return AppDomain.CurrentDomain.GetAssemblies().Any(a => a.GetName().Name == name);
+ return AppDomain.CurrentDomain.GetAssemblies().Any(assembly => new AssemblyName(assembly.FullName).Name == name);
}
public void RestartAppDomain() {
diff --git a/src/Orchard/Environment/OrchardServices.cs b/src/Orchard/Environment/OrchardServices.cs
index 42f9f492f..0f904f392 100644
--- a/src/Orchard/Environment/OrchardServices.cs
+++ b/src/Orchard/Environment/OrchardServices.cs
@@ -10,14 +10,17 @@ namespace Orchard.Environment {
[UsedImplicitly]
public class OrchardServices : IOrchardServices {
private readonly Lazy _shapeFactory;
+ private readonly IWorkContextAccessor _workContextAccessor;
public OrchardServices(
IContentManager contentManager,
ITransactionManager transactionManager,
IAuthorizer authorizer,
INotifier notifier,
- Lazy shapeFactory) {
+ Lazy shapeFactory,
+ IWorkContextAccessor workContextAccessor) {
_shapeFactory = shapeFactory;
+ _workContextAccessor = workContextAccessor;
ContentManager = contentManager;
TransactionManager = transactionManager;
Authorizer = authorizer;
@@ -29,5 +32,6 @@ namespace Orchard.Environment {
public IAuthorizer Authorizer { get; private set; }
public INotifier Notifier { get; private set; }
public dynamic New { get { return _shapeFactory.Value; } }
+ public WorkContext WorkContext { get { return _workContextAccessor.GetContext(); } }
}
}
diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs
index 5917f4d4c..885fa1a43 100644
--- a/src/Orchard/Environment/OrchardStarter.cs
+++ b/src/Orchard/Environment/OrchardStarter.cs
@@ -7,7 +7,6 @@ using System.Web.Mvc;
using Autofac;
using Autofac.Configuration;
using Orchard.Caching;
-using Orchard.Environment.AutofacUtil;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Compilers;
diff --git a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs
index 24a108c9c..c189ced00 100644
--- a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs
+++ b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs
@@ -89,10 +89,13 @@ namespace Orchard.Environment.ShellBuilders {
}
foreach (var item in blueprint.Controllers) {
- var serviceKey = (item.AreaName + "/" + item.ControllerName).ToLowerInvariant();
+ var serviceKeyName = (item.AreaName + "/" + item.ControllerName).ToLowerInvariant();
+ var serviceKeyType = item.Type;
RegisterType(builder, item)
.EnableDynamicProxy(dynamicProxyContext)
- .Keyed(serviceKey)
+ .Keyed(serviceKeyName)
+ .Keyed(serviceKeyType)
+ .WithMetadata("ControllerType", item.Type)
.InstancePerDependency()
.OnActivating(e => {
var controller = e.Instance as Controller;
diff --git a/src/Orchard/Environment/State/ShellStateCoordinator.cs b/src/Orchard/Environment/State/ShellStateCoordinator.cs
index 441df6183..ff876a139 100644
--- a/src/Orchard/Environment/State/ShellStateCoordinator.cs
+++ b/src/Orchard/Environment/State/ShellStateCoordinator.cs
@@ -7,7 +7,6 @@ using Orchard.Environment.Extensions.Models;
using Orchard.Environment.State.Models;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
-using Orchard.Utility;
namespace Orchard.Environment.State {
public class ShellStateCoordinator : IShellStateManagerEventHandler, IShellDescriptorManagerEventHandler {
@@ -102,7 +101,7 @@ namespace Orchard.Environment.State {
var shellState = _stateManager.GetShellState();
// start with description of all declared features in order - order preserved with all merging
- var orderedFeatureDescriptors = AllFeaturesInOrder();
+ var orderedFeatureDescriptors = _extensionManager.AvailableFeatures();
// merge feature state into ordered list
var orderedFeatureDescriptorsAndStates = orderedFeatureDescriptors
@@ -176,19 +175,9 @@ namespace Orchard.Environment.State {
FireApplyChangesIfNeeded();
}
- private IEnumerable AllFeaturesInOrder() {
- return OrderByDependencies(_extensionManager.AvailableExtensions().SelectMany(ext => ext.Features));
- }
-
static bool IsRising(ShellFeatureState state) {
return state.InstallState == ShellFeatureState.State.Rising ||
state.EnableState == ShellFeatureState.State.Rising;
}
-
- public static IEnumerable OrderByDependencies(IEnumerable descriptors) {
- return descriptors.OrderByDependencies((item, dep) =>
- item.Dependencies != null &&
- item.Dependencies.Any(x => StringComparer.OrdinalIgnoreCase.Equals(x, dep.Name)));
- }
}
}
diff --git a/src/Orchard/Events/IEventBusHandler.cs b/src/Orchard/Events/IEventBusHandler.cs
deleted file mode 100644
index 3cb6e12be..000000000
--- a/src/Orchard/Events/IEventBusHandler.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System.Collections.Generic;
-
-namespace Orchard.Events {
- public interface IEventBusHandler : IDependency {
- void Process(string messageName, IDictionary eventData);
- }
-}
diff --git a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs
index 7f0817619..94109df69 100644
--- a/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs
+++ b/src/Orchard/FileSystems/Media/FileSystemStorageProvider.cs
@@ -1,4 +1,5 @@
-using System;
+#if !AZURE
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -45,7 +46,7 @@ namespace Orchard.FileSystems.Media {
public string GetPublicUrl(string path) {
- return _publicPath + path.Replace(Path.DirectorySeparatorChar, '/');
+ return Map(_publicPath + path.Replace(Path.DirectorySeparatorChar, '/'));
}
public IStorageFile GetFile(string path) {
@@ -248,4 +249,5 @@ namespace Orchard.FileSystems.Media {
}
}
-}
\ No newline at end of file
+}
+#endif
\ No newline at end of file
diff --git a/src/Orchard/IOrchardServices.cs b/src/Orchard/IOrchardServices.cs
index ef68a0d09..0a99f23c7 100644
--- a/src/Orchard/IOrchardServices.cs
+++ b/src/Orchard/IOrchardServices.cs
@@ -10,5 +10,6 @@ namespace Orchard {
IAuthorizer Authorizer { get; }
INotifier Notifier { get; }
dynamic New { get; }
+ WorkContext WorkContext { get; }
}
}
diff --git a/src/Orchard/Localization/Commands/CultureCommands.cs b/src/Orchard/Localization/Commands/CultureCommands.cs
index 841187d55..0f4158dc9 100644
--- a/src/Orchard/Localization/Commands/CultureCommands.cs
+++ b/src/Orchard/Localization/Commands/CultureCommands.cs
@@ -1,17 +1,15 @@
using System.Linq;
-using JetBrains.Annotations;
using Orchard.Commands;
using Orchard.Localization.Services;
-using Orchard.Settings;
namespace Orchard.Localization.Commands {
public class CultureCommands : DefaultOrchardCommandHandler {
private readonly ICultureManager _cultureManager;
+ private readonly IOrchardServices _orchardServices;
- protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
-
- public CultureCommands(ICultureManager cultureManager) {
+ public CultureCommands(ICultureManager cultureManager, IOrchardServices orchardServices) {
_cultureManager = cultureManager;
+ _orchardServices = orchardServices;
}
[CommandHelp("cultures list \r\n\t" + "List site cultures")]
@@ -28,7 +26,7 @@ namespace Orchard.Localization.Commands {
[CommandHelp("cultures get site culture \r\n\t" + "Get culture for the site")]
[CommandName("cultures get site culture")]
public void GetSiteCulture() {
- Context.Output.WriteLine(T("Site Culture is {0}", CurrentSite.SiteCulture));
+ Context.Output.WriteLine(T("Site Culture is {0}", _orchardServices.WorkContext.CurrentSite.SiteCulture));
}
[CommandHelp("cultures set site culture \r\n\t" + "Set culture for the site")]
@@ -40,7 +38,7 @@ namespace Orchard.Localization.Commands {
Context.Output.WriteLine(T("Supplied culture name {0} is not valid.", cultureName));
return;
}
- CurrentSite.SiteCulture = cultureName;
+ _orchardServices.WorkContext.CurrentSite.SiteCulture = cultureName;
Context.Output.WriteLine(T("Site culture set to {0} successfully", cultureName));
}
diff --git a/src/Orchard/Localization/Services/DefaultCultureManager.cs b/src/Orchard/Localization/Services/DefaultCultureManager.cs
index 1ead59bc0..8ffc0d880 100644
--- a/src/Orchard/Localization/Services/DefaultCultureManager.cs
+++ b/src/Orchard/Localization/Services/DefaultCultureManager.cs
@@ -3,26 +3,27 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
-using JetBrains.Annotations;
using Orchard.Caching;
using Orchard.Data;
using Orchard.Localization.Records;
-using Orchard.Settings;
namespace Orchard.Localization.Services {
public class DefaultCultureManager : ICultureManager {
private readonly IRepository _cultureRepository;
private readonly IEnumerable _cultureSelectors;
private readonly ISignals _signals;
+ private readonly IWorkContextAccessor _workContextAccessor;
- public DefaultCultureManager(IRepository cultureRepository, IEnumerable cultureSelectors, ISignals signals) {
+ public DefaultCultureManager(IRepository cultureRepository,
+ IEnumerable cultureSelectors,
+ ISignals signals,
+ IWorkContextAccessor workContextAccessor) {
_cultureRepository = cultureRepository;
_cultureSelectors = cultureSelectors;
_signals = signals;
+ _workContextAccessor = workContextAccessor;
}
- protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
-
public IEnumerable ListCultures() {
var query = from culture in _cultureRepository.Table select culture.Culture;
return query.ToList();
@@ -75,7 +76,7 @@ namespace Orchard.Localization.Services {
}
public string GetSiteCulture() {
- return CurrentSite == null ? null : CurrentSite.SiteCulture;
+ return _workContextAccessor.GetContext().CurrentSite == null ? null : _workContextAccessor.GetContext().CurrentSite.SiteCulture;
}
// "" or
diff --git a/src/Orchard/Localization/Services/SiteCultureSelector.cs b/src/Orchard/Localization/Services/SiteCultureSelector.cs
index cac220fe6..b3e20761a 100644
--- a/src/Orchard/Localization/Services/SiteCultureSelector.cs
+++ b/src/Orchard/Localization/Services/SiteCultureSelector.cs
@@ -1,14 +1,16 @@
using System;
using System.Web;
-using JetBrains.Annotations;
-using Orchard.Settings;
namespace Orchard.Localization.Services {
public class SiteCultureSelector : ICultureSelector {
- protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; }
+ private readonly IWorkContextAccessor _workContextAccessor;
+
+ public SiteCultureSelector(IWorkContextAccessor workContextAccessor) {
+ _workContextAccessor = workContextAccessor;
+ }
public CultureSelectorResult GetCulture(HttpContextBase context) {
- string currentCultureName = CurrentSite.SiteCulture;
+ string currentCultureName = _workContextAccessor.GetContext().CurrentSite.SiteCulture;
if (String.IsNullOrEmpty(currentCultureName)) {
return null;
diff --git a/src/Orchard/Logging/LoggingModule.cs b/src/Orchard/Logging/LoggingModule.cs
index 5674b6fe2..b67da4b9c 100644
--- a/src/Orchard/Logging/LoggingModule.cs
+++ b/src/Orchard/Logging/LoggingModule.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Security;
+using System.Security.Permissions;
using Autofac;
using Autofac.Core;
using Castle.Core.Logging;
@@ -14,11 +16,17 @@ namespace Orchard.Logging {
// by default, use Orchard's logger that delegates to Castle's logger factory
moduleBuilder.RegisterType().As().InstancePerLifetimeScope();
- // by default, use Castle's TraceSource based logger factory
- moduleBuilder.RegisterType().As().InstancePerLifetimeScope();
+ try {
+ // by default, use Castle's TraceSource based logger factory
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy).Demand();
+ moduleBuilder.RegisterType().As().InstancePerLifetimeScope();
+ } catch (SecurityException) {
+ // if security model does not allow it, fall back to null logger factory
+ moduleBuilder.RegisterType().As().InstancePerLifetimeScope();
+ }
// call CreateLogger in response to the request for an ILogger implementation
- moduleBuilder.Register((ctx, ps) => CreateLogger(ctx, ps)).As().InstancePerDependency();
+ moduleBuilder.Register(CreateLogger).As().InstancePerDependency();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
@@ -70,4 +78,4 @@ namespace Orchard.Logging {
return loggerFactory.CreateLogger(containingType);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Orchard/Modules/IModule.cs b/src/Orchard/Modules/IModule.cs
deleted file mode 100644
index 4bd53880c..000000000
--- a/src/Orchard/Modules/IModule.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Collections.Generic;
-using Orchard.Environment.Extensions.Models;
-
-namespace Orchard.Modules {
- public interface IModule {
- string ModuleName { get; set; }
- string DisplayName { get; set; }
- string Description { get; set; }
- string Version { get; set; }
- string Author { get; set; }
- string HomePage { get; set; }
- string Tags { get; set; }
- IEnumerable Features { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Orchard/Modules/IModuleFeature.cs b/src/Orchard/Modules/IModuleFeature.cs
deleted file mode 100644
index cc59efa9b..000000000
--- a/src/Orchard/Modules/IModuleFeature.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Orchard.Environment.Extensions.Models;
-
-namespace Orchard.Modules {
- public interface IModuleFeature {
- FeatureDescriptor Descriptor { get; set; }
- bool IsEnabled { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Orchard/Modules/IModuleService.cs b/src/Orchard/Modules/IModuleService.cs
deleted file mode 100644
index a4033bb84..000000000
--- a/src/Orchard/Modules/IModuleService.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Collections.Generic;
-using System.Web;
-
-namespace Orchard.Modules {
- public interface IModuleService : IDependency {
- IModule GetModuleByName(string moduleName);
- IEnumerable GetInstalledModules();
- void InstallModule(HttpPostedFileBase file);
- void UninstallModule(string moduleName);
- IEnumerable GetAvailableFeatures();
- void EnableFeatures(IEnumerable featureNames);
- void EnableFeatures(IEnumerable featureNames, bool force);
- void DisableFeatures(IEnumerable featureNames);
- void DisableFeatures(IEnumerable featureNames, bool force);
- }
-}
\ No newline at end of file
diff --git a/src/Orchard/Mvc/Html/ThemeExtensions.cs b/src/Orchard/Mvc/Html/ThemeExtensions.cs
index 8ffe8d5f1..cb6da312d 100644
--- a/src/Orchard/Mvc/Html/ThemeExtensions.cs
+++ b/src/Orchard/Mvc/Html/ThemeExtensions.cs
@@ -1,7 +1,9 @@
-using System.Web.Mvc;
+using System;
+using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.UI;
using Orchard.Environment.Extensions;
+using Orchard.Environment.Extensions.Models;
using Orchard.Themes;
using Orchard.Validation;
@@ -15,12 +17,13 @@ namespace Orchard.Mvc.Html {
helper.RenderPartial(viewName);
}
+ [Obsolete("How do you know the request theme is the same as the place the theme template is rendering from?")]
public static string ThemePath(this HtmlHelper helper, string path) {
- return helper.ThemePath(helper.Resolve().GetRequestTheme(helper.ViewContext.RequestContext), path);
+ return helper.ThemePath(helper.Resolve().GetRequestTheme(helper.ViewContext.RequestContext), path);
}
- public static string ThemePath(this HtmlHelper helper, ITheme theme, string path) {
- return helper.Resolve().GetThemeLocation(theme) + path;
+ public static string ThemePath(this HtmlHelper helper, ExtensionDescriptor theme, string path) {
+ return theme.Location + "/" + theme.Name + path;
}
}
}
diff --git a/src/Orchard/Mvc/OrchardControllerFactory.cs b/src/Orchard/Mvc/OrchardControllerFactory.cs
index 8e85305e2..929cdf5fb 100644
--- a/src/Orchard/Mvc/OrchardControllerFactory.cs
+++ b/src/Orchard/Mvc/OrchardControllerFactory.cs
@@ -1,12 +1,32 @@
+using System;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using Autofac.Core;
+using Autofac.Features.Metadata;
namespace Orchard.Mvc {
+ public interface IControllerType {
+ Type ControllerType { get; }
+ }
+
public class OrchardControllerFactory : DefaultControllerFactory {
- public override IController CreateController(RequestContext requestContext, string controllerName) {
+ bool TryResolve(WorkContext workContext, object serviceKey, out T instance ) {
+ if (workContext != null) {
+ var key = new KeyedService(serviceKey, typeof (T));
+ object value;
+ if (workContext.Resolve().TryResolve(key, out value)) {
+ instance = (T) value;
+ return true;
+ }
+ }
+
+ instance = default(T);
+ return false;
+ }
+
+ protected override Type GetControllerType(RequestContext requestContext, string controllerName) {
var routeData = requestContext.RouteData;
// Determine the area name for the request, and fall back to stock orchard controllers
@@ -15,18 +35,24 @@ namespace Orchard.Mvc {
// Service name pattern matches the identification strategy
var serviceKey = (areaName + "/" + controllerName).ToLowerInvariant();
- // Now that the request container is known - try to resolve the controller
- object controller;
- var service = new KeyedService(serviceKey, typeof(IController));
-
+ // Now that the request container is known - try to resolve the controller information
+ Lazy info;
var workContext = requestContext.GetWorkContext();
-
- if (workContext != null &&
- workContext.Resolve().TryResolve(service, out controller)) {
- return (IController)controller;
+ if (TryResolve(workContext, serviceKey, out info)) {
+ return info.Metadata.ControllerType;
}
- return base.CreateController(requestContext, controllerName);
+ return null;
+ }
+
+ protected override IController GetControllerInstance(RequestContext requestContext, System.Type controllerType) {
+ IController controller;
+ var workContext = requestContext.GetWorkContext();
+ if (TryResolve(workContext, controllerType, out controller)) {
+ return controller;
+ }
+
+ return null;
}
public static string GetAreaName(RouteBase route) {
diff --git a/src/Orchard/Mvc/Routes/RoutePublisher.cs b/src/Orchard/Mvc/Routes/RoutePublisher.cs
index c8175469c..5aa62c1a9 100644
--- a/src/Orchard/Mvc/Routes/RoutePublisher.cs
+++ b/src/Orchard/Mvc/Routes/RoutePublisher.cs
@@ -2,21 +2,26 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
+using Autofac;
+using Orchard.Environment;
using Orchard.Environment.Configuration;
namespace Orchard.Mvc.Routes {
public class RoutePublisher : IRoutePublisher {
private readonly RouteCollection _routeCollection;
private readonly ShellSettings _shellSettings;
- private readonly Func _shellRouteFactory;
+ private readonly ILifetimeScope _shellLifetimeScope;
+ private readonly IRunningShellTable _runningShellTable;
public RoutePublisher(
RouteCollection routeCollection,
ShellSettings shellSettings,
- Func shellRouteFactory) {
+ ILifetimeScope shellLifetimeScope,
+ IRunningShellTable runningShellTable) {
_routeCollection = routeCollection;
_shellSettings = shellSettings;
- _shellRouteFactory = shellRouteFactory;
+ _shellLifetimeScope = shellLifetimeScope;
+ _runningShellTable = runningShellTable;
}
public void Publish(IEnumerable routes) {
@@ -41,8 +46,8 @@ namespace Orchard.Mvc.Routes {
// new routes are added
foreach (var routeDescriptor in routesArray) {
- //_routeCollection.Add(route.Name, _shellRouteFactory(_shellSettings.Name, route.Route));
- _routeCollection.Add(routeDescriptor.Name, _shellRouteFactory(routeDescriptor.Route));
+ ShellRoute shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _shellLifetimeScope, _runningShellTable);
+ _routeCollection.Add(routeDescriptor.Name, shellRoute);
}
}
}
diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs
index 4ba2f9c18..e95e7a72f 100644
--- a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs
+++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemeAwareViewEngine.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Web.Mvc;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.Extensions;
+using Orchard.Environment.Extensions.Models;
using Orchard.Themes;
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
@@ -64,15 +65,15 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
return _configuredEnginesCache.BindBareEngines(() => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine())));
}
- private IViewEngine ShallowEngines(ITheme theme) {
+ private IViewEngine ShallowEngines(ExtensionDescriptor theme) {
//return _configuredEnginesCache.BindShallowEngines(theme.ThemeName, () => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine())));
return DeepEngines(theme);
}
- private IViewEngine DeepEngines(ITheme theme) {
- return _configuredEnginesCache.BindDeepEngines(theme.ThemeName, () => {
+ private IViewEngine DeepEngines(ExtensionDescriptor theme) {
+ return _configuredEnginesCache.BindDeepEngines(theme.Name, () => {
var engines = Enumerable.Empty();
- var themeLocation = _extensionManager.GetThemeLocation(theme);
+ var themeLocation = theme.Location + "/" + theme.Name;
var themeParams = new CreateThemeViewEngineParams { VirtualPath = themeLocation };
engines = engines.Concat(_viewEngineProviders.Select(vep => vep.CreateThemeViewEngine(themeParams)));
diff --git a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs
index 17b657666..ef079d052 100644
--- a/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs
+++ b/src/Orchard/Mvc/ViewEngines/ThemeAwareness/ThemedViewResultFilter.cs
@@ -6,12 +6,12 @@ using Orchard.Themes;
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public class ThemedViewResultFilter : FilterProvider, IResultFilter {
- private readonly IThemeService _themeService;
+ private readonly IThemeManager _themeManager;
private readonly WorkContext _workContext;
private readonly ILayoutAwareViewEngine _layoutAwareViewEngine;
- public ThemedViewResultFilter(IThemeService themeService, WorkContext workContext, ILayoutAwareViewEngine layoutAwareViewEngine) {
- _themeService = themeService;
+ public ThemedViewResultFilter(IThemeManager themeManager, WorkContext workContext, ILayoutAwareViewEngine layoutAwareViewEngine) {
+ _themeManager = themeManager;
_workContext = workContext;
_layoutAwareViewEngine = layoutAwareViewEngine;
Logger = NullLogger.Instance;
@@ -26,7 +26,7 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
}
if (_workContext.CurrentTheme == null) {
- _workContext.CurrentTheme = _themeService.GetRequestTheme(filterContext.RequestContext);
+ _workContext.CurrentTheme = _themeManager.GetRequestTheme(filterContext.RequestContext);
}
viewResultBase.ViewEngineCollection = new ViewEngineCollection(new[] { _layoutAwareViewEngine });
diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj
index f93a771dd..20fc0a2bc 100644
--- a/src/Orchard/Orchard.Framework.csproj
+++ b/src/Orchard/Orchard.Framework.csproj
@@ -114,6 +114,7 @@
..\..\lib\linqnhibernate\NHibernate.Linq.dll
+ 3.5
@@ -174,6 +175,7 @@
+
@@ -185,6 +187,7 @@
+
@@ -658,18 +661,13 @@
-
-
-
-
-
@@ -712,7 +710,6 @@
-
@@ -774,17 +771,13 @@
-
-
-
-
-
+
diff --git a/src/Orchard/Properties/AssemblyInfo.cs b/src/Orchard/Properties/AssemblyInfo.cs
index d576845a5..e8e04c110 100644
--- a/src/Orchard/Properties/AssemblyInfo.cs
+++ b/src/Orchard/Properties/AssemblyInfo.cs
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -36,3 +37,4 @@ using System.Runtime.InteropServices;
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
+[assembly: SecurityTransparent]
\ No newline at end of file
diff --git a/src/Orchard/Scripting/IScriptingManager.cs b/src/Orchard/Scripting/IScriptingManager.cs
index 65256b0b4..06eea09bb 100644
--- a/src/Orchard/Scripting/IScriptingManager.cs
+++ b/src/Orchard/Scripting/IScriptingManager.cs
@@ -1,8 +1,12 @@
-namespace Orchard.Scripting {
+using System;
+using Microsoft.Scripting.Hosting;
+
+namespace Orchard.Scripting {
public interface IScriptingManager : IDependency {
dynamic GetVariable(string name);
void SetVariable(string name, object value);
dynamic ExecuteExpression(string expression);
void ExecuteFile(string fileName);
+ dynamic ExecuteOperation(Func invoke);
}
}
diff --git a/src/Orchard/Scripting/ScriptingManager.cs b/src/Orchard/Scripting/ScriptingManager.cs
index 545134f20..4589dc63f 100644
--- a/src/Orchard/Scripting/ScriptingManager.cs
+++ b/src/Orchard/Scripting/ScriptingManager.cs
@@ -5,10 +5,12 @@ namespace Orchard.Scripting {
public class ScriptingManager : IScriptingManager {
private readonly IScriptingRuntime _scriptingRuntime;
private Lazy _scope;
+ private Lazy _operations;
public ScriptingManager(IScriptingRuntime scriptingRuntime) {
_scriptingRuntime = scriptingRuntime;
_scope = new Lazy(()=>_scriptingRuntime.CreateScope());
+ _operations = new Lazy(()=>_scope.Value.Engine.CreateOperations());
}
public dynamic GetVariable(string name) {
@@ -23,6 +25,10 @@ namespace Orchard.Scripting {
return _scriptingRuntime.ExecuteExpression(expression, _scope.Value);
}
+ public dynamic ExecuteOperation(Func invoke) {
+ return invoke(_operations.Value);
+ }
+
public void ExecuteFile(string fileName) {
_scriptingRuntime.ExecuteFile(fileName, _scope.Value);
}
diff --git a/src/Orchard/Security/Authorizer.cs b/src/Orchard/Security/Authorizer.cs
index 09e249a66..a6c27b215 100644
--- a/src/Orchard/Security/Authorizer.cs
+++ b/src/Orchard/Security/Authorizer.cs
@@ -1,5 +1,4 @@
-using JetBrains.Annotations;
-using Orchard.ContentManagement;
+using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Security.Permissions;
using Orchard.UI.Notify;
@@ -14,16 +13,18 @@ namespace Orchard.Security {
public class Authorizer : IAuthorizer {
private readonly IAuthorizationService _authorizationService;
private readonly INotifier _notifier;
+ private readonly IWorkContextAccessor _workContextAccessor;
public Authorizer(
IAuthorizationService authorizationService,
- INotifier notifier) {
+ INotifier notifier,
+ IWorkContextAccessor workContextAccessor) {
_authorizationService = authorizationService;
_notifier = notifier;
+ _workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
- protected virtual IUser CurrentUser { get; [UsedImplicitly] private set; }
public Localizer T { get; set; }
public bool Authorize(Permission permission) {
@@ -35,17 +36,17 @@ namespace Orchard.Security {
}
public bool Authorize(Permission permission, IContent content, LocalizedString message) {
- if (_authorizationService.TryCheckAccess(permission, CurrentUser, content))
+ if (_authorizationService.TryCheckAccess(permission, _workContextAccessor.GetContext().CurrentUser, content))
return true;
if (message != null) {
- if (CurrentUser == null) {
+ if (_workContextAccessor.GetContext().CurrentUser == null) {
_notifier.Error(T("{0}. Anonymous users do not have {1} permission.",
message, permission.Name));
}
else {
_notifier.Error(T("{0}. Current user, {2}, does not have {1} permission.",
- message, permission.Name, CurrentUser.UserName));
+ message, permission.Name, _workContextAccessor.GetContext().CurrentUser.UserName));
}
}
diff --git a/src/Orchard/Security/SecurityModule.cs b/src/Orchard/Security/SecurityModule.cs
deleted file mode 100644
index 33c3b57c1..000000000
--- a/src/Orchard/Security/SecurityModule.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-using System.Reflection;
-using Autofac.Core;
-using Castle.Core.Interceptor;
-using Orchard.Environment.AutofacUtil.DynamicProxy2;
-using Module = Autofac.Module;
-
-namespace Orchard.Security {
- public class SecurityModule : Module {
- protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
- var implementationType = registration.Activator.LimitType;
- var property = FindProperty(implementationType);
-
- if (property != null) {
- registration.InterceptedBy();
- }
- }
-
- private static PropertyInfo FindProperty(Type type) {
- return type.GetProperty("CurrentUser",
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
- null,
- typeof(IUser),
- new Type[0],
- null);
- }
- }
-
- public interface ISecurityModuleInterceptor : IInterceptor, IDependency {
-
- }
-
- public class SecurityModuleInterceptor : ISecurityModuleInterceptor {
- private readonly IAuthenticationService _authenticationService;
-
- public SecurityModuleInterceptor(IAuthenticationService authenticationService) {
- _authenticationService = authenticationService;
- }
-
- public void Intercept(IInvocation invocation) {
- if (invocation.Method.ReturnType == typeof(IUser) && invocation.Method.Name == "get_CurrentUser") {
- invocation.ReturnValue = _authenticationService.GetAuthenticatedUser();
- }
- else {
- invocation.Proceed();
- }
- }
- }
-}
diff --git a/src/Orchard/Services/Clock.cs b/src/Orchard/Services/Clock.cs
index 6e1b5a38b..e72f7fae1 100644
--- a/src/Orchard/Services/Clock.cs
+++ b/src/Orchard/Services/Clock.cs
@@ -4,6 +4,16 @@ using Orchard.Caching;
namespace Orchard.Services {
public interface IClock : IVolatileProvider {
DateTime UtcNow { get; }
+
+ ///
+ /// Each retrieved value is cached during the specified amount of time.
+ ///
+ IVolatileToken When(TimeSpan duration);
+
+ ///
+ /// The cache is active until the specified time. Each subsequent access won't be cached.
+ ///
+ IVolatileToken WhenUtc(DateTime absoluteUtc);
}
public class Clock : IClock {
@@ -11,5 +21,33 @@ namespace Orchard.Services {
get { return DateTime.UtcNow; }
}
+ public IVolatileToken When(TimeSpan duration) {
+ return new AbsoluteExpirationToken(this, duration);
+ }
+
+ public IVolatileToken WhenUtc(DateTime absoluteUtc) {
+ return new AbsoluteExpirationToken(this, absoluteUtc);
+ }
+
+ public class AbsoluteExpirationToken : IVolatileToken {
+ private readonly IClock _clock;
+ private readonly DateTime _invalidateUtc;
+
+ public AbsoluteExpirationToken(IClock clock, DateTime invalidateUtc) {
+ _clock = clock;
+ _invalidateUtc = invalidateUtc;
+ }
+
+ public AbsoluteExpirationToken(IClock clock, TimeSpan duration) {
+ _clock = clock;
+ _invalidateUtc = _clock.UtcNow.Add(duration);
+ }
+
+ public bool IsCurrent {
+ get {
+ return _clock.UtcNow < _invalidateUtc;
+ }
+ }
+ }
}
}
diff --git a/src/Orchard/Settings/SettingsModule.cs b/src/Orchard/Settings/SettingsModule.cs
deleted file mode 100644
index d77d3b820..000000000
--- a/src/Orchard/Settings/SettingsModule.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-using System.Reflection;
-using Autofac.Core;
-using Castle.Core.Interceptor;
-using Orchard.Environment.AutofacUtil.DynamicProxy2;
-using Module = Autofac.Module;
-
-namespace Orchard.Settings {
- public class SettingsModule : Module {
- protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
- var implementationType = registration.Activator.LimitType;
- var property = FindProperty(implementationType);
-
- if (property != null) {
- registration.InterceptedBy();
- }
- }
-
- private static PropertyInfo FindProperty(Type type) {
- return type.GetProperty("CurrentSite",
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
- null,
- typeof(ISite),
- new Type[0],
- null);
- }
- }
-
- public interface ISettingsModuleInterceptor : IInterceptor, IDependency {
-
- }
-
- public class SettingsModuleInterceptor : ISettingsModuleInterceptor {
- private readonly ISiteService _siteService;
-
- public SettingsModuleInterceptor(ISiteService siteService) {
- _siteService = siteService;
- }
-
- public void Intercept(IInvocation invocation) {
- if (invocation.Method.ReturnType == typeof(ISite) && invocation.Method.Name == "get_CurrentSite") {
- invocation.ReturnValue = _siteService.GetSiteSettings();
- }
- else {
- invocation.Proceed();
- }
- }
- }
-}
diff --git a/src/Orchard/Themes/ExtensionManagerExtensions.cs b/src/Orchard/Themes/ExtensionManagerExtensions.cs
deleted file mode 100644
index 7de3840b0..000000000
--- a/src/Orchard/Themes/ExtensionManagerExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.IO;
-using System.Linq;
-using Orchard.Environment.Extensions;
-using Orchard.Environment.Extensions.Models;
-
-namespace Orchard.Themes {
- public static class ExtensionManagerExtensions {
- public static ExtensionDescriptor GetExtensionDescriptor(this IExtensionManager extensionManager, string extensionType, string extensionName) {
- return
- extensionManager.AvailableExtensions().FirstOrDefault(
- ed => ed.ExtensionType == extensionType && ed.Name == extensionName);
- }
-
- public static string GetThemeLocation(this IExtensionManager extensionManager, ITheme theme) {
- ExtensionDescriptor descriptor = extensionManager.GetExtensionDescriptor("Theme", theme.ThemeName);
-
- return descriptor != null ? Path.Combine(descriptor.Location, descriptor.Name) : "~";
- }
- }
-}
\ No newline at end of file
diff --git a/src/Orchard/Themes/ITheme.cs b/src/Orchard/Themes/ITheme.cs
deleted file mode 100644
index e7e53ce86..000000000
--- a/src/Orchard/Themes/ITheme.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Orchard.Themes {
- ///
- /// Interface provided by the "themes" model.
- ///
- public interface ITheme {
- bool Enabled { get; set; }
- string ThemeName { get; set; }
- string DisplayName { get; set; }
- string Description { get; set; }
- string Version { get; set; }
- string Author { get; set; }
- string HomePage { get; set; }
- string Tags { get; set; }
- string Zones { get; set; }
- string BaseTheme { get; set; }
- }
-}
diff --git a/src/Orchard/Themes/IThemeManager.cs b/src/Orchard/Themes/IThemeManager.cs
new file mode 100644
index 000000000..40f37ccf4
--- /dev/null
+++ b/src/Orchard/Themes/IThemeManager.cs
@@ -0,0 +1,9 @@
+using System;
+using System.Web.Routing;
+using Orchard.Environment.Extensions.Models;
+
+namespace Orchard.Themes {
+ public interface IThemeManager : IDependency {
+ ExtensionDescriptor GetRequestTheme(RequestContext requestContext);
+ }
+}
diff --git a/src/Orchard/Themes/IThemeService.cs b/src/Orchard/Themes/IThemeService.cs
deleted file mode 100644
index 53e819c5d..000000000
--- a/src/Orchard/Themes/IThemeService.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Collections.Generic;
-using System.Web;
-using System.Web.Routing;
-
-namespace Orchard.Themes {
- public interface IThemeService : IDependency {
- ITheme GetThemeByName(string themeName);
-
- ITheme GetSiteTheme();
- void SetSiteTheme(string themeName);
- ITheme GetRequestTheme(RequestContext requestContext);
-
- void EnableTheme(string themeName);
- void DisableTheme(string themeName);
-
- IEnumerable GetInstalledThemes();
- IEnumerable GetEnabledThemes();
- void InstallTheme(HttpPostedFileBase file);
- void UninstallTheme(string themeName);
- }
-}
diff --git a/src/Orchard/Themes/ThemeManager.cs b/src/Orchard/Themes/ThemeManager.cs
new file mode 100644
index 000000000..21dd709a8
--- /dev/null
+++ b/src/Orchard/Themes/ThemeManager.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Routing;
+using Orchard.Environment.Extensions;
+using Orchard.Environment.Extensions.Models;
+
+namespace Orchard.Themes {
+ public class ThemeManager : IThemeManager {
+ private readonly IEnumerable _themeSelectors;
+ private readonly IExtensionManager _extensionManager;
+
+ public ThemeManager(IEnumerable themeSelectors,
+ IExtensionManager extensionManager) {
+ _themeSelectors = themeSelectors;
+ _extensionManager = extensionManager;
+ }
+
+ public ExtensionDescriptor GetRequestTheme(RequestContext requestContext) {
+ var requestTheme = _themeSelectors
+ .Select(x => x.GetTheme(requestContext))
+ .Where(x => x != null)
+ .OrderByDescending(x => x.Priority);
+
+ if (requestTheme.Count() < 1)
+ return null;
+
+ foreach (var theme in requestTheme) {
+ var t = _extensionManager.GetExtension(theme.ThemeName);
+ if (t != null)
+ return t;
+ }
+
+ return _extensionManager.GetExtension("SafeMode");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Orchard/Themes/ThemesModule.cs b/src/Orchard/Themes/ThemesModule.cs
deleted file mode 100644
index e2d3ef45e..000000000
--- a/src/Orchard/Themes/ThemesModule.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Reflection;
-using Autofac;
-using Autofac.Core;
-using Module = Autofac.Module;
-
-namespace Orchard.Themes {
- public class ThemesModule : Module {
- protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
-
- var themeProperty = FindThemeProperty(registration.Activator.LimitType);
-
- if (themeProperty != null) {
- registration.Activated += (sender, e) => {
- var themeService = e.Context.Resolve();
- var currentTheme = themeService.GetSiteTheme();
- themeProperty.SetValue(e.Instance, currentTheme, null);
- };
- }
- }
-
- private static PropertyInfo FindThemeProperty(Type type) {
- return type.GetProperty("CurrentTheme", typeof(ITheme));
- }
- }
-}
diff --git a/src/Orchard/UI/Navigation/NavigationManager.cs b/src/Orchard/UI/Navigation/NavigationManager.cs
index e5b998390..125225eb2 100644
--- a/src/Orchard/UI/Navigation/NavigationManager.cs
+++ b/src/Orchard/UI/Navigation/NavigationManager.cs
@@ -2,7 +2,6 @@
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
-using JetBrains.Annotations;
using Orchard.Security;
using Orchard.Security.Permissions;
@@ -11,15 +10,15 @@ namespace Orchard.UI.Navigation {
private readonly IEnumerable _providers;
private readonly IAuthorizationService _authorizationService;
private readonly UrlHelper _urlHelper;
+ private readonly IOrchardServices _orchardServices;
- public NavigationManager(IEnumerable providers, IAuthorizationService authorizationService, UrlHelper urlHelper) {
+ public NavigationManager(IEnumerable providers, IAuthorizationService authorizationService, UrlHelper urlHelper, IOrchardServices orchardServices) {
_providers = providers;
_authorizationService = authorizationService;
_urlHelper = urlHelper;
+ _orchardServices = orchardServices;
}
- protected virtual IUser CurrentUser { get; [UsedImplicitly] private set; }
-
public IEnumerable