Merge dev => perf

--HG--
branch : perf
This commit is contained in:
Renaud Paquay
2010-11-15 16:23:24 -08:00
520 changed files with 29102 additions and 26066 deletions

1
.hgsub
View File

@@ -0,0 +1 @@

View File

@@ -2,3 +2,8 @@ e048b594f33613d53b59a3578d17511dc833ecb5 MIX10
a6b8d094848d4efee67c787e52e5f7d358e3f0c1 0.5
48d6ca62955335ce6a51859d5fab43b3b48d1911 0.8
0ffac89fcc3013edf7283f6ebd761ee967368e77 perf first pass
48d6ca62955335ce6a51859d5fab43b3b48d1911 0.8
0000000000000000000000000000000000000000 0.8
0000000000000000000000000000000000000000 0.8
083d09cd94a7c9175272fba453a156673be9db78 0.8
523f3564d2c053ff068970eab8c64eaf74e3dcec perf baseline

View File

@@ -48,7 +48,8 @@
<MSBuild
Projects="$(SrcFolder)\Orchard.Azure\Orchard.Azure.CloudService.sln"
Targets="Build"
Properties="Configuration=Release;OutputPath=$(CompileFolder);PlatformTarget=x64" />
Properties="Configuration=Release;OutputPath=$(CompileFolder);PlatformTarget=x64;DefineConstants=AZURE"
/>
<MSBuild
Projects="$(SrcFolder)\Orchard.Azure.sln"

View File

@@ -135,6 +135,12 @@ Website: http://code.google.com/p/nhlambdaextensions/
Copyright: Unknown http://code.google.com/p/nhlambdaextensions/people/list
License: LGPL 2.1
NuGet
-----
Website: http://www.nuget.org/nuget.codeplex.com
Copyright: Copyright 2010 Outercurve Foundation
License: Apache Software Foundation License 2.0
nUnit
-----
Website: http://www.nunit.org/index.php

View File

@@ -209,7 +209,7 @@
<ItemGroup>
<!--<MsDeploy-Folder-Input Include="$(StageFolder)\**\*" Exclude="$(StageFolder)\**\bin\**\*.pdb;$(StageFolder)\**\bin\**\*.xml" />-->
<MsDeploy-Folder-Input Include="$(StageFolder)\**\*" Exclude="$(StageFolder)\**\bin\**\*.xml" />
<MsDeploy-Parameters Include="$(LibFolder)\msdeploy\*.xml"/>
<MsDeploy-Parameters Include="$(LibFolder)\msdeploy\*.xml;$(LibFolder)\msdeploy\*.sql"/>
</ItemGroup>
<Copy SourceFiles="@(MsDeploy-Folder-Input)"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

45
lib/msdeploy/install.sql Normal file
View File

@@ -0,0 +1,45 @@
/**********************************************************************/
/* Install.SQL */
/* Creates a login and makes the user a member of db roles */
/* */
/**********************************************************************/
-- Declare variables for database name, username and password
DECLARE @dbName sysname,
@dbUser sysname,
@dbPwd nvarchar(max);
-- Set variables for database name, username and password
SET @dbName = 'PlaceHolderForDb';
SET @dbUser = 'PlaceHolderForUser';
SET @dbPwd = 'PlaceHolderForPassword';
DECLARE @cmd nvarchar(max)
-- Create login
IF( SUSER_SID(@dbUser) is null )
BEGIN
print '-- Creating login '
SET @cmd = N'CREATE LOGIN ' + quotename(@dbUser) + N' WITH PASSWORD ='''+ replace(@dbPwd, '''', '''''') + N''''
EXEC(@cmd)
END
-- Create database user and map to login
-- and add user to the datareader, datawriter, ddladmin and securityadmin roles
--
SET @cmd = N'USE ' + quotename(@DBName) + N';
IF( NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ''' + replace(@dbUser, '''', '''''') + N'''))
BEGIN
print ''-- Creating user'';
CREATE USER ' + quotename(@dbUser) + N' FOR LOGIN ' + quotename(@dbUser) + N';
print ''-- Adding user'';
EXEC sp_addrolemember ''db_ddladmin'', ''' + replace(@dbUser, '''', '''''') + N''';
print ''-- Adding user'';
EXEC sp_addrolemember ''db_securityadmin'', ''' + replace(@dbUser, '''', '''''') + N''';
print ''-- Adding user'';
EXEC sp_addrolemember ''db_datareader'', ''' + replace(@dbUser, '''', '''''') + N''';
print ''-- Adding user'';
EXEC sp_addrolemember ''db_datawriter'', ''' + replace(@dbUser, '''', '''''') + N''';
END'
EXEC(@cmd)
GO

View File

@@ -2,4 +2,7 @@
<iisapp path="Orchard" managedRuntimeVersion="v4.0" />
<setAcl path="Orchard/App_Data" setAclAccess="Modify" />
<setAcl path="Orchard/Media" setAclAccess="Modify" />
<setAcl path="Orchard/Modules" setAclAccess="Modify" />
<setAcl path="Orchard/Themes" setAclAccess="Modify" />
<dbFullSql path="install.sql" />
</MSDeploy.iisApp>

View File

@@ -1,15 +1,77 @@
<parameters>
<!-- Prompts where to copy the content files and takes a web site path (such as "contoso.com/app") -->
<parameter name="Application Path" description="Full site path where you would like to install your application (i.e., Default Web Site/orchard)" defaultValue="Default Web Site/orchard" tags="iisapp">
<parameterEntry type="ProviderPath" scope="iisapp" match="Orchard" />
</parameter>
<parameter name="SetAclParameter1" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/App_Data" tags="Hidden, NoDatabase">
<!-- This is the parameter that is used to set ACLs, it's set to the application path filled in by the user -->
<parameter name="SetAclParameter1" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/App_Data" tags="Hidden">
<parameterEntry type="ProviderPath" scope="setAcl" match="Orchard/App_Data" />
</parameter>
<parameter name="SetAclParameter2" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/Media" tags="Hidden, NoDatabase">
<parameter name="SetAclParameter2" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/Media" tags="Hidden">
<parameterEntry type="ProviderPath" scope="setAcl" match="Orchard/Media" />
</parameter>
</parameters>
<parameter name="SetAclParameter3" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/Modules" tags="Hidden">
<parameterEntry type="ProviderPath" scope="setAcl" match="Orchard/Modules" />
</parameter>
<parameter name="SetAclParameter4" description="Hidden - automatically sets write access for the app" defaultValue="{Application Path}/Themes" tags="Hidden">
<parameterEntry type="ProviderPath" scope="setAcl" match="Orchard/Themes" />
</parameter>
<!-- Prompts for database server name, this is used in the connection string parameter later -->
<parameter name="Database Server" description="Location of your database server (i.e. server name, IP address, or server\instance)" defaultValue=".\SQLEXPRESS" tags="SQL, dbServer">
</parameter>
<!-- Prompts for the database name and fills it into the database scripts -->
<parameter name="Database Name" description="Name of the database for Orchard." defaultValue="orchard" tags="SQL, dbName">
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForDb" />
</parameter>
<!-- Prompts for the database username and fills it into the database scripts.
The SQL tag indicates it is a parameter required for SQL, the DbUsername tag indicates this is a Db username -->
<parameter name="Database Username" description="User name to access you application database." defaultValue="orcharduser" tags="SQL, DbUsername">
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForUser" />
</parameter>
<!-- Prompts for the database password and fills it into the database scripts.
The SQL tag indicates it is a parameter required for SQL, the DbUserPassword tag indicates this is a Db password -->
<parameter name="Database Password" description="Password for the Database Username." tags="New, Password, SQL, DbUserPassword">
<parameterEntry type="TextFile" scope="install.sql" match="PlaceHolderForPassword" />
</parameter>
<!-- Prompts for the admin creds and uses it for the administrator connection string. This is used to create a login and assign permissions.
The SQL tag indicates it is a parameter required for SQL. The DbAdminUsername tag indicates it should be used when the user is creating a new database.
If they're not, it can be filled in with the DbUsername value. -->
<parameter name="Database Administrator" description="Administrator user name for your database This is used to create the database and user if the don't already exist." defaultValue="sa" tags="SQL, dbAdminUsername">
</parameter>
<!-- Prompts for the admin password and uses it for the administrator connection string.
This is use to create a login and assign permissions. The SQL tag indicates it is a parameter required for SQL.
The DbAdminPassword tag indicates it should be used when the user is creating a new database. If they're not, it can be filled in with the DbUserPassword value. -->
<parameter name="Database Administrator Password" description="Password for the database administrator account." tags="New, Password, SQL, dbAdminPassword">
</parameter>
<!-- This is the hidden admin connection string used to run the database scripts -->
<parameter name="Connection String" description="Automatically sets the connection string for the connection request." defaultValue="Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};" tags="Hidden, SQL">
<parameterEntry type="ProviderPath" scope="dbfullsql" match="install.sql" />
</parameter>
<parameter name="Settings Data Provider for SQL" description="Orchard SQL Data Provider Setting" defaultValue="DataProvider: SqlServer" tags="Hidden, SQL">
<parameterEntry kind="TextFile" scope="\\Settings\.txt$" match="DataProvider\s*:[^\r\n]*" />
</parameter>
<parameter name="Settings Data Connection String for SQL" description="Orchard SQL Data Connection String Setting" defaultValue="DataConnectionString: Server={Database Server};Database={Database Name};uid={Database Administrator};Pwd={Database Administrator Password};" tags="Hidden, SQL">
<parameterEntry kind="TextFile" scope="\\Settings\.txt$" match="DataConnectionString\s*:[^\r\n]*" />
</parameter>
<parameter name="Settings Data Provider for SQLCE" description="Orchard SQLCE Data Provider Setting" defaultValue="DataProvider: SqlCe" tags="Hidden, SQLCE, NoStore">
<parameterEntry kind="TextFile" scope="\\Settings\.txt$" match="DataProvider\s*:[^\r\n]*" />
</parameter>
<parameter name="Settings Data Connection String for SQLCE" description="Orchard SQLCE Data Connection String Setting" defaultValue="DataConnectionString: " tags="Hidden, SQLCE, NoStore">
<parameterEntry kind="TextFile" scope="\\Settings\.txt$" match="DataConnectionString\s*:[^\r\n]*" />
</parameter>
</parameters>

13
lib/nuget/COPYRIGHT.txt Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2010 Outercurve Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

14
lib/nuget/CREDITS.txt Normal file
View File

