<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | hide@address.com so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Wolfram Kriesing <hide@address.com> |
// +----------------------------------------------------------------------+
//
/**
*
* $Log: Internal.php,v $
* Revision 1.10 2002/11/08 22:50:23 mccain
* - fixed bug which didnt parse files properly where the very first character was a php-tag
*
* Revision 1.9 2002/11/02 19:41:24 mccain
* - optimized and made makePhpTags work much better and smoother
*
* Revision 1.8 2002/09/22 18:49:20 mccain
* - changed internal methods to be able to work with xml-files (dont use short tags anymore)
*
* Revision 1.7 2002/06/26 09:30:02 mccain
* - fixed bug in autoBraces
*
* Revision 1.6 2002/05/26 17:06:38 mccain
* - added filter which removes the xml-config string
*
* Revision 1.5 2002/03/08 18:20:19 mccain
* - removed some warnings
*
* Revision 1.4 2002/03/04 19:05:15 mccain
* - made files compatible to run on php4.1.1 with stricter php.ini settings
*
* Revision 1.3 2002/02/07 22:45:55 mccain
* - make the options stuff work
*
* Revision 1.2 2002/02/07 22:03:46 mccain
* - added informational comment
*
* Revision 1.1.1.1 2002/02/07 21:52:23 mccain
*
* ##### those are my local revisions, from before moving it to sourceforge :-) #####
* ##### just kept for informational reasons, might be removed one day
*
* Revision 1.11 2002/01/21 23:01:53 cain
* - added license statement
*
* Revision 1.10 2002/01/18 05:53:34 cain
* - bugfix when replacing the escaped delimiters
*
* Revision 1.9 2002/01/15 11:25:12 cain
* - replace print tags properly
*
* Revision 1.8 2002/01/10 19:12:04 cain
* - added comment
*
* Revision 1.7 2002/01/09 05:28:12 cain
* - some phpdoc adjustment
*
* Revision 1.6 2002/01/09 05:15:54 cain
* - removed constructor, since myPEAR_Common does that
*
* Revision 1.5 2001/12/21 14:51:42 cain
* - tried to make tpl->show work
*
* Revision 1.4 2001/12/18 15:55:49 cain
* - comments
*
* Revision 1.3 2001/12/18 00:13:06 cain
* - comments
*
* Revision 1.2 2001/12/15 14:09:24 cain
* - use regExp to replace delimiters, which watch out for escaping and taglibs stuff
*
*
*/
require_once('SimpleTemplate/Options.php');
require_once('SimpleTemplate/Filter/Basic.php');
/**
* the internal filter(s) i use and SimpleTemplate needs
*
* @package SimpleTemplate/Filter
* @access public
* @version 01/12/10
* @author Wolfram Kriesing <hide@address.com>
*/
class SimpleTemplate_Filter_Internal extends SimpleTemplate_Options
{
// i need the method setOption, that's why i extend myPEAR_Common
/**
* for passing values to the class, i.e. like the delimiters
* @access private
* @var array $options the options for initializing the filter class
*/
var $options = array( 'delimiter' => array()); // see SimpleTemplate_Engine
/**
* actually i made a constructor only to pass the delimiters to this class
* at a definite point
*
* @version 01/12/10
* @author Wolfram Kriesing <hide@address.com>
* @param array $options need to be given, use the options from your tempalte class
*/
/* function SimpleTemplate_Filter_Internal($options)
{
foreach( $options as $key=>$aOption )
$this->setOption( $key , $aOption );
}
*/
/**
* replace all delimiters with the right php tags
*
* @version 01/12/10
* @author Wolfram Kriesing <hide@address.com>
* @param string $input the original template code
* @return string the modified template
*/
function makePhpTags($input)
{
$begin = $this->getOption('delimiter',0);
$end = $this->getOption('delimiter',1);
// quote the strings
$qBegin = preg_quote($begin);
$qEnd = preg_quote($end);
// replace all varibales with $GLOBALS around it, so we can use the method "show"
// dont replace $GLOBALS
// $input = preg_replace( #'/\{(.*)\$([^(GLOBALS)]+)([^a-zA-Z0-9_].*)\}/U' , works fine but doesnt replace multiple $x inside one php tag
// '/\{(.*)\$([^(GLOBALS)]+)([^a-zA-Z0-9_].*)\}/U' ,
// '{$1$GLOBALS[\'$3\']$4 /*...1=$1...2=$2...3=$3....4=$4....5=$5.... */}' ,
// $input );
// replace { by < ?php ({ is the delimiter)
$regExp = "/(^|[^\\\])$qBegin([^%])/Um"; // modifier m makes '{foo}{bar}' on one line work too
$input = preg_replace( $regExp ,
'$1<?php $2' ,
$input );
// replace } by ? > (} is the delimiter)
$regExp = "/([^\\\%])$qEnd/Um"; // modifier m makes '{foo}{bar}' on one line work too
$input = preg_replace( $regExp ,
'$1 ?>' ,
$input );
// replace '< ?php $' by '< ?php echo $'
$regExp = "/<\?php\s\\$/Um";
$input = preg_replace( $regExp ,
'<?php echo $' ,
$input );
//
// replace escaped delimiters like \{ or \}
//
// preg_quote the entire string, to be sure that reg-expr. characters are quoted too
// i.e. if $begin is '[' it is escaped and so is the '\\' too, well it works like this, it didnt properly before :-)
$regExp = preg_quote('/\\'.$begin.'/');
$input = preg_replace( $regExp , $begin , $input );
$regExp = preg_quote('/\\'.$end.'/');
$input = preg_replace( $regExp , $end , $input );
return $input;
}
/**
* to leave out those nerv wrecking {{ } }} things we check indention (like python does)
* so that if the following comes
* {{ if(somecheck) }}
* {{$someVar}}
* <normal> html </normal> again
* we can automatically set the { } around this indented part, this would make
* code readable and force users to write nice code :-) i like that.... :-)
* NOTE: for now the indention only works if the starting delimiter and end delimiter is on the same line
* and only one time each
* i guess tabs dont work either, but i didnt try it
*
* @access private
* @version 01/12/07
* @author Wolfram Kriesing <hide@address.com>
* @param string $input the entire file content
* @return string modified string
*/
function autoBraces( $input )
{
// FIXXXXME the following fucks it up, because of the indented next line, but the echo doesnt need a {
// see proxy/modules/convert/templates/phpManual/default.tpl
// maybe check for words which require braces, like if, foreach and so on ... but this limits it again :-/ and if we
// forgot one its fucked
// and what it does wrong too, is it puts the { behind: $aBookmark['url'], see compiled template
// <a href="{$aBookmark['url']}" target="main" title="{echo htmlentities($aBookmark['selection'])}">
// {$aBookmark['title']}
// {if($aBookmark[$orderBy] && $orderBy!='title')}
// ({$aBookmark[$orderBy]})
// </a>
// this fails too, though it is not correct, since the second line doesnt need to be indented
// {%trim $x 20 ''%}
// {%trim $x 20 ''%}
//
// ths is also buggy the '{%' is translated to be '< ? php }' even though the '>' is before, the '}' should go before the '>'
// {if($aFolder['id'] == $fid)}
// class="curFolder"
// >{%trim $aFolder['extName'] after 40 "..."%}
$openDel = $this->getOption('delimiter',0);
$closeDel = $this->getOption('delimiter',1);
// remove empty lines, so we can check if the _next_ line is indented (if you buy 'autoBraces' you get that too no way around :-) )
// this way we dont run into problems if the line after an {if(...)} is empty but the next
// indented (as i had it, to make the code more readable)
$preFilter = new SimpleTemplate_Filter_Basic;
$input = call_user_func( array($preFilter,'removeEmptyLines') , $input );
// this ONLY works if '{$' is not replaced by '< ?php xxx' but by '< ?=' as it is now
// so we gotta fix that, because short tags prevent from proper use for XML :-)
$begin = '<?php';
$end = '?>';
$file = explode("\n",$input);
// this variable we use like a stack to put the open indentions on it, we fill this stack from the
// bottom, means index 0 always contains the last indention, since we are working them off this way
$openIndentions = array();
foreach( $file as $curLineIndex=>$aLine )
{
// count number of spaces at the beginning of this, prev and next line
$numSpaces = strlen($aLine) - strlen(ltrim($aLine));
$nextLine = '';
if( sizeof($file) > $curLineIndex+1 ) // check the array boundary, since php4.1 and a stricter php.ini it throws a warning
$nextLine = $file[$curLineIndex+1];
$numSpacesNextLine = strlen($nextLine) - strlen(ltrim($nextLine));
$numSpacesPrevLine = 0;
if( $curLineIndex>0 )
{
$prevLine = $file[$curLineIndex-1];
$numSpacesPrevLine = strlen($prevLine) - strlen(ltrim($prevLine));
}
// are there any open indentions that need the closing brace?
if( sizeof($openIndentions) &&
$numSpaces <= $openIndentions[0]['numSpaces']
)
{
//print("end indention ".htmlentities($file[$curLineIndex]).'<br>');
do
{
$spaces = '';
for( $i=0 ; $i<$openIndentions[0]['numSpaces'] ; $i++ ) // make the code look nice, indent the closing brace
$spaces.= ' ';
// are delimiters at the begining of this line!!!? then we only add our braces before them
// dont add the closing brace after a piece of html, so that this works too:
// {if(...)}
// test
// <br>{somePhpCode} // dont add the brace in the {somePhpCode} but before the <br> otherwise the logic would be false!
if( preg_match( '/^\s*'.preg_quote($begin).'.+[^echo].*'.preg_quote($end).'/U' , $file[$curLineIndex] ) )
{
//print "line = $curLineIndex --- ".htmlentities($file[$curLineIndex]);
// this also fixes the problem i had with the 'else', which doesnt except closing the php-tag before or after it
// since we are always writing the braces inside the existing php-tag now :-)
// replace only the first $begin with "$begin }" and dont forget to put the spaces back!! ($1)
// and there needs to be a space between a opening php-tag and a closing curly brace, otherwise php brings an error!
$file[$curLineIndex] = preg_replace( '/^(\s*)'.preg_quote($begin).'/' , "$1$begin }" , $file[$curLineIndex] );
}
else // no delimiters on this line, so we new once
{
//print "else line = $curLineIndex --- ".htmlentities($file[$curLineIndex]);
$file[$curLineIndex] = $spaces.$begin.' }'.$end."\n".$file[$curLineIndex];
}
//print " ....... after = $curLineIndex --- ".htmlentities($file[$curLineIndex])."<br>";
array_shift( $openIndentions );
$openIndentions_0_numSpaces = 0;
if( isset($openIndentions[0]['numSpaces']) )
$openIndentions_0_numSpaces = $openIndentions[0]['numSpaces'];
}
// shift out all the elements of the array until we have reached the indention that has the number of
// spaces as the indention in index 0, mostly its the first one, but in case
// you have a 'for' after an 'if' there are 2 indentions which have to be closed (on one line)
// i.e.
// {if(sizeof($array))}
// {foreach($array as $x)}
// print something here
// <next line of html> or other code ... above this line 2 indentions need to be closed
while( $numSpaces <= $openIndentions_0_numSpaces && sizeof($openIndentions)>0 );
}
//
// are there delimiters on this line?
//
// use the line read from the file, not the modified line which is in $file[$curLineIndex]
// because there might be a php-tag added, and that would make us find a possible indention here, even
// though the tag might had just been generated before to close a brace - trust me i found it while debugging
// example code that wouldnt work:
// line 1 {if($aWritableFolder['uid']!=$user->uid)}
// line 2 <option> # # # {$users[$aWritableFolder['uid']]['username']} # # # </option>
// line 3 <option value="{$aWritableFolder['id']}">
// the parser would now have added a php tag with closing braces before line 3
// and the following if _would_ find it, if we checked the modified line, as i used to, bummer
if( preg_match( '/^\s*'.preg_quote($begin).'.+[^echo].*'.preg_quote($end).'/U' , $aLine ) )
{
// is the next line indented? if so we save this indention to remember to set the closing braces
if( $numSpacesNextLine > $numSpaces )
{
array_unshift( $openIndentions , array('numSpaces'=>$numSpaces,'lineNumber'=>$curLineIndex) );
// write the opening brace in the
$file[$curLineIndex] = str_replace( $end , ' { '.$end , $file[$curLineIndex] );
//print("started indention ".htmlentities($file[$curLineIndex]).'<br>');
}
}
}
if( sizeof($openIndentions) )
{
$file[$curLineIndex].= "\n<?php ";
foreach( $openIndentions as $x )
{
$file[$curLineIndex].='}';
}
$file[$curLineIndex].= ' ?>';
}
return implode("\n",$file);
}
/**
* removes the xml-config string
*
* @access public
* @version 02/05/25
* @author Wolfram Kriesing <hide@address.com>
* @param string the input string, template file
* @return string the modified string
*/
function removeXmlConfigString( $input )
{
return preg_replace( '/<SimpleTemplate>.*<\/SimpleTemplate>/Uis' , '' , $input );
}
}
?>