préparation de la 0.5

This commit is contained in:
nojhan 2008-06-15 20:21:07 +00:00
commit 2dfde6b61e
278 changed files with 79759 additions and 0 deletions

View file

@ -0,0 +1,204 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: nobody <nobody@localhost> |
// +----------------------------------------------------------------------+
//
// $Id: Assign.php,v 1.5 2004/06/03 03:25:11 alan_k Exp $
//
// Provider for Assign API ( Eg. $flexy->assign(...) )
//
define('HTML_TEMPLATE_FLEXY_ASSIGN_ERROR_INVALIDARGS', -100);
class HTML_Template_Flexy_Assign {
/**
* The variables stored in the Assigner
*
* @var array
* @access public
*/
var $variables = array();
/**
* The references stored in the Assigner
*
* @var array
* @access public
*/
var $references = array();
/**
*
* Assigns a token-name and value to $this->_token_vars for use in a
* template.
*
* There are three valid ways to assign values to a template.
*
* Form 1: $args[0] is a string and $args[1] is mixed. This means
* $args[0] is a token name and $args[1] is the token value (which
* allows objects, arrays, strings, numbers, or anything else).
* $args[1] can be null, which means the corresponding token value in
* the template will also be null.
*
* Form 2: $args[0] is an array and $args[1] is not set. Assign a
* series of tokens where the key is the token name, and the value is
* token value.
*
* Form 3: $args[0] is an object and $args[1] is not set. Assigns
* copies of all object variables (properties) to tokens; the token
* name and value is a copy of each object property and value.
*
* @access public
*
* @param string|array|object $args[0] This param can be a string, an
* array, or an object. If $args[0] is a string, it is the name of a
* variable in the template. If $args[0] is an array, it must be an
* associative array of key-value pairs where the key is a variable
* name in the template and the value is the value for that variable
* in the template. If $args[0] is an object, copies of its
* properties will be assigned to the template.
*
* @param mixed $args[1] If $args[0] is an array or object, $args[1]
* should not be set. Otherwise, a copy of $args[1] is assigned to a
* template variable named after $args[0].
*
* @return bool|PEAR_Error Boolean true if all assignments were
* committed, or a PEAR_Error object if there was an error.
*
* @throws SAVANT_ERROR_ASSIGN Unknown reason for error, probably
* because you passed $args[1] when $args[0] is an array or object.
*
* @author Paul M. Jones <pmjones@ciaweb.net>
* @see assignRef()
*
* @see assignObject()
*
*/
function assign($args)
{
// in Form 1, $args[0] is a string name and $args[1] is mixed.
// in Form 2, $args[0] is an associative array.
// in Form 3, $args[0] is an object.
$count = count($args);
// -------------------------------------------------------------
//
// Now we assign variable copies.
//
// form 1 (string name and mixed value)
// don't check isset() on $args[1] becuase a 'null' is not set,
// and we might want to pass a null.
if (is_string($args[0]) && $count > 1) {
if (isset($this->references[$args[0]])) {
unset($this->references[$args[0]]);
}
// keep a copy in the token vars array
$this->variables[$args[0]] = $args[1];
// done!
return true;
}
// form 2 (assoc array)
if (is_array($args[0]) && $count == 1) {
foreach ($args[0] as $key=>$val) {
$this->assign($key, $val);
}
// done!
return true;
}
// form 3 (object props)
if (is_object($args[0]) && $count == 1) {
// get the object properties
$data = get_object_vars($args[0]);
foreach ($data as $key=>$val) {
$this->assign($key, $val);
}
// done!
return true;
}
// -------------------------------------------------------------
//
// Final error catch. We should not have gotten to this point.
//
return HTML_Template_Flexy::raiseError(
"invalid type sent to assign, ". print_r($args,true),
HTML_TEMPLATE_FLEXY_ASSIGN_ERROR_INVALIDARGS
);
}
/**
*
* Assign a token by reference. This allows you change variable
* values within the template and have those changes reflected back
* at the calling logic script. Works as with form 2 of assign().
*
* @access public
*
* @param string $name The template token-name for the reference.
*
* @param mixed &$ref The variable passed by-reference.
*
* @return bool|PEAR_Error Boolean true on success, or a PEAR_Error
* on failure.
*
* @throws SAVANT_ERROR_ASSIGN_REF Unknown reason for error.
*
* @see assign()
* @author Paul M. Jones <pmjones@ciaweb.net>
* @see assignObject()
*
*/
function assignRef($name, &$ref)
{
// look for the proper case: name and variable
if (is_string($name) && isset($ref)) {
if (isset($this->variables[$name])) {
unset($this->variables[$name]);
}
//
// assign the token as a reference
$this->references[$name] =& $ref;
// done!
return true;
}
// final error catch
return HTML_Template_Flexy::raiseError(
"invalid type sent to assignRef, ". print_r($name,true),
HTML_TEMPLATE_FLEXY_ASSIGN_ERROR_INVALIDARGS
);
}
}

View file

@ -0,0 +1,161 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Compiler.php,v 1.7 2004/07/08 04:56:30 alan_k Exp $
//
// Base Compiler Class (Interface)
//
/**
* Compiler Globals go here..
* public (to it's children)
*
* @var array
* @access public (to it's children)
*/
$GLOBAL['_HTML_TEMPLATE_FLEXY_COMPILER'] = array();
class HTML_Template_Flexy_Compiler {
/**
* Options
*
* @var array
* @access public
*/
var $options;
/**
* Factory constructor
*
* @param array options only ['compiler'] is used directly
*
* @return object The Compiler Object
* @access public
*/
function factory($options)
{
if (empty($options['compiler'])) {
$options['compiler'] = 'Flexy';
}
require_once 'HTML/Template/Flexy/Compiler/'.ucfirst( $options['compiler'] ) .'.php';
$class = 'HTML_Template_Flexy_Compiler_'.$options['compiler'];
$ret = new $class;
$ret->options = $options;
return $ret;
}
/**
* The compile method.
*
* @param object HTML_Template_Flexy that is requesting the compile
* @return object HTML_Template_Flexy
* @return string to compile (if not using a file as the source)
* @access public
*/
function compile(&$flexy,$string = false)
{
echo "No compiler implemented!";
}
/**
* Append HTML to compiled ouput
* These are hooks for passing data to other processes
*
* @param string to append to compiled
*
* @return string to be output
* @access public
*/
function appendHtml($string)
{
return $string;
}
/**
* Append PHP Code to compiled ouput
* These are hooks for passing data to other processes
*
* @param string PHP code to append to compiled
*
* @return string to be output
* @access public
*/
function appendPhp($string)
{
return '<?php '.$string.'?>';
}
/**
* Compile All templates in the
* These are hooks for passing data to other processes
*
* @param string PHP code to append to compiled
*
* @return string to be output
* @access public
*/
function compileAll(&$flexy, $dir = '',$regex='/.html$/')
{
$this->flexy = &$flexy;
$this->compileDir($dir,$regex);
}
function compileDir($dir = '',$regex='/.html$/')
{
foreach ($this->flexy->options['templateDir'] as $base) {
if (!file_exists($base . DIRECTORY_SEPARATOR . $dir)) {
continue;
}
$dh = opendir($base . DIRECTORY_SEPARATOR . $dir);
while (($name = readdir($dh)) !== false) {
if (!$name) { // empty!?
continue;
}
if ($name{0} == '.') {
continue;
}
if (is_dir($base . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $name)) {
$this->compileDir($dir . DIRECTORY_SEPARATOR . $name,$regex);
continue;
}
if (!preg_match($regex,$name)) {
continue;
}
//echo "Compiling $dir". DIRECTORY_SEPARATOR . "$name \n";
$this->flexy->compile($dir . DIRECTORY_SEPARATOR . $name);
}
}
}
}

View file