@@ -0,0 +1,14 @@
NuGet Project
ASP.NET Open Source Gallery at Outercurve Foundation
Copyright 2010 Outercurve Foundation
This product includes software developed at
The Outercurve Foundation (http://www.outercurve.org/).
NuGet includes or is derivative of works distributed under the licenses listed below. The full text for most of the licenses listed below can be found in the LICENSE.txt file accompanying each work. The original copyright notices have been preserved within the respective files and or packages. Please refer to the specific files and/or packages for more detailed information about the authors, copyright notices, and licenses.
ProvideBindingPathAttribute (Visual Studio SDK)
-----
Website: http://msdn.microsoft.com/en-us/library/bb166441(VS.80).aspx
Copyright: Copyright (c) 2010 Microsoft
License: Apache 2.0

177
lib/nuget/LICENSE.txt Normal file
View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

BIN
lib/nuget/NuGet.Core.dll Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -4,30 +4,6 @@
<name>YamlSerializer</name>
</assembly>
<members>
<member name="T:System.Yaml.Serialization.EasyTypeConverter">
<summary>
Converts various types to / from string.<br/>
I don't remember why this class was needed....
</summary>
<example>
<code>
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);
}
</code>
</example>
</member>
<member name="T:System.Yaml.Serialization.YamlRepresenter">
<summary>
Converts C# object to YamlNode
@@ -141,18 +117,21 @@
<param name="tag">Tag for the mapping.</param>
<returns>Created mapping node.</returns>
</member>
<member name="T:System.Yaml.ParseErrorException">
<member name="T:System.Yaml.YamlPresenter">
<summary>
<para>When <see cref="T:System.Yaml.Parser`1"/> reports syntax error by exception, this class is thrown.</para>
Converts YamlNode tree into yaml text.
</summary>
<example>
<code>
YamlNode node;
YamlPresenter.ToYaml(node);
<para>Sytax errors can also be reported by simply returing false with giving some warnings.</para>
</summary>
</member>
<member name="M:System.Yaml.ParseErrorException.#ctor(System.String)">
<summary>
Initialize an instance of <see cref="T:System.Yaml.ParseErrorException"/>
</summary>
<param name="message">Error message.</param>
YamlNode node1;
YamlNode node2;
YamlNode node3;
YamlPresenter.ToYaml(node1, node2, node3);
</code>
</example>
</member>
<member name="T:System.Yaml.Parser`1">
<summary>
@@ -855,24 +834,57 @@
Column in a text.
</summary>
</member>
<member name="T:System.Yaml.YamlTagValidator">
<member name="T:System.Yaml.StringUriEncodingExtention">
<summary>
Validates a text as a global tag in YAML.
Add string class two methods: .UriEscape(), .UriUnescape()
<a href="http://www.faqs.org/rfcs/rfc4151.html">RFC4151 - The 'tag' URI Scheme</a>>
Charset that is not escaped is represented NonUriChar member.
NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&amp;=$,\[\]]");
</summary>
</member>
<member name="M:System.Yaml.YamlTagValidator.IsValid(System.String)">
<member name="M:System.Yaml.StringUriEncodingExtention.UriEscape(System.String)">
<summary>
Validates a text as a global tag in YAML.
Escape the string in URI encoding format.
</summary>
<param name="tag">A candidate for a global tag in YAML.</param>
<returns>True if <paramref name="tag"/> is a valid global tag.</returns>
<param name="s">String to be escaped.</param>
<returns>Escaped string.</returns>
</member>
<member name="T:System.Yaml.YamlTagValidator.Status">
<member name="M:System.Yaml.StringUriEncodingExtention.UriEscapeForTag(System.String)">
<summary>
Not used in this parser
Escape the string in URI encoding format.
</summary>
<param name="s">String to be escaped.</param>
<returns>Escaped string.</returns>
</member>
<member name="M:System.Yaml.StringUriEncodingExtention.UriUnescape(System.String)">
<summary>
Unescape the string escaped in URI encoding format.
</summary>
<param name="s">String to be unescape.</param>
<returns>Unescaped string.</returns>
</member>
<member name="T:System.Yaml.UriEncoding">
<summary>
Escape / Unescape string in URI encoding format
Charset that is not escaped is represented NonUriChar member.
NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&amp;=$,\[\]]");
</summary>
</member>
<member name="T:System.Yaml.ParseErrorException">
<summary>
<para>When <see cref="T:System.Yaml.Parser`1"/> reports syntax error by exception, this class is thrown.</para>
<para>Sytax errors can also be reported by simply returing false with giving some warnings.</para>
</summary>
</member>
<member name="M:System.Yaml.ParseErrorException.#ctor(System.String)">
<summary>
Initialize an instance of <see cref="T:System.Yaml.ParseErrorException"/>
</summary>
<param name="message">Error message.</param>
</member>
<member name="T:System.Yaml.RehashableDictionary`2">
<summary>
@@ -942,159 +954,6 @@
added to or removed from the dictionary.
</summary>
</member>
<member name="T:System.Yaml.YamlParser">
<summary>
<para>A text parser for<br/>
YAML Aint Markup Language (YAML™) Version 1.2<br/>
3rd Edition (2009-07-21)<br/>
http://yaml.org/spec/1.2/spec.html </para>
<para>This class parse a YAML document and compose representing <see cref="T:System.Yaml.YamlNode"/> graph.</para>
</summary>
<example>
<code>
string yaml = LoadYamlSource();
YamlParser parser = new YamlParser();
Node[] result = null;
try {
result = parser.Parse(yaml);
...
// you can reuse parser as many times you want
...
} catch( ParseErrorException e ) {
MessageBox.Show(e.Message);
}
if(result != null) {
...
}
</code>
</example>
<remarks>
<para>Currently, this parser violates the YAML 1.2 specification in the following points.</para>
<para>- line breaks are not normalized.</para>
<para>- omission of the final line break is allowed in plain / literal / folded text.</para>
<para>- ':' followed by ns-indicator is excluded from ns-plain-char.</para>
</remarks>
</member>
<member name="M:System.Yaml.YamlParser.#ctor">
<summary>
Initialize a YAML parser.
</summary>
</member>
<member name="M:System.Yaml.YamlParser.Parse(System.String)">
<summary>
Parse YAML text and returns a list of <see cref="T:System.Yaml.YamlNode"/>.
</summary>
<param name="yaml">YAML text to be parsed.</param>
<returns>A list of <see cref="T:System.Yaml.YamlNode"/> parsed from the given text</returns>
</member>
<member name="M:System.Yaml.YamlParser.Parse(System.String,System.Yaml.YamlConfig)">
<summary>
Parse YAML text and returns a list of <see cref="T:System.Yaml.YamlNode"/>.
</summary>
<param name="yaml">YAML text to be parsed.</param>
<param name="config"><see cref="T:System.Yaml.YamlConfig">YAML Configuration</see> to be used in parsing.</param>
<returns>A list of <see cref="T:System.Yaml.YamlNode"/> parsed from the given text</returns>
</member>
<member name="M:System.Yaml.YamlParser.StoreWarning(System.String)">
<summary>
Add message in <see cref="P:System.Yaml.YamlParser.Warnings"/> property.
</summary>
<param name="message"></param>
</member>
<member name="M:System.Yaml.YamlParser.ReservedDirective(System.String,System.String[])">
<summary>
Invoked when unknown directive is found in YAML document.
</summary>
<param name="name">Name of the directive</param>
<param name="args">Parameters for the directive</param>
</member>
<member name="M:System.Yaml.YamlParser.YamlDirective(System.String)">
<summary>
Invoked when YAML directive is found in YAML document.
</summary>
<param name="version">Given version</param>
</member>
<member name="M:System.Yaml.YamlParser.Rewind">
<summary>
rewinding action
</summary>
</member>
<member name="M:System.Yaml.YamlParser.SetTag(System.String,System.String)">
<summary>
set status.tag with tag resolution
</summary>
<param name="tag_handle"></param>
<param name="tag_suffix"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.YamlParser.SetTag(System.String)">
<summary>
set status.tag with verbatim tag value
</summary>
<param name="verbatim_tag">verbatim tag</param>
<returns></returns>
</member>
<member name="M:System.Yaml.YamlParser.AutoDetectTag(System.String)">
<summary>
Used when the parser resolves a tag for a scalar node from its value.
New resolution rules can be add before calling <see cref="M:System.Yaml.YamlParser.Parse(System.String)"/> method.
</summary>
</member>
<member name="M:System.Yaml.YamlParser.eScalar">
<summary>
[105]
</summary>
</member>
<member name="M:System.Yaml.YamlParser.eNode">
<summary>
[106]
</summary>
</member>
<member name="P:System.Yaml.YamlParser.Warnings">
<summary>
Warnings that are made while parsing a YAML text.
This property is cleared by new call for <see cref="M:System.Yaml.YamlParser.Parse(System.String)"/> method.
</summary>
</member>
<member name="T:System.Yaml.YamlParser.State">
<summary>
additional fields to be rewound
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.tag">
<summary>
tag for the next value (will be cleared when the next value is created)
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.anchor">
<summary>
anchor for the next value (will be cleared when the next value is created)
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.value">
<summary>
current value
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.anchor_depth">
<summary>
anchor rewinding position
</summary>
</member>
<member name="F:System.Yaml.YamlParser.Charsets.cIndicator">
<summary>
[22]
</summary>
</member>
<member name="F:System.Yaml.YamlParser.Charsets.cFlowIndicator">
<summary>
[23]
</summary>
</member>
<member name="T:System.Yaml.Serialization.YamlConstructor">
<summary>
Construct YAML node tree that represents a given C# object.
@@ -1117,109 +976,6 @@
<param name="config"><see cref="T:System.Yaml.YamlConfig"/> to customize serialization.</param>
<returns></returns>
</member>
<member name="T:System.Yaml.StringUriEncodingExtention">
<summary>
Add string class two methods: .UriEscape(), .UriUnescape()
Charset that is not escaped is represented NonUriChar member.
NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&amp;=$,\[\]]");
</summary>
</member>
<member name="M:System.Yaml.StringUriEncodingExtention.UriEscape(System.String)">
<summary>
Escape the string in URI encoding format.
</summary>
<param name="s">String to be escaped.</param>
<returns>Escaped string.</returns>
</member>
<member name="M:System.Yaml.StringUriEncodingExtention.UriEscapeForTag(System.String)">
<summary>
Escape the string in URI encoding format.
</summary>
<param name="s">String to be escaped.</param>
<returns>Escaped string.</returns>
</member>
<member name="M:System.Yaml.StringUriEncodingExtention.UriUnescape(System.String)">
<summary>
Unescape the string escaped in URI encoding format.
</summary>
<param name="s">String to be unescape.</param>
<returns>Unescaped string.</returns>
</member>
<member name="T:System.Yaml.UriEncoding">
<summary>
Escape / Unescape string in URI encoding format
Charset that is not escaped is represented NonUriChar member.
NonUriChar = new Regex(@"[^0-9A-Za-z\-_.!~*'()\\;/?:@&amp;=$,\[\]]");
</summary>
</member>
<member name="T:System.Yaml.YamlTagPrefixes">
<summary>
Reset();
SetupDefaultTagPrefixes();
Add(tag_handle, tag_prefix);
verbatim_tag = Resolve(tag_handle, tag_name);
</summary>
</member>
<member name="T:System.Yaml.YamlPresenter">
<summary>
Converts YamlNode tree into yaml text.
</summary>
<example>
<code>
YamlNode node;
YamlPresenter.ToYaml(node);
YamlNode node1;
YamlNode node2;
YamlNode node3;
YamlPresenter.ToYaml(node1, node2, node3);
</code>
</example>
</member>
<member name="T:System.Yaml.Serialization.ObjectMemberAccessor">
<summary>
object に代入されたクラスや構造体のメンバーに、リフレクションを
解して簡単にアクセスできるようにしたクラス
アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が
期待できる
</summary>
</member>
<member name="F:System.Yaml.Serialization.ObjectMemberAccessor.MemberAccessors">
<summary>
Caches ObjectMemberAccessor instances for reuse.
</summary>
</member>
<member name="M:System.Yaml.Serialization.ObjectMemberAccessor.FindFor(System.Type)">
<summary>
指定した型へのアクセス方法を表すインスタンスを返す
キャッシュに存在すればそれを返す
キャッシュに存在しなければ新しく作って返す
作った物はキャッシュされる
</summary>
<param name="type">クラスまたは構造体を表す型情報</param>
<returns></returns>
</member>
<member name="M:System.Yaml.Serialization.ObjectMemberAccessor.GetEnumerator">
<summary>
メンバ名と Accessor のペアを巡回する
</summary>
<returns></returns>
</member>
<member name="P:System.Yaml.Serialization.ObjectMemberAccessor.Item(System.Object,System.String)">
<summary>
メンバへの読み書きを行うことができる
</summary>
<param name="obj">オブジェクト</param>
<param name="name">メンバの名前</param>
<returns></returns>
</member>
<member name="T:System.Yaml.YamlConfig">
<summary>
<para>Configuration to customize YAML serialization.</para>
@@ -2720,6 +2476,348 @@
</summary>
<value>The number of child nodes of the sequence.</value>
</member>
<member name="T:System.Yaml.YamlParser">
<summary>
<para>A text parser for<br/>
YAML Aint Markup Language (YAML™) Version 1.2<br/>
3rd Edition (2009-07-21)<br/>
http://yaml.org/spec/1.2/spec.html </para>
<para>This class parse a YAML document and compose representing <see cref="T:System.Yaml.YamlNode"/> graph.</para>
</summary>
<example>
<code>
string yaml = LoadYamlSource();
YamlParser parser = new YamlParser();
Node[] result = null;
try {
result = parser.Parse(yaml);
...
// you can reuse parser as many times you want
...
} catch( ParseErrorException e ) {
MessageBox.Show(e.Message);
}
if(result != null) {
...
}
</code>
</example>
<remarks>
<para>Currently, this parser violates the YAML 1.2 specification in the following points.</para>
<para>- line breaks are not normalized.</para>
<para>- omission of the final line break is allowed in plain / literal / folded text.</para>
<para>- ':' followed by ns-indicator is excluded from ns-plain-char.</para>
</remarks>
</member>
<member name="M:System.Yaml.YamlParser.#ctor">
<summary>
Initialize a YAML parser.
</summary>
</member>
<member name="M:System.Yaml.YamlParser.Parse(System.String)">
<summary>
Parse YAML text and returns a list of <see cref="T:System.Yaml.YamlNode"/>.
</summary>
<param name="yaml">YAML text to be parsed.</param>
<returns>A list of <see cref="T:System.Yaml.YamlNode"/> parsed from the given text</returns>
</member>
<member name="M:System.Yaml.YamlParser.Parse(System.String,System.Yaml.YamlConfig)">
<summary>
Parse YAML text and returns a list of <see cref="T:System.Yaml.YamlNode"/>.
</summary>
<param name="yaml">YAML text to be parsed.</param>
<param name="config"><see cref="T:System.Yaml.YamlConfig">YAML Configuration</see> to be used in parsing.</param>
<returns>A list of <see cref="T:System.Yaml.YamlNode"/> parsed from the given text</returns>
</member>
<member name="M:System.Yaml.YamlParser.StoreWarning(System.String)">
<summary>
Add message in <see cref="P:System.Yaml.YamlParser.Warnings"/> property.
</summary>
<param name="message"></param>
</member>
<member name="M:System.Yaml.YamlParser.ReservedDirective(System.String,System.String[])">
<summary>
Invoked when unknown directive is found in YAML document.
</summary>
<param name="name">Name of the directive</param>
<param name="args">Parameters for the directive</param>
</member>
<member name="M:System.Yaml.YamlParser.YamlDirective(System.String)">
<summary>
Invoked when YAML directive is found in YAML document.
</summary>
<param name="version">Given version</param>
</member>
<member name="M:System.Yaml.YamlParser.Rewind">
<summary>
rewinding action
</summary>
</member>
<member name="M:System.Yaml.YamlParser.SetTag(System.String,System.String)">
<summary>
set status.tag with tag resolution
</summary>
<param name="tag_handle"></param>
<param name="tag_suffix"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.YamlParser.SetTag(System.String)">
<summary>
set status.tag with verbatim tag value
</summary>
<param name="verbatim_tag">verbatim tag</param>
<returns></returns>
</member>
<member name="M:System.Yaml.YamlParser.AutoDetectTag(System.String)">
<summary>
Used when the parser resolves a tag for a scalar node from its value.
New resolution rules can be add before calling <see cref="M:System.Yaml.YamlParser.Parse(System.String)"/> method.
</summary>
</member>
<member name="M:System.Yaml.YamlParser.eScalar">
<summary>
[105]
</summary>
</member>
<member name="M:System.Yaml.YamlParser.eNode">
<summary>
[106]
</summary>
</member>
<member name="P:System.Yaml.YamlParser.Warnings">
<summary>
Warnings that are made while parsing a YAML text.
This property is cleared by new call for <see cref="M:System.Yaml.YamlParser.Parse(System.String)"/> method.
</summary>
</member>
<member name="T:System.Yaml.YamlParser.State">
<summary>
additional fields to be rewound
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.tag">
<summary>
tag for the next value (will be cleared when the next value is created)
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.anchor">
<summary>
anchor for the next value (will be cleared when the next value is created)
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.value">
<summary>
current value
</summary>
</member>
<member name="F:System.Yaml.YamlParser.State.anchor_depth">
<summary>
anchor rewinding position
</summary>
</member>
<member name="F:System.Yaml.YamlParser.Charsets.cIndicator">
<summary>
[22]
</summary>
</member>
<member name="F:System.Yaml.YamlParser.Charsets.cFlowIndicator">
<summary>
[23]
</summary>
</member>
<member name="T:System.Yaml.Serialization.EasyTypeConverter">
<summary>
Converts various types to / from string.<br/>
I don't remember why this class was needed....
</summary>
<example>
<code>
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);
}
</code>
</example>
</member>
<member name="T:System.Yaml.YamlTagPrefixes">
<summary>
Reset();
SetupDefaultTagPrefixes();
Add(tag_handle, tag_prefix);
verbatim_tag = Resolve(tag_handle, tag_name);
</summary>
</member>
<member name="T:System.Yaml.Serialization.ObjectMemberAccessor">
<summary>
object に代入されたクラスや構造体のメンバーに、リフレクションを
解して簡単にアクセスできるようにしたクラス
アクセス方法をキャッシュするので、繰り返し使用する場合に高速化が
期待できる
</summary>
</member>
<member name="F:System.Yaml.Serialization.ObjectMemberAccessor.MemberAccessors">
<summary>
Caches ObjectMemberAccessor instances for reuse.
</summary>
</member>
<member name="M:System.Yaml.Serialization.ObjectMemberAccessor.FindFor(System.Type)">
<summary>
指定した型へのアクセス方法を表すインスタンスを返す
キャッシュに存在すればそれを返す
キャッシュに存在しなければ新しく作って返す
作った物はキャッシュされる
</summary>
<param name="type">クラスまたは構造体を表す型情報</param>
<returns></returns>
</member>
<member name="M:System.Yaml.Serialization.ObjectMemberAccessor.GetEnumerator">
<summary>
メンバ名と Accessor のペアを巡回する
</summary>
<returns></returns>
</member>
<member name="P:System.Yaml.Serialization.ObjectMemberAccessor.Item(System.Object,System.String)">
<summary>
メンバへの読み書きを行うことができる
</summary>
<param name="obj">オブジェクト</param>
<param name="name">メンバの名前</param>
<returns></returns>
</member>
<member name="T:System.Yaml.TypeUtils">
<summary>
Type 関連のユーティリティメソッド
</summary>
<example>
<code>
Type type;
AttributeType attr = type.GetAttribute&lt;AttributeType&gt;();
PropertyInfo propInfo;
AttributeType attr = propInfo.GetAttribute&lt;AttributeType&gt;();
string name;
Type type = TypeUtils.GetType(name); // search from all assembly loaded
</code>
</example>
</member>
<member name="M:System.Yaml.TypeUtils.GetAttribute``1(System.Reflection.MemberInfo)">
<summary>
Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す
複数存在した場合には最後の値を返す
存在しなければ null を返す
</summary>
<typeparam name="AttributeType">取り出したい属性の型</typeparam>
<returns>取り出した属性値</returns>
</member>
<member name="M:System.Yaml.TypeUtils.GetType(System.String)">
<summary>
現在ロードされているすべてのアセンブリから name という名の型を探して返す
</summary>
<param name="name"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsPureValueType(System.Type)">
<summary>
Check if the type is a ValueType and does not contain any non ValueType members.
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsStruct(System.Type)">
<summary>
Returnes true if the specified <paramref name="type"/> is a struct type.
</summary>
<param name="type"><see cref="T:System.Type"/> to be analyzed.</param>
<returns>true if the specified <paramref name="type"/> is a struct type; otehrwise false.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.AreEqual(System.Object,System.Object)">
<summary>
Compare two objects to see if they are equal or not. Null is acceptable.
</summary>
<param name="a"></param>
<param name="b"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsNumeric(System.Object)">
<summary>
Return if an object is a numeric value.
</summary>
<param name="obj">Any object to be tested.</param>
<returns>True if object is a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.CastToNumericType(System.Object,System.Type)">
<summary>
Cast an object to a specified numeric type.
</summary>
<param name="obj">Any object</param>
<param name="type">Numric type</param>
<returns>Numeric value or null if the object is not a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.CastToDouble(System.Object)">
<summary>
Cast boxed numeric value to double
</summary>
<param name="obj">boxed numeric value</param>
<returns>Numeric value in double. Double.Nan if obj is not a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsPublic(System.Type)">
<summary>
Check if type is fully public or not.
Nested class is checked if all declared types are public.
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="T:System.Yaml.TypeUtils.EqualityComparerByRef`1">
<summary>
Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values.
</summary>
<typeparam name="T"></typeparam>
</member>
<member name="M:System.Yaml.TypeUtils.EqualityComparerByRef`1.Equals(`0,`0)">
<summary>
Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y).
</summary>
<param name="x">The first object to compare.</param>
<param name="y">The second object to compare.</param>
<returns>true if the specified objects are equal; otherwise, false.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.EqualityComparerByRef`1.GetHashCode(`0)">
<summary>
Serves as a hash function for the specified object for hashing algorithms and
data structures, such as a hash table.
</summary>
<param name="obj">The object for which to get a hash code.</param>
<returns>A hash code for the specified object.</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="obj"/> is null.</exception>
</member>
<member name="P:System.Yaml.TypeUtils.EqualityComparerByRef`1.Default">
<summary>
Returns a default equality comparer for the type specified by the generic argument.
</summary>
<value>The default instance of the System.Collections.Generic.EqualityComparer&lt;T&gt;
class for type T.</value>
</member>
<member name="T:System.Yaml.Serialization.YamlSerializer">
<summary>
<para><see cref="T:System.Yaml.Serialization.YamlSerializer"/> class has instance methods <see cref="M:System.Yaml.Serialization.YamlSerializer.Serialize(System.Object)"/> and <see cref="M:System.Yaml.Serialization.YamlSerializer.Deserialize(System.String,System.Type[])"/>,
@@ -3518,139 +3616,6 @@
</param>
</member>
<member name="T:System.Yaml.TypeUtils">
<summary>
Type 関連のユーティリティメソッド
</summary>
<example>
<code>
Type type;
AttributeType attr = type.GetAttribute&lt;AttributeType&gt;();
PropertyInfo propInfo;
AttributeType attr = propInfo.GetAttribute&lt;AttributeType&gt;();
string name;
Type type = TypeUtils.GetType(name); // search from all assembly loaded
</code>
</example>
</member>
<member name="M:System.Yaml.TypeUtils.GetAttribute``1(System.Reflection.MemberInfo)">
<summary>
Type や PropertyInfo, FieldInfo から指定された型の属性を取り出して返す
複数存在した場合には最後の値を返す
存在しなければ null を返す
</summary>
<typeparam name="AttributeType">取り出したい属性の型</typeparam>
<returns>取り出した属性値</returns>
</member>
<member name="M:System.Yaml.TypeUtils.GetType(System.String)">
<summary>
現在ロードされているすべてのアセンブリから name という名の型を探して返す
</summary>
<param name="name"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsPureValueType(System.Type)">
<summary>
Check if the type is a ValueType and does not contain any non ValueType members.
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsStruct(System.Type)">
<summary>
Returnes true if the specified <paramref name="type"/> is a struct type.
</summary>
<param name="type"><see cref="T:System.Type"/> to be analyzed.</param>
<returns>true if the specified <paramref name="type"/> is a struct type; otehrwise false.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.AreEqual(System.Object,System.Object)">
<summary>
Compare two objects to see if they are equal or not. Null is acceptable.
</summary>
<param name="a"></param>
<param name="b"></param>
<returns></returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsNumeric(System.Object)">
<summary>
Return if an object is a numeric value.
</summary>
<param name="obj">Any object to be tested.</param>
<returns>True if object is a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.CastToNumericType(System.Object,System.Type)">
<summary>
Cast an object to a specified numeric type.
</summary>
<param name="obj">Any object</param>
<param name="type">Numric type</param>
<returns>Numeric value or null if the object is not a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.CastToDouble(System.Object)">
<summary>
Cast boxed numeric value to double
</summary>
<param name="obj">boxed numeric value</param>
<returns>Numeric value in double. Double.Nan if obj is not a numeric value.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.IsPublic(System.Type)">
<summary>
Check if type is fully public or not.
Nested class is checked if all declared types are public.
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="T:System.Yaml.TypeUtils.EqualityComparerByRef`1">
<summary>
Equality comparer that uses Object.ReferenceEquals(x, y) to compare class values.
</summary>
<typeparam name="T"></typeparam>
</member>
<member name="M:System.Yaml.TypeUtils.EqualityComparerByRef`1.Equals(`0,`0)">
<summary>
Determines whether two objects of type T are equal by calling Object.ReferenceEquals(x, y).
</summary>
<param name="x">The first object to compare.</param>
<param name="y">The second object to compare.</param>
<returns>true if the specified objects are equal; otherwise, false.</returns>
</member>
<member name="M:System.Yaml.TypeUtils.EqualityComparerByRef`1.GetHashCode(`0)">
<summary>
Serves as a hash function for the specified object for hashing algorithms and
data structures, such as a hash table.
</summary>
<param name="obj">The object for which to get a hash code.</param>
<returns>A hash code for the specified object.</returns>
<exception cref="T:System.ArgumentNullException"><paramref name="obj"/> is null.</exception>
</member>
<member name="P:System.Yaml.TypeUtils.EqualityComparerByRef`1.Default">
<summary>
Returns a default equality comparer for the type specified by the generic argument.
</summary>
<value>The default instance of the System.Collections.Generic.EqualityComparer&lt;T&gt;
class for type T.</value>
</member>
<member name="T:System.Yaml.TypeUtils.HashCodeByRef`1">
<summary>
Calculate hash code by reference.
</summary>
<typeparam name="T"></typeparam>
</member>
<member name="M:System.Yaml.TypeUtils.HashCodeByRef`1.#cctor">
<summary>
Initializes a new instance of the HashCodeByRef&lt;T&gt; class.
</summary>
</member>
<member name="P:System.Yaml.TypeUtils.HashCodeByRef`1.GetHashCode">
<summary>
Calculate hash code by reference.
</summary>
</member>
<member name="T:System.Yaml.YamlTagResolver">
<summary>
Represents the way to automatically resolve Tag from the Value of a YamlScalar.
@@ -3766,5 +3731,24 @@
Unescape control codes, double quotations, backslashes escape in the YAML double quoted string format
</summary>
</member>
<member name="T:System.Yaml.YamlTagValidator">
<summary>
Validates a text as a global tag in YAML.
<a href="http://www.faqs.org/rfcs/rfc4151.html">RFC4151 - The 'tag' URI Scheme</a>>
</summary>
</member>
<member name="M:System.Yaml.YamlTagValidator.IsValid(System.String)">
<summary>
Validates a text as a global tag in YAML.
</summary>
<param name="tag">A candidate for a global tag in YAML.</param>
<returns>True if <paramref name="tag"/> is a valid global tag.</returns>
</member>
<member name="T:System.Yaml.YamlTagValidator.Status">
<summary>
Not used in this parser
</summary>
</member>
</members>
</doc>

