11using System ;
2+ using System . Linq ;
23using System . Web ;
34using Orchard . ContentManagement ;
45using Orchard . Localization ;
6+ using System . Globalization ;
7+ using System . Text . RegularExpressions ;
58
69namespace Orchard . Tokens . Providers {
710 public class RequestTokens : ITokenProvider {
811 private readonly IWorkContextAccessor _workContextAccessor ;
912 private readonly IContentManager _contentManager ;
13+ private static string [ ] _textChainableTokens ;
1014
1115 public RequestTokens ( IWorkContextAccessor workContextAccessor , IContentManager contentManager ) {
1216 _workContextAccessor = workContextAccessor ;
1317 _contentManager = contentManager ;
18+ _textChainableTokens = new string [ ] { "QueryString" , "Form" } ;
1419 T = NullLocalizer . Instance ;
1520 }
1621
1722 public Localizer T { get ; set ; }
1823
1924 public void Describe ( DescribeContext context ) {
2025 context . For ( "Request" , T ( "Http Request" ) , T ( "Current Http Request tokens." ) )
21- . Token ( "QueryString:*" , T ( "QueryString:<element>" ) , T ( "The Query String value for the specified element." ) )
22- . Token ( "Form:*" , T ( "Form:<element>" ) , T ( "The Form value for the specified element." ) )
26+ . Token ( "QueryString:*" , T ( "QueryString:<element>" ) , T ( "The Query String value for the specified element. If you want ot chain text, surround the <element> with brackets [e.g. QueryString:(param1)]. " ) )
27+ . Token ( "Form:*" , T ( "Form:<element>" ) , T ( "The Form value for the specified element. If you want ot chain text, surround the <element> with brackets [e.g. Form:(param1)]. " ) )
2328 . Token ( "Route:*" , T ( "Route:<key>" ) , T ( "The Route value for the specified key." ) )
2429 . Token ( "Content" , T ( "Content" ) , T ( "The request routed Content Item." ) , "Content" )
2530 ;
@@ -29,20 +34,30 @@ public void Evaluate(EvaluateContext context) {
2934 if ( _workContextAccessor . GetContext ( ) . HttpContext == null ) {
3035 return ;
3136 }
32-
37+ /* Supported Syntaxes for Request and Form tokens are:
38+ * 1. QueryString:(param1) or Form:(param1)
39+ * 2. QueryString:param1 or Form:param1
40+ * 3. QueryString:(param1).SomeOtherTextToken or Form:(param1).SomeOtherTextToken
41+ *
42+ * If you want to Chain TextTokens you have to use 3rd syntax
43+ * the element (here param1) has been surrounded with brackets in order to preserve backward compatibility.
44+ */
3345 context . For ( "Request" , _workContextAccessor . GetContext ( ) . HttpContext . Request )
3446 . Token (
35- token => token . StartsWith ( "QueryString:" , StringComparison . OrdinalIgnoreCase ) ? token . Substring ( "QueryString:" . Length ) : null ,
36- ( token , request ) => request . QueryString . Get ( token )
47+ FilterTokenParam ,
48+ ( token , request ) => {
49+ return request . QueryString . Get ( token ) ;
50+ }
3751 )
3852 . Token (
39- token => token . StartsWith ( "Form:" , StringComparison . OrdinalIgnoreCase ) ? token . Substring ( "Form:" . Length ) : null ,
53+ FilterTokenParam ,
4054 ( token , request ) => request . Form . Get ( token )
4155 )
4256 . Token (
4357 token => token . StartsWith ( "Route:" , StringComparison . OrdinalIgnoreCase ) ? token . Substring ( "Route:" . Length ) : null ,
4458 ( token , request ) => GetRouteValue ( token , request )
4559 )
60+ . Chain ( FilterChainParam , "Text" , ( token , request ) => request . QueryString . Get ( token ) )
4661 . Token ( "Content" ,
4762 ( request ) => DisplayText ( GetRoutedContentItem ( request ) )
4863 )
@@ -98,5 +113,53 @@ private string DisplayText(IContent content) {
98113
99114 return _contentManager . GetItemMetadata ( content ) . DisplayText ;
100115 }
116+
117+ private static string FilterTokenParam ( string token ) {
118+ string tokenPrefix ;
119+ int chainIndex , tokenLength ;
120+ if ( token . IndexOf ( ":" ) == - 1 ) {
121+ return null ;
122+ }
123+ tokenPrefix = token . Substring ( 0 , token . IndexOf ( ":" ) ) ;
124+ if ( ! _textChainableTokens . Contains ( tokenPrefix , StringComparer . OrdinalIgnoreCase ) ) {
125+ return null ;
126+ }
127+
128+ // use ")." as chars combination to discover the end of the parameter
129+ chainIndex = token . IndexOf ( ")." ) + 1 ;
130+ tokenLength = ( tokenPrefix + ":" ) . Length ;
131+ if ( chainIndex == 0 ) { // ")." has not be found
132+ return Regex . Replace ( token . Substring ( tokenLength ) , @"[\(|\)]" , "" ) ;
133+ }
134+ if ( ! token . StartsWith ( ( tokenPrefix + ":" ) , StringComparison . OrdinalIgnoreCase ) || chainIndex <= tokenLength ) {
135+ return null ;
136+ }
137+ return Regex . Replace ( token . Substring ( tokenLength , chainIndex - tokenLength ) , @"[\(|\)]" , "" ) ;
138+ }
139+ private static Tuple < string , string > FilterChainParam ( string token ) {
140+ string tokenPrefix ;
141+ int chainIndex , tokenLength ;
142+
143+ if ( token . IndexOf ( ":" ) == - 1 ) {
144+ return null ;
145+ }
146+ tokenPrefix = token . Substring ( 0 , token . IndexOf ( ":" ) ) ;
147+ if ( ! _textChainableTokens . Contains ( tokenPrefix , StringComparer . OrdinalIgnoreCase ) ) {
148+ return null ;
149+ }
150+
151+ // use ")." as chars combination to discover the end of the parameter
152+ chainIndex = token . IndexOf ( ")." ) + 1 ;
153+ tokenLength = ( tokenPrefix + ":" ) . Length ;
154+ if ( chainIndex == 0 ) { // ")." has not be found
155+ return new Tuple < string , string > ( Regex . Replace ( token . Substring ( tokenLength ) , @"[\(|\)]" , "" ) , token . Length . ToString ( ) ) ;
156+ }
157+ if ( ! token . StartsWith ( ( tokenPrefix + ":" ) , StringComparison . OrdinalIgnoreCase ) || chainIndex <= tokenLength ) {
158+ return null ;
159+ }
160+ return new Tuple < string , string > ( Regex . Replace ( token . Substring ( tokenLength , chainIndex - tokenLength ) , @"[\(|\)]" , "" ) , token . Substring ( chainIndex + 1 ) ) ;
161+
162+ }
101163 }
102- }
164+
165+ }
0 commit comments