View Issue Details

IDProjectCategoryView StatusLast Update
04424User patchesAdmin Toolspublic2012-06-21 13:22
Reporterorvil Assigned ToTMSWhite  
PrioritynormalSeveritytweak 
Status closedResolutionfixed 
Product Version 
Target Version1.91Fixed in Version1.92RC1 
Summary04424: New URL field {GATE} to switch exit-URL and parameters by logical expressions
Description

Hi,
Sometimes it is necessary to switch the exit url or parameters of the exit url by the results of some questions, by language, time or something else.

Therefore I built a {GATE} function, witch is working fine in LS1.86 and 1.90RC1

It maybe will solve some problems other users reported in the past.

Please see the attached file for detailed infomations how to imlement.

Regards
orvil

Steps To Reproduce

See attached file: gate-function.txt

Additional Information

How it is working

The general syntax is
{GATE:[key]=expression;}
where expression is a php if-statement like
(TRUE|FALSE) operator ? TRUE-PART : FALSE-PART ;
e.g.
{GATE:xyz=('A'=='B')?'yes':'no';}

NEVER FORGET THE SEMICOLON at the end!
(working on an update to fix it, if it's forgotten)

eg. the expression
{GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}
will be replaced first by the insertansReplace function to look like
{GATE:sco=('yes'=='yes')?'A':'B';}
then - because ('yes'=='yes') is true - the expression will be replaced to a simple
sco=A
so a exit-url like
http://localhost/end.php?{GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}&someother=0
will finally be
http://localhost/end.php?sco=A&someother=0
Or, if INSERTANS:1234X56X7 = "no"
the exit-url
http://localhost/end.php?{GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}&someother=0
will change into
http://localhost/end.php?{GATE:sco=('no'=='yes')?'A':'B';}&someother=0
and finally
http://localhost/end.php?sco=B&someother=0

Due to the fact of evaluating the {GATE:xxxx;} statement with the built in php-function eval() there can a lot of logical switches be done to manipulate an arguments value
e.g. combine the results of two questions logically
{GATE:xyz=('{INSERTANS:1234X50X10}'=='yes' && '{INSERTANS:1234X60X10}'=='no')?'A':'B';}

combine different URL-Fields
{GATE:abc=('{LANG}'=='DE' || '{LANG}'=='FR')?'eu':'int';}

or every php expressions
{Gate:ex=(date('D')=='Sun')?'wknd':'week';}

It is also possible to change the url by an expression (notice: there is no key set, only GATE:= )
"http://{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'www.firsturl.org':'www.otherurl.org';}/thanks.php";

or the document to call
"http://localhost/{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'thanks.html':'sorry.php';}";

or a combination of both
"http://{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'www.firsturl.org':'www.otherurl.org';}/{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'thanks.html':'sorry.php';}";

TagsNo tags attached.
Complete LimeSurvey version number (& build)8819

Relationships

related to 05103 closedTMSWhite Support conditional piping/tailoring and complex calculations via embedded equation parser 

Activities

orvil

orvil

2010-06-15 17:12

reporter  

gate-function.txt (6,515 bytes)
1. Add a new function in common.php
--------------------------------------

/** 
 *  ov: 2010-06-15 13:37
 *  gateReplace() takes a string and looks for a {GATE:xxxx;} statement
 *  to substitute with the related answer or any logical expression
 *
 *  eg. the expression
 *     {GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}
 *  will be replaced first by the insertansReplace function to look like
 *     {GATE:sco=('yes'=='yes')?'A':'B';}
 *  then the expression will be replaced to a simple
 *     sco=A
 *  so a exit-url like
 *     http://localhost/end.php?{GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}&someother=0
 *  will finally be
 *     http://localhost/end.php?sco=A&someother=0
 *  Or, if INSERTANS:1234X56X7 = "no"
 *  the exit-url 
 * 	   http://localhost/end.php?{GATE:sco=('{INSERTANS:1234X56X7}'=='yes')?'A':'B';}&someother=0
 *  will change into
 *     http://localhost/end.php?{GATE:sco=('no'=='yes')?'A':'B';}&someother=0
 *  and finally
 *     http://localhost/end.php?sco=B&someother=0
 *
 *  Due to the fact of evaluating the {GATE:xxxx;} statement with the built in php-function eval()
 *  there can a lot of logical switches be done to manipulate an arguments value
 *  e.g. combine the results of two questions logically
 *     {GATE:xyz=('{INSERTANS:1234X50X10}'=='yes' && '{INSERTANS:1234X60X10}'=='no')?'A':'B';}
 *
 *  combine different URL-Fields
 *     {GATE:abc=('{LANG}'=='DE' || '{LANG}'=='FR')?'eu':'int';}
 *
 *  or every php expressions
 *     {Gate:ex=(date('D')=='Sun')?'wknd':'week';}
 *
 *  It is also possible to change the url by an expression (notice: there is no key set, only GATE:= )
 *      "http://{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'www.firsturl.org':'www.otherurl.org';}/thanks.php";
 *
 *  or the document to call
 *      "http://localhost/{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'thanks.html':'sorry.php';}";
 *
 *  or a combination of both
 *      "http://{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'www.firsturl.org':'www.otherurl.org';}/{GATE:=('{INSERTANS:1234X50X10}'=='yes')?'thanks.html':'sorry.php';}";
 *
 * 
 * @param mixed $line   string - the string to iterate, and then return
 *
 * @return string This string is returned containing the substituted responses
 *
 */
function gateReplace($line)
{
	//find if there is a gate
	while (strpos($line,"{GATE:"))
	{
		// extract key
		$p1=strpos($line,"{GATE:");					// start of "{GATE:" string
		$p2=$p1+6;									// start of key
		$p3=strpos($line,"=",$p2);					// position of "=" after key
		$p4=strpos($line,"}",$p3);					// position of closing "}"

		$cmd=substr($line,$p1,$p4-$p1+1);			// the complete "{GATE:sco= IF_EXPRESSION }" string
		$key=substr($line,$p2,$p3-$p2);				// the key like "sco"
		$ifex=substr($line,$p3+1,$p4-$p3-1);		// the IF_EXPRESSION part
		eval("\$ifres= " . $ifex);					// evaluate the logical expression
		
		$new=$key . "=" . $ifres;					// this is for replacement
		
		//$newline = str_replace($cmd,$new,$line);// replace the gate expression by the result
		if ($ifres=='')
		{
			$line = str_replace($cmd,"",$line);	// no key and value if there is no value
		}
		else
		{
			$line = str_replace($cmd,$new,$line);// replace the gate expression by the result
		}
	}	
	return $line;
}


2. Add one line at group.php (V1.90RC1 line 225ff)
----------------------------------------------------

        if (isset($thissurvey['autoredirect']) && $thissurvey['autoredirect'] == "Y" && $thissurvey['surveyls_url'])
        {
            //Automatically redirect the page to the "url" setting for the survey

            $url = $thissurvey['surveyls_url'];
            $url = insertansReplace($thissurvey['surveyls_url']);
            $url = passthruReplace($url, $thissurvey);
            $url=str_replace("{SAVEDID}",$saved_id, $url);			   // to activate the SAVEDID in the END URL
            $url=str_replace("{TOKEN}",$clienttoken, $url);          // to activate the TOKEN in the END URL
            $url=str_replace("{SID}", $surveyid, $url);              // to activate the SID in the END URL
            $url=str_replace("{LANG}", $clang->getlangcode(), $url); // to activate the LANG in the END URL
			
			// NEW ov: adding gateReplace
			$url = gateReplace($url);
			// END NEW
			
            header("Location: {$url}");

        }
		
3. Add one line at question.php (V1.90RC1 line 279ff)
------------------------------------------------------	

		if (isset($thissurvey['autoredirect']) && $thissurvey['autoredirect'] == "Y" && $thissurvey['surveyls_url'])
        {
            //Automatically redirect the page to the "url" setting for the survey
            $url = insertansReplace($thissurvey['surveyls_url']);
            $url = passthruReplace($url, $thissurvey);
            $url=str_replace("{SAVEDID}",$saved_id, $url);           // to activate the SAVEDID in the END URL
            $url=str_replace("{TOKEN}",$clienttoken, $url);          // to activate the TOKEN in the END URL
            $url=str_replace("{SID}", $surveyid, $url);              // to activate the SID in the END URL
            $url=str_replace("{LANG}", $clang->getlangcode(), $url); // to activate the LANG in the END URL
			
			// NEW ov: adding gateReplace
			$url = gateReplace($url);
			// END NEW
			
            header("Location: {$url}");
        }	
		
		
4. Add one line at survey.php (V1.90RC1 line 174ff)
------------------------------------------------------	

		if (!$embedded && isset($thissurvey['autoredirect']) && $thissurvey['autoredirect'] == "Y" && $thissurvey['surveyls_url'])
        {

            $url = insertansReplace($thissurvey['surveyls_url']);
            $url = passthruReplace($url, $thissurvey);
            $url=str_replace("{SAVEDID}",$saved_id, $url);			           // to activate the SAVEDID in the END URL
            $url=str_replace("{TOKEN}",$clienttoken, $url);          // to activate the TOKEN in the END URL
            $url=str_replace("{SID}", $surveyid, $url);              // to activate the SID in the END URL
            $url=str_replace("{LANG}", $clang->getlangcode(), $url); // to activate the LANG in the END URL
			
            // NEW ov: adding gateReplace
			$url = gateReplace($url);
			// END NEW
			
			//Automatically redirect the page to the "url" setting for the survey
            session_write_close();

            header("Location: {$url}");
        }
gate-function.txt (6,515 bytes)
DenisChenu

DenisChenu

2010-06-18 10:24

developer   ~12259

I don't understand,

Actually we can use INSERTANS in the url.
If i want something like this patch do : i can had a some jquery function.

Do i lost something ?

orvil

orvil

2010-06-19 15:31

reporter   ~12265

Hi,
May be: of course there in an INSERTANS already, but thats not the point: in the example the insertans is also used to switch between different exit urls, not to add the result of a question to an existing url as an argument.
So depending on any logical expression (the result of a question is only one example I needed recently for my work) one can change the exit url completely, one or more arguments or url and argument(s) in combination.

Why not use the INSERTANS directly? Well, often one has no influence how an exit url or parameter has to look like to be processed and you have to fulfill requirements how parameters have to be, so that you can't use the output of instertans directly.

For my experience a jquery is often too complicated for end user and, by the way, GATE is working easyly with quota too.

DenisChenu

DenisChenu

2010-06-22 09:26

developer   ~12275

Hello,

If you had a server you can manipulate incoming link and outcoming link like you want.

For example :
mysurvey/income.php : income.php get user value and send in xxxxXxxxXxx value for LS.
mysurvey/outcome.php : outcome.php get xxxxXxxxXxx value from ls and send in value user for your convenience.

orvil

orvil

2010-06-22 19:19

reporter   ~12276

Last edited: 2010-06-22 19:20

View 3 revisions

yes, of course but that's not the point. Often you cannot deal with xxxxXxxxXxx in or out parameters. Often one has to set a parameter in a predefined way like "sco=y" od "usr=target" or any other combination, so xxxxXxxxXxx is useless.
And xxxxXxxxXxx is useless if one has to switch between different URIs, domains or pages to call with the exit-Url. That's what I wrote the patch for. I'll give you two examples:

Example 1
You are getting your participants from a company with the condition
A. to redirect the participants exactly to http://www.domanA.org/thanks.php,
B. outscreeners (those participants not fullfilling some requirements) to exactly http://www.domanA.org/sorry.php
C. those who had answered a specified question with "yes" to exactly http://www.domanB.com/welcome.php

This is easily to do with the {GATE:} patch

Example 2
You want to do some chained surveys (found this question somtimes in the forum).
Depending on an answer (or any combination of answers, which is quite possible too) you want to redirect the participants to either
http://www.yourdomain.at/LimeSurvey/index.php?sid=12345 if question A == 'yes"
or
http://www.yourdomain.at/LimeSurvey/index.php?sid=67890 if question A == "no"

You can do this easily too with the {GATE:} patch

DenisChenu

DenisChenu

2010-06-22 21:14

developer   ~12278

I answer only here and not elsewhere.

All you do is easily and more easiliy i think to do with php directly.

$user = filter_var($_GET(xxxxXxxxXxx,FILTER_SANITIZE_STRING);

if(user==A){$redirecturl=blabla;}
...
And after redirect to the url with PHP. so easy ...

And you can test 'HTTP_REFERER' to be sure user come from your survey.

orvil

orvil

2010-06-23 00:10

reporter   ~12281

Hi,
now, I think, I can't get the point. Where do you suggest to use the given code example? Within the source code or in a survey-settings backend-field?

DenisChenu

DenisChenu

2010-06-23 10:44

developer   ~12294

I use other php file to redirect.

Not in limesurvey.

external file ;)

orvil

orvil

2010-06-25 11:02

reporter   ~12300

Ah thanks!
Now I see your point. Good idea. The soulution I worked out is aimed to the common user, working with the backend of LimeSurvey - without detailed knowledge of php and an ftp access to the server.

c_schmitz

c_schmitz

2010-08-11 01:26

administrator   ~12605

Thank you for providing this patch.
The problem with your solution is the eval() call. It is a huge security hole.
I am sorry, but we cannot accept this patch if this problem is not solved in a safe way.

orvil

orvil

2010-08-13 16:05

reporter   ~12631

Indeed, you are right, I see your point. I'll try to find another solution!

jelo

jelo

2010-11-10 23:55

partner   ~13500

As a alternative a questiontype "end page/transfer to" could be created.

http://ideas.limesurvey.org/ideatorrent/idea/144/

That way you can use all conditions to choose as many exit as needed.
Screenouts and Chaining of different surveys.

TMSWhite

TMSWhite

2011-07-12 03:57

reporter   ~15732

orvil-

The new ExpressionManager will let you do this. See here: http://bugs.limesurvey.org/view.php?id=5103

Say you have variables names GotoFirstUrl and CompletedSurvey (you can use Question Title instead of SGQA if desired), you could have this syntax:

http://{if{GotoFirstUrl=='Y','www.firsturl.org','www.otherurl.org)}/{if(CompletedSurvey =='Y','thanks.php','sorry.php'}

ExpressionManager does not use eval(), so it is completely safe.

TMSWhite

TMSWhite

2012-01-17 04:43

reporter   ~16807

This can be solved using Expression Manager - see notes at end of thread

Issue History

Date Modified Username Field Change
2010-06-15 17:12 orvil New Issue
2010-06-15 17:12 orvil File Added: gate-function.txt
2010-06-18 10:24 DenisChenu Note Added: 12259
2010-06-19 15:31 orvil Note Added: 12265
2010-06-22 09:26 DenisChenu Note Added: 12275
2010-06-22 19:19 orvil Note Added: 12276
2010-06-22 19:19 orvil Note Edited: 12276 View Revisions
2010-06-22 19:20 orvil Note Edited: 12276 View Revisions
2010-06-22 21:14 DenisChenu Note Added: 12278
2010-06-23 00:10 orvil Note Added: 12281
2010-06-23 10:44 DenisChenu Note Added: 12294
2010-06-25 11:02 orvil Note Added: 12300
2010-07-07 09:41 c_schmitz Assigned To => c_schmitz
2010-07-07 09:41 c_schmitz Status new => acknowledged
2010-07-07 09:41 c_schmitz Target Version => 1.91
2010-08-11 01:26 c_schmitz Note Added: 12605
2010-08-11 01:26 c_schmitz Assigned To c_schmitz =>
2010-08-11 10:54 c_schmitz Status acknowledged => confirmed
2010-08-13 16:05 orvil Note Added: 12631
2010-11-10 23:55 jelo Note Added: 13500
2011-07-12 03:57 TMSWhite Note Added: 15732
2011-07-12 03:58 TMSWhite Relationship added related to 05103
2012-01-17 04:43 TMSWhite Note Added: 16807
2012-01-17 04:43 TMSWhite Status confirmed => resolved
2012-01-17 04:43 TMSWhite Fixed in Version => 1.92RC1
2012-01-17 04:43 TMSWhite Resolution open => fixed
2012-01-17 04:43 TMSWhite Assigned To => TMSWhite
2012-06-21 13:22 c_schmitz Status resolved => closed