Binary file not shown.

View File

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

View File

@@ -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<IStorageFile> 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<CloudBlockBlob>())
{
yield return new AzureBlobFileStorage(blobItem);
using ( new HttpContextWeaver() ) {
foreach (var blobItem in BlobClient.ListBlobsWithPrefix(prefix).OfType<CloudBlockBlob>()) {
// ignore directory entries
if(blobItem.Uri.AbsoluteUri.EndsWith(FolderEntry))
continue;
yield return new AzureBlobFileStorage(blobItem, _absoluteRoot);
}
}
}
public IEnumerable<IStorageFolder> 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<CloudBlobDirectory>()
.Select<CloudBlobDirectory, IStorageFolder>(d => new AzureBlobFolderStorage(d))
.Select<CloudBlobDirectory, IStorageFolder>(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");
}

View File

@@ -44,16 +44,25 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="Autofac.Configuration, Version=2.2.4.900, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\autofac\Autofac.Configuration.dll</HintPath>
</Reference>
<Reference Include="Autofac.Integration.Web">
<HintPath>..\..\..\lib\autofac\Autofac.Integration.Web.dll</HintPath>
</Reference>
<Reference Include="Autofac.Integration.Web.Mvc">
<HintPath>..\..\..\lib\autofac\Autofac.Integration.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="IronRuby">
<HintPath>..\..\..\lib\dlr\IronRuby.dll</HintPath>
</Reference>
<Reference Include="IronRuby.Libraries, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\dlr\IronRuby.Libraries.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Dynamic">
<HintPath>..\..\..\lib\dlr\Microsoft.Dynamic.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting">
<HintPath>..\..\..\lib\dlr\Microsoft.Scripting.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>False</Private>

