PHP conditional string processor

I'm trying to make little function in php that processes if/then type statements within a string, removing any part of the string that doesn't match the condition.  For example:

$string="ABC[if $x==2]DEF[/if]GHI";
$x=2;
print process_string($string);

should return "ABCDEFGHI".  If $x were not 2, then it should return "ABCGHI".

The "[if " is the start tag for the condition, and the condition should be valid php code (could even be a more complex evaluation).  

I essentially need to swallow the tags, as well as any data between the [if] and [/if] if it isn't true.

Next, I really need this to be able to be recursive, just like in a programming language.  For example:

$string="ABC[if $x==2]DEF[if $y>7]GHI[/if]JKL[/if]MNO";
$x=2; $y=0;
print process_string($string);

Should print out "ABCDEFJKLMNO", because the first test is true, while the second is false.
drtesterAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
Is this an academic question or part of an application?  If it's the latter, tell us a little more about what you're trying to accomplish.  I've never seen a data construct like $string="ABC[if $x==2]DEF[/if]GHI"; in real-world programming and I'd like to learn more about how you are using it.  Thanks, ~Ray
0
drtesterAuthor Commented:
This is part of a web app that will render html.  The input string will be more on the order of:

<html><head><title>[if $x=="e"]Editing Page[/if][if $x=="n"]Creating New Page[/if]</head><body>
<center><h1>[if $x=="e"]Editing Page[/if][if $x=="n"]Creating New Page[/if]</h1>

...etc...   There are already a number of other functions I have in this, such as the ability to print variables.  Now need to add conditionals so that I can only display certain things based on the variables.
0
Ray PaseurCommented:
Wow, sounds like a complicated CMS or something... I'll monitor this, but I may not be able to help.  Consider putting this into the REGEX zone if you don't get a good answer here.

Best of luck, ~Ray
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

MMDeveloperCommented:
where is this HTML coming from, a file, a database? If a file, you should be able to write raw PHP and it execute when it's included.
0
drtesterAuthor Commented:
Yeah, sorta like a CMS thing.  I was thinking of using a regex to find the [if xxx] tag, but the code could span multiple lines.  My example above could also be written:

<html><head><title>[if $x=="e"]Editing Page</head><body>
<center><h1>Editing Page[/if]
[if $x=="n"]Creating New Page</head><body>
<center><h1>Creating New Page[/if]
</h1>

I'm guessing there would be some sort of function you would call from within the function (perhaps itself?), so that when you find the if tag, you then call this to look for the un-if... and if there are further ifs in there, you either process them or skip them, depending on the original condition's evaluation.
0
drtesterAuthor Commented:
MMDeveloper: that's an idea, but a little messy.  The data may be coming from a file or a database.  I'd really like to not have to deal with writing new files inside the webserver root, dealing with permissions, etc.  Besides, this will be a multiuser thing, and different people will be using the same processor with different input and conditions.
0
ddrudikCommented:
drtester, how I see this working is if you structured your if statements as PHP would expect them and use eval to process them, otherwise you will need to write a replacement processor for conditional statements and that seems unnecessary.  However, before you consider this code or writing another such processor you should understand that in doing so you trust the user to not submit malicious code to your processor to be eval'd.

With all of that said, the following is the script that worked for me.  For the global statement within the function I used PHP's definition of what can be a variable name, however it does not cover array variables, object vars, etc.  Consider the script a starting point.:
<pre>
<?php
$string='ABC[if($x==2)]DEF[/if]GHI';
$x=2;
print process_string($string);
print "\n";
$string='ABC[if ($x==2)]DEF[if($y>7)]GHI[/if]JKL[/if]MNO';
$x=2; $y=0;
print process_string($string);
function process_string($str){
	$pass=1;
	while(preg_match('~\[(if[^\]]*)\]((?:(?!\[/?if).)*)\[/if\]~is',$str,$match)){
		$str=preg_replace_callback('~\[(if[^\]]*)\]((?:(?!\[/?if).)*)\[/if\]~is','retval',$str);
		$pass++;
	}
	return $str;
}
function retval($match){
	preg_match_all('/\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',$match[1],$vars);
	$code='';
	foreach($vars[0] as $var){
		$code.="global $var;";
	}
	eval($code);
	$code=$match[1]."{\$ret= '".$match[2]."';} else { \$ret= ''; }";
	eval($code);
	return $ret;
}
?>

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ddrudikCommented:
drtester, you can remove the
  $pass=1;
and
  $pass++;
lines, they were just there for testing and are not needed in production.
0
drtesterAuthor Commented:
Ddrudik: MOST EXCELLENT!!!  That is exactly what I was looking for!  I'm not sure I quite follow the regex yet, but I kinda see basically what's going on.  

Yes, I can be sure the string to be evaluated will be sanitized - it will be generated by other code, so no worries there.  (Can definitely see how that would be a huge hole, since we're causing php to evaluate raw code).

Thanks again!

drtester
0
ddrudikCommented:
drtester, glad to help, thanks for the question and the points.
0
ddrudikCommented:
as for the regex patterns, this one matches non-nested [if ...] ... [/if] blocks, which is to process the inner-most nested if blocks first, continuing while there are still non-nested if blocks found in the string:
'~\[(if[^\]]*)\]((?:(?!\[/?if).)*)\[/if\]~is'

and this regex pattern is for varnames:
'/\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/'
from:
http://us3.php.net/language.variables
which is used to set the variables outside of the function to global before eval so they are available in the function.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.