@ -0,0 +1,985 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Flexy.php,v 1.20 2005/10/25 02:21:16 alan_k Exp $
//
// Base Compiler Class
// Standard 'Original Flavour' Flexy compiler
// this does the main conversion, (eg. for {vars and methods})
// it relays into Compiler/Tag & Compiler/Flexy for tags and namespace handling.
require_once 'HTML/Template/Flexy/Tokenizer.php';
require_once 'HTML/Template/Flexy/Token.php';
class HTML_Template_Flexy_Compiler_Flexy extends HTML_Template_Flexy_Compiler {
/**
* The current template (Full path)
*
* @var string
* @access public
*/
var $currentTemplate;
/**
* The compile method.
*
* @params object HTML_Template_Flexy
* @params string|false string to compile of false to use a file.
* @return string filename of template
* @access public
*/
function compile(&$flexy, $string=false)
{
// read the entire file into one variable
// note this should be moved to new HTML_Template_Flexy_Token
// and that can then manage all the tokens in one place..
global $_HTML_TEMPLATE_FLEXY_COMPILER;
$this->currentTemplate = $flexy->currentTemplate;
$gettextStrings = &$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'];
$gettextStrings = array(); // reset it.
if (@$this->options['debug']) {
echo "compiling template $flexy->currentTemplate<BR>";
}
// reset the elements.
$flexy->_elements = array();
// replace this with a singleton??
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions'] = $this->options;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] = array();
$GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'] = $flexy->currentTemplate;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] = '';
$GLOBALS['_HTML_TEMPLATE_FLEXY']['compiledTemplate']= $flexy->compiledTemplate;
// initialize Translation 2, and
$this->initializeTranslator();
// load the template!
$data = $string;
$res = false;
if ($string === false) {
$data = file_get_contents($flexy->currentTemplate);
}
// PRE PROCESS {_(.....)} translation markers.
if (strpos($data, '{_(') !== false) {
$data = $this->preProcessTranslation($data);
}
// Tree generation!!!
if (!$this->options['forceCompile'] && isset($_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)])) {
$res = $_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)];
} else {
$tokenizer = new HTML_Template_Flexy_Tokenizer($data);
$tokenizer->fileName = $flexy->currentTemplate;
//$tokenizer->debug=1;
$tokenizer->options['ignore_html'] = $this->options['nonHTML'];
require_once 'HTML/Template/Flexy/Token.php';
$res = HTML_Template_Flexy_Token::buildTokens($tokenizer);
if (is_a($res, 'PEAR_Error')) {
return $res;
}
$_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)] = $res;
}
// technically we shouldnt get here as we dont cache errors..
if (is_a($res, 'PEAR_Error')) {
return $res;
}
// turn tokens into Template..
$data = $res->compile($this);
if (is_a($data, 'PEAR_Error')) {
return $data;
}
$data = $GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] . $data;
if ( $flexy->options['debug'] > 1) {
echo "<B>Result: </B><PRE>".htmlspecialchars($data)."</PRE><BR>\n";
}
if ($this->options['nonHTML']) {
$data = str_replace("?>\n", "?>\n\n", $data);
}
// at this point we are into writing stuff...
if ($flexy->options['compileToString']) {
if ( $flexy->options['debug']) {
echo "<B>Returning string:<BR>\n";
}
$flexy->elements = $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'];
return $data;
}
// error checking?
$file = $flexy->compiledTemplate;
if (isset($flexy->options['output.block'])) {
list($file, $part) = explode('#', $file);
}
if( ($cfp = fopen($file, 'w')) ) {
if ($flexy->options['debug']) {
echo "<B>Writing: </B>$file<BR>\n";
}
fwrite($cfp, $data);
fclose($cfp);
chmod($file, 0775);
// make the timestamp of the two items match.
clearstatcache();
touch($file, filemtime($flexy->currentTemplate));
if ($file != $flexy->compiledTemplate) {
chmod($flexy->compiledTemplate, 0775);
// make the timestamp of the two items match.
clearstatcache();
touch($flexy->compiledTemplate, filemtime($flexy->currentTemplate));
}
} else {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::failed to write to '.$flexy->compiledTemplate,
HTML_TEMPLATE_FLEXY_ERROR_FILE, HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
// gettext strings
if (file_exists($flexy->getTextStringsFile)) {
unlink($flexy->getTextStringsFile);
}
if($gettextStrings && ($cfp = fopen( $flexy->getTextStringsFile, 'w') ) ) {
fwrite($cfp, serialize(array_unique($gettextStrings)));
fclose($cfp);
chmod($flexy->getTextStringsFile, 0664);
}
// elements
if (file_exists($flexy->elementsFile)) {
unlink($flexy->elementsFile);
}
if( $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] &&
($cfp = fopen( $flexy->elementsFile, 'w') ) ) {
fwrite($cfp, serialize( $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements']));
fclose($cfp);
chmod($flexy->elementsFile, 0664);
// now clear it.
}
return true;
}
/**
* Initilalize the translation methods.
*
* Loads Translation2 if required.
*
*
* @return none
* @access public
*/
function initializeTranslator() {
if (is_array($this->options['Translation2'])) {
require_once 'Translation2.php';
$this->options['Translation2'] = &Translation2::factory(
$this->options['Translation2']['driver'],
isset($this->options['Translation2']['options']) ? $this->options['Translation2']['options'] : array(),
isset($this->options['Translation2']['params']) ? $this->options['Translation2']['params'] : array()
);
}
if (is_a($this->options['Translation2'], 'Translation2')) {
$this->options['Translation2']->setLang($this->options['locale']);
// fixme - needs to be more specific to which template to use..
foreach ($this->options['templateDir'] as $tt) {
$n = basename($this->currentTemplate);
if (substr($this->currentTemplate, 0, strlen($tt)) == $tt) {
$n = substr($this->currentTemplate, strlen($tt)+1);
}
//echo $n;
}
$this->options['Translation2']->setPageID($n);
} else {
setlocale(LC_ALL, $this->options['locale']);
}
}
/**
* do the early tranlsation of {_(......)_} text
*
*
* @param input string
* @return output string
* @access public
*/
function preProcessTranslation($data) {
global $_HTML_TEMPLATE_FLEXY_COMPILER;
$matches = array();
$lmatches = explode ('{_(', $data);
array_shift($lmatches);
// shift the first..
foreach ($lmatches as $k) {
if (false === strpos($k, ')_}')) {
continue;
}
$x = explode(')_}', $k);
$matches[] = $x[0];
}
//echo '<PRE>';print_r($matches);
// we may need to do some house cleaning here...
$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'] = $matches;
// replace them now..
// ** leaving in the tag (which should be ignored by the parser..
// we then get rid of the tags during the toString method in this class.
foreach($matches as $v) {
$data = str_replace('{_('.$v.')_}', '{_('.$this->translateString($v).')_}', $data);
}
return $data;
}
/**
* Flag indicating compiler is inside {_( .... )_} block, and should not
* add to the gettextstrings array.
*
* @var boolean
* @access public
*/
var $inGetTextBlock = false;
/**
* This is the base toString Method, it relays into toString{TokenName}
*
* @param object HTML_Template_Flexy_Token_*
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toString($element)
{
static $len = 26; // strlen('HTML_Template_Flexy_Token_');
if ($this->options['debug'] > 1) {
$x = $element;
unset($x->children);
//echo htmlspecialchars(print_r($x,true))."<BR>\n";
}
if ($element->token == 'GetTextStart') {
$this->inGetTextBlock = true;
return '';
}
if ($element->token == 'GetTextEnd') {
$this->inGetTextBlock = false;
return '';
}
$class = get_class($element);
if (strlen($class) >= $len) {
$type = substr($class, $len);
return $this->{'toString'.$type}($element);
}
$ret = $element->value;
$add = $element->compileChildren($this);
if (is_a($add, 'PEAR_Error')) {
return $add;
}
$ret .= $add;
if ($element->close) {
$add = $element->close->compile($this);
if (is_a($add, 'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
return $ret;
}
/**
* HTML_Template_Flexy_Token_Else toString
*
* @param object HTML_Template_Flexy_Token_Else
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringElse($element)
{
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState() === false) {
return $this->appendHTML(
"<font color=\"red\">Unmatched {else:} on line: {$element->line}</font>"
);
}
$element->pushState();
return $this->appendPhp("} else {");
}
/**
* HTML_Template_Flexy_Token_End toString
*
* @param object HTML_Template_Flexy_Token_Else
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringEnd($element)
{
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState() === false) {
return $this->appendHTML(
"<font color=\"red\">Unmatched {end:} on line: {$element->line}</font>"
);
}
return $this->appendPhp("}");
}
/**
* HTML_Template_Flexy_Token_EndTag toString
*
* @param object HTML_Template_Flexy_Token_EndTag
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringEndTag($element)
{
return $this->toStringTag($element);
}
/**
* HTML_Template_Flexy_Token_Foreach toString
*
* @param object HTML_Template_Flexy_Token_Foreach
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringForeach($element)
{
$loopon = $element->toVar($element->loopOn);
if (is_a($loopon, 'PEAR_Error')) {
return $loopon;
}
$ret = 'if ($this->options[\'strict\'] || ('.
'is_array('. $loopon. ') || ' .
'is_object(' . $loopon . '))) ' .
'foreach(' . $loopon . " ";
$ret .= "as \${$element->key}";
if ($element->value) {
$ret .= " => \${$element->value}";
}
$ret .= ") {";
$element->pushState();
$element->pushVar($element->key);
$element->pushVar($element->value);
return $this->appendPhp($ret);
}
/**
* HTML_Template_Flexy_Token_If toString
*
* @param object HTML_Template_Flexy_Token_If
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringIf($element)
{
$var = $element->toVar($element->condition);
if (is_a($var, 'PEAR_Error')) {
return $var;
}
$ret = "if (".$element->isNegative . $var .") {";
$element->pushState();
return $this->appendPhp($ret);
}
/**
* get Modifier Wrapper
*
* converts :h, :u, :r , .....
* @param object HTML_Template_Flexy_Token_Method|Var
*
* @return array prefix,suffix
* @access public
* @see toString*
*/
function getModifierWrapper($element)
{
$prefix = 'echo ';
$suffix = '';
$modifier = strlen(trim($element->modifier)) ? $element->modifier : ' ';
switch ($modifier) {
case 'h':
break;
case 'u':
$prefix = 'echo urlencode(';
$suffix = ')';
break;
case 'r':
$prefix = 'echo \'<pre>\'; echo htmlspecialchars(print_r(';
$suffix = ',true)); echo \'</pre>\';';
break;
case 'n':
// blank or value..
$numberformat = @$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'];
$prefix = 'echo number_format(';
$suffix = $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'] . ')';
break;
case 'b': // nl2br + htmlspecialchars
$prefix = 'echo nl2br(htmlspecialchars(';
// add language ?
$suffix = '))';
break;
case 'e':
$prefix = 'echo htmlentities(';
// add language ?
$suffix = ')';
break;
case ' ':
$prefix = 'echo htmlspecialchars(';
// add language ?
$suffix = ')';
break;
default:
$prefix = 'echo $this->plugin("'.trim($element->modifier) .'",';
$suffix = ')';
}
return array($prefix, $suffix);
}
/**
* HTML_Template_Flexy_Token_Var toString
*
* @param object HTML_Template_Flexy_Token_Method
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringVar($element)
{
// ignore modifier at present!!
$var = $element->toVar($element->value);
if (is_a($var, 'PEAR_Error')) {
return $var;
}
list($prefix, $suffix) = $this->getModifierWrapper($element);
return $this->appendPhp( $prefix . $var . $suffix .';');
}
/**
* HTML_Template_Flexy_Token_Method toString
*
* @param object HTML_Template_Flexy_Token_Method
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringMethod($element)
{
// set up the modifier at present!!
list($prefix, $suffix) = $this->getModifierWrapper($element);
// add the '!' to if
if ($element->isConditional) {
$prefix = 'if ('.$element->isNegative;
$element->pushState();
$suffix = ')';
}
// check that method exists..
// if (method_exists($object,'method');
$bits = explode('.', $element->method);
$method = array_pop($bits);
$object = implode('.', $bits);
$var = $element->toVar($object);
if (is_a($var, 'PEAR_Error')) {
return $var;
}
if (($object == 'GLOBALS') &&
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['globalfunctions']) {
// we should check if they something weird like: GLOBALS.xxxx[sdf](....)
$var = $method;
} else {
$prefix = 'if ($this->options[\'strict\'] || (isset('.$var.
') && method_exists('.$var .", '{$method}'))) " . $prefix;
$var = $element->toVar($element->method);
}
if (is_a($var, 'PEAR_Error')) {
return $var;
}
$ret = $prefix;
$ret .= $var . "(";
$s =0;
foreach($element->args as $a) {
if ($s) {
$ret .= ",";
}
$s =1;
if ($a{0} == '#') {
if (is_numeric(substr($a, 1, -1))) {
$ret .= substr($a, 1, -1);
} else {
$ret .= '"'. addslashes(substr($a, 1, -1)) . '"';
}
continue;
}
$var = $element->toVar($a);
if (is_a($var, 'PEAR_Error')) {
return $var;
}
$ret .= $var;
}
$ret .= ")" . $suffix;
if ($element->isConditional) {
$ret .= ' { ';
} else {
$ret .= ";";
}
return $this->appendPhp($ret);
}
/**
* HTML_Template_Flexy_Token_Processing toString
*
* @param object HTML_Template_Flexy_Token_Processing
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringProcessing($element)
{
// if it's XML then quote it..
if (strtoupper(substr($element->value, 2, 3)) == 'XML') {
return $this->appendPhp("echo '" . str_replace("'", "\\"."'", $element->value) . "';");
}
// otherwise it's PHP code - so echo it..
return $element->value;
}
/**
* HTML_Template_Flexy_Token_Text toString
*
* @param object HTML_Template_Flexy_Token_Text
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringText($element)
{
// first get rid of stuff thats not translated etc.
// empty strings => output.
// comments -> just output
// our special tags -> output..
if (!strlen(trim($element->value) )) {
return $this->appendHtml($element->value);
}
// dont add comments to translation lists.
if (substr($element->value, 0, 4) == '<!--') {
return $this->appendHtml($element->value);
}
// ignore anything wrapped with {_( .... )_}
if ($this->inGetTextBlock) {
return $this->appendHtml($element->value);
}
if (!$element->isWord()) {
return $this->appendHtml($element->value);
}
// grab the white space at start and end (and keep it!
$value = ltrim($element->value);
$front = substr($element->value, 0, -strlen($value));
$value = rtrim($element->value);
$rear = substr($element->value, strlen($value));
$value = trim($element->value);
// convert to escaped chars.. (limited..)
//$value = strtr($value,$cleanArray);
$this->addStringToGettext($value);
$value = $this->translateString($value);
// its a simple word!
return $this->appendHtml($front . $value . $rear);
}
/**
* HTML_Template_Flexy_Token_Cdata toString
*
* @param object HTML_Template_Flexy_Token_Cdata ?
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringCdata($element)
{
return $this->appendHtml($element->value);
}
/**
* addStringToGettext
*
* Adds a string to the gettext array.
*
* @param mixed preferably.. string to store
*
* @return none
* @access public
*/
function addStringToGettext($string)
{
if (!is_string($string)) {
return;
}
if (!preg_match('/[a-z]+/i', $string)) {
return;
}
$string = trim($string);
if (substr($string, 0, 4) == '<!--') {
return;
}
$GLOBALS['_HTML_TEMPLATE_FLEXY_COMPILER']['gettextStrings'][] = $string;
}
/**
* translateString - a gettextWrapper
*
* tries to do gettext or falls back on File_Gettext
* This has !!!NO!!! error handling - if it fails you just get english..
* no questions asked!!!
*
* @param string string to translate
*
* @return string translated string..
* @access public
*/
function translateString($string)
{
if (is_a($this->options['Translation2'], 'Translation2')) {
$result = $this->options['Translation2']->get($string);
if (!empty($result)) {
return $result;
}
return $string;
}
// note this stuff may have been broken by removing the \n replacement code
// since i dont have a test for it... it may remain broken..
// use Translation2 - it has gettext backend support
// and should sort out the mess that \n etc. entail.
$prefix = basename($GLOBALS['_HTML_TEMPLATE_FLEXY']['filename']).':';
if (@$this->options['debug']) {
echo __CLASS__.":TRANSLATING $string<BR>\n";
}
if (function_exists('gettext') && !$this->options['textdomain']) {
if (@$this->options['debug']) {
echo __CLASS__.":USING GETTEXT?<BR>";
}
$t = gettext($string);
if ($t != $string) {
return $t;
}
$tt = gettext($prefix.$string);
if ($tt != $prefix.$string) {
return $tt;
}
// give up it's not translated anywhere...
return $string;
}
if (!$this->options['textdomain'] || !$this->options['textdomainDir']) {
// text domain is not set..
if (@$this->options['debug']) {
echo __CLASS__.":MISSING textdomain settings<BR>";
}
return $string;
}
$pofile = $this->options['textdomainDir'] .
'/' . $this->options['locale'] .
'/LC_MESSAGES/' . $this->options['textdomain'] . '.po';
// did we try to load it already..
if (@$GLOBALS['_'.__CLASS__]['PO'][$pofile] === false) {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD failed (Cached):<BR>";
}
return $string;
}
if (!@$GLOBALS['_'.__CLASS__]['PO'][$pofile]) {
// default - cant load it..
$GLOBALS['_'.__CLASS__]['PO'][$pofile] = false;
if (!file_exists($pofile)) {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD failed: {$pofile}<BR>";
}
return $string;
}
if (!@include_once 'File/Gettext.php') {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD no File_gettext:<BR>";
}
return $string;
}
$GLOBALS['_'.__CLASS__]['PO'][$pofile] = File_Gettext::factory('PO', $pofile);
$GLOBALS['_'.__CLASS__]['PO'][$pofile]->load();
//echo '<PRE>'.htmlspecialchars(print_r($GLOBALS['_'.__CLASS__]['PO'][$pofile]->strings,true));
}
$po = &$GLOBALS['_'.__CLASS__]['PO'][$pofile];
// we should have it loaded now...
// this is odd - data is a bit messed up with CR's
$string = str_replace('\n', "\n", $string);
if (isset($po->strings[$prefix.$string])) {
return $po->strings[$prefix.$string];
}
if (!isset($po->strings[$string])) {
if (@$this->options['debug']) {
echo __CLASS__.":no match:<BR>";
}
return $string;
}
if (@$this->options['debug']) {
echo __CLASS__.":MATCHED: {$po->strings[$string]}<BR>";
}
// finally we have a match!!!
return $po->strings[$string];
}
/**
* HTML_Template_Flexy_Token_Tag toString
*
* @param object HTML_Template_Flexy_Token_Tag
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringTag($element) {
$original = $element->getAttribute('ALT');
if (($element->tag == 'IMG') && is_string($original) && strlen($original)) {
$this->addStringToGettext($original);
$quote = $element->ucAttributes['ALT']{0};
$element->ucAttributes['ALT'] = $quote . $this->translateString($original). $quote;
}
$original = $element->getAttribute('TITLE');
if (($element->tag == 'A') && is_string($original) && strlen($original)) {
$this->addStringToGettext($original);
$quote = $element->ucAttributes['TITLE']{0};
$element->ucAttributes['TITLE'] = $quote . $this->translateString($original). $quote;
}
if (strpos($element->tag, ':') === false) {
$namespace = 'Tag';
} else {
$bits = explode(':', $element->tag);
$namespace = $bits[0];
}
if ($namespace{0} == '/') {
$namespace = substr($namespace, 1);
}
if (empty($this->tagHandlers[$namespace])) {
require_once 'HTML/Template/Flexy/Compiler/Flexy/Tag.php';
$this->tagHandlers[$namespace] = &HTML_Template_Flexy_Compiler_Flexy_Tag::factory($namespace, $this);
if (!$this->tagHandlers[$namespace] ) {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::failed to create Namespace Handler '.$namespace .
' in file ' . $GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'],
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX, HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
}
return $this->tagHandlers[$namespace]->toString($element);
}
}

View file

@ -0,0 +1,222 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akkbhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Flexy.php,v 1.6 2005/01/22 06:32:20 alan_k Exp $
//
// Handler code for the <flexy: namespace
//
/**
* the <flexy:XXXX namespace
*
*
* at present it handles
* <flexy:toJavascript flexy:prefix="Javascript_prefix" javscriptName="PHPvar" .....>
* <flexy:include src="xxx.htm">
*
*
*
* @version $Id: Flexy.php,v 1.6 2005/01/22 06:32:20 alan_k Exp $
*/
class HTML_Template_Flexy_Compiler_Flexy_Flexy {
/**
* Parent Compiler for
*
* @var object HTML_Template_Flexy_Compiler
*
* @access public
*/
var $compiler;
/**
* The current element to parse..
*
* @var object
* @access public
*/
var $element;
/**
* toString - display tag, attributes, postfix and any code in attributes.
* Relays into namspace::method to get results..
*
*
* @see parent::toString()
*/
function toString($element)
{
list($namespace,$method) = explode(':',$element->oTag);
if (!strlen($method)) {
return '';
}
// things we dont handle...
if (!method_exists($this,$method.'ToString')) {
return '';
}
return $this->{$method.'ToString'}($element);
}
/**
* toJavascript handler
* <flexy:toJavascript flexy:prefix="some_prefix_" javascriptval="php.val" ....>
*
* @see parent::toString()
*/
function toJavascriptToString($element)
{
$ret = $this->compiler->appendPhp( "require_once 'HTML/Javascript/Convert.php';");
$ret .= $this->compiler->appendHTML("\n<script type='text/javascript'>\n");
$prefix = ''. $element->getAttribute('FLEXY:PREFIX');
foreach ($element->attributes as $k=>$v) {
// skip directives..
if (strpos($k,':')) {
continue;
}
if ($k == '/') {
continue;
}
$v = substr($v,1,-1);
$ret .= $this->compiler->appendPhp(
'$__tmp = HTML_Javascript_Convert::convertVar('.$element->toVar($v) .',\''.$prefix . $k.'\',true);'.
'echo (is_a($__tmp,"PEAR_Error")) ? ("<pre>".print_r($__tmp,true)."</pre>") : $__tmp;');
$ret .= $this->compiler->appendHTML("\n");
}
$ret .= $this->compiler->appendHTML("</script>");
return $ret;
}
/**
* include handler
* <flexy:include src="test.html">
*
* @see parent::toString()
*/
function includeToString($element)
{
// this is disabled by default...
// we ignore modifier pre/suffix
$arg = $element->getAttribute('SRC');
if (!$arg) {
return $this->compiler->appendHTML("<B>Flexy:Include without a src=filename</B>");
}
// ideally it would be nice to embed the results of one template into another.
// however that would involve some complex test which would have to stat
// the child templates anyway..
// compile the child template....
// output... include $this->options['compiled_templates'] . $arg . $this->options['locale'] . '.php'
return $this->compiler->appendPHP( "\n".
"\$x = new HTML_Template_Flexy(\$this->options);\n".
"\$x->compile('{$arg}');\n".
"\$_t = function_exists('clone') ? clone(\$t) : \$t;\n".
"foreach(get_defined_vars() as \$k=>\$v) {\n" .
" if (\$k != 't') { \$_t->\$k = \$v; }\n" .
"}\n" .
"\$x->outputObject(\$_t, \$this->elements);\n"
);
}
/**
* Convert flexy tokens to HTML_Template_Flexy_Elements.
*
* @param object token to convert into a element.
* @return object HTML_Template_Flexy_Element
* @access public
*/
function toElement($element)
{
return '';
}
/**
* Handler for User defined functions in templates..
* <flexy:function name="xxxxx">.... </flexy:block> // equivilant to function xxxxx() {
* <flexy:function call="{xxxxx}">.... </flexy:block> // equivilant to function {$xxxxx}() {
* <flexy:function call="xxxxx">.... </flexy:block> // equivilant to function {$xxxxx}() {
*
* This will not handle nested blocks initially!! (and may cause even more problems with
* if /foreach stuff..!!
*
* @param object token to convert into a element.
* @access public
*/
function functionToString($element)
{
if ($arg = $element->getAttribute('NAME')) {
// this is a really kludgy way of doing this!!!
// hopefully the new Template Package will have a sweeter method..
$GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] .=
$this->compiler->appendPHP(
"\nfunction _html_template_flexy_compiler_flexy_flexy_{$arg}(\$t,\$this) {\n").
$element->compileChildren($this->compiler) .
$this->compiler->appendPHP( "\n}\n");
return '';
}
if (!isset($element->ucAttributes['CALL'])) {
return HTML_Template_Flexy::raiseError(
' tag flexy:function needs an argument call or name'.
" Error on Line {$element->line} &lt;{$element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// call is a stirng : nice and simple..
if (is_string($element->ucAttributes['CALL'])) {
$arg = $element->getAttribute('CALL');
return $this->compiler->appendPHP(
"if (function_exists('_html_template_flexy_compiler_flexy_flexy_{$arg}')) " .
" _html_template_flexy_compiler_flexy_flexy_{$arg}(\$t,\$this);");
}
// we make a big assumption here.. - it should really be error checked..
// that the {xxx} element is item 1 in the list...
$e=$element->ucAttributes['CALL'][1];
$add = $e->toVar($e->value);
if (is_a($add,'PEAR_Error')) {
return $add;
}
return $this->compiler->appendPHP(
"if (function_exists('_html_template_flexy_compiler_flexy_flexy_'.{$add})) ".
"call_user_func_array('_html_template_flexy_compiler_flexy_flexy_'.{$add},array(\$t,\$this));");
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,98 @@
<?php
class HTML_Template_Flexy_Compiler_Regex {
/**
* The main flexy engine
*
* @var object HTML_Template_Flexy
* @access public
*/
var $flexy;
/**
* classicParse - the older regex based code generator.
* here all the replacing, filtering and writing of the compiled file is done
* well this is not much work, but still its in here :-)
*
* @access private
* @version 01/12/03
* @author Wolfram Kriesing <wolfram@kriesing.de>
* @author Alan Knowles <alan@akbkhome.com>
* @return boolean (basically true all the time here)
*/
function compile(&$flexy)
{
$this->flexy = &$flexy;
// read the entire file into one variable
$fileContent = file_get_contents($flexy->currentTemplate);
// apply pre filter
$fileContent = $this->applyFilters( $fileContent , "/^pre_/i" );
$fileContent = $this->applyFilters( $fileContent , "/^(pre_|post_)/i",TRUE);
$fileContent = $this->applyFilters( $fileContent , "/^post_/i" );
// write the compiled template into the compiledTemplate-File
if( ($cfp = fopen( $flexy->compiledTemplate , 'w' )) ) {
fwrite($cfp,$fileContent);
fclose($cfp);
@chmod($flexy->compiledTemplate,0775);
}
return true;
}
/**
* actually it will only be used to apply the pre and post filters
*
* @access public
* @version 01/12/10
* @author Alan Knowles <alan@akbkhome.com>
* @param string $input the string to filter
* @param array $prefix the subset of methods to use.
* @return string the filtered string
*/
function applyFilters( $input , $prefix = "",$negate=FALSE)
{
$this->flexy->debug("APPLY FILTER $prefix<BR>");
$filters = $this->options['filters'];
$this->flexy->debug(serialize($filters)."<BR>");
foreach($filters as $filtername) {
$class = "HTML_Template_Flexy_Compiler_Regex_{$filtername}";
require_once("HTML/Template/Flexy/Compiler/Regex/{$filtername}.php");
if (!class_exists($class)) {
return HTML_Template_Flexy::raiseError("Failed to load filter $filter",null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
if (!@$this->filter_objects[$class]) {
$this->filter_objects[$class] = new $class;
$this->filter_objects[$class]->_set_engine($this);
}
$filter = &$this->filter_objects[$class];
$methods = get_class_methods($class);
$this->flexy->debug("METHODS:");
$this->flexy->debug(serialize($methods)."<BR>");
foreach($methods as $method) {
if ($method{0} == "_") {
continue; // private
}
if ($method == $class) {
continue; // constructor
}
$this->flexy->debug("TEST: $negate $prefix : $method");
if ($negate && preg_match($prefix,$method)) {
continue;
}
if (!$negate && !preg_match($prefix,$method)) {
continue;
}
$this->flexy->debug("APPLYING $filtername $method<BR>");
$input = $filter->$method($input);
}
}
return $input;
}
}

View file

@ -0,0 +1,81 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* The html Body only filter
*
* @abstract
* a Simple filter to remove the everything thats not in the body!
*
* @package HTML_Template_Flexy
*
*/
class HTML_Template_Flexy_Compiler_Regex_BodyOnly
{
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine)
{
}
/**
* Strip everything before and including the BODY tag
*
* @param string The template
* @access public
*/
function strip_body_head ($input)
{
if (!preg_match("/^(.*)<body/si", $input)) {
return $input;
}
$input = preg_replace("/^(.*)<body/si", "",$input);
$input = preg_replace("/^([^>]*)>/si", "",$input);
return $input;
}
/**
* Strip everything after and including the end BODY tag
*
* @param string The template
* @access public
*/
function strip_body_foot ($input)
{
if (!preg_match("/<\/body>.*/si", $input)) {
return $input;
}
$input = preg_replace("/<\/body>.*/si", "",$input);
return $input;
}
}
?>

View file

@ -0,0 +1,57 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* The Mail filter template (sorts out cr removal in php)
*
*
* @package HTML_Template_Flexy
*
*
*
*/
class HTML_Template_Flexy_Compiler_Regex_Mail {
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine)
{
}
/*
* add an extra cr to the end php tag, so it show correctly in Emails
*
* @param string The template
* @access public
*/
function post_fix_php_cr ($input)
{
$input = str_replace("?>\n","?>\n\n",$input);
return str_replace("?>\r\n","?>\r\n\r\n",$input);
}
}
?>

View file

@ -0,0 +1,74 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* A Math Filter
*
* enable simple maths to be done in the template
*
* TODO: add an {if:t.xxx%2} type syntax..
*
* @package HTML_Template_Flexy
*
*/
class HTML_Template_Flexy_Compiler_Regex_Math {
/*
* @var string $start the start tag for the template (escaped for regex)
*/
var $start = '\{';
/*
* @var string $stop the stopt tag for the template (escaped for regex)
*/
var $stop = '\}'; //ending template tag
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine) {
}
/*
* allow simple add multiply, divide and subtraction
*
* eg.
* {(12+t.somevar)*2} maps to =(12+$t->somevar)*2
*
* @param string The template
* @access public
*/
function variables ($input) {
$input = preg_replace(
"/".$this->start."([0-9\(\)+*\/-]*)([a-z0-9]+)([0-9\(\)+*\/-]*)".$this->stop."/ie",
"'<?=\\1($'.str_replace('.','->','\\2').')\\3?>'",
$input);
return $input;
}
}
?>

View file

@ -0,0 +1,59 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* Remove PHP tags and replace them with echo '< ? '
*
* should be the first filter if you use it
*
*
*
* @package HTML_Template_Flexy
*
*/
class HTML_Template_Flexy_Compiler_Regex_Php
{
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine)
{
}
/*
* replace the php tags
*
* @param string The template
* @access public
*/
function pre_strip_php ($input)
{
$input = str_replace("<?","__{<__?}__",$input);
$input = str_replace("?>","<?php echo '?'.'>'; ?>",$input);
return str_replace("__{<__?}__","<?php echo '<'.'>'; ?>",$input);
}
}
?>

View file

@ -0,0 +1,50 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* The rtf SimpleTags filter
*
* really an extension of simple tags with \\\{ and \\\\} as the tag delimiters
* can parse an RTF template and generate a file.
*
* usually best used with callback ouput buffering to reduce memory loads.
*
* @package HTML_Template_Flexy
*
*/
require_once "HTML/Template/Flexy/Filter/SimpleTags.php";
class HTML_Template_Flexy_Compiler_Regex_RtfSimpleTags extends HTML_Template_Flexy_Compiler_Regex_simpletags
{
/*
* @var string $start the start tag for the template (escaped for regex)
*/
var $start = '\\\{';
/*
* @var string $stop the stopt tag for the template (escaped for regex)
*/
var $stop= '\\\}';
}
?>

View file

@ -0,0 +1,391 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* The Standard Tag filter
*
* @abstract
* does all the clever stuff...
*
* Security Notes:
* Templates should not originate from untrusted sources,
* - the method(#.....#) could be regarded as insecure.
* - there is no attempt to protect your from <script / <?php in templates.
*
* @package HTML_Template_Flexy
*
*/
class HTML_Template_Flexy_Compiler_Regex_SimpleTags
{
/*
* @var object HTML_Template_Flexy the main engine
*/
var $engine; // the engine (with options)
/*
* @var string $start the start tag for the template (escaped for regex)
*/
var $start = '\{';
/*
* @var string $stop the stopt tag for the template (escaped for regex)
*/
var $stop = '\}';
/*
* @var string $error show/hide the PHP error messages on/off in templates
*/
var $error = "@"; // change to blank to debug errors.
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine) {
$this->engine = &$engine;
if ($this->engine->options['debug']) {
$this->error = "";
}
}
/**
* Standard Variable replacement
*
*
* Maps variables
* {i.xyz} maps to <?php echo htmlspecialchars($i->xyz)?>
* {i.xyz:h} maps to <?php echo $i->xyz?>
* {i.xyz:u} maps to <?php echo urlencode($i->xyz)?>
* {i.xyz:ru} maps to <?php echo rawurlencode($i->xyz)?>
*
* {i.xyz:r} maps to <PRE><?php echo print_r($i->xyz)?></PRE>
* {i.xyz:n} maps to <?php echo nl2br(htmlspecialchars($i->xyz))?>
*
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function variables ($input) {
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').')?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+):h".$this->stop."/ie",
"'<?php echo ".$this->error."$'.str_replace('.','->','\\1').'?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+):u".$this->stop."/ie",
"'<?php echo urlencode(".$this->error."$'.str_replace('.','->','\\1').')?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+):ru".$this->stop."/ie",
"'<?php echo rawurlencode(".$this->error."$'.str_replace('.','->','\\1').')?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+):r".$this->stop."/ie",
"'<PRE><?php echo print_r($'.str_replace('.','->','\\1').')?></PRE>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+):n".$this->stop."/ie",
"'<?php echo nl2br(htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'))?>'",
$input);
return $input;
}
/**
* Urlencoded Variable replacement
*
* Often when you use a WYSISYG editor, it replaces { in
* the href="{somevar}" with the urlencoded version, this bit fixes it.
*
* Maps variables
* %??i.xyz%?? maps to <?php echo htmlspecialchars($i->xyz)?>
* %??i.xyz:h%?? maps to <?php echo $i->xyz?>
* %??i.xyz:u%?? maps to <?php echo urlencode($i->xyz)?>
* %??i.xyz:ru%?? maps to <?php echo urlencode($i->xyz)?>
* THIS IS PROBABLY THE ONE TO USE!
*
* %??i.xyz:uu%?? maps to <?php echo urlencode(urlencode($i->xyz))?>
*
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function urlencoded_variables ($input) {
$input = preg_replace(
"/".urlencode(stripslashes($this->start))."([a-z0-9_.]+)".urlencode(stripslashes($this->stop))."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').')?>'",
$input);
$input = preg_replace(
"/".urlencode(stripslashes($this->start))."([a-z0-9_.]+):h".urlencode(stripslashes($this->stop))."/ie",
"'<?php echo ".$this->error."$'.str_replace('.','->','\\1').'?>'",
$input);
$input = preg_replace(
"/".urlencode(stripslashes($this->start))."([a-z0-9_.]+):u".urlencode(stripslashes($this->stop))."/ie",
"'<?php echo urlencode(".$this->error."$'.str_replace('.','->','\\1').')?>'",
$input);
$input = preg_replace(
"/".urlencode(stripslashes($this->start))."([a-z0-9_.]+):uu".urlencode(stripslashes($this->stop))."/ie",
"'<?php echo urlencode(urlencode(".$this->error."$'.str_replace('.','->','\\1').'))?>'",
$input);
return $input;
}
/**
* Calling Methods
*
* This allows you to call methods of your application
*
* Maps Methods
* {t.xxxx_xxxx()} maps to <?php echo htmlspecialchars($t->xxxx_xxxx())?>
* {t.xxxx_xxxx():h} maps to <?php echo $t->xxxx_xxxx()?>
*
* {t.xxxx_xxxx(sssss.dddd)} maps to <?php echo htmlspecialchars($t->xxxx_xxxx($ssss->dddd))?>
* {t.xxxx_xxxx(sssss.dddd):h} maps to <?php echo $t->xxxx_xxxx($ssss->dddd)?>
* {t.xxxx_xxxx(sssss.dddd):s} maps to <?php highlight_string($t->xxxx_xxxx($ssss->dddd))?>
*
* {t.xxxx_xxxx(#XXXXX#)} maps to <?php echo htmlspecialchars($t->xxxx_xxxx('XXXXXX'))?>
* {t.xxxx_xxxx(#XXXXX#):h} maps to <?php echo $t->xxxx_xxxx('XXXXXX')?>
*
* {t.xxxx_xxxx(sss.ddd,sss.ddd)} maps to <?php echo htmlspecialchars($t->xxxx_xxxx($sss->ddd,$sss->ddd))?>
* {t.xxxx_xxxx(#aaaa#,sss.ddd)} maps to <?php echo htmlspecialchars($t->xxxx_xxxx("aaaa",$sss->ddd))?>
* {t.xxxx_xxxx(sss.ddd,#aaaa#)} maps to <?php echo htmlspecialchars($t->xxxx_xxxx($sss->ddd,"aaaa"))?>
*
*
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function methods($input) {
/* no vars */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'())?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(\):h".$this->stop."/ie",
"'<?php echo ".$this->error."$'.str_replace('.','->','\\1').'()?>'",
$input);
/* single vars */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(([a-z0-9_.]+)\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'($' . str_replace('.','->','\\2') . '))?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(([a-z0-9_.]+)\):h".$this->stop."/ie",
"'<?php echo ".$this->error."$'.str_replace('.','->','\\1').'($' . str_replace('.','->','\\2') . ')?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(([a-z0-9_.]+)\):s".$this->stop."/ie",
"'<?php highlight_string($'.str_replace('.','->','\\1').'($' . str_replace('.','->','\\2') . '));?>'",
$input);
/* double vars */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(([a-z0-9_.]+),([a-z0-9_.]+)\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'($' . str_replace('.','->','\\2') . ',$' . str_replace('.','->','\\3') . '))?>'",
$input);
/* double vars:: # #'d ,var */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(\#([^\#]+)\#,([a-z0-9_.]+)\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'(\''. str_replace(\"'\",\"\\\'\",'\\2') . '\',$' . str_replace('.','->','\\3') . '))?>'",
$input);
/* double vars:: var , # #'d */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(([a-z0-9_.]+),\#([^\#]+)\#\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(".$this->error."$'.str_replace('.','->','\\1').'($' . str_replace('.','->','\\2') . ',\''. str_replace(\"'\",\"\\\'\",'\\3') . '\'))?>'",
$input);
/*strings or integers */
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(\#([^\#]+)\#\)".$this->stop."/ie",
"'<?php echo htmlspecialchars(\$'.str_replace('.','->','\\1') . '(\''. str_replace(\"'\",\"\\\'\",'\\2') . '\'))?>'",
$input);
$input = preg_replace(
"/".$this->start."([a-z0-9_.]+)\(\#([^\#]+)\#\):h".$this->stop."/ie",
"'<?php echo ".$this->error."$'.str_replace('.','->','\\1').'(\"' . str_replace(\"'\",\"\\\'\",'\\2') . '\")?>'",
$input);
return $input;
}
/**
* Looping
*
* This allows you to do loops on variables (eg. nested/ repeated blocks!)
*
* Maps Methods
* {foreach:t.xyz,zzz} maps to <?php if ($i->xyz) foreach ($t->xyz as $zzz) { ?>
* {foreach:t.xyz,xxx,zzz} maps to <?php if ($i->xyz) foreach ($t->xyz as $xxx=>$zzz) { ?>
* {end:} maps to <?php }?>
* {else:} maps to <?php }else{?>
*
*
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function looping($input) {
$input = preg_replace(
"/".$this->start."foreach:([a-z0-9_.]+),([a-z0-9_.]+)".$this->stop."/ie",
"'<?php if (".$this->error."$' . str_replace('.','->','\\1') . ') foreach( $' . str_replace('.','->','\\1') . ' as $' . str_replace('.','->','\\2') . ') { ?>'",
$input);
$input = preg_replace(
"/".$this->start."foreach:([a-z0-9_.]+),([a-z0-9_.]+),([a-z0-9_.]+)".$this->stop."/ie",
"'<?php if (".$this->error."$' . str_replace('.','->','\\1') . ') foreach( $' . str_replace('.','->','\\1') . ' as $' . str_replace('.','->','\\2') . '=>$' . str_replace('.','->','\\3') .') { ?>'",
$input);
$input = str_replace(stripslashes($this->start)."else:".stripslashes($this->stop),'<?php }else{?>', $input);
$input = str_replace(stripslashes($this->start)."end:".stripslashes($this->stop),'<?php }?>', $input);
return $input;
}
/**
* Conditional inclusion
*
* This allows you to do conditional inclusion (eg. blocks!)
*
* Maps conditions
*
* {if:t.xxxx} => <?php if ($t->xxxx) { ?>
* {if:t.x_xxx()} => <?php if ($t->x_xxx()) { ?>
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function conditionals($input) {
$input = preg_replace(
"/".$this->start."if:([a-z0-9_.]+)".$this->stop."/ie",
"'<?php if (".$this->error."$' . str_replace('.','->','\\1') . ') { ?>'",
$input);
$input = preg_replace(
"/".$this->start."if:([a-z0-9_.]+)\(\)".$this->stop."/ie",
"'<?php if (".$this->error."$' . str_replace('.','->','\\1') . '()) { ?>'",
$input);
return $input;
}
/**
* sub template inclusion
*
* This allows you to do include other files (either flat or generated templates.).
*
* {include:t.abcdef} maps to <?php
* if($t->abcdef && file_exists($compileDir . "/". $t->abcdef . "en.php"))
* include($compileDir . "/". $t->abcdef . ".en.php");
* ?>
*
* include abcdef.en.php (Eg. hard coded compiled template
* {include:#abcdef#} => <?php
* if(file_exists($compileDir . "/abcdef.en.php"))
* include($compileDir . "/abcdef.en.php");
* ?>
*
* include raw
* {t_include:#abcdef.html#} => <?php
* if(file_exists($templateDir . "/abcdef.html"))
* include($compileDir . "/abcdef.html");
* ?>
* Compile and include
* {q_include:#abcdef.html#} => <?php
* HTML_Template_Flexy::staticQuickTemplate('abcedef.html',$t);
* ?>
*
*
* @param string $input the template
* @return string the result of the filtering
* @access public
*/
function include_template($input) {
$input = preg_replace(
"/".$this->start."include:([a-z0-9_.]+)".$this->stop."/ie",
"'<?php
if ((".$this->error."$' . str_replace('.','->','\\1') . ') &&
file_exists(\"" . $this->engine->options['compileDir'] .
"/\{$' . str_replace('.','->','\\1') . '}.en.php\"))
include(\"" . $this->engine->options['compileDir'] .
"/\{$' . str_replace('.','->','\\1') . '}.en.php\");?>'",
$input);
$input = preg_replace(
"/".$this->start."include:#([a-z0-9_.]+)#".$this->stop."/ie",
"'<?php if (file_exists(\"" . $this->engine->options['compileDir'] . "/\\1.en.php\")) include(\"" .
$this->engine->options['compileDir'] . "/\\1.en.php\");?>'",
$input);
$input = preg_replace(
"/".$this->start."t_include:#([a-z0-9_.]+)#".$this->stop."/ie",
"'<?php if (file_exists(\"" . $this->engine->options['templateDir'] .
"/\\1\")) include(\"" . $this->engine->options['templateDir'] . "/\\1\");?>'",
$input);
$input = preg_replace(
"/".$this->start."q_include:#([a-z0-9_.]+)#".$this->stop."/ie",
"'<?php HTML_Template_Flexy::staticQuickTemplate(\"\\1\",\$t); ?>'",
$input);
return $input;
}
}
?>

View file

@ -0,0 +1,58 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
/**
* Replace XML tags with echo '<' .'?xml';
*
* @package HTML_Template_Flexy
*
*/
class HTML_Template_Flexy_Compiler_Regex_Xml
{
/**
* Standard Set Engine
*
*
* @param object HTML_Template_Flexy the main engine
* @access private
*/
function _set_engine(&$engine)
{
}
/*
* replace the xml tags
*
* @param string The template
* @access public
*/
function pre_replace_xml ($input)
{
$input = str_replace("?>","<?php echo '?'.'>'; ?>\n",$input);
$input = str_replace("<?xml","<?php echo '<'.'?xml'; ?>",$input);
return $input;
}
}
?>

View file

@ -0,0 +1,335 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: SmartyConvertor.php,v 1.3 2004/07/03 03:46:43 alan_k Exp $
//
// Smarty Conversion compiler
// takes a smarty template, and converts it to a flexy one.
// then does a standard flexy compile.
//
// anything that is not supported gets changed to HTML comments
/* Usage:
a simple script: 'convertsmarty.php'
#!/usr/bin/php
$file = $_SERVER['argv'][1];
$x = new HTML_Template_Flexy(array(
'compileDir' => dirname(__FILE__) , // where do you want to write to..
'templateDir' => $dir , // where are your templates
'locale' => 'en', // works with gettext
'forceCompile' => true, // only suggested for debugging
'debug' => false, // prints a few errors
'nonHTML' => false, // dont parse HTML tags (eg. email templates)
'allowPHP' => false, // allow PHP in template
'compiler' => 'SmartyConvertor', // which compiler to use.
'compileToString' => true, // returns the converted template (rather than actually
// converting to PHP.
'filters' => array(), // used by regex compiler..
'numberFormat' => ",2,'.',','", // default number format = eg. 1,200.00 ( {xxx:n} )
'flexyIgnore' => 0 // turn on/off the tag to element code
));
echo $x->compile(basename($file));
then run it at the command line:
php convertsmarty.php /path/to/a/smarty/template.tpl > /path/to/the/flexy/templates.html
*/
require_once 'HTML/Template/Flexy/Compiler.php';
/**
* The Smarty Converter implementation.
* designed primarily to be used as above, to convert from one to another.
* however it could be used inline to convert simple smarty templates into
* flexy ones - then compile them on the fly.
*
* @version $Id: SmartyConvertor.php,v 1.3 2004/07/03 03:46:43 alan_k Exp $
*/
class HTML_Template_Flexy_Compiler_SmartyConvertor extends HTML_Template_Flexy_Compiler {
/**
* compile implementation
*
* see HTML_Template_Flexy_Compiler::compile()
*
* @param object The core flexy object.
* @param string optionally a string to compile.
*
* @return true | string string when compiling to String.
* @access public
*/
function compile(&$flexy,$string=false)
{
$data = $string;
if ($string === false) {
$data = file_get_contents($flexy->currentTemplate);
}
$data = $this->convertToFlexy($data);
if ($flexy->options['compileToString']) {
return $data;
}
require_once 'HTML/Template/Flexy/Compiler/Standard.php';
$flexyCompiler = new HTML_Template_Flexy_Compiler_Standard;
$flexyCompiler->compile($flexy,$data);
return true;
}
/**
* The core work of parsing a smarty template and converting it into flexy.
*
* @param string the contents of the smarty template
*
* @return string the flexy version of the template.
* @access public|private
* @see see also methods.....
*/
function convertToFlexy($data)
{
$leftq = preg_quote('{', '!');
$rightq = preg_quote('}', '!');
preg_match_all("!" . $leftq . "\s*(.*?)\s*" . $rightq . "!s", $data, $matches);
$tags = $matches[1];
// find all the tags/text...
$text = preg_split("!" . $leftq . ".*?" . $rightq . "!s", $data);
$max_text = count($text);
$max_tags = count($tags);
for ($i = 0 ; $i < $max_tags ; $i++) {
$compiled_tags[] = $this->_compileTag($tags[$i]);
}
// error handling for closing tags.
$data = '';
for ($i = 0; $i < $max_tags; $i++) {
$data .= $text[$i].$compiled_tags[$i];
}
$data .= $text[$i];
return $data;
}
/**
* stack for conditional and closers.
*
* @var array
* @access public
*/
var $stack = array(
'if' => 0,
);
/**
* compile a smarty { tag } into a flexy one.
*
* @param string the tag
*
* @return string the converted version
* @access private
*/
function _compileTag($str)
{
// skip comments
if (($str{0} == '*') && (substr($str,-1,1) == '*')) {
return '';
}
switch($str{0}) {
case '$':
// its a var
return $this->_convertVar($str);
case '#':
// its a config var
return $this->_convertConfigVar($str);
case '%':
// wtf does this do
return "<!-- what is this? $str -->";
}
// this is where it gets messy
// this is very slow - but what the hell
// - its only done once
// - its alot more readable than a long regext.
// - it doesnt infringe on copyright...
switch(true) {
case (preg_match('/^config_load\s/', $str)):
// convert to $t->TemplateConfigLoad()
$args = $this->convertAttributesToKeyVal(substr($str,strpos( $str,' ')));
return '{plugin(#smartyConfigLoad#,#'.$args['file'].'#,#'.$args['section'].'#)}';
case (preg_match('/^include\s/', $str)):
// convert to $t->TemplateConfigLoad()
$args = $this->convertAttributesToKeyVal(substr($str,strpos( $str,' ')));
return '{plugin(#smartyInclude#,#'.$args['file'].'#)}';
case ($str == 'ldelim'):
return '{';
case ($str == 'rdelim'):
return '}';
case (preg_match('/^if \$(\S+)$/', $str,$matches)):
case (preg_match('/^if \$(\S+)\seq\s""$/', $str,$matches)):
// simple if variable..
// convert to : {if:sssssss}
$this->stack['if']++;
$var = $this->_convertVar('$'.$matches[1]);
return '{if:'.substr($var,1);
case (preg_match('/^if #(\S+)#$/', $str,$matches)):
case (preg_match('/^if #(\S+)#\sne\s""$/', $str,$matches)):
// simple if variable..
// convert to : {if:sssssss}
$this->stack['if']++;
$var = $this->_convertConfigVar('#'.$matches[1].'#');
return '{if:'.substr($var,1);
// negative matches
case (preg_match('/^if\s!\s\$(\S+)$/', $str,$matches)):
case (preg_match('/^if \$(\S+)\seq\s""$/', $str,$matches)):
// simple if variable..
// convert to : {if:sssssss}
$this->stack['if']++;
$var = $this->_convertVar('$'.$matches[1]);
return '{if:!'.substr($var,1);
case ($str == 'else'):
if (!$this->stack['if']) {
break;
}
return '{else:}';
case ($str == '/if'):
if (!$this->stack['if']) {
break;
}
$this->stack['if']--;
return '{end:}';
}
return "<!-- UNSUPPORTED TAG: $str FOUND -->";
}
/**
* convert a smarty var into a flexy one.
*
* @param string the inside of the smart tag
*
* @return string a flexy version of it.
* @access private
*/
function _convertVar($str)
{
// look for modfiers first.
$mods = explode('|', $str);
$var = array_shift($mods);
$var = substr($var,1); // strip $
// various formats :
// aaaa.bbbb.cccc => aaaa[bbbb][cccc]
// aaaa[bbbb] => aaa[bbbb]
// aaaa->bbbb => aaaa.bbbb
$bits = explode('.',$var);
$var = array_shift($bits);
foreach($bits as $k) {
$var.= '['.$k .']';
}
$bits = explode('->',$var);
$var = implode('.',$bits);
$mods = implode('|',$mods);
if (strlen($mods)) {
return '{plugin(#smartyModifiers#,'.$var.',#'.$mods.'#):h}';
}
return '{'.$var .'}' . $mods;
}
/**
* convert a smarty key="value" string into a key value array
* cheap and cheerfull - doesnt handle spaces inside the strings...
*
* @param string the key value part of the tag..
*
* @return array key value array
* @access private
*/
function convertAttributesToKeyVal($str)
{
$atts = explode(' ', $str);
$ret = array();
foreach($atts as $bit) {
$bits = explode('=',$bit);
// loose stuff!!!
if (count($bits) != 2) {
continue;
}
$ret[$bits[0]] = ($bits[1]{0} == '"') ? substr($bits[1],1,-1) : $bits[1];
}
return $ret;
}
/**
* convert a smarty config var into a flexy one.
*
* @param string the inside of the smart tag
*
* @return string a flexy version of it.
* @access private
*/
function _convertConfigVar($str)
{
$mods = explode('|', $str);
$var = array_shift($mods);
$var = substr($var,1,-1); // strip #'s
$mods = implode('|',$mods);
if (strlen($mods)) {
$mods = "<!-- UNSUPPORTED MODIFIERS: $mods -->";
}
return '{configVars.'.$var .'}' . $mods;
}
}

View file

@ -0,0 +1,910 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Standard.php,v 1.43 2005/02/08 05:35:27 alan_k Exp $
//
// Base Compiler Class
// Standard 'Original Flavour' Flexy compiler
/*------------------------------------------------------------------------------------------
NOTICE:
THIS COMPILER IS DEPRECIATED
USE THE FLEXY COMPILER
The Flexy Compiler should be Compatible
------------------------------------------------------------------------------------------*/
require_once 'HTML/Template/Flexy/Tokenizer.php';
require_once 'HTML/Template/Flexy/Token.php';
// cache for po files..
$GLOBALS['_html_template_flexy_compiler_standard']['PO'] = array();
class HTML_Template_Flexy_Compiler_Standard extends HTML_Template_Flexy_Compiler
{
/**
* The compile method.
*
* @params object HTML_Template_Flexy
* @params string|false string to compile of false to use a file.
* @return string filename of template
* @access public
*/
function compile(&$flexy,$string=false)
{
// read the entire file into one variable
// note this should be moved to new HTML_Template_Flexy_Token
// and that can then manage all the tokens in one place..
global $_HTML_TEMPLATE_FLEXY_COMPILER;
$gettextStrings = &$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'];
$gettextStrings = array(); // reset it.
if (@$this->options['debug']) {
echo "compiling template $flexy->currentTemplate<BR>";
}
// reset the elements.
$flexy->_elements = array();
// replace this with a singleton??
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions'] = $this->options;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] = array();
$GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'] = $flexy->currentTemplate;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] = '';
$GLOBALS['_HTML_TEMPLATE_FLEXY']['compiledTemplate'] = $flexy->compiledTemplate;
if (is_array($this->options['Translation2'])) {
require_once 'Translation2.php';
$this->options['Translation2'] = new Translation2(
$this->options['Translation2']['driver'],
@$this->options['Translation2']['options']
);
}
if (is_a($this->options['Translation2'],'Translation2')) {
$this->options['Translation2']->setLang($this->options['locale']);
// fixme - needs to be more specific to which template to use..
foreach ($this->options['templateDir'] as $tt) {
$n = basename($flexy->currentTemplate);
if (substr($flexy->currentTemplate,0,strlen($tt)) == $tt) {
$n = substr($flexy->currentTemplate,strlen($tt)+1);
}
//echo $n;
}
$this->options['Translation2']->setPageID($n);
} else {
setlocale(LC_ALL, $this->options['locale']);
}
$data = $string;
$res = false;
if ($string === false) {
$data = file_get_contents($flexy->currentTemplate);
}
// PRE PROCESS {_(.....)} translation markers.
$got_gettext_markup = false;
if (strpos($data,'{_(') !== false) {
$matches = array();
$lmatches = explode ('{_(', $data);
array_shift($lmatches);
// shift the first..
foreach ($lmatches as $k) {
if (false === strpos($k,')_}')) {
continue;
}
$x = explode(')_}',$k);
$matches[] = $x[0];
}
//echo '<PRE>';print_r($matches);
// we may need to do some house cleaning here...
$gettextStrings = $matches;
$got_gettext_markup = true;
// replace them now..
// ** leaving in the tag (which should be ignored by the parser..
// we then get rid of the tags during the toString method in this class.
foreach($matches as $v) {
$data = str_replace('{_('.$v.')_}', '{_('.$this->translateString($v).')_}',$data);
}
}
if (isset($_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)])) {
$res = $_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)];
} else {
$tokenizer = new HTML_Template_Flexy_Tokenizer($data);
$tokenizer->fileName = $flexy->currentTemplate;
//$tokenizer->debug=1;
$tokenizer->options['ignore_html'] = $this->options['nonHTML'];
$tokenizer->options['ignore_php'] = !$this->options['allowPHP'];
$res = HTML_Template_Flexy_Token::buildTokens($tokenizer);
$_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)] = $res;
}
if (is_a($res,'PEAR_Error')) {
return $res;
}
// turn tokens into Template..
$data = $res->compile($this);
if (is_a($data,'PEAR_Error')) {
return $data;
}
$data = $GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] . $data;
if ( @$this->options['debug']) {
echo "<B>Result: </B><PRE>".htmlspecialchars($data)."</PRE><BR>";
}
if ($this->options['nonHTML']) {
$data = str_replace("?>\n","?>\n\n",$data);
}
// at this point we are into writing stuff...
if ($this->options['compileToString']) {
$flexy->elements = $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'];
return $data;
}
// error checking?
$file = $flexy->compiledTemplate;
if (isset($flexy->options['output.block'])) {
list($file,$part) = explode('#',$file );
}
if( ($cfp = fopen( $file , 'w' )) ) {
if (@$this->options['debug']) {
echo "<B>Writing: </B>".htmlspecialchars($data)."<BR>";
}
fwrite($cfp,$data);
fclose($cfp);
chmod($file,0775);
// make the timestamp of the two items match.
clearstatcache();
touch($file, filemtime($flexy->currentTemplate));
if ($file != $flexy->compiledTemplate) {
chmod($flexy->compiledTemplate,0775);
// make the timestamp of the two items match.
clearstatcache();
touch($flexy->compiledTemplate, filemtime($flexy->currentTemplate));
}
} else {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::failed to write to '.$flexy->compiledTemplate,
HTML_TEMPLATE_FLEXY_ERROR_FILE ,HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
// gettext strings
if (file_exists($flexy->getTextStringsFile)) {
unlink($flexy->getTextStringsFile);
}
if($gettextStrings && ($cfp = fopen( $flexy->getTextStringsFile, 'w') ) ) {
fwrite($cfp,serialize(array_unique($gettextStrings)));
fclose($cfp);
}
// elements
if (file_exists($flexy->elementsFile)) {
unlink($flexy->elementsFile);
}
if( $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] &&
($cfp = fopen( $flexy->elementsFile, 'w') ) ) {
fwrite($cfp,serialize( $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements']));
fclose($cfp);
// now clear it.
}
return true;
}
/**
* Flag indicating compiler is inside {_( .... )_} block, and should not
* add to the gettextstrings array.
*
* @var boolean
* @access public
*/
var $inGetTextBlock = false;
/**
* This is the base toString Method, it relays into toString{TokenName}
*
* @param object HTML_Template_Flexy_Token_*
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toString($element)
{
static $len = 26; // strlen('HTML_Template_Flexy_Token_');
if ($this->options['debug']) {
$x = $element;
unset($x->children);
echo htmlspecialchars(print_r($x,true))."<BR>\n";
}
if ($element->token == 'GetTextStart') {
$this->inGetTextBlock = true;
return '';
}
if ($element->token == 'GetTextEnd') {
$this->inGetTextBlock = false;
return '';
}
$class = get_class($element);
if (strlen($class) >= $len) {
$type = substr($class,$len);
return $this->{'toString'.$type}($element);
}
$ret = $element->value;
$add = $element->compileChildren($this);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
if ($element->close) {
$add = $element->close->compile($this);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
return $ret;
}
/**
* HTML_Template_Flexy_Token_Else toString
*
* @param object HTML_Template_Flexy_Token_Else
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringElse($element)
{
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState() === false) {
return $this->appendHTML(
"<font color=\"red\">Unmatched {else:} on line: {$element->line}</font>"
);
}
$element->pushState();
return $this->appendPhp("} else {");
}
/**
* HTML_Template_Flexy_Token_End toString
*
* @param object HTML_Template_Flexy_Token_Else
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringEnd($element)
{
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState() === false) {
return $this->appendHTML(
"<font color=\"red\">Unmatched {end:} on line: {$element->line}</font>"
);
}
return $this->appendPhp("}");
}
/**
* HTML_Template_Flexy_Token_EndTag toString
*
* @param object HTML_Template_Flexy_Token_EndTag
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringEndTag($element)
{
return $this->toStringTag($element);
}
/**
* HTML_Template_Flexy_Token_Foreach toString
*
* @param object HTML_Template_Flexy_Token_Foreach
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringForeach($element)
{
$loopon = $element->toVar($element->loopOn);
if (is_a($loopon,'PEAR_Error')) {
return $loopon;
}
$ret = 'if ($this->options[\'strict\'] || ('.
'is_array('. $loopon. ') || ' .
'is_object(' . $loopon . '))) ' .
'foreach(' . $loopon . " ";
$ret .= "as \${$element->key}";
if ($element->value) {
$ret .= " => \${$element->value}";
}
$ret .= ") {";
$element->pushState();
$element->pushVar($element->key);
$element->pushVar($element->value);
return $this->appendPhp($ret);
}
/**
* HTML_Template_Flexy_Token_If toString
*
* @param object HTML_Template_Flexy_Token_If
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringIf($element)
{
$var = $element->toVar($element->condition);
if (is_a($var,'PEAR_Error')) {
return $var;
}
$ret = "if (".$element->isNegative . $var .") {";
$element->pushState();
return $this->appendPhp($ret);
}
/**
* get Modifier Wrapper
*
* converts :h, :u, :r , .....
* @param object HTML_Template_Flexy_Token_Method|Var
*
* @return array prefix,suffix
* @access public
* @see toString*
*/
function getModifierWrapper($element)
{
$prefix = 'echo ';
$suffix = '';
$modifier = strlen(trim($element->modifier)) ? $element->modifier : ' ';
switch ($modifier{0}) {
case 'h':
break;
case 'u':
$prefix = 'echo urlencode(';
$suffix = ')';
break;
case 'r':
$prefix = 'echo \'<pre>\'; echo htmlspecialchars(print_r(';
$suffix = ',true)); echo \'</pre>\';';
break;
case 'n':
// blank or value..
$numberformat = @$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'];
$prefix = 'echo number_format(';
$suffix = $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'] . ')';
break;
case 'b': // nl2br + htmlspecialchars
$prefix = 'echo nl2br(htmlspecialchars(';
// add language ?
$suffix = '))';
break;
case ' ':
$prefix = 'echo htmlspecialchars(';
// add language ?
$suffix = ')';
break;
default:
$prefix = 'echo $this->plugin("'.trim($element->modifier) .'",';
$suffix = ')';
}
return array($prefix,$suffix);
}
/**
* HTML_Template_Flexy_Token_Var toString
*
* @param object HTML_Template_Flexy_Token_Method
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringVar($element)
{
// ignore modifier at present!!
$var = $element->toVar($element->value);
if (is_a($var,'PEAR_Error')) {
return $var;
}
list($prefix,$suffix) = $this->getModifierWrapper($element);
return $this->appendPhp( $prefix . $var . $suffix .';');
}
/**
* HTML_Template_Flexy_Token_Method toString
*
* @param object HTML_Template_Flexy_Token_Method
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringMethod($element)
{
// set up the modifier at present!!
list($prefix,$suffix) = $this->getModifierWrapper($element);
// add the '!' to if
if ($element->isConditional) {
$prefix = 'if ('.$element->isNegative;
$element->pushState();
$suffix = ')';
}
// check that method exists..
// if (method_exists($object,'method');
$bits = explode('.',$element->method);
$method = array_pop($bits);
$object = implode('.',$bits);
$var = $element->toVar($object);
if (is_a($var,'PEAR_Error')) {
return $var;
}
if (($object == 'GLOBALS') &&
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['globalfunctions']) {
// we should check if they something weird like: GLOBALS.xxxx[sdf](....)
$var = $method;
} else {
$prefix = 'if ($this->options[\'strict\'] || (isset('.$var.
') && method_exists('.$var .",'{$method}'))) " . $prefix;
$var = $element->toVar($element->method);
}
if (is_a($var,'PEAR_Error')) {
return $var;
}
$ret = $prefix;
$ret .= $var . "(";
$s =0;
foreach($element->args as $a) {
if ($s) {
$ret .= ",";
}
$s =1;
if ($a{0} == '#') {
$ret .= '"'. addslashes(substr($a,1,-1)) . '"';
continue;
}
$var = $element->toVar($a);
if (is_a($var,'PEAR_Error')) {
return $var;
}
$ret .= $var;
}
$ret .= ")" . $suffix;
if ($element->isConditional) {
$ret .= ' { ';
} else {
$ret .= ";";
}
return $this->appendPhp($ret);
}
/**
* HTML_Template_Flexy_Token_Processing toString
*
* @param object HTML_Template_Flexy_Token_Processing
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringProcessing($element)
{
// if it's XML then quote it..
if (strtoupper(substr($element->value,2,3)) == 'XML') {
return $this->appendPhp("echo '" . str_replace("'","\\"."'", $element->value) . "';");
}
// otherwise it's PHP code - so echo it..
return $element->value;
}
/**
* HTML_Template_Flexy_Token_Text toString
*
* @param object HTML_Template_Flexy_Token_Text
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringText($element)
{
// first get rid of stuff thats not translated etc.
// empty strings => output.
// comments -> just output
// our special tags -> output..
if (!strlen(trim($element->value) )) {
return $this->appendHtml($element->value);
}
// dont add comments to translation lists.
if (substr($element->value,0,4) == '<!--') {
return $this->appendHtml($element->value);
}
// ignore anything wrapped with {_( .... )_}
if ($this->inGetTextBlock) {
return $this->appendHtml($element->value);
}
// argTokens is built before the tag matching (it combined
// flexy tags into %s, into the string,
// and made a list of tokens in argTokens.
if (!count($element->argTokens) && !$element->isWord()) {
return $this->appendHtml($element->value);
}
// grab the white space at start and end (and keep it!
$value = ltrim($element->value);
$front = substr($element->value,0,-strlen($value));
$value = rtrim($element->value);
$rear = substr($element->value,strlen($value));
$value = trim($element->value);
// convert to escaped chars.. (limited..)
//$value = strtr($value,$cleanArray);
$this->addStringToGettext($value);
$value = $this->translateString($value);
// its a simple word!
if (!count($element->argTokens)) {
return $this->appendHtml($front . $value . $rear);
}
// there are subtokens..
// print_r($element->argTokens );
$args = array();
// these should only be text or vars..
foreach($element->argTokens as $i=>$token) {
$args[] = $token->compile($this);
}
// we break up the translated string, and put the compiled tags
// in between the values here.
$bits = explode('%s',$value);
$ret = $front;
foreach($bits as $i=>$v) {
$ret .= $v . @$args[$i];
}
return $ret . $rear;
}
/**
* addStringToGettext
*
* Adds a string to the gettext array.
*
* @param mixed preferably.. string to store
*
* @return none
* @access public
*/
function addStringToGettext($string)
{
if (!is_string($string)) {
return;
}
if (!preg_match('/[a-z]+/i', $string)) {
return;
}
$string = trim($string);
if (substr($string,0,4) == '<!--') {
return;
}
$GLOBALS['_HTML_TEMPLATE_FLEXY_COMPILER']['gettextStrings'][] = $string;
}
/**
* translateString - a gettextWrapper
*
* tries to do gettext or falls back on File_Gettext
* This has !!!NO!!! error handling - if it fails you just get english..
* no questions asked!!!
*
* @param string string to translate
*
* @return string translated string..
* @access public
*/
function translateString($string)
{
if (is_a($this->options['Translation2'],'Translation2')) {
$result = $this->options['Translation2']->get($string);
if (!empty($result)) {
return $result;
}
return $string;
}
// note this stuff may have been broken by removing the \n replacement code
// since i dont have a test for it... it may remain broken..
// use Translation2 - it has gettext backend support
// and should sort out the mess that \n etc. entail.
$prefix = basename($GLOBALS['_HTML_TEMPLATE_FLEXY']['filename']).':';
if (@$this->options['debug']) {
echo __CLASS__.":TRANSLATING $string<BR>";
}
if (function_exists('gettext') && !$this->options['textdomain']) {
if (@$this->options['debug']) {
echo __CLASS__.":USING GETTEXT?<BR>";
}
$t = gettext($string);
if ($t != $string) {
return $t;
}
$tt = gettext($prefix.$string);
if ($tt != $prefix.$string) {
return $tt;
}
// give up it's not translated anywhere...
return $t;
}
if (!$this->options['textdomain'] || !$this->options['textdomainDir']) {
// text domain is not set..
if (@$this->options['debug']) {
echo __CLASS__.":MISSING textdomain settings<BR>";
}
return $string;
}
$pofile = $this->options['textdomainDir'] .
'/' . $this->options['locale'] .
'/LC_MESSAGES/' . $this->options['textdomain'] . '.po';
// did we try to load it already..
if (@$GLOBALS['_'.__CLASS__]['PO'][$pofile] === false) {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD failed (Cached):<BR>";
}
return $string;
}
if (!@$GLOBALS['_'.__CLASS__]['PO'][$pofile]) {
// default - cant load it..
$GLOBALS['_'.__CLASS__]['PO'][$pofile] = false;
if (!file_exists($pofile)) {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD failed: {$pofile}<BR>";
}
return $string;
}
if (!@include_once 'File/Gettext.php') {
if (@$this->options['debug']) {
echo __CLASS__.":LOAD no File_gettext:<BR>";
}
return $string;
}
$GLOBALS['_'.__CLASS__]['PO'][$pofile] = File_Gettext::factory('PO',$pofile);
$GLOBALS['_'.__CLASS__]['PO'][$pofile]->load();
//echo '<PRE>'.htmlspecialchars(print_r($GLOBALS['_'.__CLASS__]['PO'][$pofile]->strings,true));
}
$po = &$GLOBALS['_'.__CLASS__]['PO'][$pofile];
// we should have it loaded now...
// this is odd - data is a bit messed up with CR's
$string = str_replace('\n',"\n",$string);
if (isset($po->strings[$prefix.$string])) {
return $po->strings[$prefix.$string];
}
if (!isset($po->strings[$string])) {
if (@$this->options['debug']) {
echo __CLASS__.":no match:<BR>";
}
return $string;
}
if (@$this->options['debug']) {
echo __CLASS__.":MATCHED: {$po->strings[$string]}<BR>";
}
// finally we have a match!!!
return $po->strings[$string];
}
/**
* HTML_Template_Flexy_Token_Tag toString
*
* @param object HTML_Template_Flexy_Token_Tag
*
* @return string string to build a template
* @access public
* @see toString*
*/
function toStringTag($element) {
if (strpos($element->tag,':') === false) {
$namespace = 'Tag';
} else {
$bits = explode(':',$element->tag);
$namespace = $bits[0];
}
if ($namespace{0} == '/') {
$namespace = substr($namespace,1);
}
if (empty($this->tagHandlers[$namespace])) {
require_once 'HTML/Template/Flexy/Compiler/Standard/Tag.php';
$this->tagHandlers[$namespace] = &HTML_Template_Flexy_Compiler_Standard_Tag::factory($namespace,$this);
if (!$this->tagHandlers[$namespace] ) {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::failed to create Namespace Handler '.$namespace .
' in file ' . $GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'],
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
}
return $this->tagHandlers[$namespace]->toString($element);
}
}