View File

@@ -15,13 +15,6 @@
</sectionGroup>
</configSections>
<appSettings>
<!--
This is a workaround. Theres a known issue that causes Forms Authentication to always redirect unauthenticated users
to ~/Account/Login, ignoring the forms authentication setting used in Web.config.
-->
<add key="autoFormsAuthentication" value="false" />
</appSettings>
<system.diagnostics configSource="Config\Diagnostics.config"/>
<system.web.webPages.razor>
@@ -65,6 +58,26 @@
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<remove assembly="mscorlib" />
<remove assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<remove assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<remove assembly="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<remove assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<remove assembly="System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<remove assembly="System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<remove assembly="System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<remove assembly="System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<remove assembly="System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<remove assembly="System.WorkflowServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<remove assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<remove assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove assembly="System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblies>
</compilation>
<!--
@@ -76,14 +89,6 @@
<forms loginUrl="~/Users/Account/AccessDenied" timeout="2880"/>
</authentication>
<roleManager enabled="false">
<providers>
<clear/>
<add name="OrchardRoleProvider" type="Orchard.Security.Providers.OrchardRoleProvider, Orchard.Framework"/>
<!--<add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>-->
<!--<add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>-->
</providers>
</roleManager>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
@@ -104,11 +109,11 @@
</namespaces>
</pages>
<httpHandlers>
<add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<!-- see below -->
<clear />
<add path="default.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="true" />
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
<!-- Block access to module and theme definition files -->
<add verb="*" path="module.txt" validate="false" type="System.Web.HttpNotFoundHandler" />
<add verb="*" path="theme.txt" validate="false" type="System.Web.HttpNotFoundHandler" />
</httpHandlers>
</system.web>
<system.web.extensions/>
@@ -118,16 +123,13 @@
-->
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
</modules>
<handlers>
<remove name="MvcHttpHandler"/>
<remove name="UrlRoutingHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
<!-- Block access to module and theme definition files -->
<add name="moduleHttpNotFoundHandler" preCondition="integratedMode" verb="*" path="module.txt" type="System.Web.HttpNotFoundHandler" />
<add name="themeHttpNotFoundHandler" preCondition="integratedMode" verb="*" path="theme.txt" type="System.Web.HttpNotFoundHandler" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers accessPolicy="Script">
<!-- clear all handlers, prevents executing code file extensions, prevents returning any file contents -->
<clear/>
<!-- Return 404 for all requests via managed handler. The url routing handler will substitute the mvc request handler when routes match. -->
<add name="Default" path="default.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode" requireAccess="Script"/>
<add name="NotFound" path="*" verb="*" type="System.Web.HttpNotFoundHandler" preCondition="integratedMode" requireAccess="Script"/>
</handlers>
</system.webServer>
<runtime>

View File

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

View File

@@ -41,7 +41,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -59,7 +59,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="ClaySharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="ClaySharp">
<HintPath>..\..\lib\claysharp\ClaySharp.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.0.812.4, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\moq\Moq.dll</HintPath>

View File

@@ -42,7 +42,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View File

@@ -2,9 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*.aspx" verb="*" type="System.Web.HttpNotFoundHandler"/>
<add path="*.ascx" verb="*" type="System.Web.HttpNotFoundHandler"/>
<add path="*.master" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -28,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*.aspx,*.ascx,*.master" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -41,7 +41,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

View File

@@ -6,8 +6,8 @@ Feature: Setup
Scenario: Root request shows setup form
Given I have a clean site with
| extension | names |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable, Orchard.PublishLater, Scheduling, Settings, Shapes, XmlRpc |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLater, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Scheduling, Settings, Shapes, XmlRpc |
| theme | SafeMode |
When I go to "/Default.aspx"
Then I should see "Welcome to Orchard"
@@ -17,8 +17,8 @@ Scenario: Root request shows setup form
Scenario: Setup folder also shows setup form
Given I have a clean site with
| extension | names |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable, Orchard.PublishLater, Scheduling, Settings, Shapes, XmlRpc |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLater, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Scheduling, Settings, Shapes, XmlRpc |
| theme | SafeMode |
When I go to "/Setup"
Then I should see "Welcome to Orchard"
@@ -28,8 +28,8 @@ Scenario: Setup folder also shows setup form
Scenario: Some of the initial form values are required
Given I have a clean site with
| extension | names |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable, Orchard.PublishLater, Scheduling, Settings, Shapes, XmlRpc |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLater, Orchard.Themes, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Scheduling, Settings, Shapes, XmlRpc |
| theme | SafeMode |
When I go to "/Setup"
And I hit "Finish Setup"
@@ -39,8 +39,8 @@ Scenario: Some of the initial form values are required
Scenario: Calling setup on a brand new install
Given I have a clean site with
| extension | names |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Orchard.Modules, Orchard.Widgets, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable, Orchard.PublishLater, Scheduling, Settings, Shapes, XmlRpc |
| module | Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLater, Orchard.Themes, Orchard.Modules, Orchard.Widgets, Orchard.jQuery, TinyMce |
| core | Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Scheduling, Settings, Shapes, XmlRpc |
| theme | SafeMode, TheThemeMachine |
And I am on "/Setup"
When I fill in

View File

@@ -66,12 +66,12 @@ this.ScenarioSetup(scenarioInfo);
"names"});
table1.AddRow(new string[] {
"module",
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Or" +
"chard.jQuery, TinyMce, Orchard.PublishLater"});
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLat" +
"er, Orchard.Themes, Orchard.jQuery, TinyMce"});
table1.AddRow(new string[] {
"core",
"Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable," +
" Scheduling, Settings, Shapes, XmlRpc"});
"Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Sc" +
"heduling, Settings, Shapes, XmlRpc"});
table1.AddRow(new string[] {
"theme",
"SafeMode"});
@@ -102,12 +102,12 @@ this.ScenarioSetup(scenarioInfo);
"names"});
table2.AddRow(new string[] {
"module",
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Or" +
"chard.jQuery, TinyMce, Orchard.PublishLater"});
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLat" +
"er, Orchard.Themes, Orchard.jQuery, TinyMce"});
table2.AddRow(new string[] {
"core",
"Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable," +
" Scheduling, Settings, Shapes, XmlRpc"});
"Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Sc" +
"heduling, Settings, Shapes, XmlRpc"});
table2.AddRow(new string[] {
"theme",
"SafeMode"});
@@ -138,12 +138,12 @@ this.ScenarioSetup(scenarioInfo);
"names"});
table3.AddRow(new string[] {
"module",
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Or" +
"chard.jQuery, TinyMce, Orchard.PublishLater"});
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLat" +
"er, Orchard.Themes, Orchard.jQuery, TinyMce"});
table3.AddRow(new string[] {
"core",
"Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable," +
" Scheduling, Settings, Shapes, XmlRpc"});
"Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Sc" +
"heduling, Settings, Shapes, XmlRpc"});
table3.AddRow(new string[] {
"theme",
"SafeMode"});
@@ -176,12 +176,12 @@ this.ScenarioSetup(scenarioInfo);
"names"});
table4.AddRow(new string[] {
"module",
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.Themes, Or" +
"chard.Modules, Orchard.Widgets, Orchard.jQuery, TinyMce, Orchard.PublishLater"});
"Orchard.Setup, Orchard.Users, Orchard.Roles, Orchard.Comments, Orchard.PublishLat" +
"er, Orchard.Themes, Orchard.Modules, Orchard.Widgets, Orchard.jQuery, TinyMce"});
table4.AddRow(new string[] {
"core",
"Common, Contents, Dashboard, Feeds, HomePage, Navigation, Routable," +
" Scheduling, Settings, Shapes, XmlRpc"});
"Common, Contents, Dashboard, Feeds, HomePage, Messaging, Navigation, Routable, Sc" +
"heduling, Settings, Shapes, XmlRpc"});
table4.AddRow(new string[] {
"theme",
"SafeMode, TheThemeMachine"});

View File

@@ -0,0 +1,63 @@
using NUnit.Framework;
using Orchard.Media.Extensions;
namespace Orchard.Tests.Modules.Media.Extensions {
[TestFixture]
public class LongExtensionsTests {
[Test]
public void BytesAreFriendly() {
long size = 123;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("123 B"));
}
[Test]
public void KilobytesAreFriendly() {
long size = 93845;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("92 KB"));
}
[Test]
public void MegabytesAreFriendly() {
long size = 6593528;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("6.3 MB"));
}
[Test]
public void GigabytesAreFriendly() {
long size = 46896534657;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("43.68 GB"));
}
[Test]
public void TerabytesAreFriendly() {
long size = 386594723458690;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("351.606 TB"));
}
[Test]
public void PetabytesAreSlightlyFriendlyAsTerabytes() {
long size = 56794738495678965;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("51654.514 TB"));
}
[Test]
public void VeryLargeSizeDoesNotCauseFailure() {
long size = 5679473849567896593;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("5165451.375 TB"));
}
[Test]
public void NegativeSizeDoesNotCauseFailure(){
long size = -2598;
string friendly = size.ToFriendlySizeString();
Assert.That(friendly, Is.EqualTo("-2598 B"));
}
}
}

View File

