diff --git a/etemplate/inc/class.etemplate_template_widget.inc.php b/etemplate/inc/class.etemplate_template_widget.inc.php new file mode 100644 index 0000000000..26e77e2ed9 --- /dev/null +++ b/etemplate/inc/class.etemplate_template_widget.inc.php @@ -0,0 +1,112 @@ + + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/* testwise to have autoloading +if (!isset($GLOBALS['egw_info'])) +{ + $GLOBALS['egw_info'] = array( + 'flags' => array( + 'currentapp' => 'login', + ), + ); + include_once '../../header.inc.php'; +} +*/ +/** + * eTemplate widget baseclass + */ +class etemplate_template_widget extends etemplate_widget +{ + /** + * Cache of already read templates + * + * @var array with name => template pairs + */ + protected static $cache = array(); + + /** + * Read a templates specified by name, template(-set) and version + * + * @param string $name + * @param string $template_set='default' + * @param string $version='' + * @param string $load_via='' use given template to load $name + * @todo Reading customized templates from database + * @return etemplate_template_widget|boolean false if not found + */ + public static function read($name, $template_set='default', $version='', $load_via='') + { + $start = microtime(true); + if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version))) + { + if ((!$path || self::read($load_via, $template_set)) && isset(self::$cache[$name])) + { + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache"); + return self::$cache[$name]; + } + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found!"); + return false; + } + $reader = new XMLReader(); + if (!$reader->open(EGW_SERVER_ROOT.$path)) return false; + + while($reader->read()) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'template') + { + $template = new etemplate_template_widget($reader); + //echo $template->id; _debug_array($template); + + self::$cache[$template->id] = $template; + + if ($template->id == $name) + { + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read in ".round(1000.0*(microtime(true)-$start),2)." ms"); + return $template; + } + } + } + // template not found in file, should never happen + error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found in file '$path'!"); + return false; + } + + /** + * Get path/URL relative to EGroupware install of a template + * + * @param string $name + * @param string $template_set='default' + * @param string $version='' + * @return string|boolean path of template xml file or false if not found + */ + public static function relPath($name, $template_set='default', $version='') + { + list($app, $rest) = explode('.', $name, 2); + $path = '/'.$app.'/templates/'.$template_set.'/'.$rest.'.xet'; + + if (file_exists(EGW_SERVER_ROOT.$path)) return $path; + + if ($templateSet != 'default') + { + $path = '/'.$app.'/templates/default/'.$rest.'.xet'; + + if (file_exists(EGW_SERVER_ROOT.$path)) return $path; + } + return false; + } +} +/* +header('Content-Type: text/xml'); +$template = etemplate_template_widget::read('timesheet.edit'); +$template->toXml(); +*/ diff --git a/etemplate/inc/class.etemplate_widget.inc.php b/etemplate/inc/class.etemplate_widget.inc.php new file mode 100644 index 0000000000..b000666404 --- /dev/null +++ b/etemplate/inc/class.etemplate_widget.inc.php @@ -0,0 +1,196 @@ + + * @copyright 2002-11 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +/** + * eTemplate widget baseclass + */ +class etemplate_widget +{ + /** + * Widget type + * + * @var string + */ + public $type; + + /** + * Widget id + * + * @var string + */ + public $id; + + /** + * Widget attributes + * + * @var array + */ + public $attrs = array(); + + /** + * Children + * + * @var array + */ + protected $children = array(); + + /** + * Constructor + * + * @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct + * @throws egw_exception_wrong_parameter + */ + public function __construct($xml) + { + if (is_a($xml, 'XMLReader')) + { + $reader = $xml; + } + else + { + $reader = new XMLReader(); + if (!$reader->XML($xml)) + { + throw new egw_exception_wrong_parameter("Can't parse xml:\n$xml"); + } + } + $this->type = $reader->name; + $depth = $reader->depth; + + // read all attributes + while($reader->moveToNextAttribute()) + { + if ($reader->name == 'id') + { + $this->id = $reader->value; + } + else + { + $this->attrs[$reader->name] = $reader->value; + } + } + + while($reader->read() && $reader->depth > $depth) + { + if ($reader->nodeType == XMLReader::ELEMENT && $reader->depth > $depth) + { + $this->children[] = self::factory($reader->name, $reader, $reader->getAttribute('id')); + } + } + } + + /** + * Factory method to construct all widgets + * + * @param string $type + * @param string|XMLReader $xml + * @param string $id=null + */ + public static function factory($type, $xml, $id=null) + { + static $type2class_name = array(); + + $class_name =& $type2class_name[$type]; + + if (!isset($class_name)) + { + list($basetype) = explode('-',$type); + if (!class_exists($class_name = 'etemplate_'.str_replace('-','_',$type).'_widget') && + !class_exists($class_name = 'etemplate_'.str_replace('-','_',$basetype).'_widget')) + { + // default to widget class, we can not ignore it, as the widget may contain other widgets + $class_name = 'etemplate_widget'; + } + } + // currently only overlays can contain templates, other widgets can only reference to templates via id + if ($type == 'template' && $id && ($template = etemplate_template_widget::read($id))) + { + return $template; + } + return new $class_name($xml); + } + + /** + * Iterate over children to find the one with the given id and optional type + * + * @param string $id + * @param string $type=null + * @return etemplate_widget or NULL + */ + public function getElementById($id, $type=null) + { + foreach($this->children as $child) + { + if ($child->id === $id && (is_null($type) || $child->type === $type)) + { + return $child; + } + if (($element = $child->getElementById($id, $type))) + { + return $element; + } + } + return null; + } + + /** + * Validate input of a widget + * + * @param array $content + * @param string $cname='' current namespace + * @return mixed + */ + public function validate(array $content, $cname = '') + { + + } + + /** + * Convert object to string + * + * @return string + */ + public function __toString() + { + return $this->type.'#'.$this->id; + } + + /** + * Convert widget (incl. children) to xml + * + * @param string $indent='' + * @return string + */ + public function toXml($indent='') + { + echo "$indent<$this->type"; + if ($this->id) echo ' id="'.htmlspecialchars($this->id).'"'; + foreach($this->attrs as $name => $value) + { + echo ' '.$name.'="'.htmlspecialchars($value).'"'; + } + if ($this->children) + { + echo ">\n"; + foreach($this->children as $child) + { + $child->toXml($indent."\t"); + } + echo "$indenttype>\n"; + } + else + { + echo " />\n"; + } + } +}