Including Orchard.Tokens

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2012-08-22 15:43:10 -07:00
parent 4053c45d49
commit f2bb3ee47a
39 changed files with 2039 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Orchard.Themes;
namespace Orchard.Tokens.Controllers {
public class AdminController : Controller {
private readonly ITokenManager _tokenManager;
public AdminController(ITokenManager tokenManager) {
_tokenManager = tokenManager;
}
[Themed(false)]
public ActionResult Tokens() {
var tokenTypes = _tokenManager.Describe(Enumerable.Empty<string>());
var results = new List<object>();
foreach (var tokenType in tokenTypes.OrderBy(d => d.Name.ToString()))
{
results.Add(new {
label = tokenType.Name.Text,
desc = tokenType.Description.Text,
value = string.Empty
});
foreach(var token in tokenType.Tokens) {
results.Add(new {
label = token.Name.Text,
desc = token.Description.Text,
value = "{" + token.Target + "." + token.Token + "}"
});
}
}
return Json(results, JsonRequestBehavior.AllowGet);
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Orchard.Localization;
namespace Orchard.Tokens {
public abstract class DescribeContext {
public abstract IEnumerable<TokenTypeDescriptor> Describe(params string[] targets);
public abstract DescribeFor For(string target);
public abstract DescribeFor For(string target, LocalizedString name, LocalizedString description);
}
}

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
using Orchard.Localization;
namespace Orchard.Tokens {
public abstract class DescribeFor {
public abstract IEnumerable<TokenDescriptor> Tokens { get; }
public abstract LocalizedString Name { get; }
public abstract LocalizedString Description { get; }
public abstract DescribeFor Token(string token, LocalizedString name, LocalizedString description);
public abstract DescribeFor Token(string token, LocalizedString name, LocalizedString description, string chainTarget);
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace Orchard.Tokens {
public abstract class EvaluateContext {
public abstract string Target { get; }
public abstract IDictionary<string, string> Tokens { get; }
public abstract IDictionary<string, object> Data { get; }
public abstract IDictionary<string, object> Values { get; }
public abstract EvaluateFor<TData> For<TData>(string target);
public abstract EvaluateFor<TData> For<TData>(string target, TData defaultData);
public abstract EvaluateFor<TData> For<TData>(string target, Func<TData> defaultData);
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace Orchard.Tokens {
public abstract class EvaluateFor<TData> {
public abstract TData Data { get; }
public abstract EvaluateFor<TData> Token(string token, Func<TData, object> tokenValue);
public abstract EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue);
public abstract EvaluateFor<TData> Token(Func<string, TData, object> tokenValue);
public abstract EvaluateFor<TData> Token(Func<string, string> filter, Func<string, TData, object> tokenValue);
}
}

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Orchard.Tokens {
public interface ITokenManager : IDependency {
IEnumerable<TokenTypeDescriptor> Describe(IEnumerable<string> targets);
IDictionary<string, object> Evaluate(string target, IDictionary<string, string> tokens, IDictionary<string, object> data);
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Events;
namespace Orchard.Tokens {
public interface ITokenProvider : IEventHandler {
void Describe(DescribeContext context);
void Evaluate(EvaluateContext context);
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using Orchard.Events;
namespace Orchard.Tokens {
public interface ITokenizer : IDependency {
IDictionary<string, object> Evaluate(IEnumerable<string> tokens, object data);
IDictionary<string, object> Evaluate(IEnumerable<string> tokens, IDictionary<string, object> data);
string Replace(string text, object data);
string Replace(string text, object data, ReplaceOptions options);
string Replace(string text, IDictionary<string, object> data);
string Replace(string text, IDictionary<string, object> data, ReplaceOptions options);
}
}

View File

@@ -0,0 +1,247 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Localization;
namespace Orchard.Tokens.Implementation {
public class TokenManager : ITokenManager {
private readonly IEnumerable<ITokenProvider> _providers;
public TokenManager(IEnumerable<ITokenProvider> providers) {
_providers = providers;
}
public IEnumerable<TokenTypeDescriptor> Describe(IEnumerable<string> targets) {
var context = new DescribeContextImpl();
foreach (var provider in _providers) {
provider.Describe(context);
}
return context.Describe((targets ?? Enumerable.Empty<string>()).ToArray());
}
public IDictionary<string, object> Evaluate(string target, IDictionary<string, string> tokens, IDictionary<string, object> data) {
var context = new EvaluateContextImpl(target, tokens, data, this);
foreach (var provider in _providers) {
provider.Evaluate(context);
}
return context.Produce();
}
private class EvaluateContextImpl : EvaluateContext {
private readonly string _target;
private readonly IDictionary<string, string> _tokens;
private readonly IDictionary<string, object> _data;
private readonly ITokenManager _manager;
private readonly IDictionary<string, object> _values = new Dictionary<string, object>();
public EvaluateContextImpl(string target, IDictionary<string, string> tokens, IDictionary<string, object> data, ITokenManager manager) {
_target = target;
_tokens = tokens;
_data = data;
_manager = manager;
}
public IDictionary<string, object> Produce() {
return _values;
}
public override string Target {
get { return _target; }
}
public override IDictionary<string, string> Tokens {
get { return _tokens; }
}
public override IDictionary<string, object> Data {
get { return _data; }
}
public override IDictionary<string, object> Values {
get { return _values; }
}
public override EvaluateFor<TData> For<TData>(string target) {
if (_data != null && string.Equals(target, _target, StringComparison.InvariantCulture)) {
object value;
if (_data.TryGetValue(target, out value)) {
return new EvaluateForImpl<TData>(this, (TData)value);
}
}
return new EvaluateForSilent<TData>();
}
public override EvaluateFor<TData> For<TData>(string target, TData defaultData) {
return For(target, () => defaultData);
}
public override EvaluateFor<TData> For<TData>(string target, Func<TData> defaultData) {
if (string.Equals(target, _target, StringComparison.InvariantCulture)) {
var data = default(TData);
object value;
if (_data != null && _data.TryGetValue(target, out value)) {
data = (TData)value;
}
else if (defaultData != null) {
data = defaultData();
}
return new EvaluateForImpl<TData>(this, data);
}
return new EvaluateForSilent<TData>();
}
private class EvaluateForImpl<TData> : EvaluateFor<TData> {
private readonly EvaluateContextImpl _context;
private readonly TData _data;
public EvaluateForImpl(EvaluateContextImpl context, TData data) {
_context = context;
_data = data;
}
public override TData Data {
get { return _data; }
}
public override EvaluateFor<TData> Token(string token, Func<TData, object> tokenValue) {
string originalToken;
if (_context.Tokens.TryGetValue(token, out originalToken)) {
try {
_context.Values[originalToken] = tokenValue(_data);
}
catch (NullReferenceException) {
_context.Values[originalToken] = null;
}
}
return this;
}
public override EvaluateFor<TData> Token(Func<string, TData, object> tokenValue) {
return Token(null, tokenValue);
}
public override EvaluateFor<TData> Token(Func<string, string> filter, Func<string, TData, object> tokenValue) {
foreach (var token in _context.Tokens) {
var tokenName = token.Key;
if (filter != null) {
tokenName = filter(token.Key);
if (tokenName == null)
continue;
}
var value = tokenValue(tokenName, _data);
if (value != null) {
_context.Values[token.Value] = value;
}
}
return this;
}
public override EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue) {
var subTokens = _context.Tokens
.Where(kv => kv.Key.StartsWith(token + "."))
.ToDictionary(kv => kv.Key.Substring(token.Length + 1), kv => kv.Value);
if (!subTokens.Any()) {
return this;
}
var subValues = _context._manager.Evaluate(chainTarget, subTokens, new Dictionary<string, object> { { chainTarget, chainValue(_data) } });
foreach (var subValue in subValues) {
_context.Values[subValue.Key] = subValue.Value;
}
return this;
}
}
private class EvaluateForSilent<TData> : EvaluateFor<TData> {
public override TData Data {
get { return default(TData); }
}
public override EvaluateFor<TData> Token(string token, Func<TData, object> tokenValue) {
return this;
}
public override EvaluateFor<TData> Token(Func<string, TData, object> tokenValue) {
return this;
}
public override EvaluateFor<TData> Token(Func<string, string> filter, Func<string, TData, object> tokenValue) {
return this;
}
public override EvaluateFor<TData> Chain(string token, string chainTarget, Func<TData, object> chainValue) {
return this;
}
}
}
private class DescribeContextImpl : DescribeContext {
private readonly Dictionary<string, DescribeFor> _describes = new Dictionary<string, DescribeFor>();
public override IEnumerable<TokenTypeDescriptor> Describe(params string[] targets) {
return _describes
.Where(kp => targets == null || targets.Length == 0 || targets.Contains(kp.Key))
.Select(kp => new TokenTypeDescriptor {
Target = kp.Key,
Name = kp.Value.Name,
Description = kp.Value.Description,
Tokens = kp.Value.Tokens
});
}
public override DescribeFor For(string target) {
return For(target, null, null);
}
public override DescribeFor For(string target, LocalizedString name, LocalizedString description) {
DescribeFor describeFor;
if (!_describes.TryGetValue(target, out describeFor)) {
describeFor = new DescribeForImpl(target, name, description);
_describes[target] = describeFor;
}
return describeFor;
}
}
private class DescribeForImpl : DescribeFor {
private readonly LocalizedString _name;
private readonly LocalizedString _description;
private readonly string _target;
private readonly List<TokenDescriptor> _tokens = new List<TokenDescriptor>();
public DescribeForImpl(string target, LocalizedString name, LocalizedString description) {
_target = target;
_name = name;
_description = description;
}
public override LocalizedString Name {
get {
return _name;
}
}
public override LocalizedString Description {
get {
return _description;
}
}
public override IEnumerable<TokenDescriptor> Tokens {
get { return _tokens; }
}
public override DescribeFor Token(string token, LocalizedString name, LocalizedString description) {
return Token(token, name, description, null);
}
public override DescribeFor Token(string token, LocalizedString name, LocalizedString description, string chainTarget) {
_tokens.Add(new TokenDescriptor { Token = token, Name = name, Description = description, Target = _target, ChainTarget = chainTarget });
return this;
}
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
namespace Orchard.Tokens.Implementation {
public class Tokenizer : ITokenizer {
private readonly ITokenManager _tokenManager;
public Tokenizer(ITokenManager tokenManager) {
_tokenManager = tokenManager;
}
public IDictionary<string, object> Evaluate(IEnumerable<string> tokens, object data) {
return Evaluate(tokens, new RouteValueDictionary(data));
}
public IDictionary<string, object> Evaluate(IEnumerable<string> tokens, IDictionary<string, object> data) {
var distinctTokens = tokens.Distinct().ToList();
var replacements = distinctTokens.ToDictionary(s => s, s => (object)null);
return distinctTokens
.Select(Split)
.GroupBy(item => item.Item1)
.SelectMany(grouping => _tokenManager.Evaluate(grouping.Key, grouping.ToDictionary(item => item.Item2, item => item.Item3), data))
.Aggregate(replacements, (agg, kv) => {
agg[kv.Key] = kv.Value;
return agg;
});
}
public string Replace(string text, object data) {
return Replace(text, data, ReplaceOptions.Default);
}
public string Replace(string text, object data, ReplaceOptions options) {
return Replace(text, new RouteValueDictionary(data), options);
}
public string Replace(string text, IDictionary<string, object> data) {
return Replace(text, data, ReplaceOptions.Default);
}
public string Replace(string text, IDictionary<string, object> data, ReplaceOptions options) {
var tokenset = Parse(text);
var tokens = tokenset.Item2;
var replacements = Evaluate(options.Predicate == null ? tokens : tokens.Where(options.Predicate), data);
return replacements.Aggregate(tokenset.Item1,
(current, replacement) => current.Replace("{" + replacement.Key + "}", (options.Encoding ?? ReplaceOptions.NoEncode)(replacement.Key, replacement.Value)));
}
private static Tuple<string, IEnumerable<string>> Parse(string text) {
var tokens = new List<string>();
if (!string.IsNullOrEmpty(text)) {
var inToken = false;
var tokenStart = 0;
for (var i = 0; i < text.Length; i++) {
var c = text[i];
if (c == '{') {
if (i + 1 < text.Length && text[i + 1] == '{') {
text = text.Substring(0, i) + text.Substring(i + 1);
continue;
}
}
else if (c == '}') {
if (i + 1 < text.Length && text[i + 1] == '}') {
text = text.Substring(0, i) + text.Substring(i + 1);
continue;
}
}
if (inToken) {
if (c == '}') {
inToken = false;
var token = text.Substring(tokenStart + 1, i - tokenStart - 1);
tokens.Add(token);
}
}
else if (c == '{') {
inToken = true;
tokenStart = i;
}
}
}
return new Tuple<string, IEnumerable<string>>(text, tokens);
}
private static Tuple<string, string, string> Split(string token) {
var dotIndex = token.IndexOf('.');
if (dotIndex != -1) {
return Tuple.Create(token.Substring(0, dotIndex), token.Substring(dotIndex + 1), token);
}
return Tuple.Create(token, "", token);
}
}
}

View File

@@ -0,0 +1,12 @@
Name: Tokens
AntiForgery: enabled
Author: The Orchard Team
Website: http://orchardtokens.codeplex.com
Version: 1.5
OrchardVersion: 1.4
Description: Provides a system for performing string replacements with common site values.
Features:
Orchard.Tokens:
Name: Tokens
Description: Provides a system for performing string replacements with common site values.
Category: Content

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{6F759635-13D7-4E94-BCC9-80445D63F117}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.Tokens</RootNamespace>
<AssemblyName>Orchard.Tokens</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>4.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkProfile />
<UseIISExpress>false</UseIISExpress>
</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>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</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>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Web.DynamicData" />
<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.Web" />
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\orchard-tokens-admin.js" />
<Content Include="Styles\Images\closeButtons.png" />
<Content Include="Styles\orchard-tokens-admin.css" />
<Content Include="Styles\Images\tokensPopup.gif" />
<Content Include="Web.config" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Content Include="Module.txt" />
<Content Include="Views\TokenHint.cshtml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\..\Core\Orchard.Core.csproj">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Providers\ContentTokens.cs" />
<Compile Include="Providers\RequestTokens.cs" />
<Compile Include="Providers\DateTokens.cs" />
<Compile Include="Providers\TextTokens.cs" />
<Compile Include="Providers\UserTokens.cs" />
<Compile Include="ReplaceOptions.cs" />
<Compile Include="TokenDescriptor.cs" />
<Compile Include="DescribeContext.cs" />
<Compile Include="DescribeFor.cs" />
<Compile Include="EvaluateContext.cs" />
<Compile Include="EvaluateFor.cs" />
<Compile Include="Implementation\Tokenizer.cs" />
<Compile Include="Implementation\TokenManager.cs" />
<Compile Include="ITokenizer.cs" />
<Compile Include="ITokenManager.cs" />
<Compile Include="ITokenProvider.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\Web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Styles\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Views\Admin\" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<!-- 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" DependsOnTargets="AfterBuildCompiler">
<PropertyGroup>
<AreasManifestDir>$(ProjectDir)\..\Manifests</AreasManifestDir>
</PropertyGroup>
<!-- If this is an area child project, uncomment the following line:
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
-->
<!-- If this is an area parent project, uncomment the following lines:
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
-->
</Target>
<Target Name="AfterBuildCompiler" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>45979</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,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Orchard.Tokens")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Orchard")]
[assembly: AssemblyCopyright("Copyright <20> Outercurve Foundation 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("03d51a53-fc12-4a54-9c02-4f233d35c057")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.5")]
[assembly: AssemblyFileVersion("1.5")]

View File

@@ -0,0 +1,155 @@
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Core.Common.Fields;
using Orchard.Localization;
using Orchard.ContentManagement.FieldStorage;
using Orchard.Mvc.Extensions;
namespace Orchard.Tokens.Providers {
public class ContentTokens : ITokenProvider {
private readonly IContentManager _contentManager;
private readonly IWorkContextAccessor _workContextAccessor;
public ContentTokens(IContentManager contentManager, IWorkContextAccessor workContextAccessor) {
_contentManager = contentManager;
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("Content", T("Content Items"), T("Content Items"))
.Token("Id", T("Content Id"), T("Numeric primary key value of content."))
.Token("Author", T("Content Author"), T("Person in charge of the content."), "User")
.Token("Date", T("Content Date"), T("Date the content was created."), "DateTime")
.Token("Identity", T("Identity"), T("Identity of the content."))
.Token("ContentType", T("Content Type"), T("The name of the item Content Type."), "TypeDefinition")
.Token("DisplayText", T("Display Text"), T("Title of the content."),"Text")
.Token("DisplayUrl", T("Display Url"), T("Url to display the content."), "Url")
.Token("EditUrl", T("Edit Url"), T("Url to edit the content."), "Url")
.Token("Container", T("Container"), T("The container Content Item."), "Content")
;
// Token descriptors for fields
foreach(var typeDefinition in _contentManager.GetContentTypeDefinitions()) {
foreach (var typePart in typeDefinition.Parts) {
if(!typePart.PartDefinition.Fields.Any()) {
continue;
}
var partContext = context.For("Content");
foreach (var partField in typePart.PartDefinition.Fields) {
var field = partField;
var tokenName = "Fields." + typePart.PartDefinition.Name + "." + field.Name;
// the token is chained with the technical name
partContext.Token(tokenName, T("{0} {1}", typePart.PartDefinition.Name, field.Name), T("The content of the {0} field.", partField.DisplayName), field.Name);
}
}
}
context.For("TextField", T("Text Field"), T("Tokens for Text Fields"))
.Token("Length", T("Length"), T("The length of the field."));
context.For("Url", T("Url"), T("Tokens for Urls"))
.Token("Absolute", T("Absolute"), T("Absolute url."));
context.For("TypeDefinition", T("Type Definition"), T("Tokens for Content Types"))
.Token("Name", T("Name"), T("Name of the content type."))
.Token("DisplayName", T("Display Name"), T("Display name of the content type."), "Text")
.Token("Parts", T("Parts"), T("List of the attached part names."))
.Token("Fields", T("Fields"), T("Fields for each of the attached parts. For example, Fields.Page.Approved."));
}
public void Evaluate(EvaluateContext context) {
context.For<IContent>("Content")
.Token("Id", content => content.Id)
.Token("Author", AuthorName)
.Chain("Author", "User", content => content.As<ICommonPart>().Owner)
.Token("Date", content => content.As<ICommonPart>().CreatedUtc)
.Chain("Date", "Date", content => content.As<ICommonPart>().CreatedUtc)
.Token("Identity", content => _contentManager.GetItemMetadata(content).Identity.ToString())
.Token("ContentType", content => content.ContentItem.TypeDefinition.DisplayName)
.Chain("ContentType", "TypeDefinition", content => content.ContentItem.TypeDefinition)
.Token("DisplayText", content => _contentManager.GetItemMetadata(content).DisplayText)
.Chain("DisplayText", "Text", content => _contentManager.GetItemMetadata(content).DisplayText)
.Token("DisplayUrl", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).DisplayRouteValues))
.Chain("DisplayUrl", "Url", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).DisplayRouteValues))
.Token("EditUrl", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).EditorRouteValues))
.Chain("EditUrl", "Url", content => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).RouteUrl(_contentManager.GetItemMetadata(content).EditorRouteValues))
.Token("Container", content => {
var container = Container(content);
if(container == null) {
return string.Empty;
}
return _contentManager.GetItemMetadata(container).DisplayText;
})
.Chain("Container", "Content", content => Container(content))
;
if (context.Target == "Content") {
var forContent = context.For<IContent>("Content");
// is there a content available in the context ?
if (forContent != null && forContent.Data != null && forContent.Data.ContentItem != null) {
foreach (var typePart in forContent.Data.ContentItem.TypeDefinition.Parts) {
var part = typePart;
foreach (var partField in typePart.PartDefinition.Fields) {
var field = partField;
var tokenName = "Fields." + typePart.PartDefinition.Name + "." + partField.Name;
forContent.Token(
tokenName,
content => LookupField(content, part.PartDefinition.Name, field.Name).Storage.Get<string>());
forContent.Chain(
tokenName,
partField.FieldDefinition.Name,
content => LookupField(content, part.PartDefinition.Name, field.Name));
}
}
}
}
context.For<string>("Url")
.Token("Absolute", url => new UrlHelper(_workContextAccessor.GetContext().HttpContext.Request.RequestContext).MakeAbsolute(url));
context.For<TextField>("TextField")
.Token("Length", field => (field.Value ?? "").Length);
context.For<ContentTypeDefinition>("TypeDefinition")
.Token("Name", def => def.Name)
.Token("DisplayName", def => def.DisplayName)
.Chain("DisplayName", "Text", def => def.DisplayName)
.Token("Parts", def => string.Join(", ", def.Parts.Select(x => x.PartDefinition.Name).ToArray()))
.Token("Fields", def => string.Join(", ", def.Parts.SelectMany(x => x.PartDefinition.Fields.Select(x2 => x2.FieldDefinition.Name + " " + x.PartDefinition.Name + "." + x2.Name)).ToArray()));
}
private IHtmlString AuthorName(IContent content) {
var commonPart = content.As<ICommonPart>();
var author = commonPart != null ? commonPart.Owner : null;
// todo: encoding should be done at a higher level automatically and should be configurable via an options param
// so it can be disabled
return author == null ? (IHtmlString)T("Anonymous") : new HtmlString(HttpUtility.HtmlEncode(author.UserName));
}
private static ContentField LookupField(IContent content, string partName, string fieldName) {
return content.ContentItem.Parts
.Where(part => part.PartDefinition.Name == partName)
.SelectMany(part => part.Fields.Where(field => field.Name == fieldName))
.SingleOrDefault();
}
private IContent Container(IContent content) {
var commonPart = content.As<ICommonPart>();
if(commonPart == null) {
return null;
}
return commonPart.Container;
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using Orchard.Core.Shapes.Localization;
using Orchard.Localization;
using Orchard.Mvc.Html;
using Orchard.Services;
using System.Globalization;
namespace Orchard.Tokens.Providers {
public class DateTokens : ITokenProvider {
private readonly IClock _clock;
private readonly IDateTimeLocalization _dateTimeLocalization;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly Lazy<CultureInfo> _cultureInfo;
private readonly Lazy<TimeZoneInfo> _timeZone;
public DateTokens(
IClock clock,
IDateTimeLocalization dateTimeLocalization,
IWorkContextAccessor workContextAccessor) {
_clock = clock;
_dateTimeLocalization = dateTimeLocalization;
_workContextAccessor = workContextAccessor;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(_workContextAccessor.GetContext().CurrentCulture));
_timeZone = new Lazy<TimeZoneInfo>(() => _workContextAccessor.GetContext().CurrentTimeZone);
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("Date", T("Date/time"), T("Current date/time tokens"))
.Token("Since", T("Since"), T("Relative to the current date/time."))
.Token("Local", T("Local"), T("Based on the configured time zone."))
.Token("ShortDate", T("Short Date"), T("Short date format."))
.Token("ShortTime", T("Short Time"), T("Short time format."))
.Token("Long", T("Long Date and Time"), T("Long date and time format."))
.Token("Format:*", T("Format:<date format>"), T("Optional format specifier (e.g. yyyy/MM/dd). See format strings at <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/az4se3k1.aspx\">Standard Formats</a> and <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx\">Custom Formats</a>"), "DateTime");
}
public void Evaluate(EvaluateContext context) {
context.For("Date", () => _clock.UtcNow)
// {Date.Since}
.Token("Since", DateTimeRelative)
.Chain("Since", "Date", DateTimeRelative)
// {Date.Local}
.Token("Local", d => TimeZoneInfo.ConvertTimeFromUtc(d, _timeZone.Value))
.Chain("Local", "Date", d => TimeZoneInfo.ConvertTimeFromUtc(d, _timeZone.Value))
// {Date.ShortDate}
.Token("ShortDate", d => d.ToString(_dateTimeLocalization.ShortDateFormat.Text, _cultureInfo.Value))
// {Date.ShortTime}
.Token("ShortTime", d => d.ToString(_dateTimeLocalization.ShortTimeFormat.Text, _cultureInfo.Value))
// {Date.Long}
.Token("Long", d => d.ToString(_dateTimeLocalization.LongDateTimeFormat.Text, _cultureInfo.Value))
// {Date}
.Token(
token => token == String.Empty ? String.Empty : null,
(token, d) => d.ToString(_dateTimeLocalization.ShortDateFormat.Text + " " + _dateTimeLocalization.ShortTimeFormat.Text, _cultureInfo.Value))
// {Date.Format:<formatstring>}
.Token(
token => token.StartsWith("Format:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Format:".Length) : null,
(token, d) => d.ToString(token, _cultureInfo.Value));
}
private string DateTimeRelative(DateTime dateTimeUtc) {
var time = _clock.UtcNow - dateTimeUtc.ToUniversalTime();
if (time.TotalDays > 7)
return dateTimeUtc.ToString(T("'on' MMM d yyyy 'at' h:mm tt").ToString(), _cultureInfo.Value);
if (time.TotalHours > 24)
return T.Plural("1 day ago", "{0} days ago", time.Days).ToString();
if (time.TotalMinutes > 60)
return T.Plural("1 hour ago", "{0} hours ago", time.Hours).ToString();
if (time.TotalSeconds > 60)
return T.Plural("1 minute ago", "{0} minutes ago", time.Minutes).ToString();
if (time.TotalSeconds > 10)
return T.Plural("1 second ago", "{0} seconds ago", time.Seconds).ToString();
return T("a moment ago").ToString();
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using Orchard.Localization;
namespace Orchard.Tokens.Providers {
public class RequestTokens : ITokenProvider {
private readonly IWorkContextAccessor _workContextAccessor;
public RequestTokens(IWorkContextAccessor workContextAccessor) {
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("Request", T("Http Request"), T("Current Http Request tokens."))
.Token("QueryString:*", T("QueryString:<element>"), T("The Query String value for the specified element."))
.Token("Form:*", T("Form:<element>"), T("The Form value for the specified element."))
;
}
public void Evaluate(EvaluateContext context) {
if (_workContextAccessor.GetContext().HttpContext == null) {
return;
}
context.For("Request", _workContextAccessor.GetContext().HttpContext.Request)
.Token(
token => token.StartsWith("QueryString:", StringComparison.OrdinalIgnoreCase) ? token.Substring("QueryString:".Length) : null,
(token, request) => request.QueryString.Get(token)
)
.Token(
token => token.StartsWith("Form:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Form:".Length) : null,
(token, request) => request.Form.Get(token)
);
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Web;
using Orchard.Localization;
namespace Orchard.Tokens.Providers {
public class TextTokens : ITokenProvider {
public TextTokens() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("Text", T("Text"), T("Tokens for text strings"))
.Token("Limit:*", T("Limit:<text length>[,<ellipsis>]"), T("Limit text to specified length and append an optional ellipsis text."))
.Token("Format:*", T("Format:<text format>"), T("Optional format specifier (e.g. foo{0}bar). See format strings at <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/az4se3k1.aspx\">Standard Formats</a> and <a target=\"_blank\" href=\"http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx\">Custom Formats</a>"), "DateTime")
.Token("UrlEncode", T("Url Encode"), T("Encodes a URL string."), "Text")
.Token("HtmlEncode", T("Html Encode"), T("Encodes an HTML string."), "Text")
.Token("LineEncode", T("Line Encode"), T("Replaces new lines with <br /> tags."))
;
}
public void Evaluate(EvaluateContext context) {
context.For<String>("Text", () => "")
.Token( // {Text}
token => token == String.Empty ? String.Empty : null,
(token, d) => d.ToString())
.Token( // {Text.Limit:<length>[,<ellipsis>]}
token => {
if (token.StartsWith("Limit:", StringComparison.OrdinalIgnoreCase)) {
var param = token.Substring("Limit:".Length);
return param;
}
return null;
},
(token, t) => Limit(t, token))
// {Text.Format:<formatstring>}
.Token(
token => token.StartsWith("Format:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Format:".Length) : null,
(token, d) => String.Format(d,token))
.Token("UrlEncode", HttpUtility.UrlEncode)
.Token("HtmlEncode", HttpUtility.HtmlEncode)
.Token("LineEncode", text => text.Replace(System.Environment.NewLine, "<br />"))
;
}
private string Limit(string token, string param) {
if(String.IsNullOrEmpty(token)) {
return String.Empty;
}
var index = param.IndexOf(',');
// no ellipsis
if (index == -1) {
var limit = Int32.Parse(param);
token = token.Substring(0, limit);
}
else {
var limit = Int32.Parse(param.Substring(0, index));
var ellipsis = param.Substring(index + 1);
token = token.Substring(0, limit) + ellipsis;
}
return token;
}
}
}

View File

@@ -0,0 +1,54 @@
using Orchard.Localization;
using Orchard.Security;
namespace Orchard.Tokens.Providers {
public class UserTokens : ITokenProvider {
private readonly IOrchardServices _orchardServices;
private static readonly IUser _anonymousUser = new AnonymousUser();
public UserTokens(IOrchardServices orchardServices) {
_orchardServices = orchardServices;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("User", T("User"), T("User tokens"))
.Token("Name", T("Name"), T("Username"))
.Token("Email", T("Email"), T("Email Address"))
.Token("Id", T("Id"), T("User Id"))
.Token("Content", T("Content"), T("The user's content item"));
}
public void Evaluate(EvaluateContext context) {
context.For("User", () => _orchardServices.WorkContext.CurrentUser ?? _anonymousUser)
.Token("Name", u => u.UserName)
.Token("Email", u => u.Email)
.Token("Id", u => u.Id)
.Chain("Content", "Content", u => u.ContentItem);
// todo: cross-module dependency -- should be provided by the User module?
//.Token("Roles", user => string.Join(", ", user.As<UserRolesPart>().Roles.ToArray()));
}
public class AnonymousUser : IUser {
public string UserName {
get { return "Anonymous"; }
}
public string Email {
get { return string.Empty; }
}
public ContentManagement.ContentItem ContentItem {
get { return null; }
}
public int Id {
get { return -1; }
}
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Web;
namespace Orchard.Tokens {
public class ReplaceOptions {
public Func<string, bool> Predicate { get; set; }
public Func<string, object, string> Encoding { get; set; }
public static string HtmlEncode(string token, object value) {
return HttpUtility.HtmlEncode(value);
}
public static string NoEncode(string token, object value) {
return Convert.ToString(value);
}
public static string UrlEncode(string token, object value) {
return HttpUtility.UrlEncode(value.ToString());
}
public static ReplaceOptions Default {
get {
return new ReplaceOptions { Encoding = HtmlEncode };
}
}
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,67 @@
jQuery.fn.extend({
insertAtCaret: function (myValue) {
return this.each(function(i) {
if (document.selection) {
//For browsers like Internet Explorer
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
} else if (this.selectionStart || this.selectionStart == '0') {
//For browsers like Firefox and Webkit based
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
});
}
});
jQuery(function ($) {
// provide autocomplete behavior to tokenized inputs
// tokensUrl is initialized from the view
$.get(tokensUrl, function (data) {
$('.tokenized')
.autocomplete({
minLength: 0,
source: data,
select: function (event, ui) {
$(this).insertAtCaret(ui.item.value);
return false;
}
}).each(function () {
$(this).data('autocomplete')._renderItem = function (ul, item) {
var result = item.value == '' ? $('<li class="accategory"></li>') : $("<li></li>");
var desc = item.desc.length > 50 ? item.desc.substring(0, 50) + "..." : item.desc;
return result
.data("item.autocomplete", item)
.append('<a ><span class="aclabel">' + item.label + ' </span><span class="acvalue">' + item.value + ' </span><span class="acdesc">' + desc + "</span></a>")
.appendTo(ul);
};
});
});
// add an icon to tokenized inputs
$('.tokenized').wrap('<span class="token-wrapper"></span>');
$('.token-wrapper').prepend('<div><span class="tokenized-popup">&nbsp;</span></div>');
// show the full list of tokens when the icon is clicked
$('.tokenized-popup').click(function () {
var input = $(this).parent().next();
// pass empty string as value to search for, displaying all results
input.autocomplete("search", "");
input.focus();
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,64 @@
.tokenized-popup
{
position:absolute;
background: url('images/tokensPopup.gif');
background-repeat: no-repeat;
width:10px;
height:10px;
cursor: pointer;
padding-right:8px;
margin-top:10px;
right:100%;
}
.token-wrapper {
position:relative;
}
.token-wrapper > div {
float:left;
left:100%;
position: absolute;
margin-bottom: 0px;
}
.ui-autocomplete
{
max-height: 12em;
background: white;
border: 1px solid #BDBCBC;
width: 700px;
overflow :auto;
}
.ui-autocomplete .acdesc
{
padding-right: 5px;
float: right;
}
.ui-autocomplete .acvalue
{
left: 150px;
position: absolute;
}
.ui-autocomplete .accategory
{
font-weight: bold;
}
.ui-autocomplete li a {
padding-left: 5px;
background-color: transparent;
color: #333;
}
.ui-autocomplete li:hover {
background-color: #eee;
color: white;
cursor: pointer;
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Globalization;
using Autofac;
using NUnit.Framework;
using Orchard.Core.Shapes.Localization;
using Orchard.Services;
using Orchard.Tokens.Implementation;
using Orchard.Tokens.Providers;
namespace Orchard.Tokens.Tests {
[TestFixture]
public class DateTokenTests {
private IContainer _container;
private ITokenizer _tokenizer;
private IClock _clock;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<StubOrchardServices>().As<IOrchardServices>();
builder.RegisterType<TokenManager>().As<ITokenManager>();
builder.RegisterType<Tokenizer>().As<ITokenizer>();
builder.RegisterType<DateTokens>().As<ITokenProvider>();
builder.RegisterType<StubClock>().As<IClock>();
builder.RegisterType<DateTimeLocalization>().As<IDateTimeLocalization>();
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
_container = builder.Build();
_tokenizer = _container.Resolve<ITokenizer>();
_clock = _container.Resolve<IClock>();
}
[Test]
public void TestDateTokens() {
var dateTimeLocalization = _container.Resolve<IDateTimeLocalization>();
var culture = CultureInfo.GetCultureInfo(_container.Resolve<IOrchardServices>().WorkContext.CurrentCulture);
var dateTimeFormat = dateTimeLocalization.ShortDateFormat.Text + " " + dateTimeLocalization.ShortTimeFormat.Text;
Assert.That(_tokenizer.Replace("{Date}", null), Is.EqualTo(_clock.UtcNow.ToString(dateTimeFormat, culture)));
Assert.That(_tokenizer.Replace("{Date}", new { Date = new DateTime(1978, 11, 15, 0, 0, 0, DateTimeKind.Utc) }), Is.EqualTo(new DateTime(1978, 11, 15, 0, 0, 0, DateTimeKind.Utc).ToString(dateTimeFormat, culture)));
}
[Test]
public void TestFormat() {
Assert.That(_tokenizer.Replace("{Date.Format:yyyy}", null), Is.EqualTo(_clock.UtcNow.ToString("yyyy")));
}
[Test]
public void TestSince() {
var date = _clock.UtcNow.Subtract(TimeSpan.FromHours(25));
Assert.That(_tokenizer.Replace("{Date.Since}", new { Date = date }), Is.EqualTo("1 day ago"));
}
}
}

View File

@@ -0,0 +1,83 @@
<?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>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{E07AFA7E-7B36-44C3-A537-AFCCAA93EA7A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.Tokens.Tests</RootNamespace>
<AssemblyName>Orchard.Tokens.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</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="Autofac, Version=2.2.4.900, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\..\lib\nunit\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DateTokenTests.cs" />
<Compile Include="StubClock.cs" />
<Compile Include="StubOrchardServices.cs" />
<Compile Include="StubWorkContextAccessor.cs" />
<Compile Include="UserTokenTests.cs" />
<Compile Include="TokenManagerTests.cs" />
<Compile Include="TestTokenProvider.cs" />
<Compile Include="TokenizerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Core\Orchard.Core.csproj">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Tokens.csproj">
<Project>{6F759635-13D7-4E94-BCC9-80445D63F117}</Project>
<Name>Orchard.Tokens</Name>
</ProjectReference>
</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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Orchard.Tokens.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Orchard.Tokens.Tests")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("965bf918-72ab-4333-a0dc-2e435260978b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.4.1")]
[assembly: AssemblyFileVersion("1.4.1")]

View File

@@ -0,0 +1,30 @@
using System;
using Orchard.Caching;
using Orchard.Services;
namespace Orchard.Tokens.Tests {
public class StubClock : IClock {
public StubClock() {
UtcNow = new DateTime(2009, 10, 14, 12, 34, 56, DateTimeKind.Utc);
}
public DateTime UtcNow { get; private set; }
public void Advance(TimeSpan span) {
UtcNow = UtcNow.Add(span);
}
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

@@ -0,0 +1,49 @@
using System;
using Autofac;
using Orchard.ContentManagement;
using Orchard.Data;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard.Tokens.Tests {
public class StubOrchardServices : IOrchardServices {
private readonly ILifetimeScope _lifetimeScope;
public StubOrchardServices() { }
public StubOrchardServices(ILifetimeScope lifetimeScope) {
_lifetimeScope = lifetimeScope;
}
public IContentManager ContentManager {
get { throw new NotImplementedException(); }
}
public ITransactionManager TransactionManager {
get { throw new NotImplementedException(); }
}
public IAuthorizer Authorizer {
get { throw new NotImplementedException(); }
}
public INotifier Notifier {
get { throw new NotImplementedException(); }
}
public dynamic New {
get { throw new NotImplementedException(); }
}
private WorkContext _workContext;
public WorkContext WorkContext {
get {
if (_workContext == null) {
_workContext = new StubWorkContextAccessor(_lifetimeScope).GetContext();
}
return _workContext;
}
}
}
}

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Web;
using Autofac;
using Orchard.ContentManagement;
using Orchard.Security;
using Orchard.Settings;
using System.Globalization;
namespace Orchard.Tokens.Tests {
public class StubWorkContextAccessor : IWorkContextAccessor {
private readonly ILifetimeScope _lifetimeScope;
private readonly WorkContext _workContext;
public StubWorkContextAccessor(ILifetimeScope lifetimeScope) {
_lifetimeScope = lifetimeScope;
_workContext = new WorkContextImpl(_lifetimeScope);
}
public class WorkContextImpl : WorkContext {
private readonly ILifetimeScope _lifetimeScope;
private readonly Dictionary<string, object> _contextDictonary;
public delegate void MyInitMethod(WorkContextImpl workContextImpl);
public static MyInitMethod _initMethod;
public WorkContextImpl(ILifetimeScope lifetimeScope) {
_contextDictonary = new Dictionary<string, object>();
CurrentUser = new StubUser();
var ci = new ContentItem();
ci.Weld(new StubSite());
CurrentSite = ci.As<ISite>();
_lifetimeScope = lifetimeScope;
if (_initMethod != null) {
_initMethod(this);
}
_contextDictonary["CurrentTimeZone"] = TimeZoneInfo.Local;
_contextDictonary["CurrentCulture"] = "en-US";
}
public class StubSite : ContentPart, ISite {
public static string DefaultSuperUser;
public string PageTitleSeparator {
get { throw new NotImplementedException(); }
}
public string SiteName {
get { throw new NotImplementedException(); }
}
public string SiteSalt {
get { throw new NotImplementedException(); }
}
public string SuperUser {
get { return DefaultSuperUser; }
}
public string HomePage {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string SiteCulture {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public ResourceDebugMode ResourceDebugMode {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public int PageSize {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string BaseUrl { get; set; }
public string SiteTimeZone {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public class StubUser : IUser {
public ContentItem ContentItem {
get { throw new NotImplementedException(); }
}
public int Id {
get { return 5; }
}
public string UserName {
get { return "Fake"; }
}
public string Email {
get { return "Fake@fake.com"; }
}
}
public override T Resolve<T>() {
return _lifetimeScope.Resolve<T>();
}
public override bool TryResolve<T>(out T service) {
return _lifetimeScope.TryResolve<T>(out service);
}
public override T GetState<T>(string name) {
return (T)_contextDictonary[name];
}
public override void SetState<T>(string name, T value) {
_contextDictonary[name] = value;
}
}
public WorkContext GetContext(HttpContextBase httpContext) {
return _workContext;
}
public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) {
throw new NotSupportedException();
}
public WorkContext GetContext() {
return _workContext;
}
public IWorkContextScope CreateWorkContextScope() {
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Security;
namespace Orchard.Tokens.Tests {
public class TestTokenProvider : ITokenProvider {
public TestTokenProvider() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeContext context) {
context.For("Site")
.Token("Global1", T("Global1"), T("description of token1"))
.Token("Global2", T("Global2"), T("description of token2"))
.Token("Global3", T("Global3"), T("description of token3"))
.Token("CurrentUser", T("Current User"), T("The current user"), "User");
context.For("User")
.Token("Name", T("Name"), T("Their user name"))
.Token("Birthdate", T("Birthdate"), T("Date of birth"), "DateTime");
context.For("Date")
.Token("Now", T("Now"), T("Current system date in short date format. You can chain a .NET DateTime format string to customize."));
}
public void Evaluate(EvaluateContext context) {
context.For<object>("Site", null)
.Token("Global1", o => "[global1]")
.Token("Global2", o => "[global2]")
.Token("Global3", o => "[global3]")
.Token("CurrentUser", o => new TestUser { UserName = "CurrentUser" })
.Chain("CurrentUser", "User", o => new TestUser { UserName = "CurrentUser" });
context.For<IUser>("User", () => new TestUser { UserName = "CurrentUser" })
.Token("Name", u => u.UserName)
.Token("Birthdate", u => "Nov 15")
.Chain("Birthdate", "DateTime", u => new DateTime(1978, 11, 15));
context.For<object>("Date", null)
.Token("Now", o => DateTime.Now.ToShortDateString())
.Chain("Now", "DateTime", o => DateTime.Now);
context.For<DateTime>("DateTime")
.Token((token, value) => value.ToString(token));
}
}
public class TestUser : IUser {
public string UserName { get; set; }
public string Email { get; set; }
public ContentItem ContentItem { get; set; }
public int Id { get; set; }
}
}

View File

@@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Linq;
using Autofac;
using NUnit.Framework;
using Orchard.Tokens.Implementation;
namespace Orchard.Tokens.Tests {
[TestFixture]
public class TokenManagerTests {
private IContainer _container;
private ITokenManager _tokenManager;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<TokenManager>().As<ITokenManager>();
builder.RegisterType<TestTokenProvider>().As<ITokenProvider>();
_container = builder.Build();
_tokenManager = _container.Resolve<ITokenManager>();
}
[Test]
public void TestEvaluate() {
var tokens = _tokenManager.Evaluate("Site", new Dictionary<string, string> { { "Global1", "Site.Global1" }, { "Global2", "Site.Global2" } }, null);
Assert.That(tokens["Site.Global1"], Is.EqualTo("[global1]"));
Assert.That(tokens["Site.Global2"], Is.EqualTo("[global2]"));
}
[Test]
public void TestDescribe() {
var allTokens = _tokenManager.Describe(null);
Assert.That(allTokens.Count(), Is.EqualTo(3));
Assert.That(allTokens.Any(d => d.Target == "Site"));
Assert.That(allTokens.Any(d => d.Target == "User"));
Assert.That(allTokens.Any(d => d.Target == "Date"));
var tokens = allTokens.Single(d => d.Target == "Site").Tokens;
Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Site,Site,Site,Site"));
Assert.That(string.Join(",", tokens.Select(td => td.Token)), Is.EqualTo("Global1,Global2,Global3,CurrentUser"));
Assert.That(string.Join(",", tokens.Select(td => td.Name.ToString())), Is.EqualTo("Global1,Global2,Global3,Current User"));
Assert.That(string.Join(",", tokens.Select(td => td.Description.ToString())), Is.EqualTo("description of token1,description of token2,description of token3,The current user"));
Assert.That(string.Join(",", tokens.Select(td => td.ChainTarget ?? "")), Is.EqualTo(",,,User"));
tokens = allTokens.Single(d => d.Target == "User").Tokens;
Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("User,User"));
Assert.That(string.Join(",", tokens.Select(td => td.Token)), Is.EqualTo("Name,Birthdate"));
Assert.That(string.Join(",", tokens.Select(td => td.Name.ToString())), Is.EqualTo("Name,Birthdate"));
Assert.That(string.Join(",", tokens.Select(td => td.Description.ToString())), Is.EqualTo("Their user name,Date of birth"));
Assert.That(string.Join(",", tokens.Select(td => td.ChainTarget ?? "")), Is.EqualTo(",DateTime"));
tokens = allTokens.Single(d => d.Target == "Date").Tokens;
Assert.That(string.Join(",", tokens.Select(td => td.Target)), Is.EqualTo("Date"));
Assert.That(string.Join(",", tokens.Select(td => td.Token)), Is.EqualTo("Now"));
Assert.That(string.Join(",", tokens.Select(td => td.Name.ToString())), Is.EqualTo("Now"));
Assert.That(string.Join(",", tokens.Select(td => td.Description.ToString())), Is.EqualTo("Current system date in short date format. You can chain a .NET DateTime format string to customize."));
Assert.That(string.Join(",", tokens.Select(td => td.ChainTarget ?? "")), Is.EqualTo(""));
}
[Test]
public void TestDescribeFilter() {
var tokenDescriptors = _tokenManager.Describe(null);
Assert.That(tokenDescriptors.Count(), Is.EqualTo(3));
tokenDescriptors = _tokenManager.Describe(new[] { "Site" });
Assert.That(tokenDescriptors.Count(), Is.EqualTo(1));
Assert.That(tokenDescriptors.First().Target, Is.EqualTo("Site"));
tokenDescriptors = _tokenManager.Describe(new[] { "Site", "User" });
Assert.That(tokenDescriptors.Count(), Is.EqualTo(2));
Assert.That(tokenDescriptors.Any(d => d.Target == "Site"));
Assert.That(tokenDescriptors.Any(d => d.Target == "User"));
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using Autofac;
using NUnit.Framework;
using Orchard.Tokens.Implementation;
namespace Orchard.Tokens.Tests {
[TestFixture]
public class TokenizerTests {
private IContainer _container;
private ITokenizer _tokenizer;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<Tokenizer>().As<ITokenizer>();
builder.RegisterType<TokenManager>().As<ITokenManager>();
builder.RegisterType<TestTokenProvider>().As<ITokenProvider>();
_container = builder.Build();
_tokenizer = _container.Resolve<ITokenizer>();
}
[Test]
public void TestGlobalTokens() {
Assert.That(_tokenizer.Replace("{Site.Global1}", null), Is.EqualTo("[global1]"));
Assert.That(_tokenizer.Replace("{Site.Global2}", null), Is.EqualTo("[global2]"));
Assert.That(_tokenizer.Replace("{Site.Global1}{Site.Global2}{Site.Global1}{Site.Global2}", null), Is.EqualTo("[global1][global2][global1][global2]"));
}
[Test]
public void TestContextTokens() {
Assert.That(_tokenizer.Replace("{User.Name}", null), Is.EqualTo("CurrentUser"));
Assert.That(_tokenizer.Replace("{User.Name}", new { User = new TestUser { UserName = "LocalUser" } }), Is.EqualTo("LocalUser"));
}
[Test]
public void TestChainedTokens() {
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Name}", null), Is.EqualTo("CurrentUser"));
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Name}", new { User = new TestUser { UserName = "ShouldStillUseParentValue" } }), Is.EqualTo("CurrentUser"));
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate}", null), Is.EqualTo("Nov 15"));
Assert.That(_tokenizer.Replace("{Site.CurrentUser.Birthdate.yyyy}", null), Is.EqualTo("1978"));
}
[Test]
public void TestMissingTokens() {
Assert.That(_tokenizer.Replace("[{Site.NotAToken}]", null), Is.EqualTo("[]"));
Assert.That(_tokenizer.Replace("[{NotATokenType.Foo}]", null), Is.EqualTo("[]"));
Assert.That(_tokenizer.Replace("[{Site.CurrentUser.NotASubToken}]", null), Is.EqualTo("[]"));
Assert.That(_tokenizer.Replace("[{Site}]", null), Is.EqualTo("[]"));
Assert.That(_tokenizer.Replace("[{NotATokenType}]", null), Is.EqualTo("[]"));
}
[Test]
public void TestTokenCaseSensitivity() {
Assert.That(_tokenizer.Replace("{Site.Global1}", null), Is.EqualTo("[global1]"));
Assert.That(_tokenizer.Replace("{site.Global1}", null), Is.EqualTo(""));
Assert.That(_tokenizer.Replace("{Site.global1}", null), Is.EqualTo(""));
}
[Test]
public void TestTokenEscapeSequences() {
Assert.That(_tokenizer.Replace("{{escaped}} {Site.Global1} }}{{ {{{{ }}}}", null), Is.EqualTo("{escaped} [global1] }{ {{ }}"));
Assert.That(_tokenizer.Replace("{Date.Now.{{yyyy}}}", null), Is.EqualTo(DateTime.UtcNow.ToString("{yyyy}")));
}
[Test]
public void TestHtmlEncodedByDefault() {
Assert.That(_tokenizer.Replace("{Date.Now.<>}", null), Is.EqualTo("&lt;&gt;"));
}
[Test]
public void TestNoEncode() {
Assert.That(_tokenizer.Replace("{Date.Now.<>}", null, new ReplaceOptions { Encoding = ReplaceOptions.NoEncode }), Is.EqualTo("<>"));
}
[Test]
public void TestPredicate() {
Assert.That(_tokenizer.Replace("{Site.Global1}{Site.Global2}", null, new ReplaceOptions { Predicate = token => token == "Site.Global2" }), Is.EqualTo("{Site.Global1}[global2]"));
}
}
}

View File

@@ -0,0 +1,41 @@
using Autofac;
using NUnit.Framework;
using Orchard.Tokens.Implementation;
using Orchard.Tokens.Providers;
namespace Orchard.Tokens.Tests {
[TestFixture]
public class UserTokenTests {
private IContainer _container;
private ITokenizer _tokenizer;
[SetUp]
public void Init() {
var builder = new ContainerBuilder();
builder.RegisterType<StubOrchardServices>().As<IOrchardServices>();
builder.RegisterType<TokenManager>().As<ITokenManager>();
builder.RegisterType<Tokenizer>().As<ITokenizer>();
builder.RegisterType<UserTokens>().As<ITokenProvider>();
_container = builder.Build();
_tokenizer = _container.Resolve<ITokenizer>();
}
[Test]
public void TestUserTokens() {
var str = _tokenizer.Replace("{User.Name},{User.Email},{User.Id}", new { User = new TestUser { UserName = "Joe", Email = "test@test.com", Id = 88 } });
Assert.That(str, Is.EqualTo("Joe,test@test.com,88"));
str = _tokenizer.Replace("{User.Name},{User.Email},{User.Id}", null);
Assert.That(str, Is.EqualTo("Fake,Fake@fake.com,5"));
}
[Test]
public void AnonymousUserShouldReturnEmpty() {
var result = _tokenizer.Replace("{User.Name}", new { User = default(TestUser) });
Assert.That(result, Is.Empty);
result = _tokenizer.Replace("{User}", new { User = default(TestUser) });
Assert.That(result, Is.Empty);
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
using Orchard.Localization;
namespace Orchard.Tokens {
public class TokenDescriptor {
public string Target { get; set; }
public string Token { get; set; }
public string ChainTarget { get; set; }
public LocalizedString Name { get; set; }
public LocalizedString Description { get; set; }
}
public class TokenTypeDescriptor {
public string Target { get; set; }
public LocalizedString Name { get; set; }
public LocalizedString Description { get; set; }
public IEnumerable<TokenDescriptor> Tokens { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
@{
Script.Require("jQueryUI_Autocomplete");
Script.Include("orchard-tokens-admin.js").AtFoot();
Style.Include("orchard-tokens-admin.css");
}
@using(Script.Head()) {
<script type="text/javascript">
//<![CDATA[
var tokensUrl = '@Url.Action("Tokens", "Admin", new { area = "Orchard.Tokens" })';
//]]>
</script>
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<controls>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<remove name="host" />
<remove name="pages" />
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<pages pageBaseType="Orchard.Mvc.ViewEngines.Razor.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web.webPages.razor>
<system.web>
<compilation targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</assemblies>
</compilation>
</system.web>
</configuration>