View file

@ -0,0 +1,218 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akkbhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Flexy.php,v 1.15 2004/06/24 06:12:06 alan_k Exp $
//
// Handler code for the <flexy: namespace
//
/**
* the <flexy:XXXX namespace
*
*
* at present it handles
* <flexy:toJavascript flexy:prefix="Javascript_prefix" javscriptName="PHPvar" .....>
* <flexy:include src="xxx.htm">
*
*
*
* @version $Id: Flexy.php,v 1.15 2004/06/24 06:12:06 alan_k Exp $
*/
class HTML_Template_Flexy_Compiler_Standard_Flexy {
/**
* Parent Compiler for
*
* @var object HTML_Template_Flexy_Compiler
*
* @access public
*/
var $compiler;
/**
* The current element to parse..
*
* @var object
* @access public
*/
var $element;
/**
* toString - display tag, attributes, postfix and any code in attributes.
* Relays into namspace::method to get results..
*
*
* @see parent::toString()
*/
function toString($element)
{
list($namespace,$method) = explode(':',$element->oTag);
if (!strlen($method)) {
return '';
}
// things we dont handle...
if (!method_exists($this,$method.'ToString')) {
return '';
}
return $this->{$method.'ToString'}($element);
}
/**
* toJavascript handler
* <flexy:toJavascript flexy:prefix="some_prefix_" javascriptval="php.val" ....>
*
* @see parent::toString()
*/
function toJavascriptToString($element)
{
$ret = $this->compiler->appendPhp( "require_once 'HTML/Javascript/Convert.php';");
$ret .= $this->compiler->appendHTML("\n<script type='text/javascript'>\n");
$prefix = ''. $element->getAttribute('FLEXY:PREFIX');
foreach ($element->attributes as $k=>$v) {
// skip directives..
if (strpos($k,':')) {
continue;
}
if ($k == '/') {
continue;
}
$v = substr($v,1,-1);
$ret .= $this->compiler->appendPhp(
'$__tmp = HTML_Javascript_Convert::convertVar('.$element->toVar($v) .',\''.$prefix . $k.'\',true);'.
'echo (is_a($__tmp,"PEAR_Error")) ? ("<pre>".print_r($__tmp,true)."</pre>") : $__tmp;');
$ret .= $this->compiler->appendHTML("\n");
}
$ret .= $this->compiler->appendHTML("</script>");
return $ret;
}
/**
* include handler
* <flexy:include src="test.html">
*
* @see parent::toString()
*/
function includeToString($element)
{
// this is disabled by default...
// we ignore modifier pre/suffix
$arg = $element->getAttribute('SRC');
if (!$arg) {
return $this->compiler->appendHTML("<B>Flexy:Include without a src=filename</B>");
}
// ideally it would be nice to embed the results of one template into another.
// however that would involve some complex test which would have to stat
// the child templates anyway..
// compile the child template....
// output... include $this->options['compiled_templates'] . $arg . $this->options['locale'] . '.php'
return $this->compiler->appendPHP( "\n".
"\$x = new HTML_Template_Flexy(\$this->options);\n".
"\$x->compile('{$arg}');\n".
"\$x->outputObject(\$t);\n"
);
}
/**
* Convert flexy tokens to HTML_Template_Flexy_Elements.
*
* @param object token to convert into a element.
* @return object HTML_Template_Flexy_Element
* @access public
*/
function toElement($element)
{
return '';
}
/**
* Handler for User defined functions in templates..
* <flexy:function name="xxxxx">.... </flexy:block> // equivilant to function xxxxx() {
* <flexy:function call="{xxxxx}">.... </flexy:block> // equivilant to function {$xxxxx}() {
* <flexy:function call="xxxxx">.... </flexy:block> // equivilant to function {$xxxxx}() {
*
* This will not handle nested blocks initially!! (and may cause even more problems with
* if /foreach stuff..!!
*
* @param object token to convert into a element.
* @access public
*/
function functionToString($element)
{
if ($arg = $element->getAttribute('NAME')) {
// this is a really kludgy way of doing this!!!
// hopefully the new Template Package will have a sweeter method..
$GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] .=
$this->compiler->appendPHP(
"\nfunction _html_template_flexy_compiler_standard_flexy_{$arg}(\$t,\$this) {\n").
$element->compileChildren($this->compiler) .
$this->compiler->appendPHP( "\n}\n");
return '';
}
if (!isset($element->ucAttributes['CALL'])) {
return HTML_Template_Flexy::raiseError(
' tag flexy:function needs an argument call or name'.
" Error on Line {$element->line} &lt;{$element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// call is a stirng : nice and simple..
if (is_string($element->ucAttributes['CALL'])) {
$arg = $element->getAttribute('CALL');
return $this->compiler->appendPHP(
"if (function_exists('_html_template_flexy_compiler_standard_flexy_'.{$arg})) " .
" _html_template_flexy_compiler_standard_flexy_{$arg}(\$t,\$this);");
}
// we make a big assumption here.. - it should really be error checked..
// that the {xxx} element is item 1 in the list...
$e=$element->ucAttributes['CALL'][1];
$add = $e->toVar($e->value);
if (is_a($add,'PEAR_Error')) {
return $add;
}
return $this->compiler->appendPHP(
"if (function_exists('_html_template_flexy_compiler_standard_flexy_'.{$add})) ".
"call_user_func_array('_html_template_flexy_compiler_standard_flexy_'.{$add},array(\$t,\$this));");
}
}

View file

@ -0,0 +1,893 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Tag.php,v 1.50 2004/07/29 04:26:24 alan_k Exp $
/* FC/BC compatibility with php5 */
if ( (substr(phpversion(),0,1) < 5) && !function_exists('clone')) {
eval('function clone($t) { return $t; }');
}
/**
* Compiler That deals with standard HTML Tag output.
* Since it's pretty complex it has it's own class.
* I guess this class should deal with the main namespace
* and the parent (standard compiler can redirect other namespaces to other classes.
*
* one instance of these exists for each namespace.
*
*
* @version $Id: Tag.php,v 1.50 2004/07/29 04:26:24 alan_k Exp $
*/
class HTML_Template_Flexy_Compiler_Standard_Tag {
/**
* Parent Compiler for
*
* @var object HTML_Template_Flexy_Compiler
*
* @access public
*/
var $compiler;
/**
*
* Factory method to create Tag Handlers
*
* $type = namespace eg. <flexy:toJavascript loads Flexy.php
* the default is this... (eg. Tag)
*
*
* @param string Namespace handler for element.
* @param object HTML_Template_Flexy_Compiler
*
*
* @return object tag compiler
* @access public
*/
function &factory($type,&$compiler) {
if (!$type) {
$type = 'Tag';
}
// if we dont have a handler - just use the basic handler.
if (!file_exists(dirname(__FILE__) . '/'. ucfirst(strtolower($type)) . '.php')) {
$type = 'Tag';
}
include_once 'HTML/Template/Flexy/Compiler/Standard/' . ucfirst(strtolower($type)) . '.php';
$class = 'HTML_Template_Flexy_Compiler_Standard_' . $type;
if (!class_exists($class)) {
return false;
}
$ret = new $class;
$ret->compiler = &$compiler;
return $ret;
}
/**
* The current element to parse..
*
* @var object
* @access public
*/
var $element;
/**
* Flag to indicate has attribute flexy:foreach (so you cant mix it with flexy:if!)
*
* @var boolean
* @access public
*/
var $hasForeach = false;
/**
* toString - display tag, attributes, postfix and any code in attributes.
* Note first thing it does is call any parseTag Method that exists..
*
*
* @see parent::toString()
*/
function toString($element)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
global $_HTML_TEMPLATE_FLEXY;
// store the element in a variable
$this->element = $element;
// echo "toString: Line {$this->element->line} &lt;{$this->element->tag}&gt;\n";
// if the FLEXYSTARTCHILDREN flag was set, only do children
// normally set in BODY tag.
// this will probably be superseeded by the Class compiler.
if (isset($element->ucAttributes['FLEXY:STARTCHILDREN'])) {
return $element->compileChildren($this->compiler);
}
$flexyignore = $this->parseAttributeIgnore();
// rewriting should be done with a tag.../flag.
$this->reWriteURL("HREF");
$this->reWriteURL("SRC");
// handle elements
if (($ret =$this->_parseTags()) !== false) {
return $ret;
}
// these add to the close tag..
$ret = $this->parseAttributeForeach();
$ret .= $this->parseAttributeIf();
// spit ou the tag and attributes.
if ($element->oTag{0} == '?') {
$ret .= '<?php echo "<"; ?>';
} else {
$ret .= "<";
}
$ret .= $element->oTag;
foreach ($element->attributes as $k=>$v) {
// if it's a flexy tag ignore it.
if (strtoupper($k) == 'FLEXY:RAW') {
if (!is_array($v) || !isset($v[1]) || !is_object($v[1])) {
return HTML_Template_Flexy::raiseError(
'flexy:raw only accepts a variable or method call as an argument, eg.'.
' flexy:raw="{somevalue}" you provided something else.' .
" Error on Line {$this->element->line} &lt;{$this->element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$add = $v[1]->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= ' ' . $add;
continue;
}
if (strtoupper(substr($k,0,6)) == 'FLEXY:') {
continue;
}
// true == an attribute without a ="xxx"
if ($v === true) {
$ret .= " $k";
continue;
}
// if it's a string just dump it.
if (is_string($v)) {
$ret .= " {$k}={$v}";
continue;
}
// normally the value is an array of string, however
// if it is an object - then it's a conditional key.
// eg. if (something) echo ' SELECTED';
// the object is responsible for adding it's space..
if (is_object($v)) {
$add = $v->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
continue;
}
// otherwise its a key="sometext{andsomevars}"
$ret .= " {$k}=";
foreach($v as $item) {
if (is_string($item)) {
$ret .= $item;
continue;
}
$add = $item->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
}
$ret .= ">";
// post stuff this is probably in the wrong place...
if ($element->postfix) {
foreach ($element->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
} else if ($this->element->postfix) { // if postfixed by self..
foreach ($this->element->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
}
// dump contents of script raw - to prevent gettext additions..
// print_r($element);
if ($element->tag == 'SCRIPT') {
foreach($element->children as $c) {
//print_R($c);
if (!$c) {
continue;
}
if ($c->token == 'Text') {
$ret .= $c->value;
continue;
}
// techically we shouldnt have anything else inside of script tags.
// as the tokeinzer is supposted to ignore it..
}
} else {
$add = $element->compileChildren($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
// output the closing tag.
if ($element->close) {
$add = $element->close->compile($this->compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
// reset flexyignore
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = $flexyignore;
if (isset($_HTML_TEMPLATE_FLEXY['currentOptions']['output.block']) &&
($_HTML_TEMPLATE_FLEXY['currentOptions']['output.block'] == $element->getAttribute('ID'))) {
// echo $_HTML_TEMPLATE_FLEXY['compiledTemplate'];
$fh = fopen($_HTML_TEMPLATE_FLEXY['compiledTemplate'],'w');
fwrite($fh,$ret);
fclose($fh);
}
return $ret;
}
/**
* Reads an flexy:foreach attribute -
*
*
* @return string to add to output.
* @access public
*/
function parseAttributeIgnore()
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$flexyignore = $_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'];
if ($this->element->getAttribute('FLEXY:IGNORE') !== false) {
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = true;
$this->element->clearAttribute('FLEXY:IGNORE');
}
return $flexyignore;
}
/**
* Reads an flexy:foreach attribute -
*
*
* @return string to add to output.
* @access public
*/
function parseAttributeForeach()
{
$foreach = $this->element->getAttribute('FLEXY:FOREACH');
if ($foreach === false) {
return '';
}
//var_dump($foreach);
$this->element->hasForeach = true;
// create a foreach element to wrap this with.
$foreachObj = $this->element->factory('Foreach',
explode(',',$foreach),
$this->element->line);
// failed = probably not enough variables..
if ($foreachObj === false) {
return HTML_Template_Flexy::raiseError(
"Missing Arguments: An flexy:foreach attribute was foundon Line {$this->element->line}
in tag &lt;{$this->element->tag} flexy:foreach=&quot;$foreach&quot; .....&gt;<BR>
the syntax is &lt;sometag flexy:foreach=&quot;onarray,withvariable[,withanothervar] &gt;<BR>",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// does it have a closetag?
if (!$this->element->close) {
if ($this->element->getAttribute('/') === false) {
return HTML_Template_Flexy::raiseError(
"A flexy:foreach attribute was found in &lt;{$this->element->name} tag without a corresponding &lt;/{$this->element->tag}
tag on Line {$this->element->line} &lt;{$this->element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// it's an xhtml tag!
$this->element->postfix = array($this->element->factory("End", '', $this->element->line));
} else {
$this->element->close->postfix = array($this->element->factory("End", '', $this->element->line));
}
$this->element->clearAttribute('FLEXY:FOREACH');
return $foreachObj->compile($this->compiler);
}
/**
* Reads an flexy:if attribute -
*
*
* @return string to add to output.
* @access public
*/
function parseAttributeIf()
{
// dont use the together, if is depreciated..
$if = $this->element->getAttribute('FLEXY:IF');
if ($if === false) {
return '';
}
if (isset($this->element->hasForeach)) {
return HTML_Template_Flexy::raiseError(
"You may not use FOREACH and IF tags in the same tag on Line {$this->element->line} &lt;{$this->element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// allow if="!somevar"
$ifnegative = '';
if ($if{0} == '!') {
$ifnegative = '!';
$if = substr($if,1);
}
// if="xxxxx"
// if="xxxx.xxxx()" - should create a method prefixed with 'if:'
// these checks should really be in the if/method class..!!!
if (!preg_match('/^[_A-Z][A-Z0-9_]*(\[[0-9]+\])?((\[|%5B)[A-Z0-9_]+(\]|%5D))*'.
'(\.[_A-Z][A-Z0-9_]*((\[|%5B)[A-Z0-9_]+(\]|%5D))*)*(\\([^)]*\))?$/i',$if)) {
return HTML_Template_Flexy::raiseError(
"IF tags only accept simple object.variable or object.method() values on
Line {$this->element->line} &lt;{$this->element->tag}&gt;
{$if}",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
if (substr($if,-1) == ')') {
// grab args..
$args = substr($if,strpos($if,'(')+1,-1);
// simple explode ...
$args = strlen(trim($args)) ? explode(',',$args) : array();
//print_R($args);
// this is nasty... - we need to check for quotes = eg. # at beg. & end..
$args_clean = array();
for ($i=0; $i<count($args); $i++) {
if ($args[$i]{0} != '#') {
$args_clean[] = $args[$i];
continue;
}
// single # - so , must be inside..
if ((strlen($args[$i]) > 1) && ($args[$i]{strlen($args[$i])-1}=='#')) {
$args_clean[] = $args[$i];
continue;
}
$args[$i] .=',' . $args[$i+1];
// remove args+1..
array_splice($args,$i+1,1);
$i--;
// reparse..
}
$ifObj = $this->element->factory('Method',
array('if:'.$ifnegative.substr($if,0,strpos($if,'(')), $args_clean),
$this->element->line);
} else {
$ifObj = $this->element->factory('If', $ifnegative.$if, $this->element->line);
}
// does it have a closetag? - you must have one - so you will have to hack in <span flexy:if=..><img></span> on tags
// that do not have close tags - it's done this way to try and avoid mistakes.
if (!$this->element->close) {
//echo "<PRE>";print_R($this->element);
if ($this->element->getAttribute('/') !== false) {
$this->element->postfix = array($this->element->factory("End",'', $this->element->line));
} else {
return HTML_Template_Flexy::raiseError(
"An flexy:if attribute was found in &lt;{$this->element->name} tag without a corresponding &lt;/{$this->element->name}
tag on Line {$this->element->line} &lt;{$this->element->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
} else {
$this->element->close->postfix = array($this->element->factory("End",'', $this->element->line));
}
$this->element->clearAttribute('FLEXY:IF');
return $ifObj->compile($this->compiler);
}
/**
* Reads Tags - and relays to parseTagXXXXXXX
*
*
* @return string | false = html output or ignore (just output the tag)
* @access private
*/
function _parseTags()
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
// doesnt really need strtolower etc. as php functions are not case sensitive!
if ($this->element->getAttribute('FLEXY:DYNAMIC')) {
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('ID') )
);
}
if ($this->element->getAttribute('FLEXY:IGNOREONLY') !== false) {
return false;
}
if ($_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore']) {
return false;
}
$tag = $this->element->tag;
if (strpos($tag,':') !== false) {
$bits = explode(':',$tag);
$tag = $bits[1];
}
$method = 'parseTag'.$tag;
if (!method_exists($this,$method)) {
return false;
}
// do any of the attributes use flexy data...
foreach ($this->element->attributes as $k=>$v) {
if (is_array($v)) {
return false;
}
}
//echo "call $method" . serialize($this->element->attributes). "\n";
return $this->$method();
// allow the parse methods to return output.
}
/**
* produces the code for dynamic elements
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function getElementPhp($id,$mergeWithName=false) {
global $_HTML_TEMPLATE_FLEXY;
static $tmpId=0;
if (!$id) {
return HTML_Template_Flexy::raiseError(
"Error:{$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line} &lt;{$this->element->tag}&gt;: " .
" Dynamic tags require an ID value",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// dont mix and match..
if (($this->element->getAttribute('FLEXY:IF') !== false) ||
($this->element->getAttribute('FLEXY:FOREACH') !== false) )
{
return HTML_Template_Flexy::raiseError(
"Error:{$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line} &lt;{$this->element->tag}&gt;: " .
" You can not mix flexy:if= or flexy:foreach= with dynamic form elements " .
" (turn off tag to element code with flexyIgnore=0, use flexy:ignore=&quot;yes&quot; in the tag" .
" or put the conditional outside in a span tag",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
if ((strtolower($this->element->getAttribute('type')) == 'checkbox' ) &&
(substr($this->element->getAttribute('name'),-2) == '[]')) {
if ($this->element->getAttribute('id') === false) {
$id = 'tmpId'. (++$tmpId);
$this->element->attributes['id'] = $id;
$this->element->ucAttributes['ID'] = $id;
}
$mergeWithName = true;
}
if (isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
// echo "<PRE>";print_r($this);print_r($_HTML_TEMPLATE_FLEXY['elements']);echo "</PRE>";
return HTML_Template_Flexy::raiseError(
"Error:{$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line} in Tag &lt;{$this->element->tag}&gt;:<BR> " .
"The Dynamic tag Name '$id' has already been used previously by tag &lt;{$_HTML_TEMPLATE_FLEXY['elements'][$id]->tag}&gt;",
null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// this is for a case where you can use a sprintf as the name, and overlay it with a variable element..
$_HTML_TEMPLATE_FLEXY['elements'][$id] = $this->toElement($this->element);
if ($var = $this->element->getAttribute('FLEXY:NAMEUSES')) {
$var = 'sprintf(\''.$id .'\','.$this->element->toVar($var) .')';
return
'if (!isset($this->elements['.$var.'])) $this->elements['.$var.']= $this->elements[\''.$id.'\'];
$this->elements['.$var.'] = $this->mergeElement($this->elements[\''.$id.'\'],$this->elements['.$var.']);
$this->elements['.$var.']->attributes[\'name\'] = '.$var. ';
echo $this->elements['.$var.']->toHtml();';
} elseif ($mergeWithName) {
$name = $this->element->getAttribute('NAME');
return
'$element = $this->elements[\''.$id.'\'];
$element = $this->mergeElement($element,$this->elements[\''.$name.'\']);
echo $element->toHtml();';
} else {
return 'echo $this->elements[\''.$id.'\']->toHtml();';
}
}
/**
* Reads an Script tag - check if PHP is allowed.
*
* @return false|PEAR_Error
* @access public
*/
function parseTagScript() {
$lang = $this->element->getAttribute('LANGUAGE');
if (!$lang) {
return false;
}
$lang = strtoupper($lang);
if ($GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['allowPHP']) {
return false;
}
if ($lang == "PHP") {
return HTML_Template_Flexy::raiseError('PHP code found in script',
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX,HTML_TEMPLATE_FLEXY_ERROR_RETURN
);
}
return false;
}
/**
* Reads an Input tag - build a element object for it
*
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagInput()
{
global $_HTML_TEMPLATE_FLEXY;
if (in_array(strtoupper($this->element->getAttribute('TYPE')), array('SUBMIT','BUTTON','INPUT',''))) {
$this->compiler->addStringToGettext($this->element->getAttribute('VALUE'));
}
// form elements : format:
//value - fill out as PHP CODE
// as a general rule, this uses name, rather than ID except on
// radio
$mergeWithName = false;
$id = $this->element->getAttribute('NAME');
// checkboxes need more work.. - at the momemnt assume one with the same value...
if (in_array(strtoupper($this->element->getAttribute('TYPE')), array('RADIO'))) {
if (!isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
// register it.. - so we dont overwrite it...
$_HTML_TEMPLATE_FLEXY['elements'][$id] = false;
} else if ($_HTML_TEMPLATE_FLEXY['elements'][$id] != false) {
return HTML_Template_Flexy::raiseError(
"Error:{$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line} ".
"in Tag &lt;{$this->element->tag}&gt;:<BR>".
"The Dynamic tag Name '$id' has already been used previously by ".
"tag &lt;{$_HTML_TEMPLATE_FLEXY['elements'][$id]->tag}&gt;",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE
);
}
$id = $this->element->getAttribute('ID');
if (!$id) {
return HTML_Template_Flexy::raiseError("Error in {$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line} &lt;{$this->element->tag}&gt:
Radio Input's require an ID tag..",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$mergeWithName = true;
}
if (!$id) {
return false;
}
return $this->compiler->appendPhp($this->getElementPhp( $id,$mergeWithName));
}
/**
* Deal with a TextArea tag - build a element object for it
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagTextArea()
{
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('NAME')));
}
/**
* Deal with Selects - build a element object for it (unless flexyignore is set)
*
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagSelect()
{
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('NAME')));
}
/**
* Reads an Form tag - and set up the element object header etc.
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagForm()
{
global $_HTML_TEMPLATE_FLEXY;
$copy = clone($this->element);
$copy->children = array();
$id = $this->element->getAttribute('NAME');
if (!$id) {
$id = 'form';
}
// this adds the element to the elements array.
$old = clone($this->element);
$this->element = $copy;
$this->getElementPhp($id);
$this->element= $old;
return
$this->compiler->appendPhp('echo $this->elements[\''.$id.'\']->toHtmlnoClose();') .
$this->element->compileChildren($this->compiler) .
$this->compiler->appendHtml( "</{$copy->oTag}>");
}
/**
* reWriteURL - can using the config option 'url_rewrite'
* format "from:to,from:to"
* only handle left rewrite.
* so
* "/images:/myroot/images"
* would change
* /images/xyz.gif to /myroot/images/xyz.gif
* /images/stylesheet/imagestyles.css to /myroot/images/stylesheet/imagestyles.css
* note /imagestyles did not get altered.
* will only work on strings (forget about doing /images/{someimage}
*
*
* @param string attribute to rewrite
* @return none
* @access public
*/
function reWriteURL($which)
{
global $_HTML_TEMPLATE_FLEXY;
if (!is_string($original = $this->element->getAttribute($which))) {
return;
}
if ($original == '') {
return;
}
if (empty($_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite'])) {
return;
}
$bits = explode(",",$_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite']);
$new = $original;
foreach ($bits as $bit) {
if (!strlen(trim($bit))) {
continue;
}
$parts = explode (':', $bit);
if (!isset($parts[1])) {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy: url_rewrite syntax incorrect'.
print_r(array($bits,$bits),true),null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$new = preg_replace('#^'.$parts[0].'#',$parts[1], $new);
}
if ($original == $new) {
return;
}
$this->element->ucAttributes[$which] = '"'. $new . '"';
}
/**
* Convert flexy tokens to HTML_Template_Flexy_Elements.
*
* @param object token to convert into a element.
* @return object HTML_Template_Flexy_Element
* @access public
*/
function toElement($element) {
require_once 'HTML/Template/Flexy/Element.php';
$ret = new HTML_Template_Flexy_Element;
if (strtolower(get_class($element)) != 'html_template_flexy_token_tag') {
$this->compiler->addStringToGettext($element->value);
return $element->value;
}
$ret->tag = strtolower($element->tag);
$ats = $element->getAttributes();
if (isset($element->attributes['flexy:xhtml'])) {
$ats['flexy:xhtml'] = true;
}
foreach(array_keys($ats) as $a) {
$ret->attributes[$a] = $this->unHtmlEntities($ats[$a]);
}
//print_r($ats);
if (!$element->children) {
return $ret;
}
// children - normally to deal with <element>
//print_r($this->children);
foreach(array_keys($element->children) as $i) {
// not quite sure why this happens - but it does.
if (!is_object($element->children[$i])) {
continue;
}
$ret->children[] = $this->toElement($element->children[$i]);
}
return $ret;
}
/**
* do the reverse of htmlspecialchars on an attribute..
*
* copied from get-html-translation-table man page
*
* @param mixed from attribute values
*
* @return string return
* @access public
* @see see also methods.....
*/
function unHtmlEntities ($in)
{
if (!is_string($in)) {
return $in;
}
$trans_tbl = get_html_translation_table (HTML_ENTITIES);
$trans_tbl = array_flip ($trans_tbl);
$ret = strtr ($in, $trans_tbl);
return preg_replace('/&#(\d+);/me', "chr('\\1')",$ret);
}
}

View file

@ -0,0 +1,615 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com> |
// | Based on HTML_Common by: Adam Daniel <adaniel1@eesus.jnj.com> |
// +----------------------------------------------------------------------+
//
// $Id: Element.php,v 1.46 2005/12/20 01:45:06 alan_k Exp $
/**
* Lightweight HTML Element builder and render
*
* This differs from HTML_Common in the following ways:
*
* $element->attributes is Public
* $element->override if set to anything other than false, renders the value rather than
* the defined element
*
* $element->children is a recursvable child array which is rendered by toHTML
* $element->toHtml() is implemented
* $element->toHtmlNoClose() renders only the first tag and children (designed for <form
* No support for tab offsets, comments ...
*
* Full support for Select, and common Form elements using
* setValue()
* setOptions()
*
* overlay support with SetFrom - base + inherited..
*
* attributes array values:
* key="value" // standard key="value" in output
* key = true // outputs just key.
*
* children can be
* another HTML_Element
* or string (raw text)
*
*
* @author Adam Daniel <adaniel1@eesus.jnj.com>
* @version 1.6
* @since PHP 4.0.3pl1
* @abstract
*/
class HTML_Template_Flexy_Element {
/**
* Tag that this Element represents.
* @var array
* @access public
*/
var $tag = '';
/**
* Associative array of table attributes
* Note Special values:
* true == only display the key
* false == remove
*
* @var array
* @access public
*/
var $attributes = array();
/**
* Sequence array of children
* children that are strings are assumed to be text
* @var array
* @access public
*/
var $children = array();
/**
* override the tag.
* if this is set to anything other than false, it will be output
* rather than the tags+children
* @var array
* @access public
*/
var $override = false;
/**
* prefix the tag.
* this is output by toHtml as a prefix to the tag (can be used for require tags)
* @var array
* @access private
*/
var $prefix = '';
/**
* suffix the tag.
* this is output by toHtml as a suffix to the tag (can be used for error messages)
* @var array
* @access private
*/
var $suffix = '';
/**
* a value for delayed merging into live objects
* if you set this on an element, it is merged by setValue, at merge time.
* @var array
* @access public
*/
var $value = null;
/**
* Class constructor
* @param mixed $attributes Associative array of table tag attributes
* or HTML attributes name="value" pairs
* @access public
*/
function HTML_Template_Flexy_Element($tag='', $attributes=null)
{
$this->tag = strtolower($tag);
if (false !== strpos($tag, ':')) {
$bits = explode(':',$this->tag);
$this->tag = $bits[0] . ':'.strtolower($bits[1]);
}
$this->setAttributes($attributes);
} // end constructor
/**
* Returns an HTML formatted attribute string
* @param array $attributes
* @return string
* @access private
*/
function attributesToHTML()
{
$strAttr = '';
$xhtmlclose = '';
$charset = empty($GLOBALS['HTML_Template_Flexy']['options']['charset']) ? 'ISO-8859-1' : $GLOBALS['HTML_Template_Flexy']['options']['charset'];
foreach ($this->attributes as $key => $value) {
// you shouldn't do this, but It shouldnt barf when you do..
if (is_array($value) || is_object($value)) {
continue;
}
if ($key == 'flexy:xhtml') {
continue;
}
if ($value === false) {
continue;
}
if ($value === true) {
// this is not xhtml compatible..
if ($key == '/') {
$xhtmlclose = ' /';
continue;
}
if (isset($this->attributes['flexy:xhtml'])) {
$strAttr .= " {$key}=\"{$key}\"";
} else {
$strAttr .= ' ' . $key;
}
} else {
// dont replace & with &amp;
if ($this->tag == 'textbox') { // XUL linefeed fix.
$value = str_replace("\n", '&#13;', htmlspecialchars($value,ENT_COMPAT,$charset));
} else {
$value = str_replace('&amp;nbsp;','&nbsp;',htmlspecialchars($value,ENT_COMPAT,$charset));
}
$strAttr .= ' ' . $key . '="' . $value . '"';
}
}
$strAttr .= $xhtmlclose;
return $strAttr;
} // end func _getAttrString
/**
* Static Method to get key/value array from attributes.
* Returns a valid atrributes array from either a string or array
* @param mixed $attributes Either a typical HTML attribute string or an associative array
* @access private
*/
function parseAttributes($attributes)
{
if (is_array($attributes)) {
$ret = array();
foreach ($attributes as $key => $value) {
if (is_int($key)) {
$ret[strtolower($value)] = true;
} else {
$ret[strtolower($key)] = $value;
}
}
return $ret;
} elseif (is_string($attributes)) {
$preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" .
"([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/";
if (preg_match_all($preg, $attributes, $regs)) {
for ($counter=0; $counter<count($regs[1]); $counter++) {
$name = $regs[1][$counter];
$check = $regs[0][$counter];
$value = $regs[7][$counter];
if (trim($name) == trim($check)) {
$arrAttr[strtolower(trim($name))] = strtolower(trim($name));
} else {
if (substr($value, 0, 1) == "\"" || substr($value, 0, 1) == "'") {
$value = substr($value, 1, -1);
}
$arrAttr[strtolower(trim($name))] = trim($value);
}
}
return $arrAttr;
}
}
} // end func _parseAttributes
/**
* Utility function to set values from common tag types.
* @param HTML_Element $from override settings from another element.
* @access public
*/
function setValue($value) {
// store the value in all situations
$this->value = $value;
$tag = strtolower($this->tag);
if (strpos($tag,':') !== false) {
$bits = explode(':',$tag);
$tag = $bits[1];
}
switch ($tag) {
case 'input':
switch (isset($this->attributes['type']) ? strtolower($this->attributes['type']) : '') {
case 'checkbox':
if (isset($this->attributes['checked'])) {
unset($this->attributes['checked']);
}
// if value is nto set, it doesnt make any difference what you set ?
if (!isset($this->attributes['value'])) {
return;
}
//print_r($this); echo "SET TO "; serialize($value);
if (isset($this->attributes['name']) && (substr($this->attributes['name'],-2) == '[]')) {
if (is_array($value) &&
in_array((string) $this->attributes['value'],$value)
) {
$this->attributes['checked'] = true;
}
return;
}
if ($this->attributes['value'] == $value) {
$this->attributes['checked'] = true;
}
return;
case 'radio':
if (isset($this->attributes['checked'])) {
unset($this->attributes['checked']);
}
// if we dont have values associated yet, store it..
if (!isset($this->attributes['value'])) {
$this->value = $value;
return;
}
if ($this->attributes['value'] == $value) {
$this->attributes['checked'] = true;
}
return;
default:
// no other input accepts array as a value.
if (is_array($value)) {
return;
}
$this->attributes['value'] = $value;
return;
}
case 'select':
if (!is_array($value)) {
$value = array($value);
}
// its setting the default value..
foreach($this->children as $i=>$child) {
if (is_string($child)) {
continue;
}
if ($child->tag == 'optgroup') {
foreach($this->children[$i]->children as $ii=>$child) {
// does the value exist and match..
if (isset($child->attributes['value'])
&& in_array((string) $child->attributes['value'], $value))
{
$this->children[$i]->children[$ii]->attributes['selected'] =
isset($this->attributes['flexy:xhtml']) ? 'selected' : true;
continue;
}
if (isset($child->attributes['value']) &&
isset($this->children[$i]->children[$ii]->attributes['selected']))
{
unset($this->children[$i]->children[$ii]->attributes['selected']);
continue;
}
// value doesnt exst..
if (isset($this->children[$i]->children[$ii]->attributes['selected'])) {
unset($this->children[$i]->children[$ii]->attributes['selected']);
continue;
}
}
continue;
}
// standard option value...
//echo "testing {$child->attributes['value']} against ". print_r($value,true)."\n";
// does the value exist and match..
if (isset($child->attributes['value'])
&& in_array((string) $child->attributes['value'], $value))
{
$this->children[$i]->attributes['selected'] =
isset($this->attributes['flexy:xhtml']) ? 'selected' : true;;
continue;
}
// no value attribute try and use the contents.
if (!isset($child->attributes['value'])
&& is_string($child->children[0])
&& in_array((string) $child->children[0], $value))
{
$this->children[$i]->attributes['selected'] =
isset($this->attributes['flexy:xhtml']) ? 'selected' : true;
continue;
}
if (isset($child->attributes['value']) &&
isset($this->children[$i]->attributes['selected']))
{
//echo "clearing selected\n";
unset($this->children[$i]->attributes['selected']);
continue;
}
// value doesnt exst..
if (isset($this->children[$i]->attributes['selected'])) {
//echo "clearing selected\n";
unset($this->children[$i]->attributes['selected']);
continue;
}
}
return;
case 'textarea':
$charset = empty($GLOBALS['HTML_Template_Flexy']['options']['charset']) ? 'ISO-8859-1' : $GLOBALS['HTML_Template_Flexy']['options']['charset'];
$this->children = array(htmlspecialchars($value,ENT_COMPAT,$charset));
return;
case '': // dummy objects.
$this->value = $value;
return;
// XUL elements
case 'menulist':
case 'textbox':
case 'checkbox':
require_once 'HTML/Template/Flexy/Element/Xul.php';
HTML_Template_Flexy_Element_Xul::setValue($this,$value);
return ;
default:
if (is_array($value)) {
return;
}
$this->value = $value;
}
}
/**
* Utility function equivilant to HTML_Select - loadArray **
* but using
* key=>value maps
* <option value="key">Value</option>
* Key=key (eg. both the same) maps to
* <option>key</option>
* and label = array(key=>value) maps to
* <optgroup label="label"> <option value="key">value</option></optgroup>
*
* $element->setOptions(array('a'=>'xxx','b'=>'yyy'));
* or
* $element->setOptions(array('a','b','c','d'),true);
*
*
*.
* @param HTML_Element $from override settings from another element.
* @param HTML_Element $noValue ignore the key part of the array
* @access public
*/
function setOptions($array,$noValue=false) {
if (!is_array($array)) {
$this->children = array();
return;
}
$charset = empty($GLOBALS['HTML_Template_Flexy']['options']['charset']) ? 'ISO-8859-1' : $GLOBALS['HTML_Template_Flexy']['options']['charset'];
$tag = strtolower($this->tag);
$namespace = '';
if (false !== strpos($this->tag, ':')) {
$bits = explode(':',$this->tag);
$namespace = $bits[0] . ':';
$tag = strtolower($bits[1]);
}
// if we have specified a xultag!!?
if (strlen($tag) && ($tag != 'select')) {
require_once 'HTML/Template/Flexy/Element/Xul.php';
return HTML_Template_Flexy_Element_Xul::setOptions($this,$array,$noValue);
}
foreach($array as $k=>$v) {
if (is_array($v)) { // optgroup
$child = new HTML_Template_Flexy_Element($namespace . 'optgroup',array('label'=>$k));
foreach($v as $kk=>$vv) {
$atts=array();
if (($kk !== $vv) && !$noValue) {
$atts = array('value'=>$kk);
} else {
$atts = array('value'=>$vv);
}
$add = new HTML_Template_Flexy_Element($namespace . 'option',$atts);
$add->children = array(htmlspecialchars($vv,ENT_COMPAT,$charset));
$child->children[] = $add;
}
$this->children[] = $child;
continue;
}
$atts=array();
if (($k !== $v) && !$noValue) {
$atts = array('value'=>$k);
} else {
$atts = array('value'=>$v);
}
$add = new HTML_Template_Flexy_Element($namespace . 'option',$atts);
$add->children = array(htmlspecialchars($v,ENT_COMPAT,$charset));
$this->children[] = $add;
}
}
/**
* Sets the HTML attributes
* @param mixed $attributes Either a typical HTML attribute string or an associative array
* @access public
*/
function setAttributes($attributes)
{
$attrs= $this->parseAttributes($attributes);
if (!is_array($attrs)) {
return false;
}
foreach ($attrs as $key => $value) {
$this->attributes[$key] = $value;
}
} // end func updateAttributes
/**
* Removes an attributes
*
* @param string $attr Attribute name
* @since 1.4
* @access public
* @return void
* @throws
*/
function removeAttributes($attrs)
{
if (is_string($attrs)) {
$attrs = array($attrs);
}
foreach ($attrs as $attr) {
if (isset($this->attributes[strtolower($attr)])) {
$this->attributes[strtolower($attr)] = false;
}
}
} //end func removeAttribute
/**
* Output HTML and children
*
* @access public
* @param object $overlay = merge data from object.
* @return string
* @abstract
*/
function toHtml($overlay=false)
{
//echo "BEFORE<PRE>";print_R($this);
$ret = $this;
if ($overlay !== false) {
$ret = HTML_Template_Flexy::mergeElement($this,$overlay);
}
if ($ret->override !== false) {
return $ret->override;
}
$prefix = $ret->prefix;
if (is_object($prefix)) {
$prefix = $prefix->toHtml();
}
$suffix = $ret->suffix;
if (is_object($suffix)) {
$suffix = $suffix->toHtml();
}
//echo "AFTER<PRE>";print_R($ret);
$tag = $this->tag;
if (strpos($tag,':') !== false) {
$bits = explode(':',$tag);
$tag = $bits[1];
}
// tags that never should have closers
$close = "</{$ret->tag}>";
if (in_array(strtoupper($tag),array("INPUT","IMG"))) {
$close = '';
}
if (isset($this->attributes['/'])) {
$close = '';
}
$close .= $suffix ;
return "{$prefix}<{$ret->tag}".$ret->attributesToHTML() . '>'.$ret->childrenToHTML() .$close;
} // end func toHtml
/**
* Output Open Tag and any children and not Child tag (designed for use with <form + hidden elements>
*
* @access public
* @param object $overlay = merge data from object.
* @return string
* @abstract
*/
function toHtmlnoClose($overlay=false)
{
$ret = $this;
if ($ret->override !== false) {
return $ret->override;
}
if ($overlay !== false) {
$ret = HTML_Template_Flexy::mergeElement($this,$overlay);
}
return "<{$ret->tag}".$ret->attributesToHTML() . '>' . $ret->childrenToHTML();
} // end func toHtml
/**
* Output HTML and children
*
* @access public
* @return string
* @abstract
*/
function childrenToHtml()
{
$ret = '';
foreach($this->children as $child) {
if (!is_object($child)) {
$ret .= $child;
continue;
}
$ret .= $child->toHtml();
}
return $ret;
} // end func toHtml
} // end class HTML_Template_Flexy_Element

View file

@ -0,0 +1,175 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Xul.php,v 1.6 2005/11/09 08:29:13 alan_k Exp $
/**
* Extension HTML Element builder and render to provide features for Xul
*
* All methods are static, and expect the first argument to be a HTML_Template_Flexy_Element
*
* @author Alan Knowles <alan@akbkhome.com>
*/
class HTML_Template_Flexy_Element_Xul {
/**
* Utility function to set values for common tag types.
* @param HTML_Template_Flexy_Element $element override settings from another element.
* @param mixed $value value to use.
* @access public
*/
function setValue(&$element,$value) {
// store the value in all situations
$element->value = $value;
$tag = $element->tag;
if (strpos($tag,':') !== false) {
$bits = explode(':',$tag);
$tag = $bits[1];
}
switch ($tag) {
case 'menulist':
if (!is_array($value)) {
$value = array($value);
}
// is the first childa menupopup
if (!isset($element->children[0])) {
$element->children[0] = HTML_Template_Flexy_Element('menupopup');
}
if (!is_a($element->children[0],'HTML_Template_Flexy_Element')) {
// oh sh*t big problem!
return HTML_Template_Flexy::raiseError(
__CLASS__ . '::setValue expected a Flexy Element as the child of a menuitem but got something else! '.
print_r($element,true),
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX,
HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// its setting the default value..
// if the children havent been built we dont really care?
// it will be done at the merge stage anyway..
foreach(array_keys($element->children[0]->children) as $i) {
$child = &$element->children[0]->children[$i];
if (is_string($child)) {
continue;
}
// standard option value...
//echo "testing {$child->attributes['value']} against ". print_r($value,true)."\n";
// does the value exist and match..
if (isset($child->attributes['value'])
&& in_array((string) $child->attributes['value'], $value))
{
// echo "MATCH!\n";
$child->attributes['selected'] = 'true';
continue;
}
// otherwise..
$child->attributes['selected'] = 'false';
}
return;
case 'textbox':
$this->attributes['value'] = $value;
return;
case 'checkbox':
if (!isset($this->attributes['value'])) {
return; // should be an error condition really...
}
$this->attributes['checked'] = ($value == $this->attributes['value']) ? 'true' : 'false';
return;
}
}
/**
* Utility function equivilant to HTML_Select - loadArray ** For xul:menulist.
* but using
* key=>value maps
* <option value="key">Value</option>
* Key=key (eg. both the same) maps to
*
*
*
* @param HTML_Element $from override settings from another element.
* @param HTML_Element $noValue ignore the key part of the array
* @access public
*/
function setOptions(&$element, $array,$noValue=false) {
if (!is_array($array)) {
$element->children = array();
return;
}
$tag = '';
$namespace = '';
if (false !== strpos($element->tag, ':')) {
$bits = explode(':',$element->tag);
$namespace = $bits[0] . ':';
$tag = strtolower($bits[1]);
}
if (!isset($element->children[0])) {
$element->children[0] = new HTML_Template_Flexy_Element('menupopup');
}
if (!is_a($element->children[0],'HTML_Template_Flexy_Element')) {
// oh sh*t big problem!
return HTML_Template_Flexy::raiseError(
__CLASS__ . '::setValue expected a menupopup as the child of a menuitem?',
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX,
HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
foreach($array as $k=>$v) {
$atts=array();
if (($k !== $v) && !$noValue) {
$atts = array('value'=>$k);
} else {
$atts = array('value'=>$v);
}
$atts['label'] = htmlspecialchars($v);
$atts['/'] = true;
$add = new HTML_Template_Flexy_Element($namespace . 'menuitem',$atts);
$element->children[0]->children[] = $add;
}
}
} // end class HTML_Template_Flexy_Element

View file

@ -0,0 +1,194 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: nobody <nobody@localhost> |
// +----------------------------------------------------------------------+
//
// $Id: Factory.php,v 1.9 2005/05/14 03:06:00 alan_k Exp $
//
// Factory tools for managing groups of HTML_Elements
//
require_once 'HTML/Template/Flexy/Element.php';
class HTML_Template_Flexy_Factory {
/**
* fromArray - builds a set of elements from a key=>value array (eg. DO->toArray())
* the second parameter is an optional HTML_Element array to merge it into.
*
*
* @param array key(tag name) => value
* @param optional array key(tag name) => HTML_Element
*
* @return array Array of HTML_Elements
* @access public
*/
function fromArray($ar,$ret=array())
{
foreach($ar as $k=>$v) {
if (is_array($v)) {
$ret = HTML_Template_Flexy_Factory::fromArrayPrefixed($k,$v,$ret);
}
if (!isset($ret[$k])) {
$ret[$k] = new HTML_Template_Flexy_Element();
}
$ret[$k]->setValue($v);
}
return $ret;
}
/**
* fromArrayPrefixed - takes a multi dimensional array, and builds the 'xxx[sss][xx]' => value
*
* @param array key(tag name) => value
* @param array key(tag name) => value
* @param optional array key(tag name) => HTML_Element
*
* @return array Array of HTML_Elements
* @access public
*/
function fromArrayPrefixed($prefix, $ar,$ret=array())
{
foreach($ar as $k=>$v) {
if (is_array($v)) {
$ret = HTML_Template_Flexy_Factory::fromArrayPrefixed($prefix.'['.$k.']',$v,$ret);
if (!isset($ret[$prefix.'['.$k.'][]'])) {
$ret[$prefix.'['.$k.'][]'] = new HTML_Template_Flexy_Element();
}
$ret[$prefix.'['.$k.'][]']->setValue($v);
}
if (!isset($ret[$prefix.'['.$k.']'])) {
$ret[$prefix.'['.$k.']'] = new HTML_Template_Flexy_Element();
}
$ret[$prefix.'['.$k.']']->setValue($v);
}
return $ret;
}
/**
* setErrors - sets the suffix of an element to a value..
*
* HTML_Element_Factory::setErrors($elements,array('name','not long enough'));
*
* @depreciated - this is really outside the scope of Factory - it should be
* seperated into a rendering toolkit of some kind.
* @param array of HTML_Element's
* @param array key(tag name) => error
* @param string sprintf error format..
*
* @return array Array of HTML_Elements
* @access public
*/
function &setErrors(&$ret,$set,$format='<span class="error">%s</span>')
{
if (empty($ret) || !is_array($ret)) {
$ret = array();
}
// check what you send this.. !!!
if (!is_array($set)) {
return HTML_Template_Flexy::raiseError(
'invalid arguments "$set" (should be an array) sent to HTML_Template_Flexy_Factory::setErrors',
0, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
foreach($set as $k=>$v) {
if (!$v) {
continue;
}
if (!isset($ret[$k])) {
$ret[$k] = new HTML_Template_Flexy_Element;
}
$ret[$k]->suffix .= sprintf($format,$v);
}
return $ret;
}
/**
* setRequired - sets the prefix of an element to a value..
*
* HTML_Element_Factory::setRequired($elements,array('name',true));
*
* @depreciated - this is really outside the scope of Factory - it should be
* seperated into a rendering toolkit
*
* @param array of HTML_Element's
* @param array key(tag name) => error
* @param string sprintf error format..
*
*
* @return array Array of HTML_Elements
* @access public
*/
function &setRequired(&$ret,$set,$format='<span class="required">*</span>')
{
if (empty($ret) || !is_array($ret)) {
$ret = array();
}
foreach($set as $k=>$v) {
if (!$v) {
continue;
}
if (!isset($ret[$k])) {
$ret[$k] = new HTML_Template_Flexy_Element();
}
$ret[$k]->prefix .= sprintf($format,$v);
}
return $ret;
}
/**
* freeze - freeze's an element. - just copies the value to the override.
* this probably needs more thought.. - it would probably need to merge
* the full tag info with types, to be usefull..
*
* $ar = HTML_Element_Factory::freeze($ar);
*
* @depreciated - this is really outside the scope of Factory - it should be
* seperated into a rendering toolkit
*
*
* @param array (return by referencekey(tag name) => HTML_Element
*
* @return array Array of HTML_Elements
* @access public
*/
function freeze(&$array) {
foreach($array as $k=>$v) {
$array[$k]->override = $array[$k]->value;
}
}
}

View file

@ -0,0 +1,117 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: nobody <nobody@localhost> |
// +----------------------------------------------------------------------+
//
// $Id: Plugin.php,v 1.10 2005/05/14 03:44:26 alan_k Exp $
//
// Plugin API provides support for < ? = $this->plugin(".....",.....); ? >
// or {this.plugin(#xxxxx#,#xxxx#):h}
//
// BASICALLY THIS IS SAVANT'S PLUGIN PROVIDER.
// @author Paul M. Jones <pmjones@ciaweb.net>
class HTML_Template_Flexy_Plugin {
/**
* reference to main engine..
*
* @var object HTML_Template_Flexy
* @access public
*/
var $flexy; // reference to flexy.
var $pluginCache = array(); // store of instanced plugins..
/**
* Call a Plugin method.
*
* Look up in all the plugins to see if the method exists, if it does, call it.
*
*
* @param array name of method, arguments.
*
*
* @return string hopefully
* @access public
*/
function call($args)
{
$method = $args[0];
// attempt to load the plugin on-the-fly
$class = $this->_loadPlugins($method);
if (is_a($class,'PEAR_Error')) {
//echo $class->toString();
return $class->toString();
}
// first argument is always the plugin name; shift the first
// argument off the front of the array and reduce the number of
// array elements.
array_shift($args);
return call_user_func_array(array(&$this->plugins[$class],$method), $args);
}
/**
* Load the plugins, and lookup which one provides the required method
*
*
* @param string Name
*
* @return string|PEAR_Error the class that provides it.
* @access private
*/
function _loadPlugins($name)
{
// name can be:
// ahref = maps to {class_prefix}_ahref::ahref
$this->plugins = array();
if (empty($this->plugins)) {
foreach ($this->flexy->options['plugins'] as $cname=>$file) {
if (!is_int($cname)) {
include_once $file;
$this->plugins[$cname] = new $cname;
$this->plugins[$cname]->flexy = &$this->flexy;
continue;
}
$cname = $file;
require_once 'HTML/Template/Flexy/Plugin/'. $cname . '.php';
$class = "HTML_Template_Flexy_Plugin_{$cname}";
$this->plugins[$class] = new $class;
$this->plugins[$class]->flexy = &$this->flexy;
}
}
foreach ($this->plugins as $class=>$o) {
//echo "checking :". get_class($o). ":: $name\n";
if (method_exists($o,$name)) {
return $class;
}
}
return HTML_Template_Flexy::raiseError("could not find plugin with method: '$name'");
}
}

View file

@ -0,0 +1,756 @@
<?php
/**
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
*/
class HTML_Template_Flexy_Plugin_Savant {
/**
* Output an HTML <a href="">...</a> tag.
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
*
* @access public
*
* @param string $href The URL for the resulting <a href="">...</a> tag.
*
* @param string $text The text surrounded by the <a>...</a> tag set.
*
* @param string $extra Any "extra" HTML code to place within the <a>
* opening tag.
*
* @return string
*/
function ahref($href, $text, $extra = null)
{
$output = '<a href="' . $href . '"';
if (! is_null($extra)) {
$output .= ' ' . $extra;
}
$output .= '>' . $text . '</a>';
return $output;
}
/**
*
* Output a single checkbox <input> element.
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $name The HTML "name=" value for the checkbox.
*
* @param mixed $value The value of the checkbox if checked.
*
* @param mixed $selected Check $value against this; if they match,
* mark the checkbox as checked.
*
* @param string $set_unchecked If null, this will add no HTML to the
* output. However, if set to any non-null value, the value will be
* added as a hidden element before the checkbox so that if the
* checkbox is unchecked, the hidden value will be returned instead
* of the checked value.
*
* @param string $extra Any "extra" HTML code to place within the
* checkbox element.
*
* @return string
*
*/
function checkbox(
$name,
$value,
$selected = null,
$set_unchecked = null,
$extra = null)
{
$html = '';
if (! is_null($set_unchecked)) {
// this sets the unchecked value of the checkbox.
$html .= "<input type=\"hidden\" ";
$html .= "name=\"$name\" ";
$html .= "value=\"$set_unchecked\" />\n";
}
$html .= "<input type=\"checkbox\" ";
$html .= "name=\"$name\" ";
$html .= "value=\"$value\"";
if ($value == $selected) {
$html .= " checked=\"checked\"";
}
$html .= " $extra />";
return $html;
}
/**
*
* Output a set of checkbox <input>s.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $name The HTML "name=" value of all the checkbox
* <input>s. The name will get [] appended to it to make it an array
* when returned to the server.
*
* @param array $options An array of key-value pairs where the key is
* the checkbox value and the value is the checkbox label.
*
* @param string $set_unchecked If null, this will add no HTML to the
* output. However, if set to any non-null value, the value will be
* added as a hidden element before every checkbox so that if the
* checkbox is unchecked, the hidden value will be returned instead
* of the checked value.
*
* @param string $sep The HTML text to place between every checkbox
* in the set.
*
* @param string $extra Any "extra" HTML code to place within the
* checkbox element.
*
* @return string
*
*/
function checkboxes(
$name,
$options,
$selected = array(),
$set_unchecked = null,
$sep = "<br />\n",
$extra = null)
{
// force $selected to be an array. this allows multi-checks to
// have multiple checked boxes.
settype($selected, 'array');
// the text to be returned
$html = '';
if (is_array($options)) {
// an iteration counter. we use this to track which array
// elements are checked and which are unchecked.
$i = 0;
foreach ($options as $value => $label) {
if (! is_null($set_unchecked)) {
// this sets the unchecked value of the checkbox.
$html .= "<input type=\"hidden\" ";
$html .= "name=\"{$name}[$i]\" ";
$html .= "value=\"$set_unchecked\" />\n";
}
$html .= "<input type=\"checkbox\" ";
$html .= "name=\"{$name}[$i]\" ";
$html .= "value=\"$value\"";
if (in_array($value, $selected)) {
$html .= " checked=\"checked\"";
}
if (! is_null($extra)) {
$html .= " $extra";
}
$html .= " />$label$sep";
$i++;
}
}
return $html;
}
/**
*
* Cycle through a series of values based on an iteration number,
* with optional group repetition.
*
* For example, if you have three values in a cycle (a, b, c) the iteration
* returns look like this:
*
* 0 => a
* 1 => b
* 2 => c
* 3 => a
* 4 => b
* 5 => c
*
* If you repeat each cycle value (a,b,c) 2 times on the iterations,
* the returns look like this:
*
* 0 => a
* 1 => a
* 2 => b
* 3 => b
* 4 => c
* 5 => c
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param int $iteration The iteration number for the cycle.
*
* @param array $values The values to cycle through.
*
* @param int $repeat The number of times to repeat a cycle value.
*
* @return string
*
*/
function cycle($iteration, $values = null, $repeat = 1)
{
settype($values, 'array');
// prevent divide-by-zero errors
if ($repeat == 0) {
$repeat = 1;
}
return $values[($iteration / $repeat) % count($values)];
}
/**
*
* Output a formatted date using strftime() conventions.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $datestring Any date-time string suitable for
* strtotime().
*
* @param string $format The strftime() formatting string.
*
* @return string
*
*/
function dateformat($datestring, $format = false)
{
if ($format === false) {
$format = isset($this->flexy->options['plugin.dateformat']) ?
$this->flexy->options['plugin.dateformat'] : '%d %b %Y';
}
if (trim($datestring) == '') {
return '';
}
$date = strtotime($datestring);
if ($date > 1) {
return strftime($format, $date);
}
require_once 'Date.php';
$date = new Date($date);
return $date->format($format);
}
/**
*
* Output a formatted number using number_format
*
*
*
* @param string $datestring Any date-time string suitable for
* strtotime().
*
* @param string $format The strftime() formatting string.
*
* @return string
*
*/
function numberformat($number, $dec=false,$point=false,$thousands=false)
{
if (!strlen(trim($number))) {
return;
}
// numberformat int decimals, string dec_point, string thousands_sep
$dec = ($dec !== false) ? $dec : (
isset($this->flexy->options['plugin.numberformat.decimals']) ?
$this->flexy->options['plugin.numberformat.decimals'] : 2
);
$point = ($point !== false) ? $point : (
isset($this->flexy->options['plugin.numberformat.point']) ?
$this->flexy->options['plugin.numberformat.point'] : '.');
$thousands = ($thousands !== false) ? $thousands : (
isset($this->flexy->options['plugin.numberformat.thousands']) ?
$this->flexy->options['plugin.numberformat.thousands'] : ',');
return number_format($number,$dec,$point,$thousands);
}
/**
*
* Output an <image ... /> tag.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $src The image source as a relative or absolute HREF.
*
* @param string $link Providing a link will make the image clickable,
* leading to the URL indicated by $link; defaults to null.
*
* @param string $alt Alternative descriptive text for the image;
* defaults to the filename of the image.
*
* @param int $border The border width for the image; defaults to zero.
*
* @param int $width The displayed image width in pixels; defaults to
* the width of the image.
*
* @param int $height The displayed image height in pixels; defaults to
* the height of the image.
*
*/
function image(
$src,
$alt = null,
$border = 0,
$width = null,
$height = null)
{
$size = '';
// build the alt tag
if (is_null($alt)) {
$alt = basename($src);
}
$alt = ' alt="' . htmlentities($alt) . '"';
// build the border tag
$border = ' border="' . htmlentities($border) . '"';
// get the width and height of the image
if (is_null($width) && is_null($height)) {
if (substr(strtolower($src), 0, 7) == 'http://' ||
substr(strtolower($src), 0, 8) == 'https://') {
// the image is not on the local filesystem
$root = '';
} else {
// we need to set a base root path so we can find images on the
// local file system
$root = isset($GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT'])
? $GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT'] . '/'
: '';
}
$info = @getimagesize($root . $src);
$width = (is_null($width)) ? $info[0] : $width;
$height = (is_null($height)) ? $info[1] : $height;
unset($info);
}
// build the width tag
if ($width > 0) {
$size .= ' width="' . htmlentities($width) . '"';
}
// build the height tag
if ($height > 0) {
$size .= ' height="' . htmlentities($height) . '"';
}
// done!
return '<img src="' . $src . '"' .
$alt .
$border .
$size .
' />';
}
/**
*
* Output a single <input> element.
*
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $type The HTML "type=" value (e.g., 'text',
* 'hidden', 'password').
*
* @param string $name The HTML "name=" value.
*
* @param mixed $value The initial value of the input element.
*
* @param string $extra Any "extra" HTML code to place within the
* checkbox element.
*
* @return string
*
*/
function input($type, $name, $value = '', $extra = '')
{
$output = "<input type=\"$type\" name=\"$name\" ";
$output .= "value=\"$value\" $extra />";
return $output;
}
/**
*
* Output a <script></script> link to a JavaScript file.
*
*
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $href The HREF leading to the JavaScript source
* file.
*
* @return string
*
*/
function javascript($href)
{
return '<script language="javascript" type="text/javascript" src="' .
$href . '"></script>';
}
/**
*
* Output a value using echo after processing with optional modifier
* functions.
*
* Allows you to pass a space-separated list of value-manipulation
* functions so that the value is "massaged" before output. For
* example, if you want to strip slashes, force to lower case, and
* convert to HTML entities (as for an input text box), you might do
* this:
*
* $this->modify($value, 'stripslashes strtolower htmlentities');
*
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $value The value to be printed.
*
* @param string $functions A space-separated list of
* single-parameter functions to be applied to the $value before
* printing.
*
* @return string
*
*/
function modify($value, $functions = null)
{
// is there a space-delimited function list?
if (is_string($functions)) {
// yes. split into an array of the
// functions to be called.
$list = explode(' ', $functions);
// loop through the function list and
// apply to the output in sequence.
foreach ($list as $func) {
if (!function_exists($func)) {
continue;
}
// extend this..
if (!in_array($func, array('htmlspecialchars','nl2br','urlencode'))) {
continue;
}
$value = $func($value);
}
}
return $value;
}
/**
*
* Output a series of HTML <option>s based on an associative array
* where the key is the option value and the value is the option
* label. You can pass a "selected" value as well to tell the
* function which option value(s) should be marked as seleted.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param array $options An associative array of key-value pairs; the
* key is the option value, the value is the option lable.
*
* @param mixed $selected A string or array that matches one or more
* option values, to tell the function what options should be marked
* as selected. Defaults to an empty array.
*
* @return string
*
*/
function options( $options, $selected = array(), $extra = null)
{
$html = '';
// force $selected to be an array. this allows multi-selects to
// have multiple selected options.
settype($selected, 'array');
// is $options an array?
if (is_array($options)) {
// loop through the options array
foreach ($options as $value => $label) {
$html .= '<option value="' . $value . '"';
$html .= ' label="' . $label . '"';
if (in_array($value, $selected)) {
$html .= ' selected="selected"';
}
if (! is_null($extra)) {
$html .= ' ' . $extra;
}
$html .= ">$label</option>\n";
}
}
return $html;
}
/**
*
* Output a set of radio <input>s with the same name.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $name The HTML "name=" value of all the radio <input>s.
*
* @param array $options An array of key-value pairs where the key is the
* radio button value and the value is the radio button label.
*
* $options = array (
* 0 => 'zero',
* 1 => 'one',
* 2 => 'two'
* );
*
* @param string $checked A comparison string; if any of the $option
* element values and $checked are the same, that radio button will
* be marked as "checked" (otherwise not).
*
* @param string $extra Any "extra" HTML code to place within the
* <input /> element.
*
* @param string $sep The HTML text to place between every radio
* button in the set.
*
* @return string
*
*/
function radios(
$name,
$options,
$checked = null,
$set_unchecked = null,
$sep = "<br />\n",
$extra = null)
{
$html = '';
if (is_array($options)) {
if (! is_null($set_unchecked)) {
// this sets the unchecked value of the
// radio button set.
$html .= "<input type=\"hidden\" ";
$html .= "name=\"$name\" ";
$html .= "value=\"$set_unchecked\" />\n";
}
foreach ($options as $value => $label) {
$html .= "<input type=\"radio\" ";
$html .= "name=\"$name\" ";
$html .= "value=\"$value\"";
if ($value == $checked) {
$html .= " checked=\"checked\"";
}
$html .= " $extra />$label$sep";
}
}
return $html;
}
/**
*
* Output a <link ... /> to a CSS stylesheet.
*
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $href The HREF leading to the stylesheet file.
*
* @return string
*
*/
function stylesheet($href)
{
return '<link rel="stylesheet" type="text/css" href="' .
$href . '" />';
}
/**
*
* Output a single <textarea> element.
*
* @license http://www.gnu.org/copyleft/lesser.html LGPL
*
* @author Paul M. Jones <pmjones@ciaweb.net>
*
* @package Savant
*
* @version $Id: Savant.php,v 1.7 2005/05/14 03:39:11 alan_k Exp $
*
* @access public
*
* @param string $name The HTML "name=" value.
*
* @param string $text The initial value of the textarea element.
*
* @param int $tall How many rows tall should the area be?
*
* @param mixed $wide The many columns wide should the area be?
*
* @param string $extra Any "extra" HTML code to place within the
* checkbox element.
*
* @return string
*
*/
function textarea($name, $text, $tall = 24, $wide = 80, $extra = '')
{
$output = "<textarea name=\"$name\" rows=\"$tall\" ";
$output .= "cols=\"$wide\" $extra>$text</textarea>";
return $output;
}
}

View file

@ -0,0 +1,179 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: SmartyAPI.php,v 1.2 2004/04/03 12:08:57 alan_k Exp $
//
// Description this class emulates the Smarty API to attempt to enable
// upgrading to flexy. (eg. for use with flexy templates (that have been
// converted using the SmartyConverter Compiler.
//
// I've no idea how complete this will end up being..
//
// Technically Smarty is LGPL - so theortically no code in here should
// use the copy & paste the original smarty code....
//
// to use as a full emulator :
// try
// class Smarty extends HTML_Template_Flexy_SmartyAPI {
// function Smarty() { parent::construct(); }
// }
// not implemented:
/*
append_by_ref
append
register_function / unregister_function
register_object / register_object
register_block / unregister_block
register_compiler_function / unregister_compiler_function
register_modifier / unregister_modifier
register_resource / unregister_resource
register_prefilter / unregister_prefilter
register_postfilter / unregister_postfilter
register_outputfilter / unregister_outputfilter
load_filter
clear_cache
clear_all_cache
is_cached
template_exists
get_template_vars
get_config_vars
trigger_error
fetch
get_registered_object
config_load
clear_config
_* (all the privates)
*/
/**
* Smarty API emulator for Flexy
* - designed to make transitions simpler
* - provides only basic support for variables
* - uses flexy templates (that have been converted previosly with the converor)
*
* @version $Id: SmartyAPI.php,v 1.2 2004/04/03 12:08:57 alan_k Exp $
*/
class HTML_Template_Flexy_SmartyAPI {
/**
* where the data for the template gets stored.
*
* @var array
* @access public
*/
var $vars = array();
/**
* Standard Variable assignment
*
* @param string|array element name to assign value or assoc. array
* @param mixed value of element.
*
* @return none
* @access public
*/
function assign($k,$v)
{
if (is_array($k)) {
$this->vars = $k + $this->vars;
return;
}
$this->vars[$k] = $v;
}
/**
* Standard Variable assignment (by reference)
*
* @param string element name to assign value
* @param mixed value of element.
*
* @return none
* @access public
*/
function assign_by_ref($k, &$v)
{
$this->vars[$k] = &$v;
}
/**
* Unset a variable assignment
*
* @param string element name to remove
*
* @return none
* @access public
*/
function clear_assign($k)
{
if (is_array($k)) {
foreach ($k as $kk) {
$this->clear_assign($kk);
}
return;
}
if (isset($this->vars[$k])) {
unset($this->vars[$k]);
}
}
/**
* Unset all variables
*
* @return none
* @access public
*/
function clear_all_assign()
{
$this->vars = array();
}
/**
* output a template (optionally with flexy object & element.)
*
* @param string name of flexy template.
* @param object object as per HTML_Template_Flexy:outputObject
* @param array elements array as per HTML_Template_Flexy:outputObject
*
* @return none
* @access public
*/
function display($templatename,$object=null,$elements=array())
{
// some standard stuff available to a smarty template..
$this->vars['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME'];
$o = PEAR::getStaticProperty('HTML_Template_Flexy','options');
require_once 'HTML/Template/Flexy.php';
$t = new HTML_Template_Flexy;
$t->compile($templatename);
$object = ($object !== null) ? $object : new StdClass;
foreach($this->vars as $k=>$v) {
$object->$k = $v;
}
$t->outputObject($object,$elements);
}
}

View file

@ -0,0 +1,116 @@
#!/usr/bin/php
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: nobody <nobody@localhost> |
// +----------------------------------------------------------------------+
//
// $Id: Test.php,v 1.11 2003/10/10 09:27:32 alan_k Exp $
//
// This is a temporary file - it includes some of the
// Code that will have to go in the Engine eventually..
// Used to test parsing and generation.
//
//ini_set('include_path', ini_get('include_path').realpath(dirname(__FILE__) . '/../../..'));
require_once 'Gtk/VarDump.php';
require_once 'Console/Getopt.php';
require_once 'HTML/Template/Flexy.php';
require_once 'HTML/Template/Flexy/Compiler.php';
// this is the main runable...
class HTML_Template_Flexy_Test {
function HTML_Template_Flexy_Test () {
// for testing!
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions'] = array(
'compileDir' => dirname(__FILE__),
'locale' => 'en',
);
$this->parseArgs();
$this->parse();
}
function parseArgs() {
// mapp of keys to values..
$args = Console_Getopt::ReadPHPArgV();
$vals = Console_Getopt::getopt($args,'');
//print_r($vals);
$files = $vals[1];
if (!$files) {
$this->error(0,"No Files supplied");
}
foreach($files as $file) {
$realpath = realpath($file);
if (!$realpath) {
$this->error(0,"File $path Does not exist");
}
$this->files[] = $realpath;
}
}
var $files; // array of files to compile
var $quickform;
function parse() {
foreach($this->files as $file) {
$flexy = new HTML_Template_Flexy(array(
'compileToString'=>true,
'valid_functions' => 'include'
));
$compiler = HTML_Template_Flexy_Compiler::factory($flexy->options);
$result = $compiler->compile($flexy,file_get_contents($file));
echo $result;
print_r(array_unique($GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['gettextStrings']));
print_r($flexy->elements);
}
}
function error($id,$msg) {
echo "ERROR $id : $msg\n";
exit(255);
}
function debug($id,$msg) {
echo "Debug Message ($id) : $msg\n";
}
}
new HTML_Template_Flexy_Test;
?>

View file

@ -0,0 +1,610 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Token.php,v 1.51 2005/05/14 03:44:26 alan_k Exp $
//
// This is the master Token file for The New Token driver Engine.
// All the Token output, and building routines are in here.
//
// Note overriden methods are not documented unless they differ majorly from
// The parent.
//
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['base'] = 0;
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['state'] = 0;
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['statevars'] = array();
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['activeForm'] = '';
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['tokens'] = array();
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['gettextStrings'] = array();
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['activeFormId'] = 0;
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN']['flexyIgnore'] = false;
/**
* Base Class for all Tokens.
*
* @abstract Provides the static Create Method, and default toString() methods
*
*/
class HTML_Template_Flexy_Token {
/**
* the token type (Depreciated when we have classes for all tokens
*
* @var string
* @access public
*/
var $token;
/**
* the default value (normally a string)
*
* @var string
* @access public
*/
var $value;
/**
* the line the token is from
*
* @var int
* @access public
*/
var $line;
/**
* the character Position
*
* @var int
* @access public
*/
var $charPos;
/**
* factory a Token
*
* Standard factory method.. - with object vars.
* ?? rename me to factory?
* @param string Token type
* @param mixed Initialization settings for token
* @param int line that the token is defined.
*
*
* @return object Created Object
* @access public
*/
function factory($token,$value,$line,$charPos=0) {
// try not to reload the same class to often
static $loaded = array();
$c = 'HTML_Template_Flexy_Token_'.$token;
if (!class_exists($c) && !isset($loaded[$token])) {
// make sure parse errors are picked up - no @ here..
if (file_exists(dirname(__FILE__)."/Token/{$token}.php")) {
require_once 'HTML/Template/Flexy/Token/'.$token.'.php';
}
$loaded[$token] = true;
}
$t = new HTML_Template_Flexy_Token;
if (class_exists($c)) {
$t = new $c;
}
$t->token = $token;
$t->charPos = $charPos;
if ($t->setValue($value) === false) {
// kick back error conditions..
return false;
}
$t->line = $line;
return $t;
}
/**
* Standard Value iterpretor
*
* @param mixed value recieved from factory method
* @return none
* @access public
*/
function setValue($value) {
$this->value = $value;
}
/**
* compile to String (vistor method) replaces toString
*
* @return string HTML
* @access public
*/
function compile(&$compiler) {
return $compiler->toString($this);
}
/**
* compile children (visitor approach).
*
* @return string HTML
* @access public
*/
function compileChildren( &$compiler) {
if (!$this->children) {
return '';
}
if ($this->ignoreChildren) {
return;
}
$ret = '';
//echo "output $this->id";
//new Gtk_VarDump($this);
foreach ($this->children as $child) {
if (!$child) {
continue;
}
$add = $child->compile($compiler);
if (is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
return $ret;
}
/* ======================================================= */
/* Token Managmenet = parse and store all the tokens in
* an associative array and tree.
*/
/**
* Run a Tokenizer and Store its results
* It should build a DOM Tree of the HTML
*
* @param object Tokenizer to run.. - Theoretically other Tokenizers could be done for email,rtf etc.
*
* @access public
* @return base token (really a dummy token, which contains the tree)
* @static
*/
function buildTokens($tokenizer)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
// first record is a filler - to stick all the children on !
// reset my globals..
$_HTML_TEMPLATE_FLEXY_TOKEN['base'] = 0;
$_HTML_TEMPLATE_FLEXY_TOKEN['statevars'] = array();
$_HTML_TEMPLATE_FLEXY_TOKEN['state'] = 0;
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = false;
if (@$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['flexyIgnore']) {
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = true;
}
$_HTML_TEMPLATE_FLEXY_TOKEN['activeFormId'] = 0;
$_HTML_TEMPLATE_FLEXY_TOKEN['activeForm'] = '';
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'] = array(new HTML_Template_Flexy_Token);
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]->id =0;
$_HTML_TEMPLATE_FLEXY_TOKEN['gettextStrings'] = array();
$i=1;
// initialize state - this trys to make sure that
// you dont do to many elses etc.
//echo "RUNNING TOKENIZER";
// step one just tokenize it.
while ($t = $tokenizer->yylex()) {
if ($t == HTML_TEMPLATE_FLEXY_TOKEN_ERROR) {
//echo "ERROR";
//print_r($tokenizer);
$err = "<PRE>" . $tokenizer->error . "\n" .
htmlspecialchars(substr($tokenizer->yy_buffer,0,$tokenizer->yy_buffer_end)) .
"<font color='red'>". htmlspecialchars(substr($tokenizer->yy_buffer,$tokenizer->yy_buffer_end,100)) .
".......</font></PRE>";
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::Syntax error in ".
"Template line:'. $tokenizer->yyline .
$err
, HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
if ($t == HTML_TEMPLATE_FLEXY_TOKEN_NONE) {
continue;
}
if ( $tokenizer->value->token == 'Php' ) {
if (!$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['allowPHP']) {
return HTML_Template_Flexy::raiseError('PHP code found in script (Token)',
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX,HTML_TEMPLATE_FLEXY_ERROR_RETURN
);
}
if ($GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['allowPHP'] === 'delete') {
continue;
}
}
$i++;
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i] = $tokenizer->value;
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->id = $i;
// this whole children thing needs rethinking
// - I think the body of the page should be wrapped: ..
// ?php if (!$this->bodyOnly) { .. <HTML> .... <BODY....> ?php } ?
//
// old values alias to new ones..
if (isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXYSTART'])) {
unset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXYSTART']);
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXY:START'] = true;
}
if (isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXYSTARTCHILDREN'])) {
unset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXYSTARTCHILDREN']);
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXY:STARTCHILDREN'] = true;
}
if (isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXY:START'])) {
$_HTML_TEMPLATE_FLEXY_TOKEN['base'] = $i;
unset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXY:START']);
}
if (isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->ucAttributes['FLEXY:STARTCHILDREN'])) {
$_HTML_TEMPLATE_FLEXY_TOKEN['base'] = $i;
}
//print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
}
//echo "BUILT TOKENS";
$res = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'];
// DEBUG DUMPTING : foreach($res as $k) { $k->dump(); }
$stack = array();
$total = $i +1;
// merge strings and entities - blanking out empty text.
for($i=1;$i<$total;$i++) {
if (!isset($res[$i]) || !is_a($res[$i],'HTML_Template_Flexy_Token_Text')) {
continue;
}
$first = $i;
$i++;
while ($i<$total && is_a($res[$i],'HTML_Template_Flexy_Token_Text')) {
if (isset($res[$i])) {
$res[$first]->value .= $res[$i]->value;
$res[$i]->value = '';
}
$i++;
}
}
// connect open and close tags.
// this is done by having a stack for each of the tag types..
// then removing it when it finds the closing one
// eg.
// <a href=""><img src=""></a>
// ends up with a stack for <a>'s and a stack for <img>'s
//
//
//
//echo '<PRE>' . htmlspecialchars(print_R($res,true));//exit;
//echo '<PRE>';
for($i=1;$i<$total;$i++) {
if (empty($res[$i]->tag)) {
continue;
}
//echo "Checking TAG $i {$res[$i]->tag}\n";
if ($res[$i]->tag{0} == '/') { // it's a close tag..
//echo "GOT END TAG: {$res[$i]->tag}\n";
$tag = strtoupper(substr($res[$i]->tag,1));
if (!count($stack)) {
continue;
}
$ssc = count($stack) - 1;
/* go up the stack trying to find a match */
for($s = $ssc; $s > -1; $s--) {
if (!isset($stack[$s])) {
echo "MISSED STACK? $s<BR><PRE>";print_r($stack);exit;
}
if (!isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$stack[$s]])) {
echo "STACKED BAD OFFSET : {$stack[$s]}<BR><PRE>";print_r($stack);exit;
}
$tok = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$stack[$s]];
if (strtoupper($tok->tag) == $tag) {
// got the matching closer..
// echo "MATCH: {$i}:{$tok->tag}({$tok->line}) to {$stack[$s]}:$tag<BR>";
$tok->close = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i];
array_splice($stack,$s);
//print_R($stack);
break;
}
}
continue;
}
$stack[] = $i;
// tag with no closer (or unmatched in stack..)
}
// create a dummy close for the end
$i = $total;
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i] = new HTML_Template_Flexy_Token;
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->id = $total;
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]->close = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$total];
// now is it possible to connect children...
// now we need to GLOBALIZE!! -
$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'] = $res;
HTML_Template_Flexy_Token::buildChildren(0);
//new Gtk_VarDump($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]);
//echo '<PRE>';print_R($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$_HTML_TEMPLATE_FLEXY_TOKEN['base']] );
return $_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$_HTML_TEMPLATE_FLEXY_TOKEN['base']];
}
/**
* Matching closing tag for a Token
*
* @var object|none optional closing tag
* @access public
*/
var $close;
/**
* array of children to each object.
*
* @var array
* @access public|private
*/
var $children = array();
/**
* Build the child array for each element.
* RECURSIVE FUNCTION!!!!
* @param int id of node to add children to.
*
* @access public
* @static
*/
function buildChildren($id)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$base = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$id];
$base->children = array();
$start = $base->id +1;
$end = $base->close->id;
for ($i=$start; $i<$end; $i++) {
//echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
//if ($base->id == 1176) {
// echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
// }
$base->children[] = &$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i];
if (isset($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]) &&
is_object($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->close)) {
// if the close id is greater than my id - ignore it! -
if ($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->close->id > $end) {
continue;
}
HTML_Template_Flexy_Token::buildChildren($i);
$i = $_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->close->id;
}
}
}
/**
* Flag to ignore children - Used to block output for select/text area etc.
* may not be required as I moved the Tag parsing into the toString ph
*
* @var boolean ingore children
* @access public
*/
var $ignoreChildren = false;
/* ======================================================== */
/* variable STATE management
*
* raw variables are assumed to be $this->, unless defined by foreach..
* it also monitors syntax - eg. end without an if/foreach etc.
*/
/**
* tell the generator you are entering a block
*
* @access public
*/
function pushState()
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$_HTML_TEMPLATE_FLEXY_TOKEN['state']++;
$s = $_HTML_TEMPLATE_FLEXY_TOKEN['state'];
$_HTML_TEMPLATE_FLEXY_TOKEN['statevars'][$s] = array(); // initialize statevars
}
/**
* tell the generator you are entering a block
*
* @return boolean parse error - out of bounds
* @access public
*/
function pullState()
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$s = $_HTML_TEMPLATE_FLEXY_TOKEN['state'];
$_HTML_TEMPLATE_FLEXY_TOKEN['statevars'][$s] = array(); // initialize statevars
$_HTML_TEMPLATE_FLEXY_TOKEN['state']--;
if ($s<0) {
return false;
}
return true;
}
/**
* get the real variable name formated x.y.z => $this->x->y->z
* if a variable is in the stack it return $x->y->z
*
* @return string PHP variable
* @access public
*/
function toVar($s) {
// wrap [] with quotes.
$s = str_replace('[',"['",$s);
$s = str_replace('%5b',"['",$s);
$s = str_replace('%5B',"['",$s);
$s = str_replace(']',"']",$s);
$s = str_replace('%5d',"']",$s);
$s = str_replace('%5D',"']",$s);
// strip the quotes if it's only numbers..
$s = preg_replace("/'([-]?[0-9]+)'/", "\\1",$s);
$parts = explode(".",$s);
$ret = $this->findVar($parts[0]);
if (is_a($ret,'PEAR_Error')) {
return $ret;
}
array_shift($parts);
if (!count($parts)) {
return $ret;
}
foreach($parts as $p) {
$ret .= "->{$p}";
}
return $ret;
}
/**
* do the stack lookup on the variable
* this relates to flexy
* t relates to the object being parsed.
*
* @return string PHP variable
* @access public
*/
function findVar($string)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
if (!$string || $string == 't') {
return '$t';
}
if ($string == 'this') {
return '$this';
}
// accept global access on some string
if (@$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['globals'] &&
preg_match('/^(_POST|_GET|_REQUEST|_SESSION|_COOKIE|GLOBALS)\[/',$string)) {
return '$'.$string;
}
if (!@$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['privates'] &&
($string{0} == '_')) {
return HTML_Template_Flexy::raiseError('HTML_Template_Flexy::Attempt to access private variable:'.
" on line {$this->line} of {$GLOBALS['_HTML_TEMPLATE_FLEXY']['filename']}".
", Use options[privates] to allow this."
, HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_RETURN);
}
$lookup = $string;
if ($p = strpos($string,'[')) {
$lookup = substr($string,0,$p);
}
for ($s = $_HTML_TEMPLATE_FLEXY_TOKEN['state']; $s > 0; $s--) {
if (in_array($lookup , $_HTML_TEMPLATE_FLEXY_TOKEN['statevars'][$s])) {
return '$'.$string;
}
}
return '$t->'.$string;
}
/**
* add a variable to the stack.
*
* @param string PHP variable
* @access public
*/
function pushVar($string)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$s = $_HTML_TEMPLATE_FLEXY_TOKEN['state'];
$_HTML_TEMPLATE_FLEXY_TOKEN['statevars'][$s][] = $string;
}
/**
* dump to text ATM
*
*
* @access public
*/
function dump() {
echo "{$this->token}/" . (isset($this->tag) ? "<{$this->tag}>" : '') . ": {$this->value}\n";
}
}

View file

@ -0,0 +1,35 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Else.php,v 1.3 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle Else
*
*
*/
class HTML_Template_Flexy_Token_Else extends HTML_Template_Flexy_Token {
}

View file

@ -0,0 +1,33 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: End.php,v 1.3 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle End statements (eg. close brakets)
*
*
*/
class HTML_Template_Flexy_Token_End extends HTML_Template_Flexy_Token {
}

View file

@ -0,0 +1,35 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: EndTag.php,v 1.2 2003/12/10 02:36:26 alan_k Exp $
//
/**
* The closing HTML Tag = eg. /Table or /Body etc.
*
* @abstract
* This just extends the generic HTML tag
*
*/
require_once 'HTML/Template/Flexy/Token/Tag.php';
class HTML_Template_Flexy_Token_EndTag extends HTML_Template_Flexy_Token_Tag { }

View file

@ -0,0 +1,72 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Foreach.php,v 1.3 2004/04/03 03:44:58 alan_k Exp $
//
/**
* Class to handle foreach statements
*
*
*/
class HTML_Template_Flexy_Token_Foreach extends HTML_Template_Flexy_Token {
/**
* variable to loop on.
*
* @var string
* @access public
*/
var $loopOn = '';
/**
* key value
*
* @var string
* @access public
*/
var $key = '';
/**
* optional value (in key=>value pair)
*
* @var string
* @access public
*/
var $value = '';
/**
* Setvalue - a array of all three (last one optional)
* @see parent::setValue()
*/
function setValue($value) {
$this->loopOn=$value[0];
if (!isset($value[1]) || !strlen(trim($value[1]))) {
// error condition.
return false;
}
$this->key=$value[1];
$this->value=@$value[2];
}
}

View file

@ -0,0 +1,62 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: If.php,v 1.5 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle If statements
*
*
*/
class HTML_Template_Flexy_Token_If extends HTML_Template_Flexy_Token{
/**
* Condition for the if statement.
* @var string // a variable
* @access public
*/
var $condition;
/**
* if the statement is negative = eg. !somevar..
* @var string
* @access public
*/
var $isNegative = '';
/**
* Setvalue - a string
* @see parent::setValue()
*/
function setValue($value) {
//var_dump($value);
if (strlen($value) && $value{0} == '!') {
$this->isNegative = '!';
$value = substr($value,1);
}
$this->condition=$value;
}
}

View file

@ -0,0 +1,95 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Method.php,v 1.14 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle method calls
* *
*
*/
class HTML_Template_Flexy_Token_Method extends HTML_Template_Flexy_Token {
/**
* variable modifier (h = raw, u = urlencode, none = htmlspecialchars)
* TODO
* @var char
* @access public
*/
var $modifier;
/**
* Method name
*
* @var char
* @access public
*/
var $method;
/**
* is it in if statement with a method?
*
* @var boolean
* @access public
*/
var $isConditional;
/**
* if the statement is negative = eg. !somevar..
* @var string
* @access public
*/
var $isNegative = '';
/**
* arguments, either variables or literals eg. #xxxxx yyyy#
*
* @var array
* @access public
*/
var $args= array();
/**
* setvalue - at present array method, args (need to add modifier)
* @see parent::setValue()
*/
function setValue($value) {
// var_dump($value);
$method = $value[0];
if (substr($value[0],0,3) == 'if:') {
$this->isConditional = true;
if ($value[0]{3} == '!') {
$this->isNegative = '!';
$method = substr($value[0],4);
} else {
$method = substr($value[0],3);
}
}
if (strpos($method,":")) {
list($method,$this->modifier) = explode(':',$method);
}
$this->method = $method;
$this->args = $value[1];
// modifier TODO!
}
}

View file

@ -0,0 +1,34 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Processing.php,v 1.3 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle Processing Directives = <?xml or <?php
*
*
*/
class HTML_Template_Flexy_Token_Processing extends HTML_Template_Flexy_Token {
}

View file

@ -0,0 +1,212 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Tag.php,v 1.49 2004/08/16 09:12:23 alan_k Exp $
$GLOBALS['_HTML_TEMPLATE_FLEXY_TOKEN_TAG']['activeSelect'] = false;
require_once 'HTML/Template/Flexy/Element.php';
/**
* A standard HTML Tag = eg. Table/Body etc.
*
* @abstract
* This is the generic HTML tag
* a simple one will have some attributes and a name.
*
*/
class HTML_Template_Flexy_Token_Tag extends HTML_Template_Flexy_Token {
/**
* HTML Tag: eg. Body or /Body - uppercase
*
* @var string
* @access public
*/
var $tag = '';
/**
* HTML Tag: (original case)
*
* @var string
* @access public
*/
var $oTag = '';
/**
* Associative array of attributes. (original case)
*
* key is the left, value is the right..
* note:
* values are raw (eg. include "")
* valuse can be
* text = standard
* array (a parsed value with flexy tags in)
* object (normally some PHP code that generates the key as well..)
*
*
* @var array
* @access public
*/
var $attributes = array();
/**
* Associative array of attributes ucase to Original Case for attributes..
*
* @var array
* @access public
*/
var $ucAttributes = array();
/**
* postfix tokens
* used to add code to end of tags "<xxxx>here....children .. <close tag>"
*
* @var array
* @access public
*/
var $postfix = '';
/**
* prefix tokens
* used to add code to beginning of tags TODO "here<xxxx>....children .. <close tag>"
*
* @var array
* @access public
*/
var $prefix = '';
/**
* Alias to closing tag (built externally).
* used to add < ? } ? > code to dynamic tags.
* @var object alias
* @access public
*/
var $close; // alias to closing tag.
/**
* Setvalue - gets name, attribute as an array
* @see parent::setValue()
*/
function setValue($value)
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$this->tag = strtoupper($value[0]);
$this->oTag = $value[0];
if (isset($value[1])) {
$this->attributes = $value[1];
}
foreach(array_keys($this->attributes) as $k) {
$this->ucAttributes[strtoupper($k)] =& $this->attributes[$k];
}
}
/**
* getAttribute = reads an attribute value and strips the quotes
*
* TODO
* does not handle values with flexytags in them
*
* @return string (
* @access public
*/
function getAttribute($key) {
// all attribute keys are stored Upper Case,
// however just to make sure we have not done a typo :)
$key = strtoupper($key);
//echo "looking for $key\n";
//var_dump($this->attributes);
// this is weird case isset() returns false on this being null!
if (@$this->ucAttributes[$key] === true) {
return true;
}
if (!isset($this->ucAttributes[$key])) {
return false;
}
// general assumption - none of the tools can do much with dynamic
// attributes - eg. stuff with flexy tags in it.
if (!is_string($this->ucAttributes[$key])) {
return false;
}
$v = $this->ucAttributes[$key];
// unlikely :)
if ($v=='') {
return $v;
}
switch($v{0}) {
case "\"":
case "'":
return substr($v,1,-1);
default:
return $v;
}
}
/**
* getAttributes = returns all the attributes key/value without quotes
*
*
* @return array
* @access string
*/
function getAttributes() {
$ret = array();
foreach($this->attributes as $k=>$v) {
if (substr(strtoupper($k),0,6) == 'FLEXY:') {
continue;
}
$ret[$k] = $this->getAttribute($k);
}
return $ret;
}
/**
* clearAttributes = removes an attribute from the object.
*
*
* @return array
* @access string
*/
function clearAttribute($string) {
if (isset($this->attributes[$string])) {
unset($this->attributes[$string]);
}
}
}

View file

@ -0,0 +1,54 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Text.php,v 1.12 2004/12/22 02:22:03 alan_k Exp $
//
/**
* Class that represents a text string node.
*
*
*/
class HTML_Template_Flexy_Token_Text extends HTML_Template_Flexy_Token {
/**
* Simple check to see if this piece of text is a word
* so that gettext and the merging tricks dont try
* - merge white space with a flexy tag
* - gettext doesnt translate &nbsp; etc.
*
* @return boolean true if this is a word
* @access public
*/
function isWord() {
if (!strlen(trim($this->value))) {
return false;
}
if (preg_match('/^\&[a-z0-9]+;$/i',trim($this->value))) {
return false;
}
return preg_match('/[a-z]/i',$this->value);
}
}

View file

@ -0,0 +1,53 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome> |
// +----------------------------------------------------------------------+
//
// $Id: Var.php,v 1.7 2003/12/10 02:36:26 alan_k Exp $
//
/**
* Class to handle variable output
* *
*
*/
class HTML_Template_Flexy_Token_Var extends HTML_Template_Flexy_Token {
/**
* variable modifier (h = raw, u = urlencode, none = htmlspecialchars)
*
* @var char
* @access public
*/
var $modifier;
/**
* Setvalue - at present raw text.. - needs sorting out..
* @see parent::setValue()
*/
function setValue($value) {
// comes in as raw {xxxx}, {xxxx:h} or {xxx.yyyy:h}
if (strpos($value,":")) {
list($value,$this->modifier) = explode(':',$value);
}
$this->value = $value;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,472 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: nobody <nobody@localhost> |
// +----------------------------------------------------------------------+
//
// $Id: Translator.php,v 1.8 2006/01/09 03:05:01 alan_k Exp $
//
// Controller Type Class providing translation faciliites
//
/*
usage :
$t = new HTML_Template_Flexy_Translator(array(
'baseLang' => 'en',
'targetLangs' => array('es','fr','zh'),
'appURL' => '/admin/translate.php',
));
$t->process(isset($_GET ? $_GET : array(),isset($_POST ? $_POST : array()); // read data.. etc.
// you can replace this pretty easily with your own templates..
$t->outputDefautTemplate();
*/
class HTML_Template_Flexy_Translator {
/**
* Options for Translator tool.
*
* @var array
* @access public
*/
var $options = array(
'baseLang' => 'en', // the language the templates are in.
'targetLangs' => array('fr'), // the language the templates are being translated to.
'templateDir' => '', // these are read from global config if not set.
'compileDir' => '',
'url_rewrite' => '', // for image rewriting.. -- needs better thinking through!
'appURL' => '', // url to translation too : eg. /admin/translator.php
'Translation2' => array(
'driver' => 'dataobjectsimple',
'options' => 'translations'
),
);
/**
* app URL (copied from above)
*
* @var string
* @access public
*/
var $appURL;
var $languages = array();
/**
* Array of templates and the words found in each one.
*
* @var array
* @access public
*/
var $words= array();
/**
* Array of objects with name, md5's, has it been set, the translation etc.
*
* @var array
* @access public
*/
var $status = array();
/**
* The current language
*
* @var array
* @access public
*/
var $translate = ''; // language being displayed /edited.
/**
* constructor
*
* Just set options (no checking done)
*
*
* @param array see options array in file.
* @return none
* @access public
*/
function HTML_Template_Flexy_Translator($options= array()) {
foreach($options as $k=>$v) {
$this->options[$k] = $v;
}
if (!in_array($this->options['baseLang'], $this->options['targetLangs'])) {
$this->options['targetLangs'][] = $this->options['baseLang'];
}
$o = PEAR::getStaticProperty('HTML_Template_Flexy','options');
if (!strlen($this->options['templateDir'])) {
$this->options['templateDir'] = $o['templateDir'];
}
if (!strlen($this->options['compileDir'])) {
$this->options['compileDir'] = $o['compileDir'];
}
if (!strlen($this->options['url_rewrite'])) {
$this->options['url_rewrite'] = $o['url_rewrite'];
}
if (empty($this->options['Translation2'])) {
$this->options['Translation2'] = $o['Translation2'];
}
$this->appURL = $this->options['appURL'];
$this->languages = $this->options['targetLangs'];
}
/**
* process the input
*
*
* @param array $_GET; (translate = en)
* @param array $_POST; (translate = en, en[{md5}] = translation)
* @return none
* @access public
*/
function process($get,$post) {
//DB_DataObject::debugLevel(1);
$displayLang = isset($get['translate']) ? $get['translate'] :
(isset($post['translate']) ? $post['translate'] : false);
if ($displayLang === false) {
return;
}
require_once 'Translation2/Admin.php';
$driver = $this->options['Translation2']['driver'];
$options = $this->options['Translation2']['options'];
$usingGT = ($driver == 'gettext');
$usingDO = ($driver == 'dataobjectsimple');
$trd = &Translation2_Admin::factory($driver, $options);
//$trd->setDecoratedLang('en');
foreach($this->options['targetLangs'] as $l) {
$trd->addLang(array(
'lang_id' => $l
));
}
// back to parent if no language selected..
if (!in_array($displayLang, $this->options['targetLangs'] )) {
require_once 'PEAR.php';
return PEAR::raiseError('Unknown Language :' .$displayLang);
}
$this->translate = $displayLang;
if (isset($post['_apply'])) {
$this->clearTemplateCache($displayLang);
}
$t = explode(' ',microtime()); $start= $t[0] + $t[1];
require_once 'Translation2.php';
$tr = &Translation2::factory($driver, $options);
$tr->setLang($displayLang);
if (!$usingDO) {
$suggestions = &Translation2::factory($driver, $options);
$suggestions->setLang($displayLang);
}
$this->compileAll();
//$tr->setPageID('test.html');
// delete them after we have compiled them!!
if (isset($post['_apply'])) {
$this->clearTemplateCache($displayLang);
}
//DB_DataObject::debugLevel(1);
$this->loadTranslations();
$this->loadTranslations($displayLang);
if ($usingDO) {
$this->loadTranslations();
$this->loadTranslations($displayLang);
}
$all = array();
if ($usingGT) {
$trd->storage->begin();
}
$displayLangClean = str_replace('.', '_', $displayLang);
foreach($this->words as $page=>$words) {
$status[$page] = array();
$tr->setPageID($page);
// pages....
if (isset($post['_clear']) && !PEAR::isError($p = $trd->getPage($page, $displayLang))) {
$diff = array_diff(array_keys($p), $words);
if (count($diff)) {
foreach ($diff as $string) {
$trd->remove($string, $page);
}
}
}
foreach ($words as $word) {
if (!strlen(trim($word))) {
continue;
}
$md5 = md5($page.':'.$word);
$value = $usingDO ? $this->getTranslation($page,$word,$displayLang) : $tr->get($word);
// we posted something..
if (isset($post[$displayLangClean][$md5])) {
// eak we shouldnt really deal with magic_quotes!!!
$nval = str_replace("\r\n", "\n", get_magic_quotes_gpc() ? stripslashes($post[$_displayLang][$md5]) : $post[$_displayLang][$md5]);
if ($value != $nval) {
$trd->add($word,$page,array($displayLang=>$nval));
$value = $nval;
}
}
if ($value == '') {
// try the old gettext...
if (isset($old[addslashes($word)])) {
$trd->add($word,$page,array($displayLang=>$old[addslashes($word)]));
$value = $old[addslashes($word)];
}
}
$add = new StdClass;
$add->from = $word;
$add->to = $value;
if (!$add->to || ($add->from == $add->to)) {
$add->untranslated = true;
if ($usingDO) {
$add->suggest = implode(', ', $this->getSuggestions($word, $displayLang));
} else {
$suggest = $suggestions->get($word);
if ($suggest && ($suggest != $word)) {
$add->suggest = $suggest;
}
}
}
$add->md5 = $md5;
// show big or small text entry..
$add->short = (bool) (strlen($add->from) < 30 && strstr($add->from, "\n") === false);
$status[$page][] = $add;
}
}
if ($usingGT) {
$trd->storage->commit();
}
$t = explode(' ',microtime()); $total= $t[0] + $t[1] - $start;
//printf("Built All in %0.2fs<BR>",$total);
$this->status = $status;
}
var $translations = array();
var $translationMap = array();
/**
* LoadTranslations - load all the translations from the database
* into $this->translations[{lang}][{id}] = $translation;
*
*
* @param string Language
* @access public
*/
function loadTranslations ($lang= false) {
$d = DB_DataObject::factory('translations');
$d->lang = ($lang == false) ? '-' : $lang;
$d->find();
$this->translations[$d->lang] = array();
while ($d->fetch()) {
$this->translations[$d->lang][$d->string_id] = $d->translation;
if ($lang == false) {
$this->translationMap[$d->page][$d->translation] = $d->string_id;
}
// suggestions:?
}
}
function getSuggestions($string,$lang) {
$ids = array();
//echo '<PRE>';print_r($this->translationMap);
foreach($this->translationMap as $page=>$map) {
if (isset($map[$string])) {
$ids[] = $map[$string];
}
}
//echo '<PRE>';print_r(array($string,$lang,$ids,$this->translations[$lang]));
//exit;
if (!$ids) {
return array();
}
$ret = array();
foreach($ids as $id) {
if (isset($this->translations[$lang][$id])) {
$ret[] = $this->translations[$lang][$id];
}
}
// echo '<PRE>';print_r($ret);
return $ret;
}
function getTranslation($page,$word,$lang)
{
if (!isset($this->translationMap[$page][$word])) {
//echo "No string id for $page : $word\n";
return false;
}
if (!isset($this->translations[$lang][$this->translationMap[$page][$word]])) {
return false;
}
return $this->translations[$lang][$this->translationMap[$page][$word]];
}
/**
* compile all the templates in a specified folder.
*
*
* @param string subdirectory of templateDir or empty
* @return none
* @access public
*/
function compileAll($d='') {
set_time_limit(0); // this could take quite a while!!!
$words = array();
$dname = $d ? $this->options['templateDir'] .'/'.$d : $this->options['templateDir'];
//echo "Open $dname<BR>";
$dh = opendir( $dname);
require_once 'HTML/Template/Flexy.php';
$o = $this->options;
$o['fatalError'] = PEAR_ERROR_RETURN;
$o['locale'] = 'en';
while (($name = readdir($dh)) !== false) {
$fname = $d ? $d .'/'. $name : $name;
if ($name{0} == '.') {
continue;
}
if (is_dir($this->options['templateDir'] . '/'. $fname)) {
$this->compileAll($fname);
continue;
}
if (!preg_match('/\.html$/',$name)) {
continue;
}
$oo = $o;// $oo['debug'] = 1;
$x = new HTML_Template_Flexy( $oo );
$r = $x->compile($fname);
//printf(" %0.3fs : $fname<BR>", $time);
if (is_a($r,'PEAR_Error')) {
echo "compile failed on $fname<BR>";
echo $r->toString();
continue;
}
$this->words[$fname] = file_exists($x->getTextStringsFile) ?
unserialize(file_get_contents($x->getTextStringsFile)) :
array();
}
//echo '<PRE>';print_R($words);exit;
ksort($this->words);
}
/**
* delete all the compiled templates in a specified language
*
*
* @param string language
* @param string subdirectory of templateDir or empty
* @return none
* @access public
*/
function clearTemplateCache($lang='en',$d = '') {
$dname = $d ? $this->options['templateDir'] .'/'.$d : $this->options['templateDir'];
$dh = opendir($dname);
while (($name = readdir($dh)) !== false) {
$fname = $d ? $d .'/'. $name : $name;
if ($name{0} == '.') {
continue;
}
if (is_dir($this->options['templateDir'] . '/'. $fname)) {
$this->clearTemplateCache($lang,$fname);
continue;
}
if (!preg_match('/\.html$/',$name)) {
continue;
}
$file = "{$this->options['compileDir']}/{$fname}.{$lang}.php";
if (file_exists($file)) {
// echo "DELETE $file?";
unlink($file);
}
}
clearstatcache();
}
/**
* output the default template with the editing facilities.
*
* @return none
* @access public
*/
function outputDefaultTemplate() {
$o = array(
'compileDir' => ini_get('session.save_path') . '/HTML_Template_Flexy_Translate',
'templateDir' => dirname(__FILE__).'/templates'
);
$x = new HTML_Template_Flexy( $o );
$x->compile('translator.html');
$x->outputObject($this);
}
}

View file

@ -0,0 +1,333 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// $Id: Tree.php,v 1.5 2005/01/31 06:57:44 alan_k Exp $
//
// The Html Tree Component of Flexy
// Designed to be used on it's own
//
//
//
// The concept:
// - it builds a big tokens[] array :
// - filters "Text with {placeholders}" into sprintf formated strings.
// - matches closers to openers eg. token[4]->close = &token[5];
// - it aliases the tokens into token[0] as children as a tree
// - locates the base of the file. (flexy:startchildren.
// returns a nice tree..
class HTML_Template_Flexy_Tree {
/**
* Options for Tree:
* 'ignore' => dont change {xxxX} into placeholders?
* 'filename' => filename of file being parsed. (for error messages.)
* 'ignore_html' => return <html> elements as strings.
* 'ignore_php' => DELETE/DESTROY any php code in the original template.
*/
var $options = array(
'ignore' => false, // was flexyIgnore
'filename' => false,
'ignore_html' => false,
'ignore_php' => true,
);
/**
* Array of all tokens (eg. nodes / text / tags etc. )
* All nodes have ID's
*
* eg.
* <b>some text</b>
* [0] => Token_Tag::
* tagname = '<b>'
* children = array( &tag[1] );
close = &tag[2];
* [1] => Token_Text::'some test'
* [2] => Token_Tag::
* tagname = '</b>';
*
*
* under normal situations, the tree is built into node[0], the remaining nodes are referenced by alias.
* if caching is used (the nodes > 0 will not exist, and everything will just be a child of node 0.
*
*
*
* @var array
* @access public
*/
var $tokens = array();
var $strings = array();
/**
* Run a Tokenizer and Store its results and return the tree.
* It should build a DOM Tree of the HTML
*
* @param string $data data to parse.
* @param array $options see options array.
*
* @access public
* @return base token (really a dummy token, which contains the tree)
* @static
*/
function construct($data,$options=array())
{
// local caching!
$md5 = md5($data);
if (isset($GLOBALS[__CLASS__]['cache'][$md5])) {
return $GLOBALS[__CLASS__]['cache'][$md5];
}
$t = new HTML_Template_Flexy_Tree;
$t->options = $t->options + $options;
require_once 'HTML/Template/Flexy/Token.php';
$t->tokens = array(new HTML_Template_Flexy_Token);
$t->tokens[0]->id =0;
// process
if (is_a($r = $t->tokenize($data),'PEAR_Error')) {
return $r;
}
$t->matchClosers();
$t->buildChildren(0);
//new Gtk_VarDump($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][0]);
$GLOBALS[__CLASS__]['cache'][$md5] = $t->returnStart();
return $GLOBALS[__CLASS__]['cache'][$md5];
}
/**
* The core tokenizing part - runs the tokenizer on the data,
* and stores the results in $this->tokens[]
*
* @param string Data to tokenize
*
* @return none | PEAR::Error
* @access public|private
* @see see also methods.....
*/
function tokenize($data) {
require_once 'HTML/Template/Flexy/Tokenizer.php';
$tokenizer = &HTML_Template_Flexy_Tokenizer::construct($data,$this->options);
// initialize state - this trys to make sure that
// you dont do to many elses etc.
//echo "RUNNING TOKENIZER";
// step one just tokenize it.
$i=1;
while ($t = $tokenizer->yylex()) {
if ($t == HTML_TEMPLATE_FLEXY_TOKEN_ERROR) {
return HTML_Template_Flexy::raiseError(
array(
"HTML_Template_Flexy_Tree::Syntax error in File: %s (Line %s)\n".
"Tokenizer Error: %s\n".
"Context:\n\n%s\n\n >>>>>> %s\n",
$this->options['filename'], $tokenizer->yyline ,
$tokenizer->error,
htmlspecialchars(substr($tokenizer->yy_buffer,0,$tokenizer->yy_buffer_end)),
htmlspecialchars(substr($tokenizer->yy_buffer,$tokenizer->yy_buffer_end,100))
)
,HTML_TEMPLATE_FLEXY_ERROR_SYNTAX ,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
if ($t == HTML_TEMPLATE_FLEXY_TOKEN_NONE) {
continue;
}
if ($t->token == 'Php') {
continue;
}
$i++;
$this->tokens[$i] = $tokenizer->value;
$this->tokens[$i]->id = $i;
//print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
}
//echo "BUILT TOKENS";
}
/**
* Match the opening and closing tags eg. </B> is the closer of <B>
*
* aliases the ->close to the tokens[{closeid}] element
*
* @return none
* @access public
*/
function matchClosers()
{
$res = &$this->tokens;
$total = count($this->tokens);
// connect open and close tags.
// this is done by having a stack for each of the tag types..
// then removing it when it finds the closing one
// eg.
// <a href=""><img src=""></a>
// ends up with a stack for <a>'s and a stack for <img>'s
//
//
//
for($i=1;$i<$total;$i++) {
//echo "Checking TAG $i\n";
if (!isset($res[$i]->tag)) {
continue;
}
$tag = strtoupper($res[$i]->tag);
if ($tag{0} != '/') { // it's not a close tag..
if (!isset($stack[$tag])) {
$npos = $stack[$tag]['pos'] = 0;
} else {
$npos = ++$stack[$tag]['pos'];
}
$stack[$tag][$npos] = $i;
continue;
}
//echo "GOT END TAG: {$res[$i]->tag}\n";
$tag = substr($tag,1);
if (!isset($stack[$tag]['pos'])) {
continue; // unmatched
}
$npos = $stack[$tag]['pos'];
if (!isset($stack[$tag][$npos])) {
// stack is empty!!!
continue;
}
// alias closer to opener..
$this->tokens[$stack[$tag][$npos]]->close = &$this->tokens[$i];
$stack[$tag]['pos']--;
// take it off the stack so no one else uses it!!!
unset($stack[$tag][$npos]);
if ($stack[$tag]['pos'] < 0) {
// too many closes - just ignore it..
$stack[$tag]['pos'] = 0;
}
continue;
// new entry on stack..
}
// create a dummy close for the end
$i = $total;
$this->tokens[$i] = new HTML_Template_Flexy_Token;
$this->tokens[$i]->id = $total;
$this->tokens[0]->close = &$this->tokens[$i];
// now is it possible to connect children...
// now we need to GLOBALIZE!! -
}
/**
* Build the child array for each element.
* RECURSIVE FUNCTION!!!!
*
* does not move tokens, just aliases the child nodes into the token array.
*
* @param int id of node to add children to.
*
* @access public
*/
function buildChildren($id)
{
$base = &$this->tokens[$id];
$base->children = array();
$start = $base->id +1;
$end = $base->close->id;
for ($i=$start; $i<$end; $i++) {
//echo "{$base->id}:{$base->tag} ADDING {$i}{$_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]->tag}<BR>";
//if ($base->id == 1176) {
// echo "<PRE>";print_r($_HTML_TEMPLATE_FLEXY_TOKEN['tokens'][$i]);
// }
$base->children[] = &$this->tokens[$i];
if (isset($this->tokens[$i]->close)) {
// if the close id is greater than my id - ignore it! -
if ($this->tokens[$i]->close->id > $end) {
continue;
}
$this->buildChildren($i);
$i = $this->tokens[$i]->close->id;
}
}
}
/**
* Locates Flexy:startchildren etc. if it is used.
* and returns the base of the tree. (eg. otherwise token[0].
*
* @return HTML_Template_Flexy_Token (base of tree.)
* @access public
*/
function returnStart() {
foreach(array_keys($this->tokens) as $i) {
switch(true) {
case isset($this->tokens[$i]->ucAttributes['FLEXYSTART']):
case isset($this->tokens[$i]->ucAttributes['FLEXY:START']):
$this->tokens[$i]->removeAttribute('FLEXY:START');
$this->tokens[$i]->removeAttribute('FLEXYSTART');
return $this->tokens[$i];
case isset($this->tokens[$i]->ucAttributes['FLEXYSTARTCHILDREN']):
case isset($this->tokens[$i]->ucAttributes['FLEXY:STARTCHILDREN']):
$this->tokens[0]->children = $this->tokens[$i]->children;
return $this->tokens[0];
}
}
return $this->tokens[0];
}
}

View file

@ -0,0 +1,53 @@
#!/usr/bin/php -q
<?php
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 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 |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Alan Knowles <alan@akbkhome.com>
// +----------------------------------------------------------------------+
//
// $Id: compileAll.php,v 1.3 2003/08/01 08:50:27 alan_k Exp $
//
@include 'HTML/Template/Flexy.php';
if (!class_exists('HTML_Template_Flexy')) {
ini_set('include_path',dirname(__FILE__).'/../../../');
include 'HTML/Template/Flexy.php';
}
require_once 'PEAR.php';
if (!ini_get('register_argc_argv')) {
PEAR::raiseError("\nERROR: You must turn register_argc_argv On in you php.ini file for this to work\neg.\n\nregister_argc_argv = On\n\n", null, PEAR_ERROR_DIE);
exit;
}
if (!@$_SERVER['argv'][1]) {
PEAR::raiseError("\nERROR: compileAll.php usage:\n\nC:\php\pear\HTML\Template\Flexy\compileAll.php example.ini\n\n", null, PEAR_ERROR_DIE);
exit;
}
$config = parse_ini_file($_SERVER['argv'][1], true);
$options = &PEAR::getStaticProperty('HTML_Template_Flexy','options');
$options = $config['HTML_Template_Flexy'];
if (!$options) {
PEAR::raiseError("\nERROR: could not read ini file\n\n", null, PEAR_ERROR_DIE);
exit;
}
set_time_limit(0);
//DB_DataObject::debugLevel(5);
$flexy= new HTML_Template_Flexy;
$flexy->compileAll();
?>

View file

@ -0,0 +1,36 @@
;
; To use config file with HTML_Template_Flexy
; $config = parse_ini_file('example.ini',TRUE)
; $options = &PEAR::getStaticProperty('HTML_Template_Flexy','options');
; $options = $config['HTML_Template_Flexy'];
;
[HTML_Template_Flexy]
compileDir = /home/me/Projects/myapplication/compiled_templates
; where the compiled templates go.
templateDir = /home/me/Projects/myapplication/templates
; where the original templates are.
;templateDir = /home/me/Projects/myapplication/english;/home/me/Projects/myapplication/spanish
; or use multiple paths..
forceCompile = 0
; force compile template every time...
filters = Php,SimpleTags,BodyOnly
; Order of Classes to use as filters.
;url_rewrite = "/images/:/php_sharpsite/images/"
; rewrite src and href urls from /images/ to /php_sharpsite/images/
;url_rewrite = "/abc/:/xyz/,/bbb/:/zzz/"
; rewrite src and href urls from /abc/ to /xyz/ and /bbb/ to /zzz/
; not it is only on the left of the url (not anywhere inside it)
;flexyIgnore = 0
; this turns of the transformation of HTML form elements into
; HTML_Template_Flexy_Element's, either globally, or you
; can use it in a constructor to turn it off per template.

View file

@ -0,0 +1,270 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
<link type="text/css" rel="stylesheet" href="css/arms.css">
<title>register2</title>
</head><body flexy:startchildren="yes">
<script type="text/javascript">
function xbDetectBrowser()
{
var oldOnError = window.onerror;
var element = null;
window.onerror = null;
// work around bug in xpcdom Mozilla 0.9.1
window.saveNavigator = window.navigator;
navigator.OS = '';
navigator.version = parseFloat(navigator.appVersion);
navigator.org = '';
navigator.family = '';
var platform;
if (typeof(window.navigator.platform) != 'undefined') {
platform = window.navigator.platform.toLowerCase();
if (platform.indexOf('win') != -1) {
navigator.OS = 'win';
} else if (platform.indexOf('mac') != -1) {
navigator.OS = 'mac';
} else if (platform.indexOf('unix') != -1 || platform.indexOf('linux') != -1 || platform.indexOf('sun') != -1) {
navigator.OS = 'nix';
}
}
var i = 0;
var ua = window.navigator.userAgent.toLowerCase();
if (ua.indexOf('opera') != -1) {
i = ua.indexOf('opera');
navigator.family = 'opera';
navigator.org = 'opera';
navigator.version = parseFloat('0' + ua.substr(i+6), 10);
} else if ((i = ua.indexOf('msie')) != -1) {
navigator.org = 'microsoft';
navigator.version = parseFloat('0' + ua.substr(i+5), 10);
if (navigator.version < 4) {
navigator.family = 'ie3';
} else {
navigator.family = 'ie4'
}
} else if (ua.indexOf('gecko') != -1) {
navigator.family = 'gecko';
var rvStart = navigator.userAgent.indexOf('rv:') + 3;
var rvEnd = navigator.userAgent.indexOf(')', rvStart);
var rv = navigator.userAgent.substring(rvStart, rvEnd);
var decIndex = rv.indexOf('.');
if (decIndex != -1) {
rv = rv.replace(/\./g, '')
rv = rv.substring(0, decIndex-1) + '.' + rv.substr(decIndex)
}
navigator.version = parseFloat(rv);
if (ua.indexOf('netscape') != -1) {
navigator.org = 'netscape';
} else if (ua.indexOf('compuserve') != -1) {
navigator.org = 'compuserve';
} else {
navigator.org = 'mozilla';
}
} else if ((ua.indexOf('mozilla') !=-1) &&
(ua.indexOf('spoofer')==-1) &&
(ua.indexOf('compatible') == -1) &&
(ua.indexOf('opera')==-1) &&
(ua.indexOf('webtv')==-1) &&
(ua.indexOf('hotjava')==-1)) {
var is_major = parseFloat(navigator.appVersion);
if (is_major < 4) {
navigator.version = is_major;
} else {
i = ua.lastIndexOf('/')
navigator.version = parseFloat('0' + ua.substr(i+1), 10);
}
navigator.org = 'netscape';
navigator.family = 'nn' + parseInt(navigator.appVersion);
} else if ((i = ua.indexOf('aol')) != -1 ) {
// aol
navigator.family = 'aol';
navigator.org = 'aol';
navigator.version = parseFloat('0' + ua.substr(i+4), 10);
} else if ((i = ua.indexOf('hotjava')) != -1 ) {
// hotjava
navigator.family = 'hotjava';
navigator.org = 'sun';
navigator.version = parseFloat(navigator.appVersion);
}
window.onerror = oldOnError;
}
xbDetectBrowser();
function getTableNodeName(Node){
return "pane" + Node;
}
function showNode(Node){
switch(navigator.family){
case 'nn4':
// Nav 4.x code fork...
var oTable = document.layers[getTableNodeName(Node)];
break;
case 'ie4':
// IE 4/5 code fork...
var oTable = document.all[getTableNodeName(Node)];
break;
case 'gecko':
// Standards Compliant code fork...
var oTable = document.getElementById(getTableNodeName(Node));
break;
}
oTable.style.display = "block";
}
function hideNode(Node){
switch(navigator.family){
case 'nn4':
// Nav 4.x code fork...
var oTable = document.layers[getTableNodeName(Node)];
break;
case 'ie4':
// IE 4/5 code fork...
var oTable = document.all[getTableNodeName(Node)];
break;
case 'gecko':
// Standards Compliant code fork...
var oTable = document.getElementById(getTableNodeName(Node));
break;
}
oTable.style.display = "none";
}
function toggleNodeVisibility(Node){
if (nodeIsVisible(Node)){
hideNode(Node);
}else{
showNode(Node);
}
}
function nodeIsVisible(Node){
switch(navigator.family){
case 'nn4':
// Nav 4.x code fork...
var oTable = document.layers[getTableNodeName(Node)];
break;
case 'ie4':
// IE 4/5 code fork...
var oTable = document.all[getTableNodeName(Node)];
break;
case 'gecko':
// Standards Compliant code fork...
var oTable = document.getElementById(getTableNodeName(Node));
break;
}
return (oTable && oTable.style.display == "block");
}
</script>
Select a Language To Translate To : {foreach:languages,lang}
<a href="{appURL}?translate={lang}">{lang}</a>
{end:}
<form method="post" flexy:ignoreonly="yes" action="{appURL}" flexy:if="translate">
<input name="translate" value="{translate}" type="hidden" flexy:ignoreonly="yes">
<h1>Language : {translate}&nbsp;&nbsp;
<input flexy:ignoreonly="yes" value="save" name="_submit" type="submit">
or
<input flexy:ignoreonly="yes" value="Save And Make Live" name="_apply" type="submit">
or
<input flexy:ignoreonly="yes" value="Save And Clear Un-used Translations" name="_clear" type="submit">
</h1>
{foreach:status,page,items}
<table border="0" cellspacing="2" cellpadding="2" width="600" align="center">
<tbody>
<tr>
<td bgcolor="#cccccc" colspan="2" rowspan="1" valign="top" width="600">
<a class="property" href="javascript:toggleNodeVisibility('{page}');">+
Page:<b>{page}&nbsp;&nbsp; (in {translate})</b></a><br>
</td>
</tr>
</table>
<span id="pane{page}" style="display: none;">
<table width="100%" border="0" cellspacing="2" cellpadding="2" width="600" align="center">
<tr flexy:foreach="items,item">
<td bgcolor="#eeeeee" vaslign="top" width="300">
<a name="{item.md5}">
{if:item.untranslated}
<font color="#ff0000">{item.from}</font>
{else:}{item.from}
{end:}
<br>
<i>{item.suggest}</i><br>
</a>
</td>
<td bgcolor="#ffffff" valign="top" width="300">
<a href="#%7Bitem.md5%7D" flexy:if="item.already">See here</a>
<span flexy:if="!item.already">
<span flexy:if="item.short"><input
flexy:ignoreonly="yes" value="{item.to}" name="{translate}[{item.md5}]" size="40"></span>
<textarea cols="40" rows="5" flexy:if="!item.short" flexy:ignore="yes" name="{translate}[{item.md5}]" size="40">{item.to}</textarea>
</span>
</td>
</tr>
</table>
</span>
{end:}
<br>
<br>
<!-- InstanceEndEditable --><br>
</form>
</body></html>