diff --git a/admin/inc/class.admin_account.inc.php b/admin/inc/class.admin_account.inc.php index 5e56c68749..618f6f4660 100644 --- a/admin/inc/class.admin_account.inc.php +++ b/admin/inc/class.admin_account.inc.php @@ -101,7 +101,7 @@ class admin_account $readonlys['account_passwd'] = $readonlys['account_passwd2'] = true; } return array( - 'name' => 'admin.account?'.filemtime(EGW_SERVER_ROOT.'/admin/templates/default/account.xet'), + 'name' => 'admin.account', 'prepend' => true, 'label' => 'Account', 'data' => $account, diff --git a/etemplate/inc/class.etemplate_new.inc.php b/etemplate/inc/class.etemplate_new.inc.php index 88093c5b1c..0cdb6eb9c4 100644 --- a/etemplate/inc/class.etemplate_new.inc.php +++ b/etemplate/inc/class.etemplate_new.inc.php @@ -7,7 +7,7 @@ * @subpackage api * @link http://www.egroupware.org * @author Ralf Becker - * @copyright 2002-13 by RalfBecker@outdoor-training.de + * @copyright 2002-16 by RalfBecker@outdoor-training.de * @version $Id$ */ @@ -109,19 +109,24 @@ class etemplate_new extends etemplate_widget_template $content ); - foreach($hook_data as $extras) { + foreach($hook_data as $extras) + { if (!$extras) continue; - foreach(isset($extras[0]) ? $extras : array($extras) as $extra) { - if ($extra['data'] && is_array($extra['data'])) { + foreach(isset($extras[0]) ? $extras : array($extras) as $extra) + { + if ($extra['data'] && is_array($extra['data'])) + { $content = array_merge($content, $extra['data']); } - if ($extra['preserve'] && is_array($extra['preserve'])) { + if ($extra['preserve'] && is_array($extra['preserve'])) + { $preserv = array_merge($preserv, $extra['preserve']); } - if ($extra['readonlys'] && is_array($extra['readonlys'])) { + if ($extra['readonlys'] && is_array($extra['readonlys'])) + { $readonlys = array_merge($readonlys, $extra['readonlys']); } } @@ -306,13 +311,13 @@ class etemplate_new extends etemplate_widget_template * Process via Ajax submitted content * * @param string $etemplate_exec_id - * @param array $content + * @param array $_content * @param boolean $no_validation * @throws egw_exception_wrong_parameter */ - static public function ajax_process_content($etemplate_exec_id, array $content, $no_validation) + static public function ajax_process_content($etemplate_exec_id, array $_content, $no_validation) { - //error_log(__METHOD__."(".array2string($etemplate_exec_id).', '.array2string($content).")"); + //error_log(__METHOD__."(".array2string($etemplate_exec_id).', '.array2string($_content).")"); self::$request = etemplate_request::read($etemplate_exec_id); //error_log('request='.array2string(self::$request)); @@ -337,7 +342,7 @@ class etemplate_new extends etemplate_widget_template $expand = array( 'cont' => &self::$request->content, ); - $template->run('validate', array('', $expand, $content, &$validated), true); // $respect_disabled=true: do NOT validate disabled widgets and children + $template->run('validate', array('', $expand, $_content, &$validated), true); // $respect_disabled=true: do NOT validate disabled widgets and children if ($no_validation) { @@ -345,7 +350,7 @@ class etemplate_new extends etemplate_widget_template } elseif (self::validation_errors(self::$request->ignore_validation)) { - error_log(__METHOD__."(,".array2string($content).') validation_errors='.array2string(self::$validation_errors)); + error_log(__METHOD__."(,".array2string($_content).') validation_errors='.array2string(self::$validation_errors)); self::$response->generic('et2_validation_error', self::$validation_errors); exit; } @@ -353,50 +358,41 @@ class etemplate_new extends etemplate_widget_template // tell request call to remove request, if it is not modified eg. by call to exec in callback self::$request->remove_if_not_modified(); - $hook_data = $GLOBALS['egw']->hooks->process( - array( - 'hook_location' => 'etemplate2_before_process', - 'location_name' => $template->id) + - self::complete_array_merge(self::$request->preserv, $validated) - ); - - foreach($hook_data as $extras) { + foreach($GLOBALS['egw']->hooks->process(array( + 'hook_location' => 'etemplate2_before_process', + 'location_name' => $template->id, + ) + self::complete_array_merge(self::$request->preserv, $validated)) as $extras) + { if (!$extras) continue; - foreach(isset($extras[0]) ? $extras : array($extras) as $extra) { - if ($extra['data'] && is_array($extra['data'])) { + foreach(isset($extras[0]) ? $extras : array($extras) as $extra) + { + if ($extra['data'] && is_array($extra['data'])) + { $validated = array_merge($validated, $extra['data']); } } } - unset($hook_data); //error_log(__METHOD__."(,".array2string($content).')'); //error_log(' validated='.array2string($validated)); $content = ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $validated)); - $tcontent = array(); - - if( is_array($content) ) { - $tcontent = $content; - } - else { - $tcontent = self::complete_array_merge( - self::$request->preserv, - $validated - ); - } + $tcontent = is_array($content) ? $content : + self::complete_array_merge(self::$request->preserv, $validated); $hook_data = $GLOBALS['egw']->hooks->process( array( 'hook_location' => 'etemplate2_after_process', - 'location_name' => $template->id) + - $tcontent - ); + 'location_name' => $template->id + ) + $tcontent); + unset($tcontent); - if( is_array($content) ) { - foreach($hook_data as $extras) { + if (is_array($content)) + { + foreach($hook_data as $extras) + { if (!$extras) continue; foreach(isset($extras[0]) ? $extras : array($extras) as $extra) { @@ -472,13 +468,6 @@ class etemplate_new extends etemplate_widget_template return ExecMethod(self::$request->method, self::complete_array_merge(self::$request->preserv, $validated)); } - /** - * Path of template relative to EGW_SERVER_ROOT - * - * @var string - */ - public $rel_path; - public $name; public $template_set; public $version; @@ -494,7 +483,7 @@ class etemplate_new extends etemplate_widget_template * Reads an eTemplate from filesystem or DB (not yet supported) * * @param string $name name of the eTemplate or array with the values for all keys - * @param string $template_set=null default try template-set from user and if not found "default" + * @param string $template_set =null default try template-set from user and if not found "default" * @param string $lang language, '' loads the pref. lang of the user, 'default' loads the default one '' in the db * @param int $group id of the (primary) group of the user or 0 for none, not used at the moment !!! * @param string $version version of the eTemplate @@ -505,13 +494,13 @@ class etemplate_new extends etemplate_widget_template */ public function read($name,$template_set=null,$lang='default',$group=0,$version='',$load_via='') { - + // For mobile experience try to load custom mobile templates if (html::$ua_mobile) { $template_set = "mobile"; } - + unset($lang); unset($group); // not used, but in old signature $this->rel_path = self::relPath($this->name=$name, $this->template_set=$template_set, $this->version=$version, $this->laod_via = $load_via); @@ -580,7 +569,7 @@ class etemplate_new extends etemplate_widget_template * disables all cells with name == $name * * @param sting $name cell-name - * @param boolean $disabled=true disable or enable a cell, default true=disable + * @param boolean $disabled =true disable or enable a cell, default true=disable * @return reference to attribute * @deprecated use disableElement($name, $disabled=true) */ @@ -626,7 +615,7 @@ class etemplate_new extends etemplate_widget_template /** * Debug callback just outputting content * - * @param array $content=null + * @param array $content =null */ public function debug(array $content=null) { @@ -658,8 +647,8 @@ class etemplate_new extends etemplate_widget_template * Format a number according to user prefs with decimal and thousands separator (later only for readonly) * * @param int|float|string $number - * @param int $num_decimal_places=2 - * @param boolean $readonly=true + * @param int $num_decimal_places =2 + * @param boolean $readonly =true * @return string */ static public function number_format($number,$num_decimal_places=2,$readonly=true) diff --git a/etemplate/inc/class.etemplate_widget_tabbox.inc.php b/etemplate/inc/class.etemplate_widget_tabbox.inc.php index dbe868c975..88895845f5 100644 --- a/etemplate/inc/class.etemplate_widget_tabbox.inc.php +++ b/etemplate/inc/class.etemplate_widget_tabbox.inc.php @@ -34,12 +34,11 @@ class etemplate_widget_tabbox extends etemplate_widget * content. This prevents running the method on disabled tabs. * * @param string $method_name - * @param array $params=array('') parameter(s) first parameter has to be the cname, second $expand! - * @param boolean $respect_disabled=false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children + * @param array $params =array('') parameter(s) first parameter has to be the cname, second $expand! + * @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children */ public function run($method_name, $params=array(''), $respect_disabled=false) { - // Make sure additional tabs are processed for any method if($this->attrs['tabs'] && !$this->tabs_attr_evaluated) { @@ -51,11 +50,14 @@ class etemplate_widget_tabbox extends etemplate_widget $this->children[1]->children = array(); } + $this->tabs = array(); foreach($this->attrs['tabs'] as $tab) { $template= clone etemplate_widget_template::instance($tab['template']); if($tab['id']) $template->attrs['content'] = $tab['id']; $this->children[1]->children[] = $template; + $tab['url'] = etemplate_widget_template::rel2url($template->rel_path); + $this->tabs[] = $tab; unset($template); } } @@ -67,8 +69,8 @@ class etemplate_widget_tabbox extends etemplate_widget { foreach($this->children[1]->children as $tab) { - $ro_id = explode('.',$tab->template ? $tab->template : $tab->id); - $ro_id = $ro_id[count($ro_id)-1]; + $parts = explode('.',$tab->template ? $tab->template : $tab->id); + $ro_id = array_pop($parts); if($readonlys[$ro_id]) { $tab->attrs['disabled'] = $readonlys[$ro_id]; @@ -80,6 +82,23 @@ class etemplate_widget_tabbox extends etemplate_widget parent::run($method_name, $params, $respect_disabled); } + /** + * Implemented to send tab-urls incl. cache-buster and mobile template switch to client-side + * + * They are send as tab_urls object via modifications. + * + * @param string $cname + */ + public function beforeSendToClient($cname) + { + $form_name = self::form_name($cname, $this->id); + + if (!empty($this->tabs)) + { + self::setElementAttribute($form_name, 'tabs', $this->tabs); + } + } + /** * Validate input - just pass through, tabs doesn't care * diff --git a/etemplate/inc/class.etemplate_widget_template.inc.php b/etemplate/inc/class.etemplate_widget_template.inc.php index 47965567b9..cb03c76f8e 100644 --- a/etemplate/inc/class.etemplate_widget_template.inc.php +++ b/etemplate/inc/class.etemplate_widget_template.inc.php @@ -35,6 +35,13 @@ class etemplate_widget_template extends etemplate_widget */ protected static $cache = array(); + /** + * Path of template relative to EGW_SERVER_ROOT + * + * @var string + */ + public $rel_path; + /** * Get instance of template specified by name, template(-set) and version * @@ -47,6 +54,11 @@ class etemplate_widget_template extends etemplate_widget */ public static function instance($_name, $template_set=null, $version='', $load_via='') { + if (html::$ua_mobile) + { + $template_set = "mobile"; + } + //$start = microtime(true); list($name) = explode('?', $_name); // remove optional cache-buster if (isset(self::$cache[$name]) || !($path = self::relPath($name, $template_set, $version))) @@ -96,6 +108,7 @@ class etemplate_widget_template extends etemplate_widget if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'template') { $template = new etemplate_widget_template($reader); + $template->rel_path = $path; //echo $template->id; _debug_array($template); self::$cache[$template->id] = $template; diff --git a/etemplate/js/et2_widget_tabs.js b/etemplate/js/et2_widget_tabs.js index e691d8f177..3cbc99cc65 100644 --- a/etemplate/js/et2_widget_tabs.js +++ b/etemplate/js/et2_widget_tabs.js @@ -63,7 +63,7 @@ var et2_tabbox = et2_valueWidget.extend([et2_IInput,et2_IResizeable], // Create the outer tabbox container this.container = $j(document.createElement("div")) .addClass("et2_tabbox"); - + // Create the upper container for the tab flags this.flagContainer = $j(document.createElement("div")) .addClass("et2_tabheader") @@ -212,7 +212,7 @@ var et2_tabbox = et2_valueWidget.extend([et2_IInput,et2_IResizeable], { var tab = this.options.tabs[i]; var tab_id = tab.id || tab.template; - var tab_options = {id: tab_id, template:tab.template}; + var tab_options = {id: tab_id, template:tab.template, url: tab.url}; if(tab.id) { tab_options.content = tab.id; @@ -359,9 +359,9 @@ var et2_tabbox = et2_valueWidget.extend([et2_IInput,et2_IResizeable], entry.contentDiv.appendTo(entry.flagDiv); } } - - if (this.options.align_tabs == 'v'){ - + + if (this.options.align_tabs == 'v'){ + this.container.addClass('vertical'); this.tabContainer.hide(); } diff --git a/etemplate/js/et2_widget_template.js b/etemplate/js/et2_widget_template.js index a4f21a375c..b002d9b8b1 100644 --- a/etemplate/js/et2_widget_template.js +++ b/etemplate/js/et2_widget_template.js @@ -55,6 +55,11 @@ var et2_template = et2_DOMWidget.extend( "name": "Content index", "default": et2_no_init, "description": "Used for passing in specific content to the template other than what it would get by ID." + }, + url: { + name: "URL of template", + type: "string", + description: "full URL to load template incl. cache-buster" } }, @@ -102,16 +107,20 @@ var et2_template = et2_DOMWidget.extend( if(!xml) { // Ask server - var splitted = template_name.split('.'); - // use template base url from initial template, to continue using webdav, if that was loaded via webdav - var path = this.getRoot()._inst.template_base_url + splitted.shift() + "/templates/default/" + - splitted.join('.')+ ".xet" + (cache_buster ? '?download='+cache_buster : - // if server did not give a cache-buster, fall back to current time - '?download='+(new Date).valueOf()); - - if(splitted.length) + var url = this.options.url; + if (!this.options.url) { - et2_loadXMLFromURL(path, function(_xmldoc) { + var splitted = template_name.split('.'); + // use template base url from initial template, to continue using webdav, if that was loaded via webdav + url = this.getRoot()._inst.template_base_url + splitted.shift() + "/templates/default/" + + splitted.join('.')+ ".xet" + (cache_buster ? '?download='+cache_buster : ''); + } + // if server did not give a cache-buster, fall back to current time + if (url.indexOf('?') == -1) url += '?download='+(new Date).valueOf(); + + if(this.options.url || splitted.length) + { + et2_loadXMLFromURL(url, function(_xmldoc) { // Scan for templates and store them for(var i = 0; i < _xmldoc.childNodes.length; i++) { var template = _xmldoc.childNodes[i];