From d9ec1f87e2d42d26c17b9f508334d195c6389f1c Mon Sep 17 00:00:00 2001 From: Pim Snel Date: Thu, 26 May 2005 19:38:09 +0000 Subject: [PATCH] Initial addition of the savant2 template engine and the egw-wrapper class.tplsavant2.inc.php Enjoy ;) --- phpgwapi/inc/class.tplsavant2.inc.php | 201 +++ phpgwapi/inc/savant2/Savant2.php | 1488 +++++++++++++++ phpgwapi/inc/savant2/Savant2/Compiler.php | 72 + phpgwapi/inc/savant2/Savant2/Error.php | 125 ++ phpgwapi/inc/savant2/Savant2/Filter.php | 76 + .../inc/savant2/Savant2/PHPCodeAnalyzer.php | 471 +++++ phpgwapi/inc/savant2/Savant2/Plugin.php | 74 + .../Savant2/Savant2_Compiler_basic.php | 847 +++++++++ .../Savant2/Savant2_Error_exception.php | 53 + .../savant2/Savant2/Savant2_Error_pear.php | 56 + .../savant2/Savant2/Savant2_Error_stack.php | 60 + .../Savant2/Savant2_Filter_colorizeCode.php | 123 ++ .../Savant2/Savant2_Filter_trimwhitespace.php | 104 ++ .../savant2/Savant2/Savant2_Plugin_ahref.php | 114 ++ .../Savant2/Savant2_Plugin_checkbox.php | 103 ++ .../savant2/Savant2/Savant2_Plugin_cycle.php | 97 + .../Savant2/Savant2_Plugin_dateformat.php | 136 ++ .../savant2/Savant2/Savant2_Plugin_form.php | 1596 +++++++++++++++++ .../savant2/Savant2/Savant2_Plugin_image.php | 220 +++ .../savant2/Savant2/Savant2_Plugin_input.php | 82 + .../Savant2/Savant2_Plugin_javascript.php | 54 + .../savant2/Savant2/Savant2_Plugin_modify.php | 82 + .../Savant2/Savant2_Plugin_options.php | 107 ++ .../savant2/Savant2/Savant2_Plugin_radios.php | 130 ++ .../Savant2/Savant2_Plugin_stylesheet.php | 56 + .../Savant2/Savant2_Plugin_textarea.php | 81 + .../inc/savant2/Savant2/tests/1_assign.php | 141 ++ .../inc/savant2/Savant2/tests/2_display.php | 72 + .../inc/savant2/Savant2/tests/3_fetch.php | 71 + .../inc/savant2/Savant2/tests/4_plugins.php | 85 + .../inc/savant2/Savant2/tests/5_filters.php | 42 + .../inc/savant2/Savant2/tests/6_paths.php | 52 + .../inc/savant2/Savant2/tests/7_include.php | 65 + .../inc/savant2/Savant2/tests/8_extend.php | 24 + .../inc/savant2/Savant2/tests/9_errors.php | 46 + .../inc/savant2/Savant2/tests/compile.php | 80 + phpgwapi/inc/savant2/Savant2/tests/form.php | 49 + phpgwapi/inc/savant2/Savant2/tests/form2.php | 49 + .../tests/resources/Savant2_Filter_fester.php | 18 + .../tests/resources/Savant2_Plugin_cycle2.php | 19 + .../resources/Savant2_Plugin_example.php | 22 + .../Savant2_Plugin_example_extend.php | 18 + .../tests/resources/Savant2_Plugin_fester.php | 31 + .../Savant2/tests/resources/savant.gif | Bin 0 -> 1043 bytes .../Savant2/tests/templates/assign.tpl.php | 12 + .../Savant2/tests/templates/compile.tpl.php | 31 + .../tests/templates/compile_bad.tpl.php | 35 + .../Savant2/tests/templates/extend.tpl.php | 11 + .../Savant2/tests/templates/filters.tpl.php | 44 + .../Savant2/tests/templates/footer.tpl.php | 2 + .../Savant2/tests/templates/form.tpl.php | 140 ++ .../Savant2/tests/templates/form2.tpl.php | 140 ++ .../Savant2/tests/templates/header.tpl.php | 7 + .../Savant2/tests/templates/main.tpl.php | 15 + .../Savant2/tests/templates/plugins.tpl.php | 192 ++ .../Savant2/tests/templates/test.tpl.php | 21 + phpgwapi/inc/savant2/VERSION | 1 + 57 files changed, 8143 insertions(+) create mode 100755 phpgwapi/inc/class.tplsavant2.inc.php create mode 100755 phpgwapi/inc/savant2/Savant2.php create mode 100755 phpgwapi/inc/savant2/Savant2/Compiler.php create mode 100755 phpgwapi/inc/savant2/Savant2/Error.php create mode 100755 phpgwapi/inc/savant2/Savant2/Filter.php create mode 100755 phpgwapi/inc/savant2/Savant2/PHPCodeAnalyzer.php create mode 100755 phpgwapi/inc/savant2/Savant2/Plugin.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Compiler_basic.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Error_exception.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Error_pear.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Error_stack.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Filter_colorizeCode.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Filter_trimwhitespace.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_ahref.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_checkbox.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_cycle.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_dateformat.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_form.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_image.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_input.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_javascript.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_modify.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_options.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_radios.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_stylesheet.php create mode 100755 phpgwapi/inc/savant2/Savant2/Savant2_Plugin_textarea.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/1_assign.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/2_display.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/3_fetch.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/4_plugins.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/5_filters.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/6_paths.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/7_include.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/8_extend.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/9_errors.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/compile.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/form.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/form2.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Filter_fester.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_cycle2.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example_extend.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_fester.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/resources/savant.gif create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/assign.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/compile.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/compile_bad.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/extend.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/filters.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/footer.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/form.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/form2.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/header.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/main.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/plugins.tpl.php create mode 100755 phpgwapi/inc/savant2/Savant2/tests/templates/test.tpl.php create mode 100644 phpgwapi/inc/savant2/VERSION diff --git a/phpgwapi/inc/class.tplsavant2.inc.php b/phpgwapi/inc/class.tplsavant2.inc.php new file mode 100755 index 0000000000..63440abe94 --- /dev/null +++ b/phpgwapi/inc/class.tplsavant2.inc.php @@ -0,0 +1,201 @@ + * + * * + * Wrapper for the savant2 template engine www.phpsavant.com * + * Copyright (C) 2005 Lingewoud BV and Pim Snel * + * -------------------------------------------------------------------------* + * This library is part of the eGroupWare API * + * http://www.egroupware.org * + * ------------------------------------------------------------------------ * + * This library is free software; you can redistribute it and/or modify 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 any later version. * + * This library 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. * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + \**************************************************************************/ + + /* $Id$ */ + + if(is_file(EGW_INCLUDE_ROOT.'/phpgwapi/inc/savant2/Savant2.php')) + { + include_once(EGW_INCLUDE_ROOT.'/phpgwapi/inc/savant2/Savant2.php'); + } + + /*! + @class tplsavant2 + @abstract wrapper class for the Savant2 template engine + */ + class tplsavant2 extends Savant2 + { + /*! + @var $version + @abstract the version this wrapper is testet against + */ + var $version = '2.3.3'; + + /*! + @var $do_version_check + @abstract set this to true to halt when versions of this wrapper and savant2 itself differ + */ + var $do_version_check = false; + + /*! + @function tplsavant2 + @abstract constructor function which calls the constructor of Savant2 and sets necesary things for eGroupware + */ + function tplsavant2() + { + // run constructor of the Savant2 class + $this->Savant2(); + + if($this->do_version_check) + { + $this->version_check(); + } + + $this->set_tpl_path(); + } + + /** + @function version_check + @abstract check version of this wrapper with installed savant2 version and halts when version differs + @return void + */ + function version_check() + { + $Sav2Version = @file_get_contents(EGW_INCLUDE_ROOT.'/phpgwapi/inc/savant2/VERSION',"rb"); + + if(trim($Sav2Version) != trim($this->version)) + { + $this->halt(lang('Savant2 version differs from Savant2 wrapper.
This version: %1
Savants version: %2',$this->version, $Sav2Version)); + } + } + + + /*! + @function set_tpl_path + @abstract sets the preferred and fallback template search paths + @return void + */ + function set_tpl_path() + { + $preferred_dir=$this->get_tpl_dir(); + $fallback_dir=$this->get_tpl_dir(true); + + if(!$preferred_dir && $fallback_dir) + { + $this->halt(lang('No Savant2 template directories were found in:'.EGW_APP_ROOT)); + } + else + { + if($fallback_dir) + { + $this->addPath('template',$fallback_dir); + } + // add preferred tpl dir last because savant set the last added first in the search array + if($preferred_dir) + { + $this->addPath('template',$preferred_dir); + } + + } + + } + + /*! + @function get_tpl_dir + @abstract get template dir of an application + @param $fallback if true the default fallback template dir is returned + @param $appname appication name optional can be derived from $GLOBALS['egw_info']['flags']['currentapp']; + */ + function get_tpl_dir($fallback=false,$appname = '') + { + if (! $appname) + { + $appname = $GLOBALS['egw_info']['flags']['currentapp']; + } + if ($appname == 'home' || $appname == 'logout' || $appname == 'login') + { + $appname = 'phpgwapi'; + } + + if (!isset($GLOBALS['egw_info']['server']['template_set']) && isset($GLOBALS['egw_info']['user']['preferences']['common']['template_set'])) + { + $GLOBALS['egw_info']['server']['template_set'] = $GLOBALS['egw_info']['user']['preferences']['common']['template_set']; + } + + // Setting this for display of template choices in user preferences + if ($GLOBALS['egw_info']['server']['template_set'] == 'user_choice') + { + $GLOBALS['egw_info']['server']['usrtplchoice'] = 'user_choice'; + } + + if (($GLOBALS['egw_info']['server']['template_set'] == 'user_choice' || + !isset($GLOBALS['egw_info']['server']['template_set'])) && + isset($GLOBALS['egw_info']['user']['preferences']['common']['template_set'])) + { + $GLOBALS['egw_info']['server']['template_set'] = $GLOBALS['egw_info']['user']['preferences']['common']['template_set']; + } + elseif ($GLOBALS['egw_info']['server']['template_set'] == 'user_choice' || + !isset($GLOBALS['egw_info']['server']['template_set'])) + { + $GLOBALS['egw_info']['server']['template_set'] = 'default'; + } + + $tpldir = EGW_SERVER_ROOT . '/' . $appname . '/templatesSavant2/' . $GLOBALS['egw_info']['server']['template_set']; + $tpldir_default = EGW_SERVER_ROOT . '/' . $appname . '/templatesSavant2/default'; + + if (!$fallback && @is_dir($tpldir)) + { + return $tpldir; + } + elseif (@is_dir($tpldir_default)) + { + return $tpldir_default; + } + else + { + return False; + } + } + + /***************************************************************************/ + /* public: halt(string $msg) + * msg: error message to show. + */ + function halt($msg) + { + $this->last_error = $msg; + + if ($this->halt_on_error != 'no') + { + $this->haltmsg($msg); + } + + if ($this->halt_on_error == 'yes') + { + echo('Halted.'); + } + + $GLOBALS['phpgw']->common->phpgw_exit(True); + } + + /* public, override: haltmsg($msg) + * msg: error message to show. + */ + function haltmsg($msg) + { + printf("Savant Template Error: %s
\n", $msg); + echo "Backtrace: ".function_backtrace(2)."
\n"; + } + + + } diff --git a/phpgwapi/inc/savant2/Savant2.php b/phpgwapi/inc/savant2/Savant2.php new file mode 100755 index 0000000000..54c5c9f08c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2.php @@ -0,0 +1,1488 @@ + 'assign() parameters not correct', + SAVANT2_ERROR_ASSIGNREF => 'assignRef() parameters not correct', + SAVANT2_ERROR_COMPILER => 'compiler not an object or has no compile() method', + SAVANT2_ERROR_NOFILTER => 'filter file not found', + SAVANT2_ERROR_NOPLUGIN => 'plugin file not found', + SAVANT2_ERROR_NOSCRIPT => 'compiled template script file not found', + SAVANT2_ERROR_NOTEMPLATE => 'template source file not found', + SAVANT2_ERROR_COMPILE_FAIL => 'template source failed to compile' + ); +} + + +/** +* +* Provides an object-oriented template system. +* +* Savant2 helps you separate model logic from view logic using PHP as +* the template language. By default, Savant2 does not compile templates. +* However, you may pass an optional compiler object to compile template +* source to include-able PHP code. +* +* Please see the documentation at {@link http://phpsavant.com/}, and be +* sure to donate! :-) +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @version 2.3.3 stable +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2 { + + + /** + * + * PHP5 ONLY: What method __call() will alias to. + * + * Generally 'plugin' or 'splugin' (as __call() is intended for those). + * + * @access private + * + * @var string + * + */ + + var $_call = 'plugin'; + + + /** + * + * The custom compiler (pre-processor) object, if any. + * + * @access private + * + * @var object + * + */ + + var $_compiler = null; + + + /** + * + * The class type to use when instantiating error objects. + * + * @access private + * + * @var string + * + */ + + var $_error = null; + + + /** + * + * Whether or not to extract assigned variables into fetch() scope. + * + * When true, all variables and references assigned to Savant2 are + * extracted into the local scope of the template script at fetch() + * time, and may be addressed as "$varname" instead of + * "$this->varname". The "$this->varname" notation will also work. + * + * When false, you //must// use "$this->varname" in your templates to + * address a variable instead of "$varname". This has three + * benefits: speed (no time spent extracting variables), memory use + * (saves RAM by not making new references to variables), and clarity + * (any $this->varname is obviously an assigned var, and vars created + * within the template are not prefixed with $this). + * + * @access private + * + * @var bool + * + */ + + var $_extract = false; + + + /** + * + * The output of the template script. + * + * @access private + * + * @var string + * + */ + + var $_output = null; + + + /** + * + * The set of search directories for resources (plugins/filters) and + * templates. + * + * @access private + * + * @var array + * + */ + + var $_path = array( + 'resource' => array(), + 'template' => array() + ); + + + /** + * + * Array of resource (plugin/filter) object instances. + * + * @access private + * + * @var array + * + */ + + var $_resource = array( + 'plugin' => array(), + 'filter' => array() + ); + + + /** + * + * Whether or not to automatically self-reference in plugins and filters. + * + * @access private + * + * @var bool + * + */ + + var $_reference = false; + + + /** + * + * The path to the compiled template script file. + * + * By default, the template source and template script are the same file. + * + * @access private + * + * @var string + * + */ + + var $_script = null; + + + /** + * + * The name of the default template source file. + * + * @access private + * + * @var string + * + */ + + var $_template = null; + + var $_restrict = false; + + + // ----------------------------------------------------------------- + // + // Constructor and general property setters + // + // ----------------------------------------------------------------- + + + /** + * + * Constructor. + * + * @access public + * + * @param array $conf An associative array of configuration keys for + * the Savant2 object. Any, or none, of the keys may be set. The + * keys are: + * + * 'template_path' => The default path string or array of directories + * to search for templates. + * + * 'resource_path' => The default path string or array of directories + * to search for plugin and filter resources. + * + * 'error' => The custom error class that Savant2 should use + * when returning errors. + * + * 'extract' => Whether or not to extract variables into the local + * scope when executing a template. + * + * 'template' => The default template source name to use. + * + */ + + function Savant2($conf = array()) + { + // set the default template search dirs + if (isset($conf['template_path'])) { + // user-defined dirs + $this->setPath('template', $conf['template_path']); + } else { + // default directory only + $this->setPath('template', null); + } + + // set the default filter search dirs + if (isset($conf['resource_path'])) { + // user-defined dirs + $this->setPath('resource', $conf['resource_path']); + } else { + // default directory only + $this->setPath('resource', null); + } + + // set the error class + if (isset($conf['error'])) { + $this->setError($conf['error']); + } + + // set the extraction flag + if (isset($conf['extract'])) { + $this->setExtract($conf['extract']); + } + + // set the restrict flag + if (isset($conf['restrict'])) { + $this->setRestrict($conf['restrict']); + } + + // set the Savant reference flag + if (isset($conf['reference'])) { + $this->setReference($conf['reference']); + } + + // set the default template + if (isset($conf['template'])) { + $this->setTemplate($conf['template']); + } + } + + + /** + * + * Sets a custom compiler/pre-processor for template sources. + * + * By default, Savant2 does not use a compiler; use this to set your + * own custom compiler (pre-processor) for template sources. + * + * @access public + * + * @param object $compiler The compiler object; it must have a + * "compile()" method. If null or false, the current compiler object + * is removed from Savant2. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_COMPILER code. + * + */ + + function setCompiler(&$compiler) + { + if (! $compiler) { + // nullify any current compiler + $this->_compiler = null; + } elseif (is_object($compiler) && method_exists($compiler, 'compile')) { + // refer to a compiler object + $this->_compiler =& $compiler; + } else { + // no usable compiler passed + $this->_compiler = null; + return $this->error(SAVANT2_ERROR_COMPILER); + } + } + + + /** + * + * Sets the method that __call() will alias to. + * + * @access public + * + * @param string $method The Savant2 method for __call() to alias to, + * generally 'plugin' or 'splugin'. + * + * @return void + * + */ + + function setCall($method = 'plugin') + { + $this->_call = $method; + } + + + /** + * + * Sets the custom error class for Savant2 errors. + * + * @access public + * + * @param string $error The name of the custom error class name; if + * null or false, resets the error class to 'Savant2_Error'. + * + * @return void + * + */ + + function setError($error) + { + if (! $error) { + $this->_error = null; + } else { + $this->_error = $error; + } + } + + + /** + * + * Turns path checking on/off. + * + * @access public + * + * @param bool $flag True to turn on path checks, false to turn off. + * + * @return void + * + */ + + function setRestrict($flag = false) + { + if ($flag) { + $this->_restrict = true; + } else { + $this->_restrict = false; + } + } + + + /** + * + * Turns extraction of variables on/off. + * + * @access public + * + * @param bool $flag True to turn on extraction, false to turn off. + * + * @return void + * + */ + + function setExtract($flag = true) + { + if ($flag) { + $this->_extract = true; + } else { + $this->_extract = false; + } + } + + + /** + * + * Sets the automated Savant reference for plugins and filters. + * + * @access public + * + * @param bool $flag Whether to reference Savant2 or not. + * + * @return void + * + */ + + function setReference($flag = false) + { + $this->_reference = $flag; + } + + + /** + * + * Sets the default template name. + * + * @access public + * + * @param string $template The default template name. + * + * @return void + * + */ + + function setTemplate($template) + { + $this->_template = $template; + } + + + // ----------------------------------------------------------------- + // + // Path management and file finding + // + // ----------------------------------------------------------------- + + + /** + * + * Sets an entire array of search paths. + * + * @access public + * + * @param string $type The type of path to set, typcially 'template' + * or 'resource'. + * + * @param string|array $new The new set of search paths. If null or + * false, resets to the current directory only. + * + * @return void + * + */ + + function setPath($type, $new) + { + // clear out the prior search dirs + $this->_path[$type] = array(); + + // convert from string to path + if (is_string($new) && ! strpos('://', $new)) { + // the search config is a string, and it's not a stream + // identifier (the "://" piece), add it as a path + // string. + $new = explode(PATH_SEPARATOR, $new); + } else { + // force to array + settype($new, 'array'); + } + + // always add the fallback directories as last resort + switch (strtolower($type)) { + case 'template': + $this->addPath($type, '.'); + break; + case 'resource': + $this->addPath($type, dirname(__FILE__) . '/Savant2/'); + break; + } + + // actually add the user-specified directories + foreach ($new as $dir) { + $this->addPath($type, $dir); + } + } + + + /** + * + * Adds a search directory for templates. + * + * @access public + * + * @param string $dir The directory or stream to search. + * + * @return void + * + */ + + function addPath($type, $dir) + { + // no surrounding spaces allowed! + $dir = trim($dir); + + // add trailing separators as needed + if (strpos($dir, '://') && substr($dir, -1) != '/') { + // stream + $dir .= '/'; + } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) { + // directory + $dir .= DIRECTORY_SEPARATOR; + } + + // add to the top of the search dirs + array_unshift($this->_path[$type], $dir); + } + + + /** + * + * Gets the array of search directories for template sources. + * + * @access public + * + * @return array The array of search directories for template sources. + * + */ + + function getPath($type = null) + { + if (! $type) { + return $this->_path; + } else { + return $this->_path[$type]; + } + } + + + /** + * + * Searches a series of paths for a given file. + * + * @param array $type The type of paths to search (template, plugin, + * or filter). + * + * @param string $file The file name to look for. + * + * @return string|bool The full path and file name for the target file, + * or boolean false if the file is not found in any of the paths. + * + */ + + function findFile($type, $file) + { + // get the set of paths + $set = $this->getPath($type); + + // start looping through them + foreach ($set as $path) { + + // get the path to the file + $fullname = $path . $file; + + // are we doing path checks? + if (! $this->_restrict) { + + // no. this is faster but less secure. + if (file_exists($fullname) && is_readable($fullname)) { + return $fullname; + } + + } else { + + // yes. this is slower, but attempts to restrict + // access only to defined paths. + + // is the path based on a stream? + if (strpos('://', $path) === false) { + // not a stream, so do a realpath() to avoid + // directory traversal attempts on the local file + // system. Suggested by Ian Eure, initially + // rejected, but then adopted when the secure + // compiler was added. + $path = realpath($path); // needed for substr() later + $fullname = realpath($fullname); + } + + // the substr() check added by Ian Eure to make sure + // that the realpath() results in a directory registered + // with Savant so that non-registered directores are not + // accessible via directory traversal attempts. + if (file_exists($fullname) && is_readable($fullname) && + substr($fullname, 0, strlen($path)) == $path) { + return $fullname; + } + } + } + + // could not find the file in the set of paths + return false; + } + + + // ----------------------------------------------------------------- + // + // Variable and reference assignment + // + // ----------------------------------------------------------------- + + + /** + * + * Sets variables for the template. + * + * This method is overloaded; you can assign all the properties of + * an object, an associative array, or a single value by name. + * + * You are not allowed to set variables that begin with an underscore; + * these are either private properties for Savant2 or private variables + * within the template script itself. + * + * + * + * $Savant2 =& new Savant2(); + * + * // assign directly + * $Savant2->var1 = 'something'; + * $Savant2->var2 = 'else'; + * + * // assign by name and value + * $Savant2->assign('var1', 'something'); + * $Savant2->assign('var2', 'else'); + * + * // assign by assoc-array + * $ary = array('var1' => 'something', 'var2' => 'else'); + * $Savant2->assign($obj); + * + * // assign by object + * $obj = new stdClass; + * $obj->var1 = 'something'; + * $obj->var2 = 'else'; + * $Savant2->assign($obj); + * + * + * + * Greg Beaver came up with the idea of assigning to public class + * properties. + * + * @access public + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_ASSIGN code. + * + */ + + function assign() + { + // this method is overloaded. + $arg = func_get_args(); + + // must have at least one argument. no error, just do nothing. + if (! isset($arg[0])) { + return; + } + + // assign by object + if (is_object($arg[0])) { + // assign public properties + foreach (get_object_vars($arg[0]) as $key => $val) { + if (substr($key, 0, 1) != '_') { + $this->$key = $val; + } + } + return; + } + + // assign by associative array + if (is_array($arg[0])) { + foreach ($arg[0] as $key => $val) { + if (substr($key, 0, 1) != '_') { + $this->$key = $val; + } + } + return; + } + + // assign by string name and mixed value. + // + // we use array_key_exists() instead of isset() becuase isset() + // fails if the value is set to null. + if (is_string($arg[0]) && + substr($arg[0], 0, 1) != '_' && + array_key_exists(1, $arg)) { + $this->$arg[0] = $arg[1]; + } else { + return $this->error(SAVANT2_ERROR_ASSIGN, $arg); + } + } + + + /** + * + * Sets references for the template. + * + * // assign by name and value + * $Savant2->assignRef('ref', $reference); + * + * // assign directly + * $Savant2->ref =& $reference; + * + * Greg Beaver came up with the idea of assigning to public class + * properties. + * + * @access public + * + * @param string $key The name for the reference in the template. + * + * @param mixed &$val The referenced variable. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_ASSIGNREF code. + * + */ + + function assignRef($key, &$val) + { + if (is_string($key) && substr($key, 0, 1) != '_') { + $this->$key =& $val; + } else { + return $this->error( + SAVANT2_ERROR_ASSIGNREF, + array('key' => $key, 'val' => $val) + ); + } + } + + + /** + * + * Unsets assigned variables and references. + * + * @access public + * + * @param mixed $var If null, clears all variables; if a string, clears + * the one variable named by the string; if a sequential array, clears + * the variables names in that array. + * + * @return void + * + */ + + function clear($var = null) + { + if (is_null($var)) { + // clear all variables + $var = array_keys(get_object_vars($this)); + } else { + // clear specific variables + settype($var, 'array'); + } + + // clear out the selected variables + foreach ($var as $name) { + if (substr($name, 0, 1) != '_' && isset($this->$name)) { + unset($this->$name); + } + } + } + + + /** + * + * Gets the current value of one, many, or all assigned variables. + * + * Never returns variables starting with an underscore; these are + * reserved for internal Savant2 use. + * + * @access public + * + * @param mixed $key If null, returns a copy of all variables and + * their values; if an array, returns an only those variables named + * in the array; if a string, returns only that variable. + * + * @return mixed If multiple variables were reqested, returns an + * associative array where the key is the variable name and the + * value is the variable value; if one variable was requested, + * returns the variable value only. + * + */ + + function getVars($key = null) + { + if (is_null($key)) { + $key = array_keys(get_object_vars($this)); + } + + if (is_array($key)) { + // return a series of vars + $tmp = array(); + foreach ($key as $var) { + if (substr($var, 0, 1) != '_' && isset($this->$var)) { + $tmp[$var] = $this->$var; + } + } + return $tmp; + } else { + // return a single var + if (substr($key, 0, 1) != '_' && isset($this->$key)) { + return $this->$key; + } + } + } + + + // ----------------------------------------------------------------- + // + // Template processing + // + // ----------------------------------------------------------------- + + + /** + * + * Loads a template script for execution (does not execute the script). + * + * This will optionally compile the template source into a PHP script + * if a compiler object has been passed into Savant2. + * + * Also good for including templates from the template paths within + * another template, like so: + * + * include $this->loadTemplate('template.tpl.php'); + * + * @access public + * + * @param string $tpl The template source name to look for. + * + * @param bool $setScript Default false; if true, sets the $this->_script + * property to the resulting script path (or null on error). Normally, + * only $this->fetch() will need to set this to true. + * + * @return string The full path to the compiled template script. + * + * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code. + * + */ + + function loadTemplate($tpl = null, $setScript = false) + { + // set to default template if none specified. + if (is_null($tpl)) { + $tpl = $this->_template; + } + + // find the template source. + $file = $this->findFile('template', $tpl); + if (! $file) { + return $this->error( + SAVANT2_ERROR_NOTEMPLATE, + array('template' => $tpl) + ); + } + + // are we compiling source into a script? + if (is_object($this->_compiler)) { + // compile the template source and get the path to the + // compiled script (will be returned instead of the + // source path) + $result = $this->_compiler->compile($file); + } else { + // no compiling requested, return the source path + $result = $file; + } + + // is there a script from the compiler? + if (! $result || $this->isError($result)) { + + if ($setScript) { + $this->_script = null; + } + + // return an error, along with any error info + // generated by the compiler. + return $this->error( + SAVANT2_ERROR_NOSCRIPT, + array( + 'template' => $tpl, + 'compiler' => $result + ) + ); + + } else { + + if ($setScript) { + $this->_script = $result; + } + + return $result; + + } + } + + + /** + * + * This is a an alias to loadTemplate() that cannot set the script. + * + * @access public + * + * @param string $tpl The template source name to look for. + * + * @return string The full path to the compiled template script. + * + * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code. + * + */ + + function findTemplate($tpl = null) + { + return $this->loadTemplate($tpl, false); + } + + + /** + * + * Executes a template script and returns the results as a string. + * + * @param string $_tpl The name of the template source file ... + * automatically searches the template paths and compiles as needed. + * + * @return string The output of the the template script. + * + * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code. + * + */ + + function fetch($_tpl = null) + { + // clear prior output + $this->_output = null; + + // load the template script + $_result = $this->loadTemplate($_tpl, true); + + // is there a template script to be processed? + if ($this->isError($_result)) { + return $_result; + } + + // unset so as not to introduce into template scope + unset($_tpl); + unset($_result); + + // never allow a 'this' property + if (isset($this->this)) { + unset($this->this); + } + + // are we extracting variables into local scope? + if ($this->_extract) { + // extract references to this object's public properties. + // this allows variables assigned by-reference to refer all + // the way back to the model logic. variables assigned + // by-copy only refer back to the property. + foreach (array_keys(get_object_vars($this)) as $_prop) { + if (substr($_prop, 0, 1) != '_') { + // set a variable-variable to an object property + // reference + $$_prop =& $this->$_prop; + } + } + + // unset private loop vars + unset($_prop); + } + + // start capturing output into a buffer + ob_start(); + + // include the requested template filename in the local scope + // (this will execute the view logic). + include $this->_script; + + // done with the requested template; get the buffer and + // clear it. + $this->_output = ob_get_contents(); + ob_end_clean(); + + // done! + return $this->applyFilters(); + } + + + /** + * + * Execute and display a template script. + * + * @param string $tpl The name of the template file to parse; + * automatically searches through the template paths. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code. + * + * @see fetch() + * + */ + + function display($tpl = null) + { + $result = $this->fetch($tpl); + if ($this->isError($result)) { + return $result; + } else { + echo $result; + } + } + + + // ----------------------------------------------------------------- + // + // Plugins + // + // ----------------------------------------------------------------- + + + /** + * + * Loads a plugin class and instantiates it within Savant2. + * + * @access public + * + * @param string $name The plugin name (not including Savant2_Plugin_ + * prefix). + * + * @param array $conf An associative array of plugin configuration + * options. + * + * @param bool $savantRef Default false. When true, sets the $Savant + * property of the filter to a reference to this Savant object. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. + * + */ + + function loadPlugin($name, $conf = array(), $savantRef = null) + { + // if no $savantRef is provided, use the default. + if (is_null($savantRef)) { + $savantRef = $this->_reference; + } + + // some basic information + $class = "Savant2_Plugin_$name"; + $file = "$class.php"; + + // is it loaded? + if (! class_exists($class)) { + + $result = $this->findFile('resource', $file); + if (! $result) { + return $this->error( + SAVANT2_ERROR_NOPLUGIN, + array('plugin' => $name) + ); + } else { + include_once $result; + } + } + + // is it instantiated? + if (! isset($this->_resource['plugin'][$name]) || + ! is_object($this->_resource['plugin'][$name]) || + ! is_a($this->_resource['plugin'][$name], $class)) { + + // instantiate it + $this->_resource['plugin'][$name] =& new $class($conf); + + // add a Savant reference if requested + if ($savantRef) { + $this->_resource['plugin'][$name]->Savant =& $this; + } + + } + } + + + /** + * + * Unloads one or more plugins from Savant2. + * + * @access public + * + * @param string|array $name The plugin name (not including Savant2_Plugin_ + * prefix). If null, unloads all plugins; if a string, unloads that one + * plugin; if an array, unloads all plugins named as values in the array. + * + * @return void + * + */ + + function unloadPlugin($name = null) + { + if (is_null($name)) { + $this->_resource['plugin'] = array(); + } else { + settype($name, 'array'); + foreach ($name as $key) { + if (isset($this->_resource['plugin'][$key])) { + unset($this->_resource['plugin'][$key]); + } + } + } + } + + + /** + * + * Executes a plugin with arbitrary parameters and returns the + * result. + * + * @access public + * + * @param string $name The plugin name (not including Savant2_Plugin_ + * prefix). + * + * @return mixed The plugin results. + * + * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. + * + * @see loadPlugin() + * + */ + + function splugin($name) + { + // attempt to load the plugin + $result = $this->loadPlugin($name); + if ($this->isError($result)) { + return $result; + } + + // call the plugin's "plugin()" method with arguments, + // dropping the first argument (the plugin name) + $args = func_get_args(); + array_shift($args); + return call_user_func_array( + array(&$this->_resource['plugin'][$name], 'plugin'), $args + ); + } + + + /** + * + * Executes a plugin with arbitrary parameters and displays the + * result. + * + * @access public + * + * @param string $name The plugin name (not including Savant2_Plugin_ + * prefix). + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. + * + */ + + function plugin($name) + { + $args = func_get_args(); + + $result = call_user_func_array( + array(&$this, 'splugin'), + $args + ); + + if ($this->isError($result)) { + return $result; + } else { + echo $result; + } + } + + + /** + * + * PHP5 ONLY: Magic method alias to plugin(). + * + * E.g., instead of $this->plugin('form', ...) you would use + * $this->form(...). You can set this to use any other Savant2 method + * by issuing, for example, setCall('splugin') to use splugin() ... which + * is really the only other sensible choice. + * + * @access public + * + * @param string $func The plugin name. + * + * @param array $args Arguments passed to the plugin. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. + * + */ + + function __call($func, $args) + { + // add the plugin name to the args + array_unshift($args, $func); + + // call the plugin() method + return call_user_func_array( + array(&$this, $this->_call), + $args + ); + } + + + // ----------------------------------------------------------------- + // + // Filters + // + // ----------------------------------------------------------------- + + + /** + * + * Loads a filter class and instantiates it within Savant2. + * + * @access public + * + * @param string $name The filter name (not including Savant2_Filter_ + * prefix). + * + * @param array $conf An associative array of filter configuration + * options. + * + * @param bool $savantRef Default false. When true, sets the $Savant + * property of the filter to a reference to this Savant object. + * + * @return void + * + * @throws object An error object with a SAVANT2_ERROR_NOFILTER code. + * + */ + + function loadFilter($name, $conf = array(), $savantRef = null) + { + // if no $savantRef is provided, use the default. + if (is_null($savantRef)) { + $savantRef = $this->_reference; + } + + // some basic information + $class = "Savant2_Filter_$name"; + $file = "$class.php"; + + // is it loaded? + if (! class_exists($class)) { + + $result = $this->findFile('resource', $file); + if (! $result) { + return $this->error( + SAVANT2_ERROR_NOFILTER, + array('filter' => $name) + ); + } else { + include_once $result; + } + } + + // is it instantiated? + if (! isset($this->_resource['filter'][$name]) || + ! is_object($this->_resource['filter'][$name]) || + ! is_a($this->_resource['filter'][$name], $class)) { + + // instantiate it + $this->_resource['filter'][$name] =& new $class($conf); + + // add a Savant reference if requested + if ($savantRef) { + $this->_resource['filter'][$name]->Savant =& $this; + } + + } + } + + + /** + * + * Unloads one or more filters from Savant2. + * + * @access public + * + * @param string|array $name The filter name (not including Savant2_Filter_ + * prefix). If null, unloads all filters; if a string, unloads that one + * filter; if an array, unloads all filters named as values in the array. + * + * @return void + * + */ + + function unloadFilter($name = null) + { + if (is_null($name)) { + $this->_resource['filter'] = array(); + } else { + settype($name, 'array'); + foreach ($name as $key) { + if (isset($this->_resource['filter'][$key])) { + unset($this->_resource['filter'][$key]); + } + } + } + } + + + /** + * + * Apply all loaded filters, in order, to text. + * + * @access public + * + * @param string $text The text to which filters should be applied. + * If null, sets the text to $this->_output. + * + * @return string The text after being passed through all loded + * filters. + * + */ + + function applyFilters($text = null) + { + // set to output text if no text specified + if (is_null($text)) { + $text = $this->_output; + } + + // get the list of filter names... + $filter = array_keys($this->_resource['filter']); + + // ... and apply them each in turn. + foreach ($filter as $name) { + $this->_resource['filter'][$name]->filter($text); + } + + // done + return $text; + } + + + // ----------------------------------------------------------------- + // + // Error handling + // + // ----------------------------------------------------------------- + + + /** + * + * Returns an error object. + * + * @access public + * + * @param int $code A SAVANT2_ERROR_* constant. + * + * @param array $info An array of error-specific information. + * + * @return object An error object of the type specified by + * $this->_error. + * + */ + + function &error($code, $info = array()) + { + // the error config array + $conf = array( + 'code' => $code, + 'text' => 'Savant2: ', + 'info' => (array) $info + ); + + // set an error message from the globals + if (isset($GLOBALS['_SAVANT2']['error'][$code])) { + $conf['text'] .= $GLOBALS['_SAVANT2']['error'][$code]; + } else { + $conf['text'] .= '???'; + } + + // set up the error class name + if ($this->_error) { + $class = 'Savant2_Error_' . $this->_error; + } else { + $class = 'Savant2_Error'; + } + + // set up the error class file name + $file = $class . '.php'; + + // is it loaded? + if (! class_exists($class)) { + + // find the error class + $result = $this->findFile('resource', $file); + if (! $result) { + // could not find the custom error class, revert to + // Savant_Error base class. + $class = 'Savant2_Error'; + $result = dirname(__FILE__) . '/Savant2/Error.php'; + } + + // include the error class + include_once $result; + } + + // instantiate and return the error class + $err =& new $class($conf); + return $err; + } + + + /** + * + * Tests if an object is of the Savant2_Error class. + * + * @access public + * + * @param object &$obj The object to be tested. + * + * @return boolean True if $obj is an error object of the type + * Savant2_Error, or is a subclass that Savant2_Error. False if not. + * + */ + + function isError(&$obj) + { + if (is_object($obj)) { + if (is_a($obj, 'Savant2_Error') || + is_subclass_of($obj, 'Savant2_Error')) { + return true; + } + } + + return false; + } +} +?> diff --git a/phpgwapi/inc/savant2/Savant2/Compiler.php b/phpgwapi/inc/savant2/Savant2/Compiler.php new file mode 100755 index 0000000000..ad02271072 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Compiler.php @@ -0,0 +1,72 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Compiler { + + /** + * + * Reference to the "parent" Savant object. + * + */ + + var $Savant = null; + + + /** + * + * Constructor. + * + * @access public + * + */ + + function Savant2_Compiler($conf = array()) + { + settype($conf, 'array'); + foreach ($conf as $key => $val) { + $this->$key = $val; + } + } + + + /** + * + * Stub method for extended behaviors. + * + * @access public + * + * @return void + * + */ + + function compile($tpl) + { + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Error.php b/phpgwapi/inc/savant2/Savant2/Error.php new file mode 100755 index 0000000000..0d2051e953 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Error.php @@ -0,0 +1,125 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Error { + + + /** + * + * The error code, typically a SAVANT_ERROR_* constant. + * + * @access public + * + * @var int + * + */ + + var $code = null; + + + /** + * + * An array of error-specific information. + * + * @access public + * + * @var array + * + */ + + var $info = array(); + + + /** + * + * The error message text. + * + * @access public + * + * @var string + * + */ + + var $text = null; + + + /** + * + * A debug backtrace for the error, if any. + * + * @access public + * + * @var array + * + */ + + var $backtrace = null; + + + /** + * + * Constructor. + * + * @access public + * + * @param array $conf An associative array where the key is a + * Savant2_Error property and the value is the value for that + * property. + * + */ + + function Savant2_Error($conf = array()) + { + // set public properties + foreach ($conf as $key => $val) { + $this->$key = $val; + } + + // generate a backtrace + if (function_exists('debug_backtrace')) { + $this->backtrace = debug_backtrace(); + } + + // extended behaviors + $this->error(); + } + + + /** + * + * Stub method for extended behaviors. + * + * @access public + * + * @return void + * + */ + + function error() + { + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Filter.php b/phpgwapi/inc/savant2/Savant2/Filter.php new file mode 100755 index 0000000000..632f5b7d86 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Filter.php @@ -0,0 +1,76 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Filter { + + /** + * + * Optional reference to the calling Savant object. + * + * @var object + * + */ + + var $Savant = null; + + + /** + * + * Constructor. + * + * @access public + * + */ + + function Savant2_Filter($conf = array()) + { + settype($conf, 'array'); + foreach ($conf as $key => $val) { + $this->$key = $val; + } + } + + + /** + * + * Stub method for extended behaviors. + * + * @access public + * + * @param string &$text The text to filter. + * + * @return void + * + */ + + function filter(&$text) + { + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/PHPCodeAnalyzer.php b/phpgwapi/inc/savant2/Savant2/PHPCodeAnalyzer.php new file mode 100755 index 0000000000..9f9d56eb54 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/PHPCodeAnalyzer.php @@ -0,0 +1,471 @@ + +* @copyright Joshua Eichorn 2004 +* @package PHPCodeAnalyzer +* +* This program is free software; you can redistribute it and/or modify +* 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 +*/ + +/**#@+ +* compat tokeniezer defines +*/ +if (! defined('T_OLD_FUNCTION')) { + define('T_OLD_FUNCTION', T_FUNCTION); +} +if (!defined('T_ML_COMMENT')) { + define('T_ML_COMMENT', T_COMMENT); +} else { + define('T_DOC_COMMENT', T_ML_COMMENT); +} +/**#@-*/ + +/** +* Code Analysis class +* +* Example Usage: +* +* $analyzer = new PHPCodeAnalyzer(); +* $analyzer->source = file_get_contents(__FILE__); +* $analyzer->analyze(); +* print_r($analyzer->calledMethods); +* +* +* @todo is it important to grab the details from creating new functions defines classes? +* @todo support php5 only stuff like interface +* +* @version 0.4 +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* @copyright Joshua Eichorn 2004 +* @package PHPCodeAnalyzer +* @author Joshua Eichorn +*/ +class PHPCodeAnalyzer +{ + /** + * Source code to analyze + */ + var $source = ""; + + /** + * functions called + */ + var $calledFunctions = array(); + + /** + * Called constructs + */ + var $calledConstructs = array(); + + /** + * methods called + */ + var $calledMethods = array(); + + /** + * static methods called + */ + var $calledStaticMethods = array(); + + /** + * new classes instantiated + */ + var $classesInstantiated = array(); + + /** + * variables used + */ + var $usedVariables = array(); + + /** + * member variables used + */ + var $usedMemberVariables = array(); + + /** + * classes created + */ + var $createdClasses = array(); + + /** + * functions created + */ + var $createdFunctions = array(); + + /** + * Files includes or requried + */ + var $filesIncluded = array(); + + // private variables + /**#@+ + * @access private + */ + var $currentString = null; + var $currentStrings = null; + var $currentVar = false; + var $staticClass = false; + var $inNew = false; + var $inInclude = false; + var $lineNumber = 1; + /**#@-*/ + + /** + * parse source filling informational arrays + */ + function analyze() + { + $tokens = token_get_all($this->source); + + // mapping of token to method to call + $handleMap = array( + T_STRING => 'handleString', + T_CONSTANT_ENCAPSED_STRING => 'handleString', + T_ENCAPSED_AND_WHITESPACE => 'handleString', + T_CHARACTER => 'handleString', + T_NUM_STRING => 'handleString', + T_DNUMBER => 'handleString', + T_FUNC_C => 'handleString', + T_CLASS_C => 'handleString', + T_FILE => 'handleString', + T_LINE => 'handleString', + T_DOUBLE_ARROW => 'handleString', + + T_DOUBLE_COLON => 'handleDoubleColon', + T_NEW => 'handleNew', + T_OBJECT_OPERATOR => 'handleObjectOperator', + T_VARIABLE => 'handleVariable', + T_FUNCTION => 'handleFunction', + T_OLD_FUNCTION => 'handleFunction', + T_CLASS => 'handleClass', + T_WHITESPACE => 'handleWhitespace', + T_INLINE_HTML => 'handleWhitespace', + T_OPEN_TAG => 'handleWhitespace', + T_CLOSE_TAG => 'handleWhitespace', + + T_AS => 'handleAs', + + T_ECHO => 'handleConstruct', + T_EVAL => 'handleConstruct', + T_UNSET => 'handleConstruct', + T_ISSET => 'handleConstruct', + T_PRINT => 'handleConstruct', + T_FOR => 'handleConstruct', + T_FOREACH=> 'handleConstruct', + T_EMPTY => 'handleConstruct', + T_EXIT => 'handleConstruct', + T_CASE => 'handleConstruct', + T_GLOBAL=> 'handleConstruct', + T_UNSET => 'handleConstruct', + T_WHILE => 'handleConstruct', + T_DO => 'handleConstruct', + T_IF => 'handleConstruct', + T_LIST => 'handleConstruct', + T_RETURN=> 'handleConstruct', + T_STATIC=> 'handleConstruct', + T_ENDFOR=> 'handleConstruct', + T_ENDFOREACH=> 'handleConstruct', + T_ENDIF=> 'handleConstruct', + T_ENDSWITCH=> 'handleConstruct', + T_ENDWHILE=> 'handleConstruct', + + T_INCLUDE => 'handleInclude', + T_INCLUDE_ONCE => 'handleInclude', + T_REQUIRE => 'handleInclude', + T_REQUIRE_ONCE => 'handleInclude', + ); + + foreach($tokens as $token) + { + if (is_string($token)) + { + // we have a simple 1-character token + $this->handleSimpleToken($token); + } + else + { + list($id, $text) = $token; + if (isseT($handleMap[$id])) + { + $call = $handleMap[$id]; + $this->$call($id,$text); + } + /*else + { + echo token_name($id).": $text
\n"; + }*/ + } + } + } + + /** + * Handle a 1 char token + * @access private + */ + function handleSimpleToken($token) + { + if ($token !== ";") + { + $this->currentStrings .= $token; + } + switch($token) + { + case "(": + // method is called + if ($this->staticClass !== false) + { + if (!isset($this->calledStaticMethods[$this->staticClass][$this->currentString])) + { + $this->calledStaticMethods[$this->staticClass][$this->currentString] + = array(); + } + $this->calledStaticMethods[$this->staticClass][$this->currentString][] + = $this->lineNumber; + $this->staticClass = false; + } + else if ($this->currentVar !== false) + { + if (!isset($this->calledMethods[$this->currentVar][$this->currentString])) + { + $this->calledMethods[$this->currentVar][$this->currentString] = array(); + } + $this->calledMethods[$this->currentVar][$this->currentString][] = $this->lineNumber; + $this->currentVar = false; + } + else if ($this->inNew !== false) + { + $this->classInstantiated(); + } + else if ($this->currentString !== null) + { + $this->functionCalled(); + } + //$this->currentString = null; + break; + case "=": + case ";": + if ($this->inNew !== false) + { + $this->classInstantiated(); + } + else if ($this->inInclude !== false) + { + $this->fileIncluded(); + } + else if ($this->currentVar !== false) + { + $this->useMemberVar(); + } + $this->currentString = null; + $this->currentStrings = null; + break; + } + } + + /** + * handle includes and requires + * @access private + */ + function handleInclude($id,$text) + { + $this->inInclude = true; + $this->handleConstruct($id,$text); + } + + /** + * handle String tokens + * @access private + */ + function handleString($id,$text) + { + $this->currentString = $text; + $this->currentStrings .= $text; + } + + /** + * handle variables + * @access private + */ + function handleVariable($id,$text) + { + $this->currentString = $text; + $this->currentStrings .= $text; + $this->useVariable(); + } + + + /** + * handle Double Colon tokens + * @access private + */ + function handleDoubleColon($id,$text) + { + $this->staticClass = $this->currentString; + $this->currentString = null; + } + + /** + * handle new keyword + * @access private + */ + function handleNew($id,$text) + { + $this->inNew = true; + } + + /** + * handle function + * @access private + */ + function handleFunction($id,$text) + { + $this->createdFunctions[] = $this->lineNumber; + } + + /** + * handle class + * @access private + */ + function handleClass($id,$text) + { + $this->createdClasses[] = $this->lineNumber; + } + + /** + * Handle -> + * @access private + */ + function handleObjectOperator($id,$text) + { + $this->currentVar = $this->currentString; + $this->currentString = null; + $this->currentStrings .= $text; + } + + /** + * handle whitespace to figure out line counts + * @access private + */ + function handleWhitespace($id,$text) + { + $this->lineNumber+=substr_count($text,"\n"); + if ($id == T_CLOSE_TAG) + { + $this->handleSimpleToken(";"); + } + } + + + /** + * as has been used we must have a var before it + * + * @access private + */ + function handleAs($id,$text) + { + $this->handleSimpleToken(";"); + } + + /** + * a language construct has been called record it + * @access private + */ + function handleConstruct($id,$construct) + { + if (!isset($this->calledConstructs[$construct])) + { + $this->calledConstructs[$construct] = array(); + } + $this->calledConstructs[$construct][] = $this->lineNumber; + $this->currentString = null; + } + + /** + * a class was Instantiated record it + * @access private + */ + function classInstantiated() + { + if (!isset($this->classesInstantiated[$this->currentString])) + { + $this->classesInstantiated[$this->currentString] = array(); + } + $this->classesInstantiated[$this->currentString][] = $this->lineNumber; + $this->inNew = false; + } + + /** + * a file was included record it + * @access private + */ + function fileIncluded() + { + if (!isset($this->filesIncluded[$this->currentStrings])) + { + $this->filesIncluded[$this->currentStrings] = array(); + } + $this->filesIncluded[$this->currentStrings][] = $this->lineNumber; + $this->inInclude = false; + $this->currentString = null; + $this->currentStrings = ""; + } + + /** + * a function was called record it + * @access private + */ + function functionCalled($id = false) + { + if (!isset($this->calledFunctions[$this->currentString])) + { + $this->calledFunctions[$this->currentString] = array(); + } + $this->calledFunctions[$this->currentString][] = $this->lineNumber; + $this->currentString = null; + } + + /** + * we used a member variable record it + * @access private + */ + function useMemberVar() + { + if (!isset($this->usedMemberVariables[$this->currentVar][$this->currentString])) + { + $this->usedMemberVariables[$this->currentVar][$this->currentString] = array(); + } + $this->usedMemberVariables[$this->currentVar][$this->currentString][] = $this->lineNumber; + $this->currentVar = false; + $this->currentString = null; + } + + /** + * we used a variable record it + * @access private + */ + function useVariable() + { + if (!isset($this->usedVariables[$this->currentString])) + { + $this->usedVariables[$this->currentString] = array(); + } + $this->usedVariables[$this->currentString][] = $this->lineNumber; + } +} +?> diff --git a/phpgwapi/inc/savant2/Savant2/Plugin.php b/phpgwapi/inc/savant2/Savant2/Plugin.php new file mode 100755 index 0000000000..c3422541f5 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Plugin.php @@ -0,0 +1,74 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin { + + /** + * + * Optional reference to the calling Savant object. + * + * @var object + * + */ + + var $Savant = null; + + + /** + * + * Constructor. + * + * @access public + * + */ + + function Savant2_Plugin($conf = array()) + { + settype($conf, 'array'); + foreach ($conf as $key => $val) { + $this->$key = $val; + } + } + + + /** + * + * Stub method for extended behaviors. + * + * @access public + * + * @return void + * + */ + + function plugin() + { + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Compiler_basic.php b/phpgwapi/inc/savant2/Savant2/Savant2_Compiler_basic.php new file mode 100755 index 0000000000..440949e89c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Compiler_basic.php @@ -0,0 +1,847 @@ +', but then it +* will mess up your HTML comments ;-). +* +* When in "restrict" mode, ise of PHP commands not in the whitelists +* will cause the compiler to * fail. Use of various constructs and +* superglobals, likewise. +* +* Use {$var} or {$this->var} to print a variable. +* +* Use {: function-list} to print the results of function calls. +* +* Use {['pluginName', 'arg1', $arg2, $this->arg3]} to call plugins. +* +* Use these for looping: +* {foreach ():} ... {endforeach} +* {for ():} ... {endfor} +* {while ():} ... {endwhile} +* +* Use these for conditionals (normal PHP can go in the parens): +* {if (...):} +* {elseif (...):} +* {else:} +* {endif} +* {switch (...):} +* {case ...:} +* {default:} +* {endswitch} +* +* {break} and {continue} are supported as well. +* +* Use this to include a template: +* {tpl 'template.tpl.php'} +* {tpl $tplname} +* {tpl $this->tplname} +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +require_once 'Savant2/Compiler.php'; +require_once 'Savant2/Error.php'; +require_once 'Savant2/PHPCodeAnalyzer.php'; + +class Savant2_Compiler_basic extends Savant2_Compiler { + + + /** + * + * The template directive prefix. + * + * @access public + * + * @var array + * + */ + + var $prefix = '{'; + + + /** + * + * The template directive suffix. + * + * @access public + * + * @var array + * + */ + + var $suffix = '}'; + + + /** + * + * The conversion regular expressions. + * + * @access public + * + * @var array + * + */ + + var $convert = array( + + // branching + '(if\s*(.+):)' => '$1', + '(elseif\s*(.+):)' => '$1', + '(else\s*(.+):)' => '$1', + '(endif)' => '$1', + '(switch\s*(.+):)' => '$1', + '(case\s*(.+):)' => '$1', + '(default:)' => '$1', + '(endswitch)' => '$1', + '(break)' => '$1', + + // looping + '(foreach\s*(.+):)' => '$1', + '(endforeach)' => '$1', + '(for\s*(.+):)' => '$1', + '(endfor)' => '$1', + '(while\s*(.+):)' => '$1', + '(endwhile)' => '$1', + '(continue)' => '$1', + + // simple variable printing + '(\$(.+))' => 'print $1', + + // extended printing + '(\:(.+))' => 'print ($2)', + + // comments + '\*(.*)?\*' => '/**$1*/', + + // template includes + 'tpl (.*)' => 'include $this->findTemplate($1)', + + // plugins + '\[\s*(.+)?\s*\]' => '$this->plugin($1)', + ); + + + /** + * + * The list of allowed functions when in restricted mode. + * + * @access public + * + * @var array + * + */ + + var $allowedFunctions = array(); + + + /** + * + * The list of allowed static methods when in restricted mode. + * + * @access public + * + * @var array + * + */ + + var $allowedStatic = array(); + + + /** + * + * The directory where compiled templates are saved. + * + * @access public + * + * @var string + * + */ + + var $compileDir = null; + + + /** + * + * Whether or not to force every template to be compiled every time. + * + * @access public + * + * @var bool + * + */ + + var $forceCompile = false; + + + + /** + * + * Whether or not to strict-check the compiled template. + * + * Strict-checks are off by default until all problems with + * PhpCodeAnalyzer have been resolved. + * + * @access public + * + * @var bool + * + */ + + var $strict = false; + + + /** + * + * Constructor. + * + */ + + function Savant2_Compiler_basic($conf = array()) + { + parent::Savant2_Compiler($conf); + $this->ca =& new PHPCodeAnalyzer(); + $this->allowedFunctions = $this->allowedFunctions(); + $this->allowedStatic = $this->allowedStatic(); + } + + + /** + * + * Has the source template changed since it was last compiled? + * + * @access public + * + * @var string $tpl The source template file. + * + */ + + function changed($tpl) + { + // the path for the compiled file + $file = $this->getPath($tpl); + + // if the copmiled file does not exist, or if the mod-time of + // the source is later than that of the existing compiled file, + // then the source template file has changed. + if (! file_exists($file) || + filemtime($tpl) > filemtime($file)) { + return true; + } else { + return false; + } + } + + + /** + * + * Saves the PHP compiled from template source. + * + * @access public + * + * @var string $tpl The source template file. + * + */ + + function saveCompiled($tpl, $php) + { + $fp = fopen($this->getPath($tpl), 'w'); + if (! $fp) { + return false; + } else { + $result = fwrite($fp, $php); + fclose($fp); + return $result; + } + } + + + /** + * + * Gets the path to the compiled PHP for a template source. + * + * @access public + * + * @var string $tpl The source template file. + * + */ + + function getPath($tpl) + { + $dir = $this->compileDir; + if (substr($dir, -1) != DIRECTORY_SEPARATOR) { + $dir .= DIRECTORY_SEPARATOR; + } + return $dir . 'Savant2_' . md5($tpl); + } + + + /** + * + * Compiles a template source into PHP code for Savant. + * + * @access public + * + * @var string $tpl The source template file. + * + */ + + function compile($tpl) + { + // create a end-tag so that text editors don't + // stop colorizing text + $end = '?' . '>'; + + // recompile only if we are forcing compiled, or + // if the template source has changed. + if ($this->forceCompile || $this->changed($tpl)) { + + // get the template source text + $php = file_get_contents($tpl); + + /** + * @todo Do we really care about PHP tags? The code analyzer + * will disallow any offending PHP regardless. + */ + + // disallow PHP long tags + $php = str_replace('convert as $find => $replace) { + + // allow whitespace around the command + $find = preg_quote($this->prefix) . '\s*' . $find . + '\s*' . preg_quote($this->suffix); + + // actually do the find-and-replace + $php = preg_replace( + "/$find/U", + "saveCompiled($tpl, $php); + // --- DEBUG + + // are we doing strict checking? + if ($this->strict) { + // analyze the code for restriction violations. + $report = $this->analyze($php); + if (count($report) > 0) { + // there were violations, report them as a generic + // Savant error and return. Savant will wrap this + // generic rror with another error that will report + // properly to the customized error handler (if any). + return new Savant2_Error( + array( + 'code' => SAVANT2_ERROR_COMPILE_FAIL, + 'text' => $GLOBALS['_SAVANT2']['error'][SAVANT2_ERROR_COMPILE_FAIL], + 'info' => $report + ) + ); + } + } + + // otherwise, save the compiled template + $this->saveCompiled($tpl, $php); + } + + // return the path to the compiled PHP script + return $this->getPath($tpl); + } + + + /** + * + * Analyze a compiled template for restriction violations. + * + * @access public + * + * @var string $php The compiled PHP code from a template source. + * + * @return array An array of restriction violations; if empty, then + * there were no violations discovered by analysis. + * + */ + + function analyze(&$php) + { + // analyze the compiled code + $ca =& $this->ca; + $ca->source =& $php; + $ca->analyze(); + + // array of captured restriction violations + $report = array(); + + // ------------------------------------------------------------- + // + // go through the list of called functions and make sure each + // one is allowed via the whitelist. if not, record each non- + // allowed function. this also restricts variable-functions + // such as $var(). + // + + foreach ($ca->calledFunctions as $func => $lines) { + if (! in_array($func, $this->allowedFunctions)) { + $report[$func] = $lines; + } + } + + // ------------------------------------------------------------- + // + // disallow use of various constructs (include is allowed, we + // need it for {tpl}). + // + + $tmp = array( + 'eval', + 'global', + 'include_once', + 'require', + 'require_once', + 'parent', + 'self' + ); + + foreach ($tmp as $val) { + if (isset($ca->calledConstructs[$val])) { + $report[$val] = $ca->calledConstructs[$val]; + } + } + + // ------------------------------------------------------------- + // + // disallow instantiation of new classes + // + + foreach ($ca->classesInstantiated as $key => $val) { + $report['new ' . $key] = $val; + } + + // ------------------------------------------------------------- + // + // disallow access to the various superglobals + // so that templates cannot manipulate them. + // + + $tmp = array( + '$_COOKIE', + '$_ENV', + '$_FILES', + '$_GET', + '$_POST', + '$_REQUEST', + '$_SERVER', + '$_SESSION', + '$GLOBALS', + '$HTTP_COOKIE_VARS', + '$HTTP_ENV_VARS', + '$HTTP_GET_VARS', + '$HTTP_POST_FILES', + '$HTTP_POST_VARS', + '$HTTP_SERVER_VARS', + '$HTTP_SESSION_VARS' + ); + + foreach ($ca->usedVariables as $var => $lines) { + if (in_array(strtoupper($var), $tmp)) { + $report[$var] = $lines; + } + } + + // ------------------------------------------------------------- + // + // allow only certain $this methods + // + + $tmp = array('plugin', 'splugin', 'findTemplate'); + if (isset($ca->calledMethods['$this'])) { + foreach ($ca->calledMethods['$this'] as $method => $lines) { + if (! in_array($method, $tmp)) { + $report['$this->' . $method] = $lines; + } + } + } + + // ------------------------------------------------------------- + // + // disallow private and variable-variable $this properties + // + + if (isset($ca->usedMemberVariables['$this'])) { + foreach ($ca->usedMemberVariables['$this'] as $prop => $lines) { + $char = substr($prop, 0, 1); + if ($char == '_' || $char == '$') { + $report['$this->' . $prop] = $lines; + } + } + } + + // ------------------------------------------------------------- + // + // allow only certain static method calls + // + + foreach ($ca->calledStaticMethods as $class => $methods) { + foreach ($methods as $method => $lines) { + if (! array_key_exists($class, $this->allowedStatic)) { + + // the class itself is not allowed + $report["$class::$method"] = $lines; + + } elseif (! in_array('*', $this->allowedStatic[$class]) && + ! in_array($method, $this->allowedStatic[$class])){ + + // the specific method is not allowed, + // and there is no wildcard for the class methods. + $report["$class::$method"] = $lines; + + } + } + } + + // ------------------------------------------------------------- + // + // only allow includes via $this->findTemplate(*) + // + + foreach ($ca->filesIncluded as $text => $lines) { + + // in each include statment, look for $this->findTemplate. + preg_match( + '/(.*)?\$this->findTemplate\((.*)?\)(.*)/i', + $text, + $matches + ); + + if (! empty($matches[1]) || ! empty($matches[3]) || + empty($matches[2])) { + + // there is something before or after the findTemplate call, + // or it's a direct include (which is not allowed) + $report["include $text"] = $lines; + + } + } + + // ------------------------------------------------------------- + // + // do not allow the use of "$this" by itself; + // it must be always be followed by "->" or another + // valid variable-name character (a-z, 0-9, or _). + // + + $regex = '/(.*)?\$this(?!(\-\>)|([a-z0-9_]))(.*)?/i'; + preg_match_all($regex, $php, $matches, PREG_SET_ORDER); + foreach ($matches as $val) { + $report['\'$this\' without \'->\''][] = $val[0]; + } + + /** @todo disallow standalone variable-variables, $$var */ + + /** @todo disallow vars from static classes? class::$var */ + + + // ------------------------------------------------------------- + // + // done! + // + + // +++ DEBUG + //echo "
";
+		//print_r($ca);
+		//echo "
"; + // --- DEBUG + + return $report; + } + + + /** + * + * A list of allowed static method calls for templates. + * + * The format is ... + * + * array( + * 'Class1' => array('method1', 'method2'), + * 'Class2' => array('methodA', 'methodB'), + * 'Class3' => '*' + * ); + * + * If you want to allow all methods from the static class to be allowed, + * use a '*' in the method name list. + * + */ + + function allowedStatic() + { + return array(); + } + + + /** + * + * A list of allowed functions for templates. + * + */ + + function allowedFunctions() + { + return array( + + // arrays + 'array_count_values', + 'array_key_exists', + 'array_keys', + 'array_sum', + 'array_values', + 'compact', + 'count', + 'current', + 'each', + 'end', + 'extract', + 'in_array', + 'key', + 'list', + 'next', + 'pos', + 'prev', + 'reset', + 'sizeof', + + // calendar + 'cal_days_in_month', + 'cal_from_jd', + 'cal_to_jd', + 'easter_date', + 'easter_days', + 'FrenchToJD', + 'GregorianToJD', + 'JDDayOfWeek', + 'JDMonthName', + 'JDToFrench', + 'JDToGregorian', + 'jdtojewish', + 'JDToJulian', + 'jdtounix', + 'JewishToJD', + 'JulianToJD', + 'unixtojd', + + // date + 'checkdate', + 'date_sunrise', + 'date_sunset', + 'date', + 'getdate', + 'gettimeofday', + 'gmdate', + 'gmmktime', + 'gmstrftime', + 'idate', + 'localtime', + 'microtime', + 'mktime', + 'strftime', + 'strptime', + 'strtotime', + 'time', + + // gettext + '_', + 'gettext', + 'ngettext', + + // math + 'abs', + 'acos', + 'acosh', + 'asin', + 'asinh', + 'atan2', + 'atan', + 'atanh', + 'base_convert', + 'bindec', + 'ceil', + 'cos', + 'cosh', + 'decbin', + 'dechex', + 'decoct', + 'deg2rad', + 'exp', + 'expm1', + 'floor', + 'fmod', + 'getrandmax', + 'hexdec', + 'hypot', + 'is_finite', + 'is_infinite', + 'is_nan', + 'lcg_value', + 'log10', + 'log1p', + 'log', + 'max', + 'min', + 'mt_getrandmax', + 'mt_rand', + 'mt_srand', + 'octdec', + 'pi', + 'pow', + 'rad2deg', + 'rand', + 'round', + 'sin', + 'sinh', + 'sqrt', + 'srand', + 'tan', + 'tanh', + + // strings + 'chop', + 'count_chars', + 'echo', + 'explode', + 'hebrev', + 'hebrevc', + 'html_entity_decode', + 'htmlentities', + 'htmlspecialchars', + 'implode', + 'join', + 'localeconv', + 'ltrim', + 'money_format', + 'nl_langinfo', + 'nl2br', + 'number_format', + 'ord', + 'print', + 'printf', + 'quoted_printable_decode', + 'rtrim', + 'sprintf', + 'sscanf', + 'str_pad', + 'str_repeat', + 'str_replace', + 'str_rot13', + 'str_shuffle', + 'str_word_count', + 'strcasecmp', + 'strchr', + 'strcmp', + 'strcoll', + 'strcspn', + 'strip_tags', + 'stripcslashes', + 'stripos', + 'stripslashes', + 'stristr', + 'strlen', + 'strnatcasecmp', + 'strnatcmp', + 'strncasecmp', + 'strncmp', + 'strpbrk', + 'strpos', + 'strrchr', + 'strrev', + 'strripos', + 'strrpos', + 'strspn', + 'strstr', + 'strtok', + 'strtolower', + 'strtoupper', + 'strtr', + 'substr_compare', + 'substr_count', + 'substr_replace', + 'substr', + 'trim', + 'ucfirst', + 'ucwords', + 'wordwrap', + + // url + 'base64_decode', + 'base64_encode', + 'rawurldecode', + 'rawurlencode', + 'urldecode', + 'urlencode', + + // variables + 'empty', + 'is_array', + 'is_bool', + 'is_double', + 'is_float', + 'is_int', + 'is_integer', + 'is_long', + 'is_null', + 'is_numeric', + 'is_object', + 'is_real', + 'is_resource', + 'is_scalar', + 'is_string', + 'isset', + 'print_r', + 'unset', + 'var_dump', + ); + } +} + + + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Error_exception.php b/phpgwapi/inc/savant2/Savant2/Savant2_Error_exception.php new file mode 100755 index 0000000000..61a7106e0e --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Error_exception.php @@ -0,0 +1,53 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Error_exception extends Savant2_Error { + + + /** + * + * Throws an Savant2_Exception in PHP5. + * + * @return void + * + */ + + function error() + { + throw new Savant2_Exception($this->text, $this->code); + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Error_pear.php b/phpgwapi/inc/savant2/Savant2/Savant2_Error_pear.php new file mode 100755 index 0000000000..f7e62d3b81 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Error_pear.php @@ -0,0 +1,56 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Error_pear extends Savant2_Error { + + + /** + * + * Extended behavior for PEAR_Error. + * + * @access public + * + * @return void + * + */ + + function error() + { + // throw a PEAR_Error + PEAR::throwError($this->text, $this->code, $this->info); + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Error_stack.php b/phpgwapi/inc/savant2/Savant2/Savant2_Error_stack.php new file mode 100755 index 0000000000..32a783fd9e --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Error_stack.php @@ -0,0 +1,60 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Error_stack extends Savant2_Error { + + + /** + * + * Pushes an error onto the PEAR_ErrorStack. + * + * @return void + * + */ + + function error() + { + // push an error onto the stack + PEAR_ErrorStack::staticPush( + 'Savant2', // package name + $this->code, // error code + null, // error level + $this->info, // user info + $this->text // error message + ); + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Filter_colorizeCode.php b/phpgwapi/inc/savant2/Savant2/Savant2_Filter_colorizeCode.php new file mode 100755 index 0000000000..0a5d287454 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Filter_colorizeCode.php @@ -0,0 +1,123 @@ +... tags. +* +* @author Paul M. Jones +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Filter_colorizeCode extends Savant2_Filter { + + /** + * + * Colorizes all text between ... tags. + * + * Colorizes all text between ... tags with PHP's + * highlight_string function. Additionally, this will convert HTML + * entities within blocks, so you can demonstrate HTML tags + * without them being honored in the browser. Also converts tabs to four + * spaces. + * + * To mark the beginning of php code in a block, use the custom + * tag , and use to mark the end. You can't use the normal + * php code tags because Savant2 will try to execute that code when the + * template runs. + * + * @access public + * + * @param string &$text The source text to be filtered. + * + * @return void + * + */ + + function filter(&$text) + { + // break the source into blocks by the beginning tag. + // this will remove the text "" from the block, so + // we'll need to add it in again later. + $blocks = explode('', $text); + + // loop through each block and convert text within + // tags. + foreach ($blocks as $key => $val) { + + // now find then the ending within the block + $pos = strpos($val, ''); + + if ($pos === false) { + + // there was no tag -- do nothing + + } else { + + // change all and tags + $val = str_replace('', '', '?>', $val); // , and + // thus the part we want to modify. + // + // $tmp[1] will be the part after the + // block, which we will leave + // alone. + // + // this will remove the text "" from the + // text, so we'll need to add it in again when modifying + // the text. + $tmp = explode('', $val); + + // set entities by highlighting the string. we do the + // output buffering ob() thing because the native + // highlight_string() dumps the output to the screen + // instead of returning to a variable (before PHP + // 4.2.2). + $tmp[0] = trim($tmp[0]); + + ob_start(); + highlight_string($tmp[0]); + $tmp[0] = ob_get_contents(); + ob_end_clean(); + + // remove break tags from the highlighted text + $tmp[0] = str_replace("
", "\n", $tmp[0]); + + // convert tabs to 4-spaces and then + // re-surround with tags + $tmp[0] = str_replace("\t", ' ', $tmp[0]); + + // save the modified text in the block + $blocks[$key] = $tmp[0] . $tmp[1]; + } + + } + + // reassemble the blocks + $text = implode('', $blocks); + } +} \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Filter_trimwhitespace.php b/phpgwapi/inc/savant2/Savant2/Savant2_Filter_trimwhitespace.php new file mode 100755 index 0000000000..aebe0b9b7c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Filter_trimwhitespace.php @@ -0,0 +1,104 @@ + +* +* @author Contributions from Lars Noschinski +* +* @author Converted to a Savant2 filter by Paul M. Jones +* +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Filter_trimwhitespace extends Savant2_Filter { + + /** + * + * Removes extra white space within the text. + * + * Trim leading white space and blank lines from template source after it + * gets interpreted, cleaning up code and saving bandwidth. Does not + * affect
>
and blocks.
+ * + * @access public + * + * @param string &$source The source text to be filtered. + * + */ + + function filter(&$source) + { + // Pull out the script blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_script_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SAVANT:TRIM:SCRIPT@@@', $source); + + // Pull out the pre blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_pre_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SAVANT:TRIM:PRE@@@', $source); + + // Pull out the textarea blocks + preg_match_all("!]+>.*?!is", $source, $match); + $_textarea_blocks = $match[0]; + $source = preg_replace("!]+>.*?!is", + '@@@SAVANT:TRIM:TEXTAREA@@@', $source); + + // remove all leading spaces, tabs and carriage returns NOT + // preceeded by a php close tag. + $source = trim(preg_replace('/((?)\n)[\s]+/m', '\1', $source)); + + // replace script blocks + Savant2_Filter_trimwhitespace::_replace( + "@@@SAVANT:TRIM:SCRIPT@@@",$_script_blocks, $source); + + // replace pre blocks + Savant2_Filter_trimwhitespace::_replace( + "@@@SAVANT:TRIM:PRE@@@",$_pre_blocks, $source); + + // replace textarea blocks + Savant2_Filter_trimwhitespace::_replace( + "@@@SAVANT:TRIM:TEXTAREA@@@",$_textarea_blocks, $source); + + return $source; + } + + function _replace($search_str, $replace, &$subject) + { + $_len = strlen($search_str); + $_pos = 0; + for ($_i=0, $_count=count($replace); $_i<$_count; $_i++) { + if (($_pos=strpos($subject, $search_str, $_pos))!==false) { + $subject = substr_replace($subject, $replace[$_i], $_pos, $_len); + } else { + break; + } + } + } + +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_ahref.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_ahref.php new file mode 100755 index 0000000000..14b9a2abe5 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_ahref.php @@ -0,0 +1,114 @@ +... tag. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_ahref extends Savant2_Plugin { + + /** + * + * Output an HTML ... tag. + * + * @access public + * + * @param string|array $href A string URL for the resulting tag. May + * also be an array with any combination of the keys 'scheme', + * 'host', 'path', 'query', and 'fragment' (c.f. PHP's native + * parse_url() function). + * + * @param string $text The displayed text of the link. + * + * @param string|array $attr Any extra attributes for the tag. + * + * @return string The ... tag. + * + */ + + function plugin($href, $text, $attr = null) + { + $html = ' $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $html .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // from scalar + $html .= " $attr"; + } + + // set the link text, close the tag, and return + $html .= '>' . htmlspecialchars($text) . ''; + return $html; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_checkbox.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_checkbox.php new file mode 100755 index 0000000000..d84a3f20bf --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_checkbox.php @@ -0,0 +1,103 @@ + element. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_checkbox extends Savant2_Plugin { + + /** + * + * Outputs a single checkbox element. + * + * @access public + * + * @param string $name The HTML "name=" value for the checkbox. + * + * @param string $value The value of the checkbox when checked. + * + * @param array $checked If $value is in this array of values, + * mark the checkbox as checked. + * + * @param array $default The value to return if the checkbox is not + * checked. + * + * @param string|array $attr Any extra HTML attributes to place + * within the checkbox element. + * + * @return string + * + */ + + function plugin( + $name, + $value = '1', + $checked = null, + $default = null, + $attr = null) + { + $html = ''; + + // define the hidden default value (if any) when not checked + if (! is_null($default)) { + $html .= ''; + $html .= "\n"; + } + + // start the checkbox tag with name and value + $html .= ' $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $html .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // add from scalar + $html .= " $attr"; + } + + // close the checkbox tag and return + $html .= ' />'; + return $html; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_cycle.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_cycle.php new file mode 100755 index 0000000000..a90c7233e5 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_cycle.php @@ -0,0 +1,97 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_cycle extends Savant2_Plugin { + + /** + * + * An associative array of predefined cycle value sets. + * + * You can preset cycle values via Savant::loadPlugin(). + * + * $conf = array( + * 'values' => array( + * 'lightdark' => array('light', 'dark'), + * 'threesome' => array('one', 'two', 'three') + * ) + * ); + * + * $Savant->loadPlugin('cycle', $conf); + * + * ... and in your template you can call: + * + * $this->plugin('cycle', 'lightdark', $iteration); + * + * @access public + * + * @var array + * + */ + + var $values = array(); + + + /** + * + * Cycles through a series of values. + * + * @access public + * + * @param string|array $cycle If a string, the preset cycle value key to use + * from $this->cycles; if an array, use the array as the cycle values. + * + * @param int $iteration The iteration number for the cycle. + * + * @param int $repeat The number of times to repeat each cycle value. + * + * @return mixed The value of the cycle iteration. + * + */ + + function plugin($cycle, $iteration, $repeat = 1) + { + // get the proper value set as an array + if (is_string($cycle) && isset($this->values[$cycle])) { + $values = (array) $this->values[$cycle]; + } else { + $values = (array) $cycle; + } + + // prevent divide-by-zero errors + if ($repeat == 0) { + $repeat = 1; + } + + // return the perper value for iteration and repetition + return $values[($iteration / $repeat) % count($values)]; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_dateformat.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_dateformat.php new file mode 100755 index 0000000000..cc6fb09fc6 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_dateformat.php @@ -0,0 +1,136 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_dateformat extends Savant2_Plugin { + + /** + * + * The default strftime() format string to use for dates. + * + * You can preset the default format string via Savant::loadPlugin(). + * + * $conf = array( + * 'format' => '%Y-%m-%d %H:%M:%S' + * ); + * + * $Savant->loadPlugin('dateformat', $conf); + * + * ... and in your template, to use the default format string: + * + * $this->plugin('date', $datestring); + * + * ... or, to use a custom string at call-time: + * + * $this->plugin('date', $datestring, '%b'); + * + * @access public + * + * @var string + * + */ + + var $format = '%c'; + + + /** + * + * The default strftime() format string to use for dates. + * + * You can preset the custom format strings via Savant::loadPlugin(). + * + * $conf = array( + * 'custom' => array( + * 'mydate' => '%Y-%m-%d', + * 'mytime' => '%R' + * ) + * ); + * + * $Savant->loadPlugin('dateformat', $conf); + * + * ... and in your template, to use a preset custom string by name: + * + * $this->plugin('date', $datestring, 'mydate'); + * + * @access public + * + * @var array + * + */ + + var $custom = array( + 'date' => '%Y-%m-%d', + 'time' => '%H:%M:%S' + ); + + + /** + * + * Outputs a formatted date using strftime() conventions. + * + * @access public + * + * @param string $datestring Any date-time string suitable for + * strtotime(). + * + * @param string $format The strftime() formatting string, or a named + * custom string key from $this->custom. + * + * @return string + * + */ + + function plugin($datestring, $format = null) + { + settype($format, 'string'); + + // does the format string have a % sign in it? + if (strpos($format, '%') === false) { + // no, look for a custom format string + if (isset($this->custom[$format])) { + // found a custom format string + $format = $this->custom[$format]; + } else { + // did not find the custom format, revert to default + $format = $this->format; + } + } + + // convert the date string to the specified format + if (trim($datestring != '')) { + return strftime($format, strtotime($datestring)); + } else { + // no datestring, return VOID + return; + } + } + +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_form.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_form.php new file mode 100755 index 0000000000..a32f8f714c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_form.php @@ -0,0 +1,1596 @@ + +* +* @package Savant2 +* +* @todo Add non-standard elements: date, time, hierselect, autocomplete +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_form extends Savant2_Plugin { + + + /** + * + * The CSS class to use when generating form layout. + * + * This class name will be applied to the following tags: + * + * - div + * - fieldset + * - legend + * - table + * - tr + * - th + * - td + * - label + * + * @access public + * + * @var array + * + */ + + var $class = ''; + + + /** + * + * The default 'float' style for fieldset blocks. + * + * @access public + * + * @var string + * + */ + + var $float = ''; + + + /** + * + * The default 'clear' style for fieldset blocks. + * + * @access public + * + * @var string + * + */ + + var $clear = ''; + + + /** + * + * The sprintf() format for element notes in col-type blocks. + * + * @access public + * + * @var string + * + */ + + var $noteCol = '%s'; + + + /** + * + * The sprintf() format for element notes in row-type blocks. + * + * @access public + * + * @var string + * + */ + + var $noteRow = '%s'; + + + /** + * + * The text used to separate radio buttons in col-type blocks. + * + * @access public + * + * @var string + * + */ + + var $radioCol = '
'; + + + /** + * + * The text used to separate radio buttons in row-type blocks. + * + * @access public + * + * @var string + * + */ + + var $radioRow = '  '; + + + /** + * + * The base number of tabs to use when tidying up the generated XHTML. + * + * @access public + * + * @var int + * + */ + + var $tabBase = 2; + + + /** + * + * The sprintf() format for validation messages in col-type blocks. + * + * @access public + * + * @var string + * + */ + + var $validCol = '
%s'; + + + /** + * + * The sprintf() format for validation messages in col-type blocks. + * + * @access public + * + * @var string + * + */ + + var $validRow = '
%s'; + + + /** + * + * Whether or not to automatically dispel magic quotes from values. + * + * @access public + * + * @var bool + * + */ + + var $unquote = true; + + + /** + * + * Whether or not to use automatic layout. + * + * @access public + * + * @var bool + * + */ + + var $layout = true; + + + /** + * + * The kind of fieldset block being generated ('col' or 'row'). + * + * @access private + * + * @var bool + * + */ + + var $_blockType = null; + + + /** + * + * The legend for the fieldset block, if any. + * + * @access private + * + * @var string + * + */ + + var $_blockLabel = null; + + + /** + * + * Whether or not the form is generating elements within a fieldset block. + * + * @access private + * + * @var bool + * + */ + + var $_inBlock = false; + + + /** + * + * Whether or not the form is generating elements as a group. + * + * @access private + * + * @var bool + * + */ + + var $_inGroup = false; + + + /** + * + * The number of tabs to use before certain tags when tidying XHTML layout. + * + * @access private + * + * @var bool + * + */ + + var $_tabs = array( + 'form' => 0, + '/form' => 0, + 'div' => 1, + '/div' => 1, + 'fieldset' => 1, + '/fieldset' => 1, + 'legend' => 2, + 'table' => 2, + '/table' => 2, + 'tr' => 3, + '/tr' => 3, + 'th' => 4, + '/th' => 4, + 'td' => 4, + '/td' => 4, + 'label' => 5, + 'input type="button"' => 5, + 'input type="checkbox"' => 5, + 'input type="file"' => 5, + 'input type="hidden"' => 5, + 'input type="image"' => 5, + 'input type="password"' => 5, + 'input type="reset"' => 5, + 'input type="submit"' => 5, + 'input type="text"' => 5, + 'textarea' => 5, + 'select' => 5, + '/select' => 5, + 'option' => 6 + ); + + + /** + * + * Central switcher API for the the various public methods. + * + * @access public + * + * @param string $method The public method to call from this class; all + * additional parameters will be passed to the called method, and all + * returns from the mehtod will be tidied. + * + * @return string XHTML generated by the public method. + * + */ + + function plugin($method) + { + // only pass calls to public methods (i.e., no leading underscore) + if (substr($method, 0, 1) != '_' && method_exists($this, $method)) { + + // get all arguments and drop the first one (the method name) + $args = func_get_args(); + array_shift($args); + + // call the method, then return the tidied-up XHTML results + $xhtml = call_user_func_array(array(&$this, $method), $args); + return $this->_tidy($xhtml); + } + } + + + /** + * + * Sets the value of a public property. + * + * @access public + * + * @param string $key The name of the property to set. + * + * @param mixed $val The new value for the property. + * + * @return void + * + */ + + function set($key, $val) + { + if (substr($key, 0, 1) != '_' && isset($this->$key)) { + $this->$key = $val; + } + } + + + // --------------------------------------------------------------------- + // + // Form methods + // + // --------------------------------------------------------------------- + + + /** + * + * Starts the form. + * + * The form defaults to 'action="$_SERVER['REQUEST_URI']"' and + * 'method="post"', but you can override those, and add any other + * attributes you like. + * + * @access public + * + * @param array|string $attr Attributes to add to the form tag. + * + * @return A
tag. + * + */ + + function start($attr = null) + { + // make sure there is at least an empty array of attributes + if (is_null($attr)) { + $attr = array(); + } + + // make sure there is a default action and method from + // the attribute array. + if (is_array($attr)) { + + // default action + if (! isset($attr['action'])) { + $attr['action'] = $_SERVER['REQUEST_URI']; + } + + // default method + if (! isset($attr['method'])) { + $attr['method'] = 'post'; + } + + // default encoding + if (! isset($attr['enctype'])) { + $attr['enctype'] = 'multipart/form-data'; + } + } + + // start the form + $xhtml = '_attr($attr) . ">"; + return $xhtml; + } + + + /** + * + * Ends the form and closes any existing layout. + * + * @access public + * + * @return The ending layout XHTML and a tag. + * + */ + + function end() + { + $xhtml = ''; + $xhtml .= $this->group('end'); + $xhtml .= $this->block('end'); + return $xhtml . ''; + } + + + // --------------------------------------------------------------------- + // + // Element methods + // + // --------------------------------------------------------------------- + + + /** + * + * Generates a 'button' element. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param string $label The element label. + * + * @param array|string $attr Attributes for the element tag. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element XHTML. + * + */ + + function button($name, $value = null, $label = null, $attr = null, + $validCode = null, $validMsg = null) + { + $xhtml = $this->_input('button', $name, $value, $attr); + return $this->_element($label, $xhtml, $validCode, $validMsg); + } + + + /** + * + * Generates a 'checkbox' element. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param string $label The element label. + * + * @param mixed $options If a scalar (single value), then value of the + * checkbox when checked; if an array, element 0 is the value when + * checked, and element 1 is the value when not-checked. + * + * @param array|string $attr Attributes for the element tag. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element XHTML. + * + */ + + function checkbox($name, $value = null, $label = null, $options = null, + $attr = null, $validCode = null, $validMsg = null) + { + if (is_null($options)) { + $options = array(1, 0); + } else { + settype($options, 'array'); + } + + $options = $this->_unquote($options); + + if (isset($options[1])) { + $xhtml = $this->_input('hidden', $name, $options[1]); + } else { + $xhtml = ''; + } + + $xhtml .= '_attr($attr); + $xhtml .= ' />'; + return $this->_element($label, $xhtml, $validCode, $validMsg); + } + + + /** + * + * Generates a 'file' element. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param string $label The element label. + * + * @param array|string $attr Attributes for the element tag. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element XHTML. + * + */ + + function file($name, $value = null, $label = null, $attr = null, + $validCode = null, $validMsg = null) + { + $xhtml = $this->_input('file', $name, $value, $attr); + return $this->_element($label, $xhtml, $validCode, $validMsg); + } + + + /** + * + * Generates a 'hidden' element (no layout is generated). + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param array|string $attr Attributes for the element tag. + * + * @return string The element XHTML. + * + */ + + function hidden($name, $value = null, $attr = null) + { + return $this->_input('hidden', $name, $value, $attr); + } + + + /** + * + * Generates an 'image' element. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $src The image HREF source. + * + * @param string $label The element label. + * + * @param array|string $attr Attributes for the element tag. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element XHTML. + * + */ + + function image($name, $src, $label = null, $attr = null, $validCode = null, + $validMsg = null) + { + $xhtml = '_attr($attr); + $xhtml .= ' />'; + return $this->_element($label, $xhtml, $validCode, $validMsg); + } + + + /** + * + * Generates a 'password' element. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param string $label The element label. + * + * @param array|string $attr Attributes for the element tag. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element XHTML. + * + */ + + function password($name, $value = null, $label = null, $attr = null, + $validCode = null, $validMsg = null) + { + $xhtml = $this->_input('password', $name, $value, $attr); + return $this->_element($label, $xhtml, $validCode, $validMsg); + } + + + /** + * + * Generates a set of radio button elements. + * + * @access public + * + * @param string $name The element name. + * + * @param mixed $value The radio value to mark as 'checked'. + * + * @param string $label The element label. + * + * @param array $options An array of key-value pairs where the array + * key is the radio value, and the array value is the radio text. + * + * @param array|string $attr Attributes added to each radio. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The radio buttons XHTML. + * + */ + + function radio($name, $value = null, $label = null, $options = null, + $attr = null, $validCode = null, $validMsg = null) + { + settype($options, 'array'); + $value = $this->_unquote($value); + + $list = array(); + foreach ($options as $optval => $optlabel) { + $radio = ''; + } + $xhtml .= ''; + $xhtml .= $this->_tag('td'); + } + + // build a 'row' group? + if ($this->_blockType == 'row') { + $xhtml .= $this->_tag('td'); + if (! is_null($label)) { + $xhtml .= $this->_tag('label'); + $xhtml .= htmlspecialchars($label); + $xhtml .= '
'; + } + } + + // we're in a group now + $this->_inGroup = true; + + } + + // are we ending a current group? + if ($type == 'end' && $this->_inGroup) { + + // we're out of the group now + $this->_inGroup = false; + + if ($this->_blockType == 'col') { + $xhtml .= ''; + } + + if ($this->_blockType == 'row') { + $xhtml .= ''; + } + } + + // done! + return $xhtml; + } + + + // --------------------------------------------------------------------- + // + // Private support methods + // + // --------------------------------------------------------------------- + + + /** + * + * Builds an attribute string for a tag. + * + * @access private + * + * @param array|string $attr The attributes to add to a tag; if an array, + * the key is the attribute name and the value is the attribute value; if a + * string, adds the literal string to the tag. + * + * @return string A string of tag attributes. + * + */ + + function _attr($attr = null) + { + if (is_array($attr)) { + // add from array + $xhtml = ''; + foreach ($attr as $key => $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $xhtml .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // add from scalar + $xhtml = " $attr"; + } else { + $xhtml = null; + } + + return $xhtml; + } + + + /** + * + * Builds an XHTML opening tag with class and attributes. + * + * @access private + * + * @param string $type The tag type ('td', 'th', 'div', etc). + * + * @param array|string $attr Additional attributes for the tag. + * + * @return string The opening tag XHTML. + * + */ + + function _tag($type, $attr = null) + { + // open the tag + $xhtml = '<' . $type; + + // add a CSS class attribute + if ($this->class) { + $xhtml .= ' class="' . $this->class . '"'; + } + + // add other attributes + $xhtml .= $this->_attr($attr); + + // done! + return $xhtml . ">"; + } + + + /** + * + * Adds an element to the table layout; auto-starts a block as needed. + * + * @access private + * + * @param string $label The label for the element. + * + * @param string $fieldXhtml The XHTML for the element field. + * + * @param mixed $validCode A validation code. If exactly boolean + * true, or exactly null, no validation message will be displayed. + * If any other integer, string, or array value, the element is + * treated as not-valid and will display the corresponding message. + * + * @param mixed array|string $validMsg A validation message. If an + * array, the $validCode value is used as a key for this array to + * determine which message(s) should be displayed. + * + * @return string The element layout XHTML. + * + */ + + function _element($label, $fieldXhtml, $validCode = null, $validMsg = null) + { + // the XHTML to return + $xhtml = ''; + + // if we're starting an element without having started + // a block first, forcibly start a default block + if (! $this->_inBlock) { + + // is there a label for the element? + if (is_null($label)) { + // not in a block, and no label specified. this is most + // likely a hidden element above the form itself. just + // return the XHTML as it is, no layout at all. + return $fieldXhtml; + } else { + // start a block and continue + $xhtml .= $this->block(); + } + } + + // are we checking validation and adding validation messages? + if ($validCode === null || $validCode === true) { + + // do nothing + + } else { + + // force to arrays so we can have multiple messages. + settype($validCode, 'array'); + settype($validMsg, 'array'); + + // pick the format + if ($this->_inBlock && $this->_blockType == 'row') { + $format = $this->validRow; + } else { + $format = $this->validCol; + } + + // add the validation messages + foreach ($validCode as $code) { + if (isset($validMsg[$code])) { + // print the message + $fieldXhtml .= sprintf( + $format, + $validMsg[$code] + ); + } else { + // print the code + $fieldXhtml .= sprintf( + $format, + $code + ); + } + } + } + + // are we in a group? + if (! $this->_inGroup) { + // no, put the element in a group by itself + $xhtml .= $this->group('start', $label); + $xhtml .= $fieldXhtml; + $xhtml .= $this->group('end'); + } else { + // yes, just add the element to the current group. + // elements in groups do not get their own labels, + // the group has already set the label. + $xhtml .= $fieldXhtml; + } + + // done! + return $xhtml; + } + + + /** + * + * Recursively removes magic quotes from values and arrays. + * + * @access private + * + * @param mixed $value The value from which to remove magic quotes. + * + * @return mixed The un-quoted value. + * + */ + + function _unquote($value) + { + if (! $this->unquote) { + return $value; + } + + static $mq; + if (! isset($mq)) { + $mq = get_magic_quotes_gpc() || get_magic_quotes_runtime(); + } + + if ($mq) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = $this->_unquote($v); + } + } else { + $value = stripslashes($value); + } + } + + return $value; + } + + + /** + * + * Builds an 'input' element. + * + * @access private + * + * @param string $type The input type ('text', 'hidden', etc). + * + * @param string $name The element name. + * + * @param mixed $value The element value. + * + * @param array|string $attr Attributes for the element tag. + * + * @return The 'input' tag XHTML. + * + */ + + function _input($type, $name, $value = null, $attr = null) + { + $value = $this->_unquote($value); + $xhtml = '_attr($attr); + $xhtml .= ' />'; + return $xhtml; + } + + + /** + * + * Puts in newlines and tabs to make the source code readable. + * + * @access private + * + * @param string $xhtml The XHTML to tidy up. + * + * @return string The tidied XHTML. + * + */ + + function _tidy($xhtml) + { + // only tidy up if layout is turned on + if ($this->layout) { + foreach ($this->_tabs as $key => $val) { + $key = '<' . $key; + $pad = str_pad('', $val + $this->tabBase, "\t"); + $xhtml = str_replace($key, "\n$pad$key", $xhtml); + } + } + return $xhtml; + } + + + /** + * + * Generates XHTML to start a fieldset block. + * + * @access private + * + * @param string $label The fieldset legend. If an empty string, + * builds a fieldset with no legend; if null, builds a div (not a + * fieldset). + * + * @param string $type The layout type to use, 'col' or 'row'. The + * 'col' layout uses a left-column for element labels and a + * right-column for the elements; the 'row' layout shows the elements + * left-to-right, with the element label over the element, all in a + * single row. + * + * @param string $float Whether the block should float 'left' or + * 'right' (set to an empty string if you don't want floating). + * Defaults to the value of $this->float. + * + * @param string $float Whether the block should be cleared of 'left' + * or 'right' floating blocks (set to an empty string if you don't + * want to clear). Defaults to the value of $this->clear. + * + * @return string The XHTML to start a block. + * + */ + + function _blockStart($label = null, $type = 'col', $float = null, + $clear = null) + { + // the XHTML text to return. + $xhtml = ''; + + // if not using automated layout, stop now. + if (! $this->layout) { + return $xhtml; + } + + // are we already in a block? if so, end the current one + // so we can start a new one. + if ($this->_inBlock) { + $xhtml .= $this->block('end'); + } + + // set the new block type and label + $this->_inBlock = true; + $this->_blockType = $type; + $this->_blockLabel = $label; + + // build up the "style" attribute for the new block + $style = ''; + + if ($float) { + $style .= " float: $float;"; + } + + if ($clear) { + $style .= " clear: $clear;"; + } + + if (! empty($style)) { + $attr = 'style="' . trim($style) . '"'; + } else { + $attr = null; + } + + // build the block opening XHTML itself; use a fieldset when a label + // is specifed, or a div when the label is not specified + if (is_string($this->_blockLabel)) { + + // has a label, use a fieldset with e style attribute + $xhtml .= $this->_tag('fieldset', $attr); + + // add the label as a legend, if it exists + if (! empty($this->_blockLabel)) { + $xhtml .= $this->_tag('legend'); + $xhtml .= htmlspecialchars($this->_blockLabel); + $xhtml .= ''; + } + + } else { + // no label, use a div with the style attribute + $xhtml .= $this->_tag('div', $attr); + } + + // start a table for the block elements + $xhtml .= $this->_tag('table'); + + // if the block is row-based, start a row + if ($this->_blockType == 'row') { + $xhtml .= $this->_tag('tr'); + } + + // done! + return $xhtml; + } + + + /** + * + * Generates the XHTML to end a block. + * + * @access public + * + * @return string The XHTML to end a block. + * + */ + + function _blockEnd() + { + // the XHTML to return + $xhtml = ''; + + // if not using automated layout, stop now. + if (! $this->layout) { + return $xhtml; + } + + // if not in a block, return right away + if (! $this->_inBlock) { + return; + } + + // are we in a group? if so, end it. + if ($this->_inGroup) { + $xhtml .= $this->group('end'); + } + + // end the block layout proper + if ($this->_blockType == 'row') { + // previous block was type 'row' + $xhtml .= ''; + } else { + // previous block was type 'col' + $xhtml .= ''; + } + + // end the fieldset or div tag for the block + if (is_string($this->_blockLabel)) { + // there was a label, so the block used fieldset + $xhtml .= ''; + } else { + // there was no label, so the block used div + $xhtml .= ''; + } + + // reset tracking properties + $this->_inBlock = false; + $this->_blockType = null; + $this->_blockLabel = null; + + // done! + return $xhtml; + } + + + /** + * + * Generates the layout to split the layout within a block. + * + * @access public + * + * @return string The XHTML to split the layout with in a block. + * + */ + + function _blockSplit() + { + // the XHTML to return + $xhtml = ''; + + // if not using automated layout, stop now. + if (! $this->layout) { + return $xhtml; + } + + // not already in a block, so don't bother. + if (! $this->_inBlock) { + return; + } + + // end any group we might already be in + if ($this->_inGroup) { + $xhtml .= $this->group('end'); + } + + // end the current block and start a new one + switch ($this->_blockType) { + + case 'row': + $xhtml .= ''; + $xhtml .= $this->_tag('tr'); + break; + + case 'col': + $xhtml .= ''; + $xhtml .= $this->_tag('table'); + break; + } + + // done! + return $xhtml; + } +} + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_image.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_image.php new file mode 100755 index 0000000000..1060d06b13 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_image.php @@ -0,0 +1,220 @@ + tag. +* +* Support for alpha transparency of PNG files in Microsoft IE added by +* Edward Ritter; thanks, Edward. +* +* $Id$ +* +* @author Paul M. Jones +* +* @author Edward Ritter +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_image extends Savant2_Plugin { + + + /** + * + * The document root. + * + * @access public + * + * @var string + * + */ + + var $documentRoot = null; + + + /** + * + * The base directory for images within the document root. + * + * @access public + * + * @var string + * + */ + + var $imageDir = null; + + + /** + * + * Outputs an tag. + * + * Microsoft IE alpha PNG support added by Edward Ritter. + * + * @access public + * + * @param string $file The path to the image on the local file system + * relative to $this->imageDir. + * + * @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 plugin($file, $alt = null, $height = null, $width = null, + $attr = null) + { + // is the document root set? + if (is_null($this->documentRoot)) { + // no, so set it + $this->documentRoot = $_SERVER['DOCUMENT_ROOT']; + } + + // the image file type code (PNG = 3) + $type = null; + + // get the file information + $info = false; + if (strpos($file, '://') === false) { + // no "://" in the file, so it's local + $file = $this->imageDir . $file; + $info = @getimagesize($this->documentRoot . $file); + } else { + // get the file size info as from a stream + $info = @getimagesize($file); + } + + // did we find the file? + if (is_array($info)) { + + // capture type info regardless + $type = $info[2]; + + // capture size info where both not specified + if (is_null($width) && is_null($height)) { + $width = $info[0]; + $height = $info[1]; + } + } + + // clean up + unset($info); + + // is the file a PNG? if so, check user agent, we will need to + // make special allowances for Microsoft IE. + if (stristr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && $type === 3) { + + // support alpha transparency for PNG files in MSIE + $html = '_attr($attr); + + // done + $html .= '>'; + + } else { + + // not IE, so build a normal image tag. + $html = '_attr($attr); + + // done + $html .= ' />'; + + } + + // done! + return $html; + } + + + /** + * + * Create additional HTML attributes. + * + * @access private + * + * @param array|string $attr An array or string of attributes. + * + * @return string A string of attributes. + * + */ + + function _attr($attr = null) + { + $html = ''; + + // add other attributes + if (is_array($attr)) { + // from array + foreach ($attr as $key => $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $html .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // from scalar + $html .= " $attr"; + } + + return $html; + } +} + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_input.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_input.php new file mode 100755 index 0000000000..265fbb101a --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_input.php @@ -0,0 +1,82 @@ + element. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_input extends Savant2_Plugin { + + /** + * + * Outputs a single element. + * + * @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 $attr Any extra HTML attributes to place within the + * input element. + * + * @return string + * + */ + + function plugin($type, $name, $value = '', $attr = null) + { + $type = htmlspecialchars($type); + $name = htmlspecialchars($name); + $value = htmlspecialchars($value); + + // start the tag + $html = " $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $html .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // add from scalar + $html .= " $attr"; + } + + // end the tag and return + $html .= ' />'; + return $html; + } +} + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_javascript.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_javascript.php new file mode 100755 index 0000000000..2bd0a54268 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_javascript.php @@ -0,0 +1,54 @@ + link to a JavaScript file. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_javascript extends Savant2_Plugin { + + /** + * + * Output a link to a JavaScript file. + * + * @access public + * + * @param string $href The HREF leading to the JavaScript source + * file. + * + * @return string + * + */ + + function plugin($href) + { + return ''; + } + +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_modify.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_modify.php new file mode 100755 index 0000000000..191af341aa --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_modify.php @@ -0,0 +1,82 @@ + +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_modify extends Savant2_Plugin { + + /** + * + * Modifies a value with a series of 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'); + * + * @param object &$savant A reference to the calling Savant2 object. + * + * @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 plugin($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)) { + $value = $func($value); + } + } + } + + return $value; + } + +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_options.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_options.php new file mode 100755 index 0000000000..3960d92200 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_options.php @@ -0,0 +1,107 @@ +s. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_options extends Savant2_Plugin { + + + /** + * + * Outputs a series of HTML \n"; + } + + return $html; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_radios.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_radios.php new file mode 100755 index 0000000000..516d8bba39 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_radios.php @@ -0,0 +1,130 @@ +s with the same name. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_radios extends Savant2_Plugin { + + + /** + * + * Outputs a set of radio s with the same name. + * + * @access public + * + * @param string $name The HTML "name=" value of all the radio s. + * + * @param array $radios An array of key-value pairs where the key is the + * radio button value and the value is the radio button label. + * + * @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 array $default The value to return if no radio buttons are + * checked. + * + * @param string|array $attr Any extra HTML attributes to place + * within the checkbox element. + * + * @param string $sep The HTML text to place between every radio + * button in the set. + * + * @return string + * + */ + + function plugin( + $name, + $radios, + $checked = null, + $default = null, + $sep = "
\n", + $attr = null, + $labelIsValue = false + ) + { + settype($radios, 'array'); + $html = ''; + + // define the hidden default value (if any) when no buttons are checked + if (! is_null($default)) { + $html .= ''; + $html .= "\n"; + } + + // the array of individual radio buttons + $radio = array(); + + // build the full set of radio buttons + foreach ($radios as $value => $label) { + + // reset to blank HTML for this radio button + $tmp = ''; + + // is the label being used as the value? + if ($labelIsValue) { + $value = $label; + } + + // start the radio button tag + $tmp .= ' $val) { + $key = htmlspecialchars($key); + $val = htmlspecialchars($val); + $tmp .= " $key=\"$val\""; + } + } elseif (! is_null($attr)) { + // add from scalar + $tmp .= " $attr"; + } + + // add the label and save the button in the array + $tmp .= ' />' . htmlspecialchars($label); + $radio[] = $tmp; + } + + // return the radio buttons with separators + return $html . implode($sep, $radio); + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_stylesheet.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_stylesheet.php new file mode 100755 index 0000000000..ace96bda61 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_stylesheet.php @@ -0,0 +1,56 @@ + to a CSS stylesheet. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_stylesheet extends Savant2_Plugin { + + /** + * + * Output a to a CSS stylesheet. + * + * @access public + * + * @param object &$savant A reference to the calling Savant2 object. + * + * @param string $href The HREF leading to the stylesheet file. + * + * @return string + * + */ + + function plugin($href) + { + return ''; + } + +} + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_textarea.php b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_textarea.php new file mode 100755 index 0000000000..b81ded5f84 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/Savant2_Plugin_textarea.php @@ -0,0 +1,81 @@ + element. +* +* $Id$ +* +* @author Paul M. Jones +* +* @package Savant2 +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* This program is free software; you can redistribute it and/or modify +* 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. +* +*/ + +class Savant2_Plugin_textarea extends Savant2_Plugin { + + /** + * + * Outputs a single '; + return $html; + } +} + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/1_assign.php b/phpgwapi/inc/savant2/Savant2/tests/1_assign.php new file mode 100755 index 0000000000..1cc7577532 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/1_assign.php @@ -0,0 +1,141 @@ + 'templates')); + +echo "

assign 0 (string, null)

"; +$val = null; +$result = $savant->assign('nullvar', $val); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + + +echo "

assign 1 (string, mixed)

"; +$result = $savant->assign('variable', 'variable_value'); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + + +echo "

assign 2 (array)

"; +$result = $savant->assign(array('array1' => 'value1', 'array2' => 'value2')); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + +echo "

assign 3 (object)

"; +$object = new StdClass(); +$object->obj1 = 'this'; +$object->obj2 = 'that'; +$object->obj3 = 'other'; +$result = $savant->assign($object); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + + +echo "

assignRef

"; +$reference = 'reference_value'; +$result = $savant->assignRef('reference', $reference); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + +/* +echo "

assignObject

"; +$object = new stdClass(); +$result = $savant->assignObject('object', $object); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; +*/ + +echo "

Assign variable without value

"; +$result = $savant->assign('variable_without_value'); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + + +echo "

Assign reference without value

"; +$result = $savant->assignRef('reference_without_value'); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + +/* +echo "

Assign object when value is not object

"; +$reference3 = 'failed!'; +$result = $savant->assignObject('object2', $reference3); +echo "result:
";
+print_r($result);
+echo "
"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; +*/ + +echo "

Change reference values from logic

"; +$reference = 'CHANGED VALUE FROM LOGIC'; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + +echo "

getVars

"; + +echo "

All

";
+print_r($savant->getVars());
+echo "
"; + +echo "

Some

";
+print_r($savant->getVars(array('obj1', 'obj2', 'obj3')));
+echo "
"; + +echo "

One

";
+print_r($savant->getVars('variable'));
+echo "
"; + +echo "

Nonexistent

";
+var_dump($savant->getVars('nosuchvar'));
+echo "
"; + +$savant->display('assign.tpl.php'); +echo "

After: $reference

"; + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/2_display.php b/phpgwapi/inc/savant2/Savant2/tests/2_display.php new file mode 100755 index 0000000000..15337ac820 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/2_display.php @@ -0,0 +1,72 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +$array = array( + 'key0' => 'val0', + 'key1' => 'val1', + 'key2' => 'val2', +); + +$var1 = 'variable1'; +$var2 = 'variable2'; +$var3 = 'variable3'; + +$ref1 = 'reference1'; +$ref2 = 'reference2'; +$ref3 = 'reference3'; + +// assign vars +$savant->assign($var1, $var1); +$savant->assign($var2, $var2); +$savant->assign($var3, $var3); + +// assigns $array to a variable $set +$savant->assign('set', $array); + +// assigns the keys and values of array +$savant->assign($array); + +// assign references +$savant->assignRef($ref1, $ref1); +$savant->assignRef($ref2, $ref2); +$savant->assignRef($ref3, $ref3); + + +echo "

Display non-existent template

"; +$result = $savant->display('no_such_template.tpl.php'); +echo "result:
";
+print_r($result);
+echo "
"; + +echo "

Storage

"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + + +echo "

Display existing template

"; +$result = $savant->display('test.tpl.php'); +echo "result:
";
+var_dump($result);
+echo "
"; + + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/3_fetch.php b/phpgwapi/inc/savant2/Savant2/tests/3_fetch.php new file mode 100755 index 0000000000..ff02c6088f --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/3_fetch.php @@ -0,0 +1,71 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +$array = array( + 'key0' => 'val0', + 'key1' => 'val1', + 'key2' => 'val2', +); + +$var1 = 'variable1'; +$var2 = 'variable2'; +$var3 = 'variable3'; + +$ref1 = 'reference1'; +$ref2 = 'reference2'; +$ref3 = 'reference3'; + +// assign vars +$savant->assign($var1, $var1); +$savant->assign($var2, $var2); +$savant->assign($var3, $var3); + +// assigns $array to a variable $set +$savant->assign('set', $array); + +// assigns the keys and values of array +$savant->assign($array); + +// assign references +$savant->assignRef($ref1, $ref1); +$savant->assignRef($ref2, $ref2); +$savant->assignRef($ref3, $ref3); + + +echo "

Fetch non-existent template

"; +$result = $savant->fetch('no_such_template.tpl.php'); +echo "result:
";
+print_r($result);
+echo "
"; + +echo "

Storage

"; +echo "properties:
";
+print_r(get_object_vars($savant));
+echo "
"; + +echo "

Fetch existing template

"; +$result = $savant->fetch('test.tpl.php'); +echo "fetched this code:
";
+print_r(htmlentities($result));
+echo "
"; + + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/4_plugins.php b/phpgwapi/inc/savant2/Savant2/tests/4_plugins.php new file mode 100755 index 0000000000..2f10a157c1 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/4_plugins.php @@ -0,0 +1,85 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +$array = array( + 'key0' => 'val0', + 'key1' => 'val1', + 'key2' => 'val2', +); + +$var1 = 'variable1'; +$var2 = 'variable2'; +$var3 = 'variable3'; + +$ref1 = 'reference1'; +$ref2 = 'reference2'; +$ref3 = 'reference3'; + +// assign vars +$savant->assign($var1, $var1); +$savant->assign($var2, $var2); +$savant->assign($var3, $var3); + +// assigns $array to a variable $set +$savant->assign('set', $array); + +// assigns the keys and values of array +$savant->assign($array); + +// assign references +$savant->assignRef($ref1, $ref1); +$savant->assignRef($ref2, $ref2); +$savant->assignRef($ref3, $ref3); + +// load the cycle plugin with preset cycle values +$savant->loadPlugin( + 'cycle', + array( + 'values' => array( + 'lightdark' => array('light', 'dark') + ) + ) +); + +// preload the image plugin +$savant->loadPlugin('image', + array( + 'imageDir' => 'resources/' + ) +); + +// preload the dateformat plugin +$savant->loadPlugin('dateformat', + array( + 'custom' => array( + 'mydate' => '%d/%m/%Y' + ) + ) +); + +// preload a custom plugin +$savant->loadPlugin('fester', null, true); + +// run through the template +$savant->display('plugins.tpl.php'); + +// done! +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/5_filters.php b/phpgwapi/inc/savant2/Savant2/tests/5_filters.php new file mode 100755 index 0000000000..9193088827 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/5_filters.php @@ -0,0 +1,42 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +// set up filters +$savant->loadFilter('colorizeCode'); +$savant->loadFilter('trimwhitespace'); +$savant->loadFilter('fester', null, true); + +// run through the template +$savant->display('filters.tpl.php'); + +// do it again to test object persistence +$savant->display('filters.tpl.php'); + +// do it again to test object persistence +$savant->display('filters.tpl.php'); + +echo "
\n"; +echo "
";
+print_r($savant);
+echo "
"; + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/6_paths.php b/phpgwapi/inc/savant2/Savant2/tests/6_paths.php new file mode 100755 index 0000000000..59bec9e74c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/6_paths.php @@ -0,0 +1,52 @@ +\n"; + print_r($val); + echo "\n"; +} + +error_reporting(E_ALL); + +require_once 'Savant2.php'; + +$conf = array( + 'template_path' => 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +echo "

Paths to begin with

\n"; +preprint($savant->getPath('resource')); +preprint($savant->getPath('template')); + +echo "

Add a path

\n"; +$savant->addPath('resource', 'no/such/path'); +preprint($savant->getPath('resource')); + +echo "

Find an existing resource (non-default)

\n"; +$file = $savant->findFile('resource', 'Savant2_Plugin_cycle.php'); +preprint($file); + +echo "

Find an existing resource (default)

\n"; +$file = $savant->findFile('resource', 'Savant2_Plugin_input.php'); +preprint($file); + +echo "

Find a non-existent template

\n"; +$file = $savant->findFile('template', 'no_such_template.tpl.php'); +if ($file) { + preprint($file); +} else { + preprint("false or null"); +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/7_include.php b/phpgwapi/inc/savant2/Savant2/tests/7_include.php new file mode 100755 index 0000000000..c85b782d00 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/7_include.php @@ -0,0 +1,65 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +$array = array( + 'key0' => 'val0', + 'key1' => 'val1', + 'key2' => 'val2', +); + +$var1 = 'variable1'; +$var2 = 'variable2'; +$var3 = 'variable3'; + +$ref1 = 'reference1'; +$ref2 = 'reference2'; +$ref3 = 'reference3'; + +// assign vars +$savant->assign($var1, $var1); +$savant->assign($var2, $var2); +$savant->assign($var3, $var3); + +// assigns $array to a variable $set +$savant->assign('set', $array); + +// assigns the keys and values of array +$savant->assign($array); + +// assign references +$savant->assignRef($ref1, $ref1); +$savant->assignRef($ref2, $ref2); +$savant->assignRef($ref3, $ref3); + +// load the cycle plugin with preset cycle values +$savant->loadPlugin( + 'cycle', + array( + 'values' => array( + 'lightdark' => array('light', 'dark') + ) + ) +); + +// run through the template +$savant->display('main.tpl.php'); + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/8_extend.php b/phpgwapi/inc/savant2/Savant2/tests/8_extend.php new file mode 100755 index 0000000000..d8498d781c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/8_extend.php @@ -0,0 +1,24 @@ + 'templates', + 'resource_path' => 'resources' +); + +$savant =& new Savant2($conf); + +$savant->display('extend.tpl.php'); + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/9_errors.php b/phpgwapi/inc/savant2/Savant2/tests/9_errors.php new file mode 100755 index 0000000000..58ab1dcff8 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/9_errors.php @@ -0,0 +1,46 @@ +PEAR_Error\n"; +$savant->setError('pear'); +$result = $savant->loadPlugin('nosuchthing'); +echo "
\n";
+print_r($result);
+echo "
\n\n"; + +echo "

PEAR_ErrorStack

\n"; +$savant->setError('stack'); +$result = $savant->loadPlugin('nosuchthing'); +echo "
\n";
+print_r($result);
+echo "
\n\n"; + +echo "
\n";
+print_r(print_r($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']));
+echo "
\n\n"; + +echo "

Exception

\n"; +$savant->setError('exception'); +$result = $savant->loadPlugin('nosuchthing'); +echo "
\n";
+print_r($result);
+echo "
\n\n"; + + +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/compile.php b/phpgwapi/inc/savant2/Savant2/tests/compile.php new file mode 100755 index 0000000000..a68ed08de5 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/compile.php @@ -0,0 +1,80 @@ +\n"; + print_r($val); + echo "\n"; +} + +error_reporting(E_ALL); + +// instantiate Savant +require_once 'Savant2.php'; + +$conf = array( + 'template_path' => 'templates', + 'resource_path' => 'resources', + 'restrict' => true // adding path restrictions! +); + +$savant =& new Savant2($conf); + +// instantiate a compiler... +require_once 'Savant2/Savant2_Compiler_basic.php'; +$compiler =& new Savant2_Compiler_basic(); +$compiler->compileDir = '/tmp/'; +$compiler->forceCompile = true; + +// and tell Savant to use it. +$savant->setCompiler($compiler); + +// set up vars +$array = array( + 'key0' => 'val0', + 'key1' => 'val1', + 'key2' => 'val2', +); + +$var1 = 'variable1'; +$var2 = 'variable2'; +$var3 = 'variable3'; + +$ref1 = 'reference1'; +$ref2 = 'reference2'; +$ref3 = 'reference3'; + +// assign vars +$savant->assign($var1, $var1); +$savant->assign($var2, $var2); +$savant->assign($var3, $var3); + +// assigns $array to a variable $set +$savant->assign('set', $array); + +// assigns the keys and values of array +$savant->assign($array); + +// assign references +$savant->assignRef($ref1, $ref1); +$savant->assignRef($ref2, $ref2); +$savant->assignRef($ref3, $ref3); + +echo "

The 'good' template

"; +$compiler->strict = false; +$result = $savant->display('compile.tpl.php'); +preprint($result); + +echo "

The 'bad' template

"; +$compiler->strict = true; +$result = $savant->display('compile_bad.tpl.php'); +preprint($result); +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/form.php b/phpgwapi/inc/savant2/Savant2/tests/form.php new file mode 100755 index 0000000000..2412870312 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/form.php @@ -0,0 +1,49 @@ +addPath('template', 'templates/'); +$Savant2->addPath('resource', 'resources/'); + +$defaults = array( + 'hideme' => null, + 'mytext' => null, + 'xbox' => null, + 'picker' => null, + 'picker2' => null, + 'chooser' => null, + 'myarea' => null +); + +$values = array_merge($defaults, $_POST); + +$tmp = array(); + +if ($values['mytext'] == '') { + // required + $tmp[] = 'required'; +} + +if (strlen($values['mytext']) > 5) { + // max 5 chars + $tmp[] = 'maxlen'; +} + +if (preg_match('/[0-9]+/', $values['mytext'])) { + // no digits + $tmp[] = 'no_digits'; +} + +if (count($tmp) == 0) { + $valid = array('mytext' => true); +} else { + $valid = array('mytext' => $tmp); +} + +$Savant2->assign('opts', array('one', 'two', 'three', 'four', 'five')); +$Savant2->assign($values); +$Savant2->assign('valid', $valid); + +$Savant2->display('form.tpl.php'); +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/form2.php b/phpgwapi/inc/savant2/Savant2/tests/form2.php new file mode 100755 index 0000000000..cad4706396 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/form2.php @@ -0,0 +1,49 @@ +addPath('template', 'templates/'); +$Savant2->addPath('resource', 'resources/'); + +$defaults = array( + 'hideme' => null, + 'mytext' => null, + 'xbox' => null, + 'picker' => null, + 'picker2' => null, + 'chooser' => null, + 'myarea' => null +); + +$values = array_merge($defaults, $_POST); + +$tmp = array(); + +if ($values['mytext'] == '') { + // required + $tmp[] = 'required'; +} + +if (strlen($values['mytext']) > 5) { + // max 5 chars + $tmp[] = 'maxlen'; +} + +if (preg_match('/[0-9]+/', $values['mytext'])) { + // no digits + $tmp[] = 'no_digits'; +} + +if (count($tmp) == 0) { + $valid = array('mytext' => true); +} else { + $valid = array('mytext' => $tmp); +} + +$Savant2->assign('opts', array('one', 'two', 'three', 'four', 'five')); +$Savant2->assign($values); +$Savant2->assign('valid', $valid); + +$Savant2->display('form2.tpl.php'); +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Filter_fester.php b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Filter_fester.php new file mode 100755 index 0000000000..060f6440e9 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Filter_fester.php @@ -0,0 +1,18 @@ +Fester has a light bulb in his mouth (" . + $this->count ++ . ")\n"; + + $text .= "
Fester has a light bulb in his mouth again (" . + $this->count ++ . ")\n"; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_cycle2.php b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_cycle2.php new file mode 100755 index 0000000000..2548ab6243 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_cycle2.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example.php b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example.php new file mode 100755 index 0000000000..d04c255976 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example.php @@ -0,0 +1,22 @@ +msg . "this is an example!"; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example_extend.php b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example_extend.php new file mode 100755 index 0000000000..527d8c60c1 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_example_extend.php @@ -0,0 +1,18 @@ +loadPlugin('example'); + +class Savant2_Plugin_example_extend extends Savant2_Plugin_example { + + var $msg = "Extended Example! "; + +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_fester.php b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_fester.php new file mode 100755 index 0000000000..113c2d369b --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/resources/Savant2_Plugin_fester.php @@ -0,0 +1,31 @@ +message .= " is printing this: "; + } + + function plugin(&$text) + { + $output = $this->message . $text . " ({$this->count})"; + $this->count++; + return $output; + } +} +?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/resources/savant.gif b/phpgwapi/inc/savant2/Savant2/tests/resources/savant.gif new file mode 100755 index 0000000000000000000000000000000000000000..10361019ca25139303751e425b565451dc1be48b GIT binary patch literal 1043 zcmV+u1nm1qNk%w1VQc^-0K@KRG0_|Yr?|X-K(pyJw0k_rkn={!)a;w`1}9={}K{$ z`0eeW5fK0Y00000A^8LZ6afDKEC2ui0Bisx000I5ARvxpX`X1Ru59a)S}f0WZQppV z?|iR`zMybOEdBt-q;fec1fBsKkV&oj9)heuinMyaHLR9pDs6CISl z!`f|aDl1g-c^EVSfPpo65HyH0goRmxH40i!fE|a90tzyG8XTBenv9vZJ?ODouo?^UGh$g}G8cIl6#|&E0U>~bTw2m;Sd|6Vy)3B+ z8bp{yVXi2(64KD8hX$ucjv~&0;O~<{4S9I~l@!3C2FXztC(XbogCjo~APdpz^bZ3X znlgT6S+EQkjiLfB_~aNf3r2Ao^TFE_Ze)N8>$J3t!ObYtiZ$M4QL3fgjIKL@YPdKv zYR#!0tBO=clWj(@HKxIxVfU+mrUIU#blYn$xV8z*J=`awYX@Ehy8b0tNN{5aYyGc{-eANKY)@8aeCL;N8%-Y->(q zpX5OMR@Gi|1Xi=rX2EnT)vtRoGbc1BFyO;e6;HnW5d!Gbt6$H)z5Dm@>&T0lUF4k9pNjs!F~00A(Pn4W?g9N>Tk2OL0v z1`Z^tD#@giC~6SF0SLIbfd)S^xnztm zHb6jsRw0x8W=FZq69$cfCCXQ(4_%bHlP8QR;m}~mxgM9 zsG^LfcL10JD2d*e88CpJ0ZdM*9-QbwxoD|N9w|Wv2n>pzg0XsvUZS%$s)3dcFlZ&K z4Sv{VdT$P3sg1pU8mxK}48W?8s_5C8UIc-viRh2Q&T8fW3_xkAss62Z=&#^L3ucf# zW}4oz*(Pd027gA&ZhHevP~n%Rt}B57&}JYntirAbCjty$scX8OB09sOp0XP6#phD}0TBoa=85|XJHwKt!Z|9sydr4x&Gprc^Ugf4r*qFhF!J(IkWb06TX}#{d8T literal 0 HcmV?d00001 diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/assign.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/assign.tpl.php new file mode 100755 index 0000000000..72742b4d96 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/assign.tpl.php @@ -0,0 +1,12 @@ + +

Change reference values from template

+

Before: reference; $this->reference = "Changed Value From Template!" ?>

diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/compile.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/compile.tpl.php new file mode 100755 index 0000000000..91dc938097 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/compile.tpl.php @@ -0,0 +1,31 @@ +{* Savant2_Compiler_basic : compile.tpl.php *} + +{tpl 'header.tpl.php'} + +

{$this->variable1}

+

{$this->variable2}

+

{$this->variable3}

+

{$this->key0}

+

{$this->key1}

+

{$this->key2}

+

{$this->reference1}

+

{$this->reference2}

+

{$this->reference3}

+ +

{$this->variable1}

+ +

Extended printing: {: $this->variable1 . ' ' . $this->variable2}

+ +
    +{foreach ($this->set as $key => $val):} +
  • {$key} = {$val} ({$this->set[$key]})
  • +{endforeach} +
+ +{['form', 'start']} +{['form', 'text', 'example', 'default value', 'label:']} +{['form', 'end']} + +

+ +{tpl 'footer.tpl.php'} \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/compile_bad.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/compile_bad.tpl.php new file mode 100755 index 0000000000..29310f6e88 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/compile_bad.tpl.php @@ -0,0 +1,35 @@ +{* Savant2_Compiler_basic *} + +{tpl 'header.tpl.php'} + +

{$varivari; $this->$varivari}

+

{$this->variable1; global $_SERVER;}

+

{$this->variable2; $obj =& new StdClass;}

+

{$this->variable3; eval("echo 'bad guy!';")}

+

{$this->key0; print_r($this->_compiler);}

+

{$this->key1; File::read('/etc/passwd');}

+

{$this->key2; include "/etc/passwd";}

+

{$this->reference1; include $this->findTemplate('template.tpl.php') . '../../etc/passwd';}

+

{$this->reference2; $newvar = $this; $newvar =& $this; $newvar = & $this; $newvar += +& +$this; +$newvar = array(&$this); }

+ +

{$this->reference3; $thisIsOk; $thisIs_OK; $function(); }

+ +

{$this->variable1; echo parent::findTemplate('template.tpl.php')}

+ +
    +{foreach ($this->set as $key => $val): $this->$key; $this->$val(); } +
  • {$key} = {$val} ({$this->set[$key]})
  • +{endforeach; echo htmlspecialchars(file_get_contents('/etc/httpd/php.ini')); } +
+ +{['form', 'start']} +{['form', 'text', 'example', 'default value', 'My Text Field:']} +{['form', 'end']} + +

+ +{tpl 'footer.tpl.php'} \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/extend.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/extend.tpl.php new file mode 100755 index 0000000000..1effa601e9 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/extend.tpl.php @@ -0,0 +1,11 @@ + +

plugin('example'); var_dump($result); ?>

+

plugin('example_extend'); var_dump($result); ?>

diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/filters.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/filters.tpl.php new file mode 100755 index 0000000000..106e6cb079 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/filters.tpl.php @@ -0,0 +1,44 @@ + + + +

Filters

+ + + + + +

This and that

+ + + + + + +

And the other

+ + + +

+
+	// this is a test of PHP colorizing
+	echo "some text";
+	highlight_string("something");
+	$variable = 'value';
+	
+	function fester()
+	{
+		// does nothing
+	}
+
+
+ + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/footer.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/footer.tpl.php new file mode 100755 index 0000000000..4d4a7e5285 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/footer.tpl.php @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/form.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/form.tpl.php new file mode 100755 index 0000000000..ffafd56d98 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/form.tpl.php @@ -0,0 +1,140 @@ + + + Form Test + + + + plugin('form', 'start'); + $this->plugin('form', 'set', 'class', 'Savant-Form'); + + // add a hidden value before the layout + $this->plugin('form', 'hidden', 'hideme', 'hidden & valued'); + + // NEW BLOCK + $this->plugin('form', 'block', 'start', "First Section", 'row'); + + // text field + $this->plugin('form', 'text', 'mytext', $this->mytext, 'Enter some text here:', null); + + // messages for the text field + $this->plugin('form', 'note', null, null, $this->valid['mytext'], + array('required' => 'This field is required.', 'maxlen' => 'No more than 5 letters.', 'no_digits' => 'No digits allowed.')); + + $this->plugin('form', 'block', 'split'); + + // checkbox with default value (array(checked, not-checked)) + $this->plugin('form', 'checkbox', 'xbox', $this->xbox, 'Check this:', array(1,0), 'style="text-align: center;"'); + + // single select + $this->plugin('form', 'select', 'picker', $this->picker, 'Pick one:', $this->opts); + + // END THE BLOCK and put in some custom stuff. + $this->plugin('form', 'block', 'end'); + ?> + + +

Custom HTML Between Fieldset Blocks

+ + plugin('form', 'block', 'start', "Second Section", 'col'); + + // multi-select with note + $this->plugin('form', 'group', 'start', 'Pick many:'); + $this->plugin('form', 'select', 'picker2[]', $this->picker2, 'Pick many:', $this->opts, 'multiple="multiple"'); + $this->plugin('form', 'note', "
Pick as many as you like; use the Ctrl key on Windows, or the Cmd key on Macintosh."); + $this->plugin('form', 'group', 'end'); + + // radio buttons + $this->plugin('form', 'radio', 'chooser', $this->chooser, 'Choose one:', $this->opts); + + // NEW BLOCK + $this->plugin('form', 'block', 'start', null, 'row'); + + // text area + $this->plugin('form', 'textarea', 'myarea', $this->myarea, 'Long text:', array('rows'=>12,'cols'=>40)); + + // NEW BLOCK (clears floats) + $this->plugin('form', 'block', 'start', null, 'row', null, 'both'); + $this->plugin('form', 'submit', 'op', 'Save'); + $this->plugin('form', 'reset', 'op', 'Reset'); + $this->plugin('form', 'button', '', 'Click Me!', null, array('onClick' => 'return alert("hello!")')); + + + // end the form + $this->plugin('form', 'end'); + ?> + + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/form2.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/form2.tpl.php new file mode 100755 index 0000000000..f792e50a54 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/form2.tpl.php @@ -0,0 +1,140 @@ + + + Form Test + + + + form('start'); + $this->form('set', 'class', 'Savant-Form'); + + // add a hidden value before the layout + $this->form('hidden', 'hideme', 'hidden & valued'); + + // NEW BLOCK + $this->form('block', 'start', "First Section", 'row'); + + // text field + $this->form('text', 'mytext', $this->mytext, 'Enter some text here:', null); + + // messages for the text field + $this->form('note', null, null, $this->valid['mytext'], + array('required' => 'This field is required.', 'maxlen' => 'No more than 5 letters.', 'no_digits' => 'No digits allowed.')); + + $this->form('block', 'split'); + + // checkbox with default value (array(checked, not-checked)) + $this->form('checkbox', 'xbox', $this->xbox, 'Check this:', array(1,0), 'style="text-align: center;"'); + + // single select + $this->form('select', 'picker', $this->picker, 'Pick one:', $this->opts); + + // END THE BLOCK and put in some custom stuff. + $this->form('block', 'end'); + ?> + + +

Custom HTML Between Fieldset Blocks

+ + form('block', 'start', "Second Section", 'col'); + + // multi-select with note + $this->form('group', 'start', 'Pick many:'); + $this->form('select', 'picker2[]', $this->picker2, 'Pick many:', $this->opts, 'multiple="multiple"'); + $this->form('note', "
Pick as many as you like; use the Ctrl key on Windows, or the Cmd key on Macintosh."); + $this->form('group', 'end'); + + // radio buttons + $this->form('radio', 'chooser', $this->chooser, 'Choose one:', $this->opts); + + // NEW BLOCK + $this->form('block', 'start', null, 'row'); + + // text area + $this->form('textarea', 'myarea', $this->myarea, 'Long text:', array('rows'=>12,'cols'=>40)); + + // NEW BLOCK (clears floats) + $this->form('block', 'start', null, 'row', null, 'both'); + $this->form('submit', 'op', 'Save'); + $this->form('reset', 'op', 'Reset'); + $this->form('button', '', 'Click Me!', null, array('onClick' => 'return alert("hello!")')); + + + // end the form + $this->form('end'); + ?> + + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/header.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/header.tpl.php new file mode 100755 index 0000000000..be152721e0 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/header.tpl.php @@ -0,0 +1,7 @@ + + + Savant2 Testing + + + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/main.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/main.tpl.php new file mode 100755 index 0000000000..4b54e9362c --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/main.tpl.php @@ -0,0 +1,15 @@ + + +loadTemplate('header.tpl.php') ?> + +loadTemplate('plugins.tpl.php') ?> + +loadTemplate('footer.tpl.php') ?> \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/plugins.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/plugins.tpl.php new file mode 100755 index 0000000000..d2c527fc95 --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/plugins.tpl.php @@ -0,0 +1,192 @@ + + + +

ahref

+ +

from strings

+
+splugin('ahref', 'http://example.com/index.html?this=this&that=that#something', 'Example Link', 'target="_blank"');
+	echo '

' . $this->splugin('modify', $result, 'htmlentities nl2br') . '

'; + echo "

$result

"; +?> +
+ +

from arrays

+
+splugin(
+		'ahref',
+		parse_url('http://example.com/index.html?this=this&that=that#something'),
+		'Example Link',
+		array('target' => "_blank")
+	);
+	echo '

' . $this->splugin('modify', $result, 'htmlentities nl2br') . '

'; + echo "

$result

"; +?> +
+ + +

checkbox

+ +
+set as $key => $val) {
+		$result .= $this->splugin(
+			'checkbox', // plugin 
+			"xboxen[$key]", // checkbox name
+			$key, // checkbox value
+			'key1', // pre-checked
+			'', // default value when not checked
+			'dumb="dumber"' // attributes
+		);
+		$result .= $val . "

\n"; + } + + $this->plugin('modify', $result, 'htmlentities nl2br'); + ?> +
+ +
+ + +

cycle

+ + +

repeat 1 on array

+
+
+	plugin('cycle', array('a', 'b', 'c'), $i) ?>
+ +
+ + + + + +

repeat 3 on preset

+ + +
+
+	plugin('cycle', 'lightdark', $i, 3) ?>
+ +
+ + + + + + +

dateformat

+

plugin('dateformat', "Aug 8, 1970") ?>

+

plugin('dateformat', "Aug 8, 1970", 'mydate') ?>

+ + + + +

javascript

+
splugin('javascript', 'path/to/file.js')) ?>
+ + +

image

+ +

local

+
splugin('image', 'savant.gif')) ?>
+plugin('image', 'savant.gif') ?> + +

