2011-08-18 20:08:40 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware - eTemplate serverside template widget
|
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
2016-03-19 14:06:07 +01:00
|
|
|
* @package api
|
|
|
|
* @subpackage etemplate
|
2011-08-18 20:08:40 +02:00
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
2016-03-16 12:27:49 +01:00
|
|
|
* @copyright 2002-16 by RalfBecker@outdoor-training.de
|
2011-08-18 20:08:40 +02:00
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
2016-03-19 14:06:07 +01:00
|
|
|
namespace EGroupware\Api\Etemplate\Widget;
|
|
|
|
|
|
|
|
use EGroupware\Api\Etemplate;
|
|
|
|
use EGroupware\Api;
|
|
|
|
use XMLReader;
|
|
|
|
|
|
|
|
/* allow to call direct for tests (see end of class)
|
2011-08-18 20:08:40 +02:00
|
|
|
if (!isset($GLOBALS['egw_info']))
|
|
|
|
{
|
|
|
|
$GLOBALS['egw_info'] = array(
|
|
|
|
'flags' => array(
|
|
|
|
'currentapp' => 'login',
|
2011-08-19 10:22:19 +02:00
|
|
|
'debug' => 'etemplate_widget_template',
|
2011-08-18 23:56:37 +02:00
|
|
|
)
|
2011-08-18 20:08:40 +02:00
|
|
|
);
|
|
|
|
include_once '../../header.inc.php';
|
2016-03-19 14:06:07 +01:00
|
|
|
} */
|
2011-08-18 23:56:37 +02:00
|
|
|
|
2011-08-18 20:08:40 +02:00
|
|
|
/**
|
|
|
|
* eTemplate widget baseclass
|
|
|
|
*/
|
2016-03-19 14:06:07 +01:00
|
|
|
class Template extends Etemplate\Widget
|
2011-08-18 20:08:40 +02:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Cache of already read templates
|
|
|
|
*
|
|
|
|
* @var array with name => template pairs
|
|
|
|
*/
|
|
|
|
protected static $cache = array();
|
|
|
|
|
2016-02-03 16:20:50 +01:00
|
|
|
/**
|
|
|
|
* Path of template relative to EGW_SERVER_ROOT
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $rel_path;
|
|
|
|
|
2011-08-18 20:08:40 +02:00
|
|
|
/**
|
2011-08-18 23:56:37 +02:00
|
|
|
* Get instance of template specified by name, template(-set) and version
|
2011-08-18 20:08:40 +02:00
|
|
|
*
|
2014-10-13 14:15:30 +02:00
|
|
|
* @param string $_name
|
|
|
|
* @param string $template_set =null default try template-set from user and if not found "default"
|
|
|
|
* @param string $version =''
|
|
|
|
* @param string $load_via ='' use given template to load $name
|
2016-03-19 14:06:07 +01:00
|
|
|
* @return Template|boolean false if not found
|
2011-08-18 20:08:40 +02:00
|
|
|
*/
|
2014-10-13 14:15:30 +02:00
|
|
|
public static function instance($_name, $template_set=null, $version='', $load_via='')
|
2011-08-18 20:08:40 +02:00
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
if (Api\Header\UserAgent::mobile())
|
2016-02-03 16:20:50 +01:00
|
|
|
{
|
|
|
|
$template_set = "mobile";
|
|
|
|
}
|
|
|
|
|
2014-03-17 18:12:02 +01:00
|
|
|
//$start = microtime(true);
|
2014-10-13 14:15:30 +02:00
|
|
|
list($name) = explode('?', $_name); // remove optional cache-buster
|
2011-08-18 20:08:40 +02:00
|
|
|
if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version)))
|
|
|
|
{
|
|
|
|
if ((!$path || self::read($load_via, $template_set)) && isset(self::$cache[$name]))
|
|
|
|
{
|
2011-08-18 23:56:37 +02:00
|
|
|
//error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read from cache");
|
2011-08-18 20:08:40 +02:00
|
|
|
return self::$cache[$name];
|
|
|
|
}
|
2011-10-06 17:23:24 +02:00
|
|
|
// Template not found, try again as if $name were a partial name
|
2013-09-02 09:52:57 +02:00
|
|
|
else if(!$path && strpos($name,'.') === false)
|
2011-10-06 17:23:24 +02:00
|
|
|
{
|
|
|
|
foreach(self::$cache as $c_name => $c_template)
|
|
|
|
{
|
2014-03-17 18:12:02 +01:00
|
|
|
list(,, $c_sub) = explode('.',$c_name, 3);
|
2013-11-01 22:39:45 +01:00
|
|
|
if($name == $c_sub)
|
|
|
|
{
|
|
|
|
//error_log(__METHOD__ . "('$name' loaded from cache ($c_name)");
|
|
|
|
return $c_template;
|
|
|
|
}
|
2013-11-18 11:45:32 +01:00
|
|
|
|
2013-10-17 01:16:29 +02:00
|
|
|
$parts = explode('.',$c_name);
|
|
|
|
if($name == $parts[count($parts)-1]) return $c_template;
|
2011-10-06 17:23:24 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-18 18:38:27 +02:00
|
|
|
// Template not found, try again with content expansion
|
|
|
|
if (is_array(self::$request->content))
|
|
|
|
{
|
|
|
|
$expand_name = self::expand_name($name, '','','','',self::$cont);
|
2015-03-17 15:07:20 +01:00
|
|
|
if ($expand_name && $expand_name != $name &&
|
|
|
|
($template = self::instance($expand_name, $template_set, $version, $load_via)))
|
2013-11-01 22:39:45 +01:00
|
|
|
{
|
|
|
|
// Remember original, un-expanded name in case content changes while still cached
|
|
|
|
$template->original_name = $name;
|
|
|
|
return $template;
|
|
|
|
}
|
2013-06-18 18:38:27 +02:00
|
|
|
}
|
2011-10-06 17:23:24 +02:00
|
|
|
|
2011-08-18 20:08:40 +02:00
|
|
|
error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') template NOT found!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$reader = new XMLReader();
|
2013-12-05 22:06:35 +01:00
|
|
|
if (!$reader->open(self::rel2path($path))) return false;
|
2011-08-18 20:08:40 +02:00
|
|
|
|
|
|
|
while($reader->read())
|
|
|
|
{
|
|
|
|
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'template')
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$template = new Template($reader);
|
2016-02-03 16:20:50 +01:00
|
|
|
$template->rel_path = $path;
|
2011-08-18 20:08:40 +02:00
|
|
|
//echo $template->id; _debug_array($template);
|
|
|
|
|
|
|
|
self::$cache[$template->id] = $template;
|
|
|
|
|
|
|
|
if ($template->id == $name)
|
|
|
|
{
|
2011-08-18 23:56:37 +02:00
|
|
|
//error_log(__METHOD__."('$name', '$template_set', '$version', '$load_via') read in ".round(1000.0*(microtime(true)-$start),2)." ms");
|
2011-08-18 20:08:40 +02:00
|
|
|
return $template;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-10-06 17:23:24 +02:00
|
|
|
|
2011-08-18 20:08:40 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2013-12-05 22:06:35 +01:00
|
|
|
const VFS_TEMPLATE_PATH = '/etemplates';
|
|
|
|
|
2011-08-18 20:08:40 +02:00
|
|
|
/**
|
2013-12-05 22:06:35 +01:00
|
|
|
* Get path/URL relative to EGroupware install of a template of full vfs url
|
2011-08-18 20:08:40 +02:00
|
|
|
*
|
|
|
|
* @param string $name
|
2014-10-13 14:15:30 +02:00
|
|
|
* @param string $template_set =null default try template-set from user and if not found "default"
|
|
|
|
* @param string $version =''
|
2013-12-05 22:06:35 +01:00
|
|
|
* @return string path of template xml file or null if not found
|
2011-08-18 20:08:40 +02:00
|
|
|
*/
|
2013-11-18 11:45:32 +01:00
|
|
|
public static function relPath($name, $template_set=null, $version='')
|
2011-08-18 20:08:40 +02:00
|
|
|
{
|
2016-10-19 16:44:04 +02:00
|
|
|
static $prefixes = null;
|
2014-03-17 18:12:02 +01:00
|
|
|
unset($version); // not used currently
|
2011-08-18 20:08:40 +02:00
|
|
|
list($app, $rest) = explode('.', $name, 2);
|
|
|
|
|
2013-11-18 11:45:32 +01:00
|
|
|
if (empty($template_set))
|
|
|
|
{
|
|
|
|
$template_set = $GLOBALS['egw_info']['user']['preferences']['common']['template_set'];
|
|
|
|
}
|
2013-12-05 22:06:35 +01:00
|
|
|
$template_path = '/'.$app.'/templates/'.$template_set.'/'.$rest.'.xet';
|
|
|
|
$default_path = '/'.$app.'/templates/default/'.$rest.'.xet';
|
2011-08-18 20:08:40 +02:00
|
|
|
|
2016-10-19 16:44:04 +02:00
|
|
|
// check if /etemplates is mounted in VFS and prefer it in that case over phy. file-system
|
|
|
|
if (!isset($prefixes))
|
|
|
|
{
|
|
|
|
$prefixes = array(EGW_SERVER_ROOT);
|
|
|
|
$fs_tab = Api\Vfs::mount();
|
|
|
|
if (isset($fs_tab[self::VFS_TEMPLATE_PATH]))
|
|
|
|
{
|
|
|
|
array_unshift($prefixes, Api\Vfs::PREFIX.self::VFS_TEMPLATE_PATH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach($prefixes as $prefix)
|
2011-08-18 20:08:40 +02:00
|
|
|
{
|
2013-12-05 22:06:35 +01:00
|
|
|
if (file_exists($prefix.$template_path))
|
|
|
|
{
|
|
|
|
$path = $template_path;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (file_exists($prefix.$default_path))
|
|
|
|
{
|
|
|
|
$path = $default_path;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// for a vfs template path we keep the prefix, to be able to distinquish between real filesystem and vfs
|
|
|
|
if (isset($path) && $prefix !== EGW_SERVER_ROOT)
|
|
|
|
{
|
|
|
|
$path = $prefix.$path;
|
2011-08-18 20:08:40 +02:00
|
|
|
}
|
2013-11-18 11:45:32 +01:00
|
|
|
//error_log(__METHOD__."('$name', '$template_set') returning ".array2string($path));
|
|
|
|
return $path;
|
2011-08-18 20:08:40 +02:00
|
|
|
}
|
2011-08-18 23:56:37 +02:00
|
|
|
|
2013-12-05 22:06:35 +01:00
|
|
|
/**
|
|
|
|
* Convert relative template path from relPath to an absolute path
|
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function rel2path($path)
|
|
|
|
{
|
|
|
|
if ($path[0] === '/')
|
|
|
|
{
|
|
|
|
$path = EGW_SERVER_ROOT.$path;
|
|
|
|
}
|
|
|
|
return $path;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert relative template path from relPath to an url incl. cache-buster modification time postfix
|
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
* @return string url
|
|
|
|
*/
|
|
|
|
public static function rel2url($path)
|
|
|
|
{
|
|
|
|
if ($path)
|
|
|
|
{
|
|
|
|
if ($path[0] === '/')
|
|
|
|
{
|
|
|
|
$url = $GLOBALS['egw_info']['server']['webserver_url'].$path.'?'.filemtime(self::rel2path($path));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
$url = Api\Vfs::download_url($path);
|
2013-12-05 23:46:31 +01:00
|
|
|
|
2016-04-07 22:42:06 +02:00
|
|
|
if ($url[0] == '/') $url = Api\Framework::link($url);
|
2014-10-13 14:15:30 +02:00
|
|
|
|
|
|
|
// mtime postfix has to use '?download=', as our WebDAV treats everything else literal and not ignore them like Apache for static files!
|
2015-05-27 14:15:36 +02:00
|
|
|
$url .= '?download='.filemtime($path);
|
2013-12-05 22:06:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//error_log(__METHOD__."('$path') returning $url");
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
2011-08-18 23:56:37 +02:00
|
|
|
/**
|
2011-08-20 12:27:38 +02:00
|
|
|
* Run method on all children
|
2011-08-18 23:56:37 +02:00
|
|
|
*
|
2011-08-19 08:30:06 +02:00
|
|
|
* Reimplemented because templates can have an own namespace specified in attrs[content], NOT id!
|
2011-08-18 23:56:37 +02:00
|
|
|
*
|
2012-05-03 16:17:47 +02:00
|
|
|
* @param string $method_name
|
2014-10-13 14:15:30 +02:00
|
|
|
* @param array $params =array('') parameter(s) first parameter has to be cname, second $expand!
|
|
|
|
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
2011-08-18 23:56:37 +02:00
|
|
|
*/
|
2011-08-21 13:55:56 +02:00
|
|
|
public function run($method_name, $params=array(''), $respect_disabled=false)
|
2011-08-18 23:56:37 +02:00
|
|
|
{
|
2011-08-20 12:27:38 +02:00
|
|
|
$cname =& $params[0];
|
2013-06-11 20:56:42 +02:00
|
|
|
$old_cname = $params[0];
|
2012-05-03 16:17:47 +02:00
|
|
|
if ($this->attrs['content']) $cname = self::form_name($cname, $this->attrs['content'], $params[1]);
|
2013-11-18 11:45:32 +01:00
|
|
|
|
2013-11-01 22:39:45 +01:00
|
|
|
// Check for template from content, and run over it
|
2015-03-18 22:31:16 +01:00
|
|
|
// templates included via template tag have their name to load them from in attribute "template"
|
|
|
|
$expand_name = self::expand_name($this->id ? $this->id : $this->attrs['template'], '','','','',self::$request->content);
|
2013-11-01 22:39:45 +01:00
|
|
|
if($this->original_name)
|
|
|
|
{
|
|
|
|
$expand_name = self::expand_name($this->original_name, '','','','',self::$request->content);
|
|
|
|
}
|
|
|
|
//error_log("$this running $method_name() cname: {$this->id} -> expand_name: $expand_name");
|
|
|
|
if($expand_name && $expand_name != $this->id)
|
|
|
|
{
|
2016-03-19 14:06:07 +01:00
|
|
|
if (($row_template = self::instance($expand_name)))
|
2015-03-18 22:31:16 +01:00
|
|
|
{
|
|
|
|
$row_template->run($method_name, $params, $respect_disabled);
|
|
|
|
}
|
2013-11-01 22:39:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parent::run($method_name, $params, $respect_disabled);
|
|
|
|
}
|
2013-06-11 20:56:42 +02:00
|
|
|
$params[0] = $old_cname;
|
2011-08-18 23:56:37 +02:00
|
|
|
}
|
2016-03-16 12:27:49 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill type options in self::$request->sel_options to be used on the client
|
|
|
|
*
|
|
|
|
* @param string $cname
|
|
|
|
* @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
|
|
|
|
*/
|
|
|
|
public function beforeSendToClient($cname, array $expand=null)
|
|
|
|
{
|
|
|
|
//error_log(__METHOD__."('$cname') this->id=$this->id, this->type=$this->type, this->attrs=".array2string($this->attrs));
|
|
|
|
$form_name = self::form_name($cname, $this->id, $expand);
|
|
|
|
|
|
|
|
self::setElementAttribute($form_name, 'url', self::rel2url($this->rel_path));
|
|
|
|
}
|
2011-08-18 20:08:40 +02:00
|
|
|
}
|
2011-08-18 23:56:37 +02:00
|
|
|
|
2013-12-05 22:06:35 +01:00
|
|
|
/*
|
2011-08-19 10:22:19 +02:00
|
|
|
if ($GLOBALS['egw_info']['flags']['debug'] == 'etemplate_widget_template')
|
2011-08-18 23:56:37 +02:00
|
|
|
{
|
2011-08-19 10:22:19 +02:00
|
|
|
$name = isset($_GET['name']) ? $_GET['name'] : 'timesheet.edit';
|
2016-03-19 14:06:07 +01:00
|
|
|
if (!($template = Template::instance($name)))
|
2011-08-19 10:22:19 +02:00
|
|
|
{
|
|
|
|
header('HTTP-Status: 404 Not Found');
|
|
|
|
echo "<html><head><title>Not Found</title><body><h1>Not Found</h1><p>The requested eTemplate '$name' was not found!</p></body></html>\n";
|
|
|
|
exit;
|
|
|
|
}
|
2011-08-18 23:56:37 +02:00
|
|
|
header('Content-Type: text/xml');
|
|
|
|
echo $template->toXml();
|
2011-10-06 17:23:24 +02:00
|
|
|
}
|
2013-12-05 22:06:35 +01:00
|
|
|
*/
|