@@ -41,7 +41,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -59,8 +59,12 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
<Reference Include="ClaySharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="Castle.Core">
<HintPath>..\..\lib\Castle Windsor 2.0\bin\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="ClaySharp">
<HintPath>..\..\lib\claysharp\ClaySharp.dll</HintPath>
</Reference>
<Reference Include="FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\fluentnhibernate\FluentNHibernate.dll</HintPath>
@@ -122,10 +126,15 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="CodeGeneration\Commands\CodeGenerationCommandsTests.cs" />
<Compile Include="DatabaseEnabledTestsBase.cs" />
<Compile Include="Media\Extensions\LongExtensionsTests.cs" />
<EmbeddedResource Include="Packaging\HelloDriver.cs.txt" />
<Compile Include="Packaging\PackageExpanderTests.cs" />
<Compile Include="Packaging\PackageBuilderTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Roles\Controllers\AdminControllerTests.cs" />
<Compile Include="Roles\Services\RoleServiceTests.cs" />
@@ -155,10 +164,18 @@
<Project>{C0C45321-B51D-4D8D-9B7B-AA4C2E0B2962}</Project>
<Name>Orchard.CodeGeneration</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Media\Orchard.Media.csproj">
<Project>{D9A7B330-CD22-4DA1-A95A-8DE1982AD8EB}</Project>
<Name>Orchard.Media</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Modules\Orchard.Modules.csproj">
<Project>{17F86780-9A1F-4AA1-86F1-875EEC2730C7}</Project>
<Name>Orchard.Modules</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Packaging\Orchard.Packaging.csproj">
<Project>{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}</Project>
<Name>Orchard.Packaging</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Web\Modules\Orchard.Roles\Orchard.Roles.csproj">
<Project>{D10AD48F-407D-4DB5-A328-173EC7CB010F}</Project>
<Name>Orchard.Roles</Name>
@@ -201,7 +218,9 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Packaging\Hello.World.csproj.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Hello.World</RootNamespace>
<AssemblyName>Hello.World</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Commands\GalleryCommands.cs" />
<Compile Include="Commands\PackagingCommands.cs" />
<Compile Include="Controllers\DownloadStreamResult.cs" />
<Compile Include="Controllers\GalleryController.cs" />
<Compile Include="DefaultPackagingUpdater.cs" />
<Compile Include="ResourceManifest.cs" />
<Compile Include="Services\AtomExtensions.cs" />
<Compile Include="Services\IPackageBuilder.cs" />
<Compile Include="Services\IPackageExpander.cs" />
<Compile Include="Services\IPackageManager.cs" />
<Compile Include="Services\IPackagingSourceManager.cs" />
<Compile Include="Services\PackageBuilder.cs" />
<Compile Include="Services\PackageData.cs" />
<Compile Include="Services\PackageExpander.cs" />
<Compile Include="Services\PackageManager.cs" />
<Compile Include="Services\PackagingEntry.cs" />
<Compile Include="Services\PackagingSource.cs" />
<Compile Include="Services\PackagingSourceManager.cs" />
<Compile Include="ViewModels\PackagingAddSourceViewModel.cs" />
<Compile Include="ViewModels\PackagingHarvestViewModel.cs" />
<Compile Include="ViewModels\PackagingModulesViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\PackagingSourcesViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Styles\admin.css" />
<Content Include="Views\Gallery\AddSource.cshtml" />
<Content Include="Views\Gallery\Harvest.cshtml" />
<Content Include="Views\Gallery\Modules.cshtml" />
<Content Include="Views\Gallery\Sources.cshtml" />
<Content Include="Views\Gallery\_Subnav.cshtml" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Content\" />
<Folder Include="Models\" />
<Folder Include="Scripts\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\external\nupack\NuPack.Core\NuPack.Core.csproj">
<Project>{F879F274-EFA0-4157-8404-33A19B4E6AEC}</Project>
<Name>NuPack.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Gallery\Themes.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target> -->
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>40980</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.Tests.Modules.Packaging {
class HelloDriver {
}
}

View File

