mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Including Orchard.Tokens
--HG-- branch : 1.x
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
10
src/Orchard.Web/Modules/Orchard.Tokens/DescribeContext.cs
Normal file
10
src/Orchard.Web/Modules/Orchard.Tokens/DescribeContext.cs
Normal 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);
|
||||
}
|
||||
}
|
12
src/Orchard.Web/Modules/Orchard.Tokens/DescribeFor.cs
Normal file
12
src/Orchard.Web/Modules/Orchard.Tokens/DescribeFor.cs
Normal 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);
|
||||
}
|
||||
}
|
15
src/Orchard.Web/Modules/Orchard.Tokens/EvaluateContext.cs
Normal file
15
src/Orchard.Web/Modules/Orchard.Tokens/EvaluateContext.cs
Normal 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);
|
||||
}
|
||||
}
|
11
src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs
Normal file
11
src/Orchard.Web/Modules/Orchard.Tokens/EvaluateFor.cs
Normal 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);
|
||||
}
|
||||
}
|
8
src/Orchard.Web/Modules/Orchard.Tokens/ITokenManager.cs
Normal file
8
src/Orchard.Web/Modules/Orchard.Tokens/ITokenManager.cs
Normal 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);
|
||||
}
|
||||
}
|
8
src/Orchard.Web/Modules/Orchard.Tokens/ITokenProvider.cs
Normal file
8
src/Orchard.Web/Modules/Orchard.Tokens/ITokenProvider.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Orchard.Events;
|
||||
|
||||
namespace Orchard.Tokens {
|
||||
public interface ITokenProvider : IEventHandler {
|
||||
void Describe(DescribeContext context);
|
||||
void Evaluate(EvaluateContext context);
|
||||
}
|
||||
}
|
13
src/Orchard.Web/Modules/Orchard.Tokens/ITokenizer.cs
Normal file
13
src/Orchard.Web/Modules/Orchard.Tokens/ITokenizer.cs
Normal 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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
12
src/Orchard.Web/Modules/Orchard.Tokens/Module.txt
Normal file
12
src/Orchard.Web/Modules/Orchard.Tokens/Module.txt
Normal 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
|
161
src/Orchard.Web/Modules/Orchard.Tokens/Orchard.Tokens.csproj
Normal file
161
src/Orchard.Web/Modules/Orchard.Tokens/Orchard.Tokens.csproj
Normal 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>
|
@@ -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")]
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
28
src/Orchard.Web/Modules/Orchard.Tokens/ReplaceOptions.cs
Normal file
28
src/Orchard.Web/Modules/Orchard.Tokens/ReplaceOptions.cs
Normal 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 };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
25
src/Orchard.Web/Modules/Orchard.Tokens/Scripts/Web.config
Normal file
25
src/Orchard.Web/Modules/Orchard.Tokens/Scripts/Web.config
Normal 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>
|
@@ -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"> </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 |
25
src/Orchard.Web/Modules/Orchard.Tokens/Styles/Web.config
Normal file
25
src/Orchard.Web/Modules/Orchard.Tokens/Styles/Web.config
Normal 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>
|
@@ -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;
|
||||
}
|
||||
|
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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>
|
@@ -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")]
|
30
src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubClock.cs
Normal file
30
src/Orchard.Web/Modules/Orchard.Tokens/Tests/StubClock.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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; }
|
||||
}
|
||||
}
|
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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("<>"));
|
||||
}
|
||||
|
||||
[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]"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
19
src/Orchard.Web/Modules/Orchard.Tokens/TokenDescriptor.cs
Normal file
19
src/Orchard.Web/Modules/Orchard.Tokens/TokenDescriptor.cs
Normal 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; }
|
||||
}
|
||||
}
|
@@ -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>
|
||||
}
|
41
src/Orchard.Web/Modules/Orchard.Tokens/Views/Web.config
Normal file
41
src/Orchard.Web/Modules/Orchard.Tokens/Views/Web.config
Normal 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>
|
41
src/Orchard.Web/Modules/Orchard.Tokens/Web.config
Normal file
41
src/Orchard.Web/Modules/Orchard.Tokens/Web.config
Normal 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>
|
Reference in New Issue
Block a user