nonexistent

+
splugin('image', 'savantx.gif', 'image does not exist')) ?>
+plugin('image', 'savantx.gif', 'image does not exist') ?> + +

stream

+
splugin('image', 'http://phpsavant.com/etc/fester.jpg')) ?>
+plugin('image', 'http://phpsavant.com/etc/fester.jpg') ?> + + +

options

+ +

assoc

+
+splugin('options', $this->set, 'key1', 'dumb="dumber"');
+	$this->plugin('modify', $result, 'htmlentities nl2br');
+?>
+
+
+ + +

seq

+
+splugin('options', $this->set, 'val2', array('attrib' => 'this & that'), true);
+	$this->plugin('modify', $result, 'htmlentities nl2br');
+?>
+
+
+ + + +

radios

+ +

assoc

+
+splugin('radios', 'das_radio', $this->set, 'key1', 'nil', "

\n", 'dumb="dumber"'); + $this->plugin('modify', $result, 'htmlentities nl2br'); +?> +
+
+ +

seq

+
+splugin('radios', 'das_radio', $this->set, 'val2', 'nil', "

\n", 'dumb="dumber"', true); + $this->plugin('modify', $result, 'htmlentities nl2br'); +?> +
+
+ + + +

stylesheet

+
splugin('stylesheet', 'path/to/styles.css')) ?>
+ + +

textarea

+
+splugin('textarea', 'longtext', "some really long text");
+	$this->plugin('modify', $result, 'htmlentities nl2br');
+?>
+
+ + + + +

fester

+ +plugin('fester', 'Gomez') ?>
+plugin('fester', 'Morticia') ?>
+plugin('fester', 'Cara Mia!') ?>
+ + +

Plugin Objects

+ +_resource[plugin]:
_resource['plugin']) ?>
+ + + + + \ No newline at end of file diff --git a/phpgwapi/inc/savant2/Savant2/tests/templates/test.tpl.php b/phpgwapi/inc/savant2/Savant2/tests/templates/test.tpl.php new file mode 100755 index 0000000000..6e53c63e7a --- /dev/null +++ b/phpgwapi/inc/savant2/Savant2/tests/templates/test.tpl.php @@ -0,0 +1,21 @@ + +

variable1 ?>

+

variable2 ?>

+

variable3 ?>

+

key0 ?>

+

key1 ?>

+

key2 ?>

+

reference1 ?>

+

reference2 ?>

+

reference3 ?>

+
    +set as $key => $val) echo "
  • $key = $val
  • \n" ?> +
diff --git a/phpgwapi/inc/savant2/VERSION b/phpgwapi/inc/savant2/VERSION new file mode 100644 index 0000000000..0bee604df7 --- /dev/null +++ b/phpgwapi/inc/savant2/VERSION @@ -0,0 +1 @@ +2.3.3