@@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.Tests.Modules.Packaging {
class Migrations {
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using Autofac;
using NUnit.Framework;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.WebSite;
using Orchard.Packaging.Services;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.Modules.Packaging {
[TestFixture]
public class PackageBuilderTests : ContainerTestBase {
protected override void Register(Autofac.ContainerBuilder builder) {
builder.RegisterType<PackageBuilder>().As<IPackageBuilder>();
builder.RegisterType<InMemoryWebSiteFolder>().As<IWebSiteFolder>()
.As<InMemoryWebSiteFolder>().InstancePerLifetimeScope();
}
private Stream BuildHelloWorld(IPackageBuilder packageBuilder) {
// add some content because NuGet requires it
var folder = _container.Resolve<InMemoryWebSiteFolder>();
using ( var sourceStream = GetType().Assembly.GetManifestResourceStream(GetType(), "Hello.World.csproj.txt") ) {
folder.AddFile("~/Modules/Hello.World/Hello.World.csproj", new StreamReader(sourceStream).ReadToEnd());
}
return packageBuilder.BuildPackage(new ExtensionDescriptor {
ExtensionType = "Module",
Name = "Hello.World",
Version = "1.0",
Description = "a",
Author = "b"
});
}
[Test]
public void PackageForModuleIsOpcPackage() {
var packageBuilder = _container.Resolve<IPackageBuilder>();
var stream = BuildHelloWorld(packageBuilder);
var package = Package.Open(stream);
Assert.That(package, Is.Not.Null);
Assert.That(package.PackageProperties.Identifier, Is.EqualTo("Orchard.Module.Hello.World"));
}
[Test]
public void PropertiesPassThroughAsExpected() {
var packageBuilder = _container.Resolve<IPackageBuilder>();
var stream = BuildHelloWorld(packageBuilder);
var package = Package.Open(stream);
Assert.That(package.PackageProperties.Description, Is.EqualTo("a"));
Assert.That(package.PackageProperties.Creator, Is.EqualTo("b"));
Assert.That(package.PackageProperties.Version, Is.EqualTo("1.0"));
}
[Test]
public void ProjectFileIsAdded() {
var packageBuilder = _container.Resolve<IPackageBuilder>();
var stream = BuildHelloWorld(packageBuilder);
string content;
using ( var sourceStream = GetType().Assembly.GetManifestResourceStream(GetType(), "Hello.World.csproj.txt") ) {
content = new StreamReader(sourceStream).ReadToEnd();
}
var package = Package.Open(stream);
var projectUri = PackUriHelper.CreatePartUri(new Uri("/Content/Modules/Hello.World/Hello.World.csproj", UriKind.Relative));
var projectPart = package.GetPart(projectUri);
using (var projectStream = projectPart.GetStream()) {
var projectContent = new StreamReader(projectStream).ReadToEnd();
Assert.That(projectContent, Is.EqualTo(content));
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using Autofac;
using NUnit.Framework;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.VirtualPath;
using Orchard.FileSystems.WebSite;
using Orchard.Packaging.Services;
using Orchard.Services;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.Modules.Packaging {
[TestFixture]
public class PackageExpanderTests : ContainerTestBase {
protected override void Register(Autofac.ContainerBuilder builder) {
builder.RegisterType<PackageBuilder>().As<IPackageBuilder>();
builder.RegisterType<PackageInstaller>().As<IPackageInstaller>();
builder.RegisterInstance<IVirtualPathProvider>(new StubVirtualPathProvider(new StubFileSystem(new Clock())));
builder.RegisterType<InMemoryWebSiteFolder>().As<IWebSiteFolder>()
.As<InMemoryWebSiteFolder>().InstancePerLifetimeScope();
}
private Stream BuildHelloWorld(IPackageBuilder packageBuilder) {
return packageBuilder.BuildPackage(new ExtensionDescriptor {
ExtensionType = "Module",
Name = "Hello.World",
Version = "1.0",
Description = "a",
Author = "b"
});
}
}
}

View File

@@ -117,16 +117,17 @@ namespace Orchard.Tests.Modules.Users.Controllers {
[Test]
[Ignore("Needs to instead be a specflow test.")]
public void CreateShouldAddUserAndRedirect() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
var controller = _container.Resolve<AdminController>();
var result = controller.CreatePOST(new UserCreateViewModel {
UserName = "four",
Email = "six@example.org",
Password = "five",
ConfirmPassword = "five"
});
ActionResult result = null; // controller.CreatePOST(new UserCreateViewModel {
// UserName = "four",
// Email = "six@example.org",
// Password = "five",
// ConfirmPassword = "five"
//});
Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
var redirect = (RedirectToRouteResult)result;
@@ -137,7 +138,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
}
[Test]
[Ignore("Needs fixing")]
[Ignore("Needs fixing. Needs to instead be a specflow test.")]
public void EditShouldDisplayUserAndStoreChanges() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
@@ -145,7 +146,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
var id = repository.Get(x => x.UserName == "two").Id;
var result = (ViewResult)_container.Resolve<AdminController>().Edit(id);
var model = (UserEditViewModel)result.ViewData.Model;
Assert.That(model.UserName, Is.EqualTo("two"));
//Assert.That(model.UserName, Is.EqualTo("two"));
var controller = _container.Resolve<AdminController>();
controller.ValueProvider = Values.From(new {

View File

@@ -0,0 +1,85 @@
using System;
using Autofac;
using NUnit.Framework;
using Orchard.Caching;
using Orchard.Services;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.Caching {
[TestFixture]
public class ClockCachingTests {
private IContainer _container;
private ICacheManager _cacheManager;
private StubClock _clock;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterModule(new CacheModule());
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance();
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
builder.RegisterInstance<IClock>(_clock = new StubClock());
builder.RegisterType<DefaultCacheManager>().As<ICacheManager>();
_container = builder.Build();
_cacheManager = _container.Resolve<ICacheManager>(new TypedParameter(typeof(Type), GetType()));
}
[Test]
public void WhenAbsoluteShouldHandleAbsoluteTime() {
var inOneSecond = _clock.UtcNow.AddSeconds(1);
var cached = 0;
// each call after the specified datetime will be reevaluated
Func<int> retrieve = ()
=> _cacheManager.Get("testItem",
ctx => {
ctx.Monitor(_clock.WhenUtc(inOneSecond));
return ++cached;
});
Assert.That(retrieve(), Is.EqualTo(1));
for ( var i = 0; i < 10; i++ ) {
Assert.That(retrieve(), Is.EqualTo(1));
}
_clock.Advance(TimeSpan.FromSeconds(1));
Assert.That(retrieve(), Is.EqualTo(2));
Assert.That(retrieve(), Is.EqualTo(3));
Assert.That(retrieve(), Is.EqualTo(4));
}
[Test]
public void WhenAbsoluteShouldHandleAbsoluteTimeSpan() {
var cached = 0;
// each cached value has a lifetime of the specified duration
Func<int> retrieve = ()
=> _cacheManager.Get("testItem",
ctx => {
ctx.Monitor(_clock.When(TimeSpan.FromSeconds(1)));
return ++cached;
});
Assert.That(retrieve(), Is.EqualTo(1));
for ( var i = 0; i < 10; i++ ) {
Assert.That(retrieve(), Is.EqualTo(1));
}
_clock.Advance(TimeSpan.FromSeconds(1));
for ( var i = 0; i < 10; i++ ) {
Assert.That(retrieve(), Is.EqualTo(2));
}
_clock.Advance(TimeSpan.FromSeconds(1));
for ( var i = 0; i < 10; i++ ) {
Assert.That(retrieve(), Is.EqualTo(3));
}
}
}
}

View File

@@ -248,6 +248,15 @@ namespace Orchard.Tests.ContentManagement {
}
[Test]
public void CountReturnsNumber() {
AddSampleData();
var count = _manager.Query()
.Count();
Assert.That(count, Is.EqualTo(4));
}
[Test]
public void QueryShouldJoinVersionedRecords() {

View File

@@ -26,6 +26,7 @@ namespace Orchard.Tests.DataMigration {
private string _tempFolder;
private SchemaBuilder _schemaBuilder;
private DefaultDataMigrationInterpreter _interpreter;
private ISession _session;
[SetUp]
public void Setup() {
@@ -38,7 +39,7 @@ namespace Orchard.Tests.DataMigration {
var builder = new ContainerBuilder();
var session = _sessionFactory.OpenSession();
_session = _sessionFactory.OpenSession();
builder.RegisterInstance(appDataFolder).As<IAppDataFolder>();
builder.RegisterType<SqlCeDataServicesProvider>().As<IDataServicesProvider>();
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>();
@@ -46,7 +47,7 @@ namespace Orchard.Tests.DataMigration {
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>();
builder.RegisterType<SessionFactoryHolder>().As<ISessionFactoryHolder>();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(session)).As<ISessionLocator>();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();
builder.RegisterInstance(new ShellBlueprint { Records = Enumerable.Empty<RecordBlueprint>() }).As<ShellBlueprint>();
builder.RegisterInstance(new ShellSettings { Name = "temp", DataProvider = "SqlCe", DataTablePrefix = "TEST" }).As<ShellSettings>();
builder.RegisterModule(new DataModule());
@@ -133,10 +134,24 @@ namespace Orchard.Tests.DataMigration {
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.AlterColumn("Lastname", column => column.WithDefault("John")))
.AlterColumn("Lastname", column => column.WithDefault("Doe")))
.AlterTable("User", table => table
.DropColumn("Firstname")
);
// creating a new row should assign a default value to Firstname and Age
_schemaBuilder
.ExecuteSql("insert into TEST_User VALUES (DEFAULT, DEFAULT)");
// ensure wehave one record woth the default value
var command = _session.Connection.CreateCommand();
command.CommandText = "SELECT count(*) FROM TEST_User WHERE Lastname = 'Doe'";
Assert.That(command.ExecuteScalar(), Is.EqualTo(1));
// ensure this is not a false positive
command = _session.Connection.CreateCommand();
command.CommandText = "SELECT count(*) FROM TEST_User WHERE Lastname = 'Foo'";
Assert.That(command.ExecuteScalar(), Is.EqualTo(0));
}
[Test]

View File

@@ -20,8 +20,21 @@ namespace Orchard.Tests.Mvc {
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<FooController>()
.Keyed<IController>("/foo")
.Keyed<IController>(typeof(FooController))
.WithMetadata("ControllerType", typeof(FooController))
.InstancePerDependency();
builder.RegisterType<BarController>()
.Keyed<IController>("/bar")
.Keyed<IController>(typeof(BarController))
.WithMetadata("ControllerType", typeof(BarController))
.InstancePerDependency();
builder.RegisterType<ReplacementFooController>()
.Keyed<IController>("/foo")
.Keyed<IController>(typeof(ReplacementFooController))
.WithMetadata("ControllerType", typeof(ReplacementFooController))
.InstancePerDependency();
var container = builder.Build();
@@ -47,6 +60,7 @@ namespace Orchard.Tests.Mvc {
}
[Test]
[Ignore("OrchardControllerFactory depends on metadata, calling base when no context is causing errors.")]
public void WhenNullOrMissingContainerNormalControllerFactoryRulesShouldBeUsedAsFallback() {
var requestContext = GetRequestContext(null);
var controller = _controllerFactory.CreateController(requestContext, "foo");

View File

@@ -41,7 +41,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -160,6 +160,7 @@
<ItemGroup>
<Compile Include="Caching\CacheScopeTests.cs" />
<Compile Include="Caching\CacheTests.cs" />
<Compile Include="Caching\ClockCachingTests.cs" />
<Compile Include="Commands\CommandHandlerDescriptorBuilderTests.cs" />
<Compile Include="Commands\CommandHandlerTests.cs" />
<Compile Include="Commands\CommandManagerTests.cs" />
@@ -245,6 +246,7 @@
<Compile Include="Mvc\Routes\UrlPrefixTests.cs" />
<Compile Include="Records\BigRecord.cs" />
<Compile Include="Scripting\ScriptingTests.cs" />
<Compile Include="Stubs\InMemoryWebSiteFolder.cs" />
<Compile Include="Stubs\StubHttpContextAccessor.cs" />
<Compile Include="Stubs\StubWorkContextAccessor.cs" />
<Compile Include="Stubs\StubExtensionManager.cs" />

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Orchard.Caching;
using Orchard.FileSystems.WebSite;
namespace Orchard.Tests.Stubs {
public class InMemoryWebSiteFolder : IWebSiteFolder {
Dictionary<string, string> _contents = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public void AddFile(string virtualPath, string contents) {
_contents[Canonical(virtualPath)] = contents;
}
private string Canonical(string virtualPath) {
return virtualPath.Replace("\\", "/");
}
public IEnumerable<string> ListDirectories(string virtualPath) {
throw new NotImplementedException();
}
public IEnumerable<string> ListFiles(string virtualPath, bool recursive) {
throw new NotImplementedException();
}
public bool FileExists(string virtualPath) {
return _contents.ContainsKey(virtualPath);
}
public string ReadFile(string virtualPath) {
string value;
return _contents.TryGetValue(Canonical(virtualPath), out value) ? value : null;
}
public string ReadFile(string virtualPath, bool actualContent) {
throw new NotImplementedException();
}
public void CopyFileTo(string virtualPath, Stream destination) {
string value;
if (_contents.TryGetValue(Canonical(virtualPath), out value)) {
var bytes = Encoding.Default.GetBytes(value);
destination.Write(bytes, 0, bytes.Length);
}
}
public void CopyFileTo(string virtualPath, Stream destination, bool actualContent) {
throw new NotImplementedException();
}
public IVolatileToken WhenPathChanges(string virtualPath) {
throw new NotImplementedException();
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Orchard.Caching;
using Orchard.Services;
namespace Orchard.Tests.Stubs {
@@ -16,5 +17,14 @@ namespace Orchard.Tests.Stubs {
public DateTime FutureMoment(TimeSpan span) {
return UtcNow.Add(span);
}
public IVolatileToken When(TimeSpan duration) {
return new Clock.AbsoluteExpirationToken(this, duration);
}
public IVolatileToken WhenUtc(DateTime absoluteUtc) {
return new Clock.AbsoluteExpirationToken(this, absoluteUtc);
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Orchard.UI.Navigation;
using Orchard.UI;
namespace Orchard.Tests.UI.Navigation {
[TestFixture]
@@ -10,7 +10,7 @@ namespace Orchard.Tests.UI.Navigation {
[SetUp]
public void Init() {
_comparer = new PositionComparer();
_comparer = new FlatPositionComparer();
}
@@ -47,6 +47,22 @@ namespace Orchard.Tests.UI.Navigation {
AssertSame("007", "7");
}
[Test]
public void NegativeNumericValuesAreLessThanPositive() {
AssertLess("-5", "5");
AssertSame("-5", "-5");
AssertMore("42", "-42");
}
[Test]
public void NegativeNumericValuesShouldCompareNumerically() {
AssertMore("-3", "-5");
AssertLess("-8", "-5");
AssertSame("-5", "-5");
AssertLess("-100", "-5");
AssertSame("-007", "-7");
}
[Test]
public void DotsSplitParts() {
AssertLess("0500.3", "0500.5");

View File

@@ -41,7 +41,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

View File

@@ -10,10 +10,10 @@
-->
<!-- edit shapes getting default placements -->
<!-- edit "shape" -->
<Place Parts_Common_Body_Edit="Primary:2"/>
<Place Parts_Common_Owner_Edit="Primary:20"/>
<Place Parts_Common_Container_Edit="Primary:20"/>
<Place Fields_Common_Text_Edit="Primary:2.5"/>
<Place Parts_Common_Body_Edit="Content:2"/>
<Place Parts_Common_Owner_Edit="Content:20"/>
<Place Parts_Common_Container_Edit="Content:20"/>
<Place Fields_Common_Text_Edit="Content:2.5"/>
<!-- default positioning -->
<!-- show summary for all DisplayType by default -->
<Place Parts_Common_Body_Summary="Content:5"/>
@@ -22,7 +22,8 @@
<Match DisplayType="Detail">
<!-- hide summary, show full content, for Detail -->
<Place Parts_Common_Body_Summary="-"
Parts_Common_Body="Content:5" />
Parts_Common_Body="Content:5"
Parts_Common_Metadata="Meta:2"/>
</Match>
<Match DisplayType="Summary">
<Place Parts_Common_Metadata_Summary="Meta:2"/>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
namespace Orchard.Core.Containers {
public interface IContainersPathConstraint : IRouteConstraint, ISingletonDependency {
void SetPaths(IEnumerable<string> paths);
string FindPath(string path);
void AddPath(string path);
}
public class ContainersPathConstraint : IContainersPathConstraint {
private IDictionary<string, string> _paths = new Dictionary<string, string>();
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
if (routeDirection == RouteDirection.UrlGeneration)
return true;
object value;
if (values.TryGetValue(parameterName, out value)) {
var parameterValue = Convert.ToString(value);
return _paths.ContainsKey(parameterValue);
}
return false;
}
public void SetPaths(IEnumerable<string> paths) {
// Note: this does not need to be synchronized as long as the dictionary itself is treated as immutable.
// do not add or remove to the dictionary instance once created. recreate and reassign instead.
_paths = paths.Distinct().ToDictionary(path => path, StringComparer.OrdinalIgnoreCase);
}
public string FindPath(string path) {
string actual;
return _paths.TryGetValue(path, out actual) ? actual : path;
}
public void AddPath(string path) {
SetPaths(_paths.Keys.Concat(new[] { path }));
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Extensions;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
using Orchard.DisplayManagement;
using Orchard.Themes;
using Orchard.UI.Navigation;
namespace Orchard.Core.Containers.Controllers {
public class ItemController : Controller {
private readonly IContentManager _contentManager;
private readonly IContainersPathConstraint _containersPathConstraint;
public ItemController(IContentManager contentManager, IContainersPathConstraint containersPathConstraint, IShapeFactory shapeFactory) {
_contentManager = contentManager;
_containersPathConstraint = containersPathConstraint;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
[Themed]
public ActionResult Display(string path, Pager pager) {
var matchedPath = _containersPathConstraint.FindPath(path);
if (string.IsNullOrEmpty(matchedPath)) {
throw new ApplicationException("404 - should not have passed path constraint");
}
var hits = _contentManager
.Query<RoutePart, RoutePartRecord>(VersionOptions.Published)
.Where(r => r.Path == matchedPath)
.Slice(0, 2);
if (hits.Count() == 0) {
throw new ApplicationException("404 - should not have passed path constraint");
}
if (hits.Count() != 1) {
throw new ApplicationException("Ambiguous content");
}
var container = _contentManager.Get(hits.Single().Id);
IContentQuery<ContentItem> query = _contentManager
.Query(VersionOptions.Published)
.Join<CommonPartRecord>().Where(cr => cr.Container.Id == container.Id);
var descendingOrder = container.As<ContainerPart>().Record.OrderByDirection == (int) OrderByDirection.Descending;
query = query.OrderBy(container.As<ContainerPart>().Record.OrderByProperty, descendingOrder);
pager.PageSize = pager.PageSize != Pager.PageSizeDefault && container.As<ContainerPart>().Record.Paginated
? pager.PageSize
: container.As<ContainerPart>().Record.PageSize;
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var startIndex = container.As<ContainerPart>().Record.Paginated ? pager.GetStartIndex() : 0;
var pageOfItems = query.Slice(startIndex, pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, "Summary")));
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape)
.ShowPager(container.As<ContainerPart>().Record.Paginated);
return View(viewModel);
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Localization;
namespace Orchard.Core.Containers.Drivers {
public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
private readonly IContentManager _contentManager;
public ContainablePartDriver(IContentManager contentManager) {
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Editor(ContainablePart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainablePart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_Containable_Edit",
() => {
var commonPart = part.As<ICommonPart>();
var model = new ContainableViewModel();
if (commonPart.Container != null) {
model.ContainerId = commonPart.Container.Id;
}
if (updater != null) {
var oldContainerId = model.ContainerId;
updater.TryUpdateModel(model, "Containable", null, null);
if (oldContainerId != model.ContainerId) {
commonPart.Container = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
}
}
var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).List();
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
.Concat(containers.Select(x => new SelectListItem {
Value = Convert.ToString(x.Id),
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
Selected = x.Id == model.ContainerId,
}))
.ToList();
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
});
}
}
}

View File

@@ -0,0 +1,30 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Containers.Models;
using Orchard.Data;
namespace Orchard.Core.Containers.Drivers {
public class ContainerCustomPartDriver : ContentPartDriver<ContainerCustomPart> {
protected override DriverResult Editor(ContainerCustomPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerCustomPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerCustom_Edit",
() => {
if (updater != null)
updater.TryUpdateModel(part, "ContainerCustom", null, null);
return shapeHelper.EditorTemplate(TemplateName: "ContainerCustom", Model: part, Prefix: "ContainerCustom");
});
}
}
public class ContainerCustomPartHandler : ContentHandler {
public ContainerCustomPartHandler(IRepository<ContainerCustomPartRecord> repository) {
Filters.Add(StorageFilter.For(repository));
}
}
}

View File

@@ -0,0 +1,41 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.Settings;
using Orchard.Data;
namespace Orchard.Core.Containers.Drivers {
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
protected override DriverResult Editor(ContainerPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerPart part, ContentManagement.IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_Container_Edit",
() => {
if (updater != null)
updater.TryUpdateModel(part, "Container", null, null);
return shapeHelper.EditorTemplate(TemplateName: "Container", Model: part, Prefix: "Container");
});
}
}
public class ContainerPartHandler : ContentHandler {
public ContainerPartHandler(IRepository<ContainerPartRecord> repository, IOrchardServices orchardServices) {
Filters.Add(StorageFilter.For(repository));
OnInitializing<ContainerPart>((context, part) => {
part.Record.PageSize = part.Settings.GetModel<ContainerTypePartSettings>().PageSizeDefault
?? part.PartDefinition.Settings.GetModel<ContainerPartSettings>().PageSizeDefault;
part.Record.Paginated = part.Settings.GetModel<ContainerTypePartSettings>().PaginatedDefault
?? part.PartDefinition.Settings.GetModel<ContainerPartSettings>().PaginatedDefault;
//hard-coded defaults for ordering
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.PublishedUtc" : "";
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
});
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Extensions;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Data;
using Orchard.Localization;
namespace Orchard.Core.Containers.Drivers {
public class ContainerWidgetPartDriver : ContentPartDriver<ContainerWidgetPart> {
private readonly IContentManager _contentManager;
public ContainerWidgetPartDriver(IContentManager contentManager) {
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Display(ContainerWidgetPart part, string displayType, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerWidget",
() => {
var container = _contentManager.Get(part.Record.ContainerId);
IContentQuery<ContentItem> query = _contentManager
.Query(VersionOptions.Published)
.Join<CommonPartRecord>().Where(cr => cr.Container.Id == container.Id);
var descendingOrder = part.Record.OrderByDirection == (int)OrderByDirection.Descending;
query = query.OrderBy(part.Record.OrderByProperty, descendingOrder);
if (part.Record.ApplyFilter)
query = query.Where(part.Record.FilterByProperty, part.Record.FilterByOperator, part.Record.FilterByValue);
var pageOfItems = query.Slice(0, part.Record.PageSize).ToList();
var list = shapeHelper.List();
list.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, "Summary")));
return shapeHelper.Parts_ContainerWidget(ContentItems: list);
});
}
protected override DriverResult Editor(ContainerWidgetPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerWidgetPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerWidget_Edit",
() => {
var model = new ContainerWidgetViewModel {Part = part};
if (updater != null) {
updater.TryUpdateModel(model, "ContainerWidget", null, null);
}
var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).List();
var listItems = containers.Count() < 1
? new[] {new SelectListItem {Text = T("(None - create container enabled items first)").Text, Value = "0"}}
: containers.Select(x => new SelectListItem {
Value = Convert.ToString(x.Id),
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
Selected = x.Id == model.Part.Record.ContainerId,
});
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.Part.Record.ContainerId);
return shapeHelper.EditorTemplate(TemplateName: "ContainerWidget", Model: model, Prefix: "ContainerWidget");
});
}
}
public class ContainerWidgetPartHandler : ContentHandler {
public ContainerWidgetPartHandler(IRepository<ContainerWidgetPartRecord> repository, IOrchardServices orchardServices) {
Filters.Add(StorageFilter.For(repository));
OnInitializing<ContainerWidgetPart>((context, part) => {
part.Record.ContainerId = 0;
part.Record.PageSize = 5;
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.PublishedUtc" : "";
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
part.Record.FilterByProperty = "ContainerCustomPart.CustomOne";
part.Record.FilterByOperator = "=";
});
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
namespace Orchard.Core.Containers.Extensions
{
public static class ContentQueryExtensions {
public static IContentQuery<T> OrderBy<T>(this IContentQuery<T> query, string partAndProperty, bool descendingOrder) where T : IContent {
//todo: (heskew) order by custom part properties
switch (partAndProperty) {
case "RoutePart.Title":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Title)
: query.OrderBy<RoutePartRecord, string>(record => record.Title);
break;
case "RoutePart.Slug":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Slug)
: query.OrderBy<RoutePartRecord, string>(record => record.Slug);
break;
case "ContainerCustomPart.CustomOne":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomOne)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomOne);
break;
case "ContainerCustomPart.CustomTwo":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomTwo)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomTwo);
break;
case "ContainerCustomPart.CustomThree":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomThree)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomThree);
break;
default: // "CommonPart.PublishedUtc"
query = descendingOrder
? query.OrderByDescending<CommonPartRecord, DateTime?>(record => record.PublishedUtc)
: query.OrderBy<CommonPartRecord, DateTime?>(record => record.PublishedUtc);
break;
}
return query;
}
public static IContentQuery<ContentItem> Where(this IContentQuery<ContentItem> query, string partAndProperty, string comparisonOperator, string comparisonValue) {
var filterKey = string.Format("{0}|{1}", partAndProperty, comparisonOperator);
if (!_filters.ContainsKey(filterKey))
return query;
return _filters[filterKey](query, comparisonValue);
}
// convoluted: yes; quick and works for now: yes; technical debt: not much
private static readonly Dictionary<string, Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>> _filters = new Dictionary<string, Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>> {
{"RoutePart.Title|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Title.CompareTo(s) == -1*/))},
{"RoutePart.Title|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Title.CompareTo(s) == 1*/))},
{"RoutePart.Title|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Title.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Title|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Title.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Slug|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Slug.CompareTo(s) == -1*/))},
{"RoutePart.Slug|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Slug.CompareTo(s) == 1*/))},
{"RoutePart.Slug|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Slug.Equals(s.Trim(), StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Slug|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Slug.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"CommonPart.PublishedUtc|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc < DateTime.Parse(s)))},
{"CommonPart.PublishedUtc|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc > DateTime.Parse(s)))},
{"CommonPart.PublishedUtc|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc == DateTime.Parse(s)))}, // todo: (heskew) not practical as is. needs some sense of precision....
{"CommonPart.PublishedUtc|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => true /* can't modified PublishedUtc for partial comparisons */))},
// todo: (hesekw) this could benefit from a better filter implementation as this is currently very limited in functionality and I have no idea how the custom parts will be used by folks
{"ContainerCustomPart.CustomOne|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomOne.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomOne|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomOne.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomOne|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomOne.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomOne|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomOne.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomTwo|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomTwo.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomTwo|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomTwo.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomTwo|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomTwo.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomTwo|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomTwo.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomThree|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomThree.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomThree|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomThree.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomThree|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomThree.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomThree|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomThree.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
};
}
}

View File

@@ -0,0 +1,49 @@
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
namespace Orchard.Core.Containers {
public class Migrations : DataMigrationImpl {
public int Create() {
SchemaBuilder.CreateTable("ContainerPartRecord",
table => table
.ContentPartRecord()
.Column<bool>("Paginated")
.Column<int>("PageSize")
.Column<string>("OrderByProperty")
.Column<int>("OrderByDirection"));
SchemaBuilder.CreateTable("ContainerWidgetPartRecord",
table => table
.ContentPartRecord()
.Column<int>("ContainerId")
.Column<int>("PageSize")
.Column<string>("OrderByProperty")
.Column<int>("OrderByDirection")
.Column<bool>("ApplyFilter")
.Column<string>("FilterByProperty")
.Column<string>("FilterByOperator")
.Column<string>("FilterByValue"));
SchemaBuilder.CreateTable("ContainerCustomPartRecord",
table => table
.ContentPartRecord()
.Column<string>("CustomOne")
.Column<string>("CustomTwo")
.Column<string>("CustomThree"));
ContentDefinitionManager.AlterTypeDefinition("ContainerWidget",
cfg => cfg
.WithPart("CommonPart")
.WithPart("WidgetPart")
.WithPart("ContainerWidgetPart")
.WithSetting("Stereotype", "Widget"));
ContentDefinitionManager.AlterPartDefinition("ContainerPart", builder => builder.Attachable());
ContentDefinitionManager.AlterPartDefinition("ContainablePart", builder => builder.Attachable());
ContentDefinitionManager.AlterPartDefinition("ContainerCustomPart", builder => builder.Attachable());
return 1;
}
}
}

View File

@@ -0,0 +1,6 @@
using Orchard.ContentManagement;
namespace Orchard.Core.Containers.Models {
public class ContainablePart : ContentPart {
}
}

View File

@@ -0,0 +1,13 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerCustomPart : ContentPart<ContainerCustomPartRecord> {
}
public class ContainerCustomPartRecord : ContentPartRecord {
public virtual string CustomOne { get; set; }
public virtual string CustomTwo { get; set; }
public virtual string CustomThree { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerPart : ContentPart<ContainerPartRecord> {
}
public class ContainerPartRecord : ContentPartRecord {
public virtual bool Paginated { get; set; }
public virtual int PageSize { get; set; }
public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerWidgetPart : ContentPart<ContainerWidgetPartRecord> {
}
public class ContainerWidgetPartRecord : ContentPartRecord {
public virtual int ContainerId { get; set; }
public virtual int PageSize { get; set; }
public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; }
public virtual bool ApplyFilter { get; set; }
public virtual string FilterByProperty { get; set; }
public virtual string FilterByOperator { get; set; }
public virtual string FilterByValue { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Containers.Models {
public enum OrderByDirection {
Ascending,
Descending,
}
}

View File

@@ -0,0 +1,12 @@
Name: Containers
AntiForgery: enabled
Author: The Orchard Team
Website: http://orchardproject.net
Version: 0.8.0
OrchardVersion: 0.8.0
Description: The containers module introduces container and containable behaviors for content items.
Features:
Containers:
Description: Container and containable parts to enable parent-child relationships between content items.
Dependencies: Contents, Routable
Category: Content

View File

@@ -0,0 +1,8 @@
<Placement>
<Place Parts_Containable_Edit="Content:before.3"/>
<Place Parts_Container_Edit="Content:5"/>
<Place Parts_ContainerCustom_Edit="Content:5"/>
<Place Parts_ContainerWidget_Edit="Content:5"/>
<Place Parts_Container_SiteSettings="Content:10"/>
<Place Parts_ContainerWidget="Content"/>
</Placement>

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Core.Containers {
public class Routes : IRouteProvider {
private readonly IContainersPathConstraint _containersPathConstraint;
public Routes(IContainersPathConstraint containersPathConstraint) {
_containersPathConstraint = containersPathConstraint;
}
public void GetRoutes(ICollection<RouteDescriptor> routes) {
foreach (var routeDescriptor in GetRoutes())
routes.Add(routeDescriptor);
}
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Priority = 15,
Route = new Route(
"{*path}",
new RouteValueDictionary {
{"area", "Containers"},
{"controller", "Item"},
{"action", "Display"}
},
new RouteValueDictionary {
{"path", _containersPathConstraint}
},
new RouteValueDictionary {
{"area", "Containers"}
},
new MvcRouteHandler())
}
};
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
using Orchard.Environment;
using Orchard.Tasks;
namespace Orchard.Core.Containers.Services {
public class ContainersPathConstraintUpdater : IOrchardShellEvents, IBackgroundTask {
private readonly IContainersPathConstraint _containersPathConstraint;
private readonly IContentManager _contentManager;
public ContainersPathConstraintUpdater(IContainersPathConstraint containersPathConstraint, IContentManager contentManager) {
_containersPathConstraint = containersPathConstraint;
_contentManager = contentManager;
}
void IOrchardShellEvents.Activated() {
Refresh();
}
void IOrchardShellEvents.Terminating() {
}
void IBackgroundTask.Sweep() {
Refresh();
}
private void Refresh() {
var routeParts = _contentManager.Query<RoutePart, RoutePartRecord>().Join<ContainerPartRecord>().List();
_containersPathConstraint.SetPaths(routeParts.Select(x=>x.Path));
}
}
}

View File

@@ -0,0 +1,87 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.Core.Containers.Settings {
public class ContainerPartSettings {
public const int PageSizeDefaultDefault = 10;
public const bool PaginatedDefaultDefault = true;
private int? _pageSizeDefault;
private bool? _paginiatedDefault;
public int PageSizeDefault {
get {
return _pageSizeDefault != null
? (int)_pageSizeDefault
: PageSizeDefaultDefault;
}
set { _pageSizeDefault = value; }
}
public bool PaginatedDefault {
get {
return _paginiatedDefault != null
? (bool)_paginiatedDefault
: PaginatedDefaultDefault;
}
set { _paginiatedDefault = value; }
}
}
public class ContainerTypePartSettings {
public int? PageSizeDefault { get; set; }
public bool? PaginatedDefault { get; set; }
}
public class ContainerSettingsHooks : ContentDefinitionEditorEventsBase {
public override IEnumerable<TemplateViewModel> TypePartEditor(ContentTypePartDefinition definition) {
if (definition.PartDefinition.Name != "ContainerPart")
yield break;
var model = definition.Settings.GetModel<ContainerTypePartSettings>();
var partModel = definition.PartDefinition.Settings.GetModel<ContainerPartSettings>();
if (model.PageSizeDefault == null)
model.PageSizeDefault = partModel.PageSizeDefault;
if (model.PaginatedDefault == null)
model.PaginatedDefault = partModel.PaginatedDefault;
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> PartEditor(ContentPartDefinition definition) {
if (definition.Name != "ContainerPart")
yield break;
var model = definition.Settings.GetModel<ContainerPartSettings>();
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Name != "ContainerPart")
yield break;
var model = new ContainerTypePartSettings();
updateModel.TryUpdateModel(model, "ContainerTypePartSettings", null, null);
builder.WithSetting("ContainerTypePartSettings.PageSizeDefault", model.PageSizeDefault.ToString());
builder.WithSetting("ContainerTypePartSettings.PaginatedDefault", model.PaginatedDefault.ToString());
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> PartEditorUpdate(ContentPartDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Name != "ContainerPart")
yield break;
var model = new ContainerPartSettings();
updateModel.TryUpdateModel(model, "ContainerPartSettings", null, null);
builder.WithSetting("ContainerPartSettings.PageSizeDefault", model.PageSizeDefault.ToString());
builder.WithSetting("ContainerPartSettings.PaginatedDefault", model.PaginatedDefault.ToString());
yield return DefinitionTemplate(model);
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Common.Settings {
public class LocationSettings {
public string Zone { get; set; }
public string Position { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
using System.Web.Mvc;
namespace Orchard.Core.Containers.ViewModels {
public class ContainableViewModel {
public int ContainerId { get; set; }
public SelectList AvailableContainers { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Web.Mvc;
using Orchard.Core.Containers.Models;
namespace Orchard.Core.Containers.ViewModels {
public class ContainerWidgetViewModel {
public bool UseFilter { get; set; }
public SelectList AvailableContainers { get; set; }
public ContainerWidgetPart Part { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
@model Orchard.Core.Containers.Settings.ContainerPartSettings
<fieldset>
<label for="@Html.FieldIdFor(m => m.PageSizeDefault)">@T("Default Page Size")</label>
@Html.EditorFor(m => m.PageSizeDefault)
</fieldset>
<fieldset>
@Html.EditorFor(m => m.PaginatedDefault)
<label for="@Html.FieldIdFor( m => m.PaginatedDefault)" class="forcheckbox">@T("Show paging controls")</label>
</fieldset>

View File

@@ -0,0 +1,9 @@
@model Orchard.Core.Containers.Settings.ContainerTypePartSettings
<fieldset>
<label for="@Html.FieldIdFor(m => m.PageSizeDefault)">@T("Default Page Size")</label>
@Html.EditorFor(m => m.PageSizeDefault)
</fieldset>
<fieldset>
<label for="@Html.FieldIdFor( m => m.PaginatedDefault)">@T("Show paging controls")</label>
@Html.EditorFor(m => m.PaginatedDefault)
</fieldset>

View File

@@ -0,0 +1,5 @@
@model Orchard.Core.Containers.ViewModels.ContainableViewModel
<fieldset>
@Html.LabelFor(m => m.ContainerId, T("Add to"))
@Html.DropDownListFor(m => m.ContainerId, Model.AvailableContainers)
</fieldset>

View File

@@ -0,0 +1,27 @@
@model Orchard.Core.Containers.Models.ContainerPart
@using Orchard.Core.Containers.Models;
<fieldset>
@Html.LabelFor(m => m.Record.OrderByProperty, T("Order by"))
<select id="@Html.FieldIdFor(m => m.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Record.OrderByProperty)">
@Html.SelectOption(Model.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select id="@Html.FieldIdFor(m => m.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Record.OrderByDirection)">
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select>
</fieldset>
<fieldset class="with-checkbox">
<span>
@Html.LabelFor(m => m.Record.PageSize, T("Page size"))
@Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" })
</span>
<span class="checkbox-and-label">
@Html.CheckBoxFor(m => m.Record.Paginated)
<label for="@Html.FieldIdFor(m => m.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
</span>
</fieldset>

View File

@@ -0,0 +1,13 @@
@model Orchard.Core.Containers.Models.ContainerCustomPart
<fieldset>
@Html.LabelFor(m => m.Record.CustomOne, T("Custom One"))
@Html.EditorFor(m => m.Record.CustomOne)
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Record.CustomTwo, T("Custom Two"))
@Html.EditorFor(m => m.Record.CustomTwo)
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Record.CustomThree, T("Custom Three"))
@Html.EditorFor(m => m.Record.CustomThree)
</fieldset>

View File

@@ -0,0 +1,56 @@
@model Orchard.Core.Containers.ViewModels.ContainerWidgetViewModel
@using Orchard.Core.Containers.Models;
@{
Script.Require("ShapesBase");
}
<fieldset>
@Html.LabelFor(m => m.Part.Record.ContainerId, T("Show items from"))
@Html.DropDownListFor(m => m.Part.Record.ContainerId, Model.AvailableContainers)
</fieldset>
<fieldset>
<span>
@Html.LabelFor(m => m.Part.Record.PageSize, T("Maximum number of items to display"))
@Html.TextBoxFor(m => m.Part.Record.PageSize, new { @class = "text text-small" })
</span>
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Part.Record.OrderByProperty, T("Order by"))
<select id="@Html.FieldIdFor(m => m.Part.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByProperty)">
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select title="@T("Order direction")" id="@Html.FieldIdFor(m => m.Part.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByDirection)">
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select>
</fieldset>
<fieldset>
<div>
@Html.EditorFor(m => m.Part.Record.ApplyFilter)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Part.Record.ApplyFilter)">@T("Filter items")</label>
</div>
<div data-controllerid="@Html.FieldIdFor(m => m.Part.Record.ApplyFilter)">
@Html.LabelFor(m => m.Part.Record.FilterByProperty, T("Filter where"))
<select id="@Html.FieldIdFor(m => m.Part.Record.FilterByProperty)" name="@Html.FieldNameFor(m => m.Part.Record.FilterByProperty)">
@Html.SelectOption(Model.Part.Record.FilterByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select title="@T("Filter operator")" id="@Html.FieldIdFor(m => m.Part.Record.FilterByOperator)" name="@Html.FieldNameFor(m => m.Part.Record.FilterByOperator)">
@Html.SelectOption(Model.Part.Record.FilterByOperator, "=", T("is equal to").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, "<", T("is less than").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, ">", T("is greater than").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, "^=", T("starts with").Text)
</select>
<span>
@Html.TextBoxFor(m => m.Part.Record.FilterByValue, new { @class = "text", title = T("Filter value") })
</span>
</div>
</fieldset>

View File

@@ -0,0 +1,4 @@
@Display(Model.ContentItems)
@if (Model.ShowPager) {
@Display(Model.Pager)
}

View File

@@ -0,0 +1 @@
@Display(Model.ContentItems)

View File

@@ -21,16 +21,22 @@ namespace Orchard.Core.Contents {
public void GetNavigation(NavigationBuilder builder) {
var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name);
builder.Add(T("Content"), "2", menu => {
menu.Add(T("Manage Content"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable)) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
if (createRouteValues.Any())
menu.Add(T("Create {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
builder.Add(T("Content"), "2",
menu => menu.Add(T("Content Items"), "1", item => item.Action("List", "Admin", new {area = "Contents", id = ""})));
var contentTypes = contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable).OrderBy(ctd => ctd.DisplayName);
if (contentTypes.Count() > 0) {
builder.Add(T("New"), "-1", menu => {
foreach (var contentTypeDefinition in contentTypes) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
// review: the display name should be a LocalizedString
if (createRouteValues.Any())
menu.Add(T(contentTypeDefinition.DisplayName), "5", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
}
}
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Core.Contents.Settings;
using Orchard.Core.Contents.ViewModels;
@@ -15,6 +16,7 @@ using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
namespace Orchard.Core.Contents.Controllers {
@@ -44,13 +46,10 @@ namespace Orchard.Core.Contents.Controllers {
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public ActionResult List(ListContentsViewModel model) {
public ActionResult List(ListContentsViewModel model, Pager pager) {
if (model.ContainerId != null && _contentManager.GetLatest((int)model.ContainerId) == null)
return HttpNotFound();
const int pageSize = 20;
var skip = (Math.Max(model.Page ?? 0, 1) - 1) * pageSize;
var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes().Select(ctd => ctd.Name).ToArray());
if (!string.IsNullOrEmpty(model.TypeName)) {
@@ -67,56 +66,34 @@ namespace Orchard.Core.Contents.Controllers {
if (model.ContainerId != null)
query = query.Join<CommonPartRecord>().Where(cr => cr.Container.Id == model.ContainerId);
// Ordering
//-- want something like
//switch (model.Options.OrderBy) {
// case ContentsOrder.Modified:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
// break;
// case ContentsOrder.Published:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
// break;
// case ContentsOrder.Created:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
// break;
//}
//-- but resorting to
var contentItems = query.List();
switch (model.Options.OrderBy) {
case ContentsOrder.Modified:
contentItems = contentItems.OrderByDescending(ci => ci.VersionRecord.Id);
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
break;
case ContentsOrder.Published:
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
break;
//case ContentsOrder.Published:
// would be lying w/out a published date instead of a bool but that only comes with the common aspect
// contentItems = contentItems.OrderByDescending(ci => ci.VersionRecord.Published/*Date*/);
// break;
case ContentsOrder.Created:
contentItems = contentItems.OrderByDescending(ci => ci.Id);
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
break;
}
//-- for the moment
//-- because I'd rather do this
//var contentItems = query.Slice(skip, pageSize);
//-- instead of this (having the ordering and skip/take after the query)
contentItems = contentItems.Skip(skip).Take(pageSize).ToList();
model.Options.SelectedFilter = model.TypeName;
model.Options.FilterOptions = GetCreatableTypes()
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
.ToList().OrderBy(kvp => kvp.Key);
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(contentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
list.AddRange(pageOfContentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape)
.Options(model.Options)
.TypeDisplayName(model.TypeDisplayName ?? "");
@@ -215,24 +192,39 @@ namespace Orchard.Core.Contents.Controllers {
return View(model);
}
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Save")]
public ActionResult CreatePOST(string id) {
return CreatePOST(id, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST(string id) {
[FormValueRequired("submit.Publish")]
public ActionResult CreateAndPublishPOST(string id) {
return CreatePOST(id, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult CreatePOST(string id, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.New(id);
if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Couldn't create content")))
return new HttpUnauthorizedResult();
_contentManager.Create(contentItem, VersionOptions.Draft);
var model = _contentManager.UpdateEditor(contentItem, this);
var isDraftable = contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable;
_contentManager.Create(
contentItem,
isDraftable ? VersionOptions.Draft : VersionOptions.Published);
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been created.")
@@ -255,7 +247,21 @@ namespace Orchard.Core.Contents.Controllers {
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Save")]
public ActionResult EditPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Publish")]
public ActionResult EditAndPublishPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult EditPOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.Get(id, VersionOptions.DraftRequired);
if (contentItem == null)
@@ -270,9 +276,7 @@ namespace Orchard.Core.Contents.Controllers {
return View("Edit", model);
}
//need to go about this differently - to know when to publish (IPlublishableAspect ?)
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been saved.")

View File

@@ -1,5 +1,7 @@
using Orchard.ContentManagement;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Contents.Settings;
namespace Orchard.Core.Contents.Drivers {
public class ContentsDriver : ContentPartDriver<ContentPart> {
@@ -13,5 +15,18 @@ namespace Orchard.Core.Contents.Drivers {
() => shapeHelper.Parts_Contents_Publish_SummaryAdmin(ContentPart: part))
);
}
protected override DriverResult Editor(ContentPart part, dynamic shapeHelper) {
var results = new List<DriverResult> { ContentShape("Content_SaveButton", saveButton => saveButton) };
if (part.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
results.Add(ContentShape("Content_PublishButton", publishButton => publishButton));
return Combined(results.ToArray());
}
protected override DriverResult Editor(ContentPart part, IUpdateModel updater, dynamic shapeHelper) {
return Editor(part, updater);
}
}
}

View File

@@ -6,6 +6,9 @@ namespace Orchard.Core.Contents.Extensions {
public static ContentTypeDefinitionBuilder Creatable(this ContentTypeDefinitionBuilder builder, bool creatable = true) {
return builder.WithSetting("ContentTypeSettings.Creatable", creatable.ToString());
}
public static ContentTypeDefinitionBuilder Draftable(this ContentTypeDefinitionBuilder builder, bool draftable = true) {
return builder.WithSetting("ContentTypeSettings.Draftable", draftable.ToString());
}
public static ContentPartDefinitionBuilder Attachable(this ContentPartDefinitionBuilder builder, bool attachable = true) {
return builder.WithSetting("ContentPartSettings.Attachable", attachable.ToString());
}

View File

@@ -4,10 +4,13 @@
Parts_Contents_Publish
Parts_Contents_Publish_SummaryAdmin
-->
<!-- edit "shape" -->
<Place Content_PublishButton="Sidebar:24"/>
<Place Content_SaveButton="Sidebar:23"/>
<Match DisplayType="Detail">
<Place Parts_Contents_Publish="Content:5"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Contents_Publish_SummaryAdmin="Secondary:5"/>
<Place Parts_Contents_Publish_SummaryAdmin="Actions:5"/>
</Match>
</Placement>

View File

@@ -1,8 +1,12 @@
namespace Orchard.Core.Contents.Settings {
public class ContentTypeSettings {
/// <summary>
/// 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
/// </summary>
public bool Creatable { get; set; }
/// <summary>
/// Used to determine if this content type supports draft versions
/// </summary>
public bool Draftable { get; set; }
}
}

View File

@@ -35,11 +35,12 @@
<select id="orderResults" name="Options.OrderBy">
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Created, T("recently created").ToString())
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Modified, T("recently modified").ToString())
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Published, T("recently published").ToString())
</select>
<button type="submit" name="submit.Filter" value="yes please">@T("Apply")</button>
</fieldset>
<fieldset class="contentItems bulk-items">
@Display(Model.ContentItems)
@Display(Model.ContentItems2)
</fieldset>
@Display(Model.Pager)
}

Some files were not shown because too many files have changed in this diff Show More