ConLite/conlite/classes/template/class.clIfFunctionParser.php

253 Zeilen
12 KiB
PHP

<?php
/**
* class.clIfFunctionParser.php
*
* clIfFunctionParser class
* Template parser class for IF constructs
*
* @package ConLite
* @subpackage CoreClasses
* @version $Rev$
*
* $Id$
*/
/**
* @package ConLite Backend classes
* @version 1.1
* @author Stefan Welpot
* @modified René Mansveld
* @copyright ConLite <www.conlite.org>
* @license http://www.conlite.org/license/LIZENZ.txt
* @link http://www.conlite.org
* @since file available since ConLite release 2.0.0
*/
/**
* class clIfFunctionParser
*
* Implemenation des AbstractTemplateParser zum Auswerten von
* If-Konstrukten im Template
* Als Tags im Template sind vorgesehen:
* - {if(Bedigung)}
* - {else if(Bedingung)}
* - {else}
* - {/if}
*
* Ein If-Konstrukt besteht dabei mindestens aus {if(Bedingung)} und einem abschließenden {/if}.
* Das {else if(Bedingung)} kann beliebig oft hintereinander verwendet werden.
* Die Konstrukte an sich können beliebig tief geschachtelt werden.
* Die Bedinungen der {if()}- und {else if()}-Teile werden durch eval ausgewertet
* und können somit auch PHP-Funktionen interpretieren.
*/
include_once('class.clAbstractTemplateParser.php');
class clIfFunctionParser extends clAbstractTemplateParser {
/**
* Regexp-Pattern für {if(Bedingung)}
* @var pattern_if
*/
var $pattern_if = "\{if\040*\((.*?)\)\}";
/**
* Regexp-Pattern für {else if(Bedingung)}
* @var pattern_elseif
*/
var $pattern_elseif = "\{else if\040*\((.*?)\)\}";
/**
* Regexp-Pattern für {else}
* @var pattern_else
*/
var $pattern_else = "\{else\}";
/**
* Regexp-Pattern für {/if}
* @var pattern_endif
*/
var $pattern_endif = "\{\/if\}";
/**
* Länge des {if(Bedinung)}-Tags ohne Bedingung
* @var patternlength_if
*/
var $patternlength_if = 6;
/**
* Länge des {else if(Bedinung)}-Tags ohne Bedingung
* @var patternlength_elseif
*/
var $patternlength_elseif = 11;
/**
* Länge des {else}-Tags
* @var patternlength_else
*/
var $patternlength_else = 6;
/**
* Länge des {/if}-Tags
* @var patternlength_endif
*/
var $patternlength_endif = 5;
/**
* Konstruktor
*/
public function __construct() {}
/**
* @see AbstractTemplateParser#parse(string)
*/
public function parse($template) {
$array2_uncompletedConstructs = array(); //geöffnete, aber noch nicht geschlossene funktionen
//hilfsvariablen
$array_match_all = array();
$array_match_part = array();
$uncompletedConstructsIndex = 0;
$elseifIndex = 0;
$currentOffset = 0;
$oldOffset = -1;
$array_construct = array();
$pattern_all = "/(?is)(" . $this->pattern_if . "|" . $this->pattern_elseif . "|" . $this->pattern_else . "|" . $this->pattern_endif . ")/";
//das template solange nach konstruktteilen durchsuchen bis keine mehr gefunden werden
while($currentOffset != $oldOffset) {
$oldOffset = $currentOffset;
//wenn irgendein teil einer if-konstruktion gefunden wird
if(preg_match($pattern_all, $template, $array_match_all, PREG_OFFSET_CAPTURE, $currentOffset) > 0) {
//herausfinden, welcher teil gefunden wurde
//if-teil
if(preg_match("/(?is)" . $this->pattern_if . "/", $array_match_all[0][0], $array_match_part) > 0) {
$uncompletedConstructsIndex++; //inkrement openFunctionIndex
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['condition'] = $array_match_part[1];
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['pos_start'] = $array_match_all[0][1];
# 2013-01-15 Mansveld: Längenberechnung berücksichtigte keine Leerstellen
#$array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['pos_end'] = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['pos_start'] + $this->patternlength_if + strlen($array_match_part[1]);
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['pos_end'] = $array_match_all[0][1] + strlen($array_match_part[0]);
$currentOffset = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['if']['pos_end'];
}
//elseif-teil
else if(preg_match("/(?is)" . $this->pattern_elseif . "/", $array_match_all[0][0], $array_match_part) > 0) {
if(is_countable($array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'])) {
$elseifIndex = count($array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif']);
}
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['condition'] = $array_match_part[1];
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['pos_start'] = $array_match_all[0][1];
# 2013-01-15 Mansveld: Längenberechnung berücksichtigte keine Leerstellen
#$array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['pos_end'] = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['pos_start'] + $this->patternlength_elseif + strlen($array_match_part[1]);
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['pos_end'] = $array_match_all[0][1] + strlen($array_match_part[0]);
$currentOffset = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['elseif'][$elseifIndex]['pos_end'];
}
//else-teil
else if(preg_match("/(?is)" . $this->pattern_else . "/", $array_match_all[0][0], $array_match_part) > 0) {
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['else']['pos_start'] = $array_match_all[0][1];
# 2013-01-15 Mansveld: Längenberechnung berücksichtigte keine Leerstellen
#$array2_uncompletedConstructs[$uncompletedConstructsIndex]['else']['pos_end'] = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['else']['pos_start'] + $this->patternlength_else;
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['else']['pos_end'] = $array_match_all[0][1] + strlen($array_match_part[0]);
$currentOffset = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['else']['pos_end'];
}
//endif
else if(preg_match("/(?is)" . $this->pattern_endif . "/", $array_match_all[0][0], $array_match_part) > 0) {
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['endif']['pos_start'] = $array_match_all[0][1];
# 2013-01-15 Mansveld: Längenberechnung berücksichtigte keine Leerstellen
#$array2_uncompletedConstructs[$uncompletedConstructsIndex]['endif']['pos_end'] = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['endif']['pos_start'] + $this->patternlength_endif;
$array2_uncompletedConstructs[$uncompletedConstructsIndex]['endif']['pos_end'] = $array_match_all[0][1] + strlen($array_match_part[0]);
$currentOffset = $array2_uncompletedConstructs[$uncompletedConstructsIndex]['endif']['pos_end'];
//gefundene komplette funktion sofort ersetzen
$array_construct = array_pop($array2_uncompletedConstructs);
$uncompletedConstructsIndex--;
$template = $this->replaceConstruct($array_construct, $template);
//offset korrigieren = anfang der ersetzten funktion
$currentOffset = $array_construct['if']['pos_start'];
}
}
} // end while
if($uncompletedConstructsIndex > 0) { // wenn noch offene Funktionen vorhanden sind => Fehler im Template
$template = "Fehler in IF-Konstruktionen. Folgende If-Statements sind nicht abgeschlossen:<br>\n";
foreach($array2_uncompletedConstructs as $array_construct) {
$template .= "- {if(" . $array_construct['if']['condition'] . ")}<br>\n";
}
}
return $template;
} // end function
/**
* Ersetzt die als Array übergebene Funktion durch
* den ersten Teil mit einer wahren Bedingung
*
* @param $array_construct Array das komplette If-Konstrukt das ausgewertet werden soll
* @param $template string das Template in dem das Konstrukt ersetzt werden soll
*
* @return string das Template mit dem ersetzten Konstrukt
*/
private function replaceConstruct($array_construct, $template) {
$array_elseif = array();
$key = 0;
$replace_text = "";
$boolConditionTrue = false;
//prüfen ob der if-teil wahr ist und $replace_text finden
if(eval("return " . $array_construct['if']['condition'] . ";")) {
if(array_key_exists('elseif', $array_construct)) { //wenn ein elseif-teil existiert
$replace_text = substr($template, $array_construct['if']['pos_end'], $array_construct['elseif'][0]['pos_start'] - $array_construct['if']['pos_end']);
}
else if(array_key_exists('else', $array_construct)) { //wenn nur ein else-teil existiert
$replace_text = substr($template, $array_construct['if']['pos_end'], $array_construct['else']['pos_start'] - $array_construct['if']['pos_end']);
}
else {//wenn der nächste teil schon endif ist
$replace_text = substr($template, $array_construct['if']['pos_end'], $array_construct['endif']['pos_start'] - $array_construct['if']['pos_end']);
}
}
else {
//alle elseif-teile prüfen
if(is_array($array_construct['elseif'])) {
foreach($array_construct['elseif'] as $key => $array_elseif) {
if(eval("return " . $array_elseif['condition'] . ";")) {
$boolConditionTrue = true;
if(array_key_exists(($key + 1), $array_construct['elseif'])) { //wenn ein weiterer elseif-teil existiert
$replace_text = substr($template, $array_elseif['pos_end'], $array_construct['elseif'][$key+1]['pos_start'] - $array_elseif['pos_end']);
}
else if(array_key_exists('else', $array_construct)) { //wenn nächster teil nur ein else-teil ist
$replace_text = substr($template, $array_elseif['pos_end'], $array_construct['else']['pos_start'] - $array_elseif['pos_end']);
}
else {//wenn der nächste teil schon endif ist
$replace_text = substr($template, $array_elseif['pos_end'], $array_construct['endif']['pos_start'] - $array_elseif['pos_end']);
}
break;
}
}
}
//wenn bisher noch keine wahre Bedingung gefunden wurde
if(!$boolConditionTrue) {
if(array_key_exists('else', $array_construct)) { // wenn ein else-teil existiert
$replace_text = substr($template, $array_construct['else']['pos_end'], $array_construct['endif']['pos_start'] - $array_construct['else']['pos_end']);
}
else { // sonst wird das gesamte kontrukt durch einen leeren string ersetzt
$replace_text = "";
}
}
} // end else
//if-konstruktion durch wahren teil ersetzen
$template = substr_replace($template, $replace_text, $array_construct['if']['pos_start'], $array_construct['endif']['pos_end'] - $array_construct['if']['pos_start']);
return $template;
}
}
?>