• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 399
  • Last Modified:

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.
0
drtester
Asked:
drtester
  • 4
  • 4
  • 2
  • +1
1 Solution
 
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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
 
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

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

  • 4
  • 4
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now