[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/etemplate/inc/ -> class.uietemplate.inc.php (source)

   1  <?php
   2      /**************************************************************************\
   3      * eGroupWare - EditableTemplates - HTML User Interface                     *
   4      * http://www.egroupware.org                                                *
   5      * Written by Ralf Becker <RalfBecker@outdoor-training.de>                  *
   6      * --------------------------------------------                             *
   7      *  This program is free software; you can redistribute it and/or modify it *
   8      *  under the terms of the GNU General Public License as published by the   *
   9      *  Free Software Foundation; either version 2 of the License, or (at your  *
  10      *  option) any later version.                                              *
  11      \**************************************************************************/
  12  
  13      /* $Id: class.uietemplate.inc.php 22881 2006-12-04 14:02:40Z ralfbecker $ */
  14  
  15      include_once (EGW_INCLUDE_ROOT . '/etemplate/inc/class.boetemplate.inc.php');
  16  
  17      /**
  18       * creates dialogs / HTML-forms from eTemplate descriptions
  19       *
  20       * Usage example:
  21       *<code>
  22       * $tmpl =& CreateObject('etemplate.etemplate','app.template.name');
  23       * $tmpl->exec('app.class.callback',$content_to_show);
  24       *</code>
  25       * This creates a form from the eTemplate 'app.template.name' and takes care that
  26       * the method / public function 'callback' in class 'class' of 'app' gets called
  27       * if the user submits the form. For the complete param's see the description of exec.
  28       *
  29       * etemplate or uietemplate extends boetemplate, all vars and public functions are inherited
  30       *
  31       * @package etemplate
  32       * @subpackage api
  33       * @author Ralf Becker <RalfBecker@outdoor-training.de>
  34       * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
  35       */
  36      class etemplate extends boetemplate
  37      {
  38          /**
  39           * @var int/string='' integer debug-level or template-name or cell-type or '' = off
  40           * 1=calls to show and process_show, 2=content after process_show,
  41           * 3=calls to show_cell and process_show_cell
  42           */
  43          var $debug;
  44          var $html;    /* instance of html-class */
  45          var $xslt = false;    /* do we run in the xslt framework (true) or the regular eGW one (false) */
  46          var $class_conf = array('nmh' => 'th','nmr0' => 'row_on','nmr1' => 'row_off');
  47          var $public_functions = array('process_exec' => True);
  48          /**
  49           * @var int $innerWidth inner width of browser window
  50           */
  51          var $innerWidth;
  52          /**
  53           * @var array $content reference to the content-param of the last call to show, for extensions to use
  54           */
  55          var $content;
  56          /**
  57           * @var array $sel_options reference to the sel_options-param of the last call to show, for extensions to use
  58           */
  59          var $sel_options;
  60          /**
  61           * @var string $name_form name of the currently processed etemplate, reference to $GLOBALS['egw_info']['etemplate']['name_form']
  62           */
  63          var $name_form;
  64          /**
  65           * @var array $name_forms used form-names in this request, reference to $GLOBALS['egw_info']['etemplate']['name_forms']
  66           */
  67          var $name_forms;
  68  
  69          /**
  70           * constructor of etemplate class, reads an eTemplate if $name is given
  71           *
  72           * @param string $name of etemplate or array with name and other keys
  73           * @param string/array $load_via with keys of other etemplate to load in order to get $name
  74           */
  75  		function etemplate($name='',$load_via='')
  76          {
  77              if (!is_object($GLOBALS['egw']->html))
  78              {
  79                  $GLOBALS['egw']->html =& CreateObject('phpgwapi.html');
  80              }
  81              $this->html = &$GLOBALS['egw']->html;
  82  
  83              if (!is_object($GLOBALS['egw']->template))
  84              {
  85                  $GLOBALS['egw']->template =& CreateObject('phpgwapi.Template');
  86              }
  87              $this->boetemplate($name,$load_via);
  88  
  89              $this->xslt = is_object($GLOBALS['egw']->xslttpl);
  90              
  91              $this->sitemgr = is_object($GLOBALS['Common_BO']);
  92              
  93              if (($this->innerWidth = (int) $_POST['innerWidth']))
  94              {
  95                  $GLOBALS['egw']->session->appsession('innerWidth','etemplate',$this->innerWidth);
  96              }
  97              elseif (!($this->innerWidth = (int) $GLOBALS['egw']->session->appsession('innerWidth','etemplate')))
  98              {
  99                  $this->innerWidth = 1018;    // default width for an assumed screen-resolution of 1024x768
 100              }
 101              //echo "<p>_POST[innerWidth]='$_POST[innerWidth]', innerWidth=$this->innerWidth</p>\n";
 102              $this->name_form =& $GLOBALS['egw_info']['etemplate']['name_form'];
 103              $this->name_forms =& $GLOBALS['egw_info']['etemplate']['name_forms'];
 104              if (!is_array($this->name_forms)) $this->name_forms = array();
 105          }
 106  
 107          /**
 108           * Abstracts a html-location-header call
 109           *
 110           * In other UI's than html this needs to call the methode, defined by menuaction or
 111           * open a browser-window for any other links.
 112           * 
 113           * @param string/array $params url or array with get-params incl. menuaction
 114           */
 115  		function location($params='')
 116          {
 117              $GLOBALS['egw']->redirect_link(is_array($params) ? '/index.php' : $params,
 118                  is_array($params) ? $params : '');
 119          }
 120  
 121          /**
 122           * Generats a Dialog from an eTemplate - abstract the UI-layer
 123           *
 124           * This is the only function an application should use, all other are INTERNAL and
 125           * do NOT abstract the UI-layer, because they return HTML.
 126           * Generates a webpage with a form from the template and puts process_exec in the
 127           * form as submit-url to call process_show for the template before it
 128           * ExecuteMethod's the given $method of the caller.
 129           *
 130           * @param string $method Methode (e.g. 'etemplate.editor.edit') to be called if form is submitted
 131           * @param array $content with content to fill the input-fields of template, eg. the text-field
 132           *         with name 'name' gets its content from $content['name']
 133           * @param $sel_options array or arrays with the options for each select-field, keys are the
 134           *         field-names, eg. array('name' => array(1 => 'one',2 => 'two')) set the
 135           *         options for field 'name'. ($content['options-name'] is possible too !!!)
 136           * @param array $readonlys with field-names as keys for fields with should be readonly
 137           *         (eg. to implement ACL grants on field-level or to remove buttons not applicable)
 138           * @param array $preserv with vars which should be transported to the $method-call (eg. an id) array('id' => $id) sets $_POST['id'] for the $method-call
 139           * @param int $output_mode 0 = echo incl. navbar, 1 = return html, 2 = echo without navbar (eg. for popups)
 140           *    -1 = first time return html, after use 0 (echo html incl. navbar), eg. for home
 141           * @param string $ignore_validation if not empty regular expression for validation-errors to ignore
 142           * @param array $changes change made in the last call if looping, only used internaly by process_exec
 143           * @return string html for $output_mode == 1, else nothing
 144           */
 145  		function exec($method,$content,$sel_options='',$readonlys='',$preserv='',$output_mode=0,$ignore_validation='',$changes='')
 146          {
 147              //echo "<br>globals[java_script] = '".$GLOBALS['egw_info']['etemplate']['java_script']."', this->java_script() = '".$this->java_script()."'\n";
 148              if (!$sel_options)
 149              {
 150                  $sel_options = array();
 151              }
 152              if (!$readonlys)
 153              {
 154                  $readonlys = array();
 155              }
 156              if (!$preserv)
 157              {
 158                  $preserv = array();
 159              }
 160              if (!$changes)
 161              {
 162                  $changes = array();
 163              }
 164              if (isset($content['app_header']))
 165              {
 166                  $GLOBALS['egw_info']['flags']['app_header'] = $content['app_header'];
 167              }
 168              if ($GLOBALS['egw_info']['flags']['currentapp'] != 'etemplate')
 169              {
 170                  $GLOBALS['egw']->translation->add_app('etemplate');    // some extensions have own texts
 171              }
 172              $id = $this->appsession_id();
 173              
 174              // use different form-names to allows multiple eTemplates in one page, eg. addressbook-view
 175              $this->name_form = 'eTemplate';
 176              if (in_array($this->name_form,$this->name_forms))
 177              {
 178                  $this->name_form .= count($this->name_forms);
 179              }
 180              $this->name_forms[] = $this->name_form;
 181  
 182              $GLOBALS['egw_info']['etemplate']['output_mode'] = $output_mode;    // let extensions "know" they are run eg. in a popup
 183              $GLOBALS['egw_info']['etemplate']['loop'] = False;
 184              $GLOBALS['egw_info']['etemplate']['form_options'] = '';    // might be set in show
 185              $GLOBALS['egw_info']['etemplate']['to_process'] = array();
 186              $html = $this->html->form($this->include_java_script(1).
 187                      $this->html->input_hidden(array(
 188                          'submit_button' => '',
 189                          'innerWidth'    => '',
 190                      ),'',False).
 191                      $this->show($this->complete_array_merge($content,$changes),$sel_options,$readonlys,'exec'),array(
 192                          'etemplate_exec_id' => $id
 193                      ),$this->sitemgr ? '' : '/etemplate/process_exec.php?menuaction='.$method,
 194                      '',$this->name_form,$GLOBALS['egw_info']['etemplate']['form_options'].
 195                      // dont set the width of popups!
 196                      ($output_mode != 0 ? '' : ' onsubmit="this.innerWidth.value=window.innerWidth ? window.innerWidth : document.body.clientWidth;"'));
 197                      //echo "to_process="; _debug_array($GLOBALS['egw_info']['etemplate']['to_process']); 
 198              
 199              if ($this->sitemgr)
 200              {
 201                  
 202              }
 203              elseif (!$this->xslt)
 204              {
 205                  $hooked = isset($GLOBALS['egw_info']['etemplate']['content']) ? $GLOBALS['egw_info']['etemplate']['content'] :
 206                      $GLOBALS['egw']->template->get_var('phpgw_body');
 207  
 208                  if (!@$GLOBALS['egw_info']['etemplate']['hooked'] && (int) $output_mode != 1 && (int) $output_mode != -1)    // not just returning the html
 209                  {
 210                      $GLOBALS['egw_info']['flags']['java_script'] .= $this->include_java_script(2);
 211                      $GLOBALS['egw']->common->egw_header();
 212                  }
 213                  elseif (!isset($GLOBALS['egw_info']['etemplate']['content']))
 214                  {
 215                      $html = $this->include_java_script(2).$html;    // better than nothing
 216                  }
 217                  // saving the etemplate content for other hooked etemplate apps (atm. infolog hooked into addressbook)
 218                  $GLOBALS['egw_info']['etemplate']['content'] =& $html;
 219              }
 220              else
 221              {
 222                  $hooked = $GLOBALS['egw']->xslttpl->get_var('phpgw');
 223                  $hooked = $hooked['body_data'];
 224                  $GLOBALS['egw']->xslttpl->set_var('phpgw',array('java_script' => $GLOBALS['egw_info']['flags']['java_script'].$this->include_java_script(2)));
 225              }
 226              //echo "<p>uietemplate::exec($method,...) after show: sitemgr=$this->sitemgr, xslt=$this->xslt, hooked=$hooked, output_mode=$output_mode</p>\n";
 227  
 228              if (!$this->sitemgr && (int) $output_mode != 1 && (int) $output_mode != -1)    // NOT returning html
 229              {
 230                  if (!$this->xslt)
 231                  {
 232                      if (!@$GLOBALS['egw_info']['etemplate']['hooked'])
 233                      {
 234                          if((int) $output_mode != 2)
 235                          {
 236                              echo parse_navbar();
 237                          }
 238                          else
 239                          {
 240                              echo '<div id="divMain">'."\n";
 241                              if ($GLOBALS['egw_info']['user']['apps']['manual'])    // adding a manual icon to every popup
 242                              {
 243                                  $manual =& new etemplate('etemplate.popup.manual');
 244                                  echo $manual->show(array());
 245                                  unset($manual);
 246                              }
 247                          }
 248                      }
 249                      echo $GLOBALS['egw_info']['etemplate']['hook_content'].$html;
 250  
 251                      if (!@$GLOBALS['egw_info']['etemplate']['hooked'] &&
 252                              (!isset($_GET['menuaction']) || strstr($_SERVER['PHP_SELF'],'process_exec.php')))
 253                      {
 254                          if((int) $output_mode == 2)
 255                          {
 256                              echo "</div>\n";
 257                          }
 258                          $GLOBALS['egw']->common->egw_footer();
 259                      }
 260                  }
 261                  else
 262                  {
 263                      // need to add some logic here to support popups (output_mode==2) for xslt, but who cares ...
 264                      $GLOBALS['egw']->xslttpl->set_var('phpgw',array('body_data' => $html));
 265                  }
 266              }
 267              $this->save_appsession($this->as_array(2) + array(
 268                  'readonlys' => $readonlys,
 269                  'content' => $content,
 270                  'changes' => $changes,
 271                  'sel_options' => $sel_options,
 272                  'preserv' => $preserv,
 273                  'extension_data' => $GLOBALS['egw_info']['etemplate']['extension_data'],
 274                  'to_process' => $GLOBALS['egw_info']['etemplate']['to_process'],
 275                  'java_script' => $GLOBALS['egw_info']['etemplate']['java_script'],
 276                  'java_script_from_flags' => $GLOBALS['egw_info']['flags']['java_script'],
 277                  'java_script_body_tags' => $GLOBALS['egw']->js->body,
 278                  'dom_enabled' => $GLOBALS['egw_info']['etemplate']['dom_enabled'],
 279                  'hooked' => $hooked != '' ? $hooked : $GLOBALS['egw_info']['etemplate']['hook_content'],
 280                  'hook_app' => $hooked ? $GLOBALS['egw_info']['flags']['currentapp'] : $GLOBALS['egw_info']['etemplate']['hook_app'],
 281                  'app_header' => $GLOBALS['egw_info']['flags']['app_header'],
 282                  'output_mode' => $output_mode != -1 ? $output_mode : 0,
 283                  'session_used' => 0,
 284                  'ignore_validation' => $ignore_validation,
 285                  'method' => $method,
 286              ),$id);
 287  
 288              if ($this->sitemgr || (int) $output_mode == 1 || (int) $output_mode == -1)    // return html
 289              {
 290                  return $html;
 291              }
 292          }
 293  
 294          /**
 295           * Check if we have not ignored validation errors
 296           *
 297           * @param string $ignore_validation if not empty regular expression for validation-errors to ignore
 298           * @param string $cname name-prefix, which need to be ignored
 299           * @return boolean true if there are not ignored validation errors, false otherwise
 300           */
 301  		function validation_errors($ignore_validation,$cname='exec')
 302          {
 303              //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') validation_error="; _debug_array($GLOBALS['egw_info']['etemplate']['validation_errors']);
 304              if (!$ignore_validation) return count($GLOBALS['egw_info']['etemplate']['validation_errors']) > 0;
 305  
 306              foreach($GLOBALS['egw_info']['etemplate']['validation_errors'] as $name => $error)
 307              {
 308                  if ($cname) $name = preg_replace('/^'.$cname.'\[([^\]]+)\](.*)$/','\\1\\2',$name);
 309  
 310                  if (!preg_match($ignore_validation,$name))
 311                  {
 312                      //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) not ignored!!!</p>\n";
 313                      return true;
 314                  }
 315                  //echo "<p>uietemplate::validation_errors('$ignore_validation','$cname') name='$name' ($error) ignored</p>\n";
 316              }
 317              return false;
 318          }
 319  
 320          /**
 321           * Makes the necessary adjustments to _POST before it calls the app's method
 322           *
 323           * This function is only to submit forms to, create with exec.
 324           * All eTemplates / forms executed with exec are submited to this function
 325           * via /etemplate/process_exec.php?menuaction=<callback>. We cant use the global index.php as
 326           * it would set some constants to etemplate instead of the calling app. 
 327           * process_exec then calls process_show for the eTemplate (to adjust the content of the _POST) and
 328           * ExecMethod's the given callback from the app with the content of the form as first argument.
 329           *
 330           * @return mixed false if no sessiondata and $this->sitemgr, else the returnvalue of exec of the method-calls
 331           */
 332  		function process_exec()
 333          {
 334              //echo "process_exec: _POST ="; _debug_array($_POST);
 335              $session_data = $this->get_appsession($_POST['etemplate_exec_id']);
 336              //echo "<p>process_exec: session_data ="; _debug_array($session_data);
 337  
 338              if (!$_POST['etemplate_exec_id'] || !is_array($session_data) || count($session_data) < 10)
 339              {
 340                  if ($this->sitemgr) return false;
 341                  //echo "uitemplate::process_exec() id='$_POST[etemplate_exec_id]' invalid session-data !!!"; _debug_array($_SESSION);
 342                  // this prevents an empty screen, if the sessiondata gets lost somehow
 343                  $this->location(array('menuaction' => $_GET['menuaction']));
 344              }
 345              if (isset($_POST['submit_button']) && !empty($_POST['submit_button']))
 346              {
 347                  $this->set_array($_POST,$_POST['submit_button'],'pressed');
 348              }
 349              $content = $_POST['exec'];
 350              if (!is_array($content))
 351              {
 352                  $content = array();
 353              }
 354              $this->init($session_data);
 355              $GLOBALS['egw_info']['etemplate']['extension_data'] = $session_data['extension_data'];
 356              $GLOBALS['egw_info']['etemplate']['java_script'] = $session_data['java_script'] || $_POST['java_script'];
 357              $GLOBALS['egw_info']['etemplate']['dom_enabled'] = $session_data['dom_enabled'] || $_POST['dom_enabled'];
 358              //echo "globals[java_script] = '".$GLOBALS['egw_info']['etemplate']['java_script']."', session_data[java_script] = '".$session_data['java_script']."', _POST[java_script] = '".$_POST['java_script']."'\n";
 359              //echo "process_exec($this->name) content ="; _debug_array($content);
 360              if ($GLOBALS['egw_info']['flags']['currentapp'] != 'etemplate')
 361              {
 362                  $GLOBALS['egw']->translation->add_app('etemplate');    // some extensions have own texts
 363              }
 364              $this->process_show($content,$session_data['to_process'],'exec');
 365  
 366              $GLOBALS['egw_info']['etemplate']['loop'] |= !$this->canceled && $this->button_pressed &&
 367                  $this->validation_errors($session_data['ignore_validation']);    // set by process_show
 368  
 369              //echo "process_exec($this->name) process_show(content) ="; _debug_array($content);
 370              //echo "process_exec($this->name) session_data[changes] ="; _debug_array($session_data['changes']);
 371              $content = $this->complete_array_merge($session_data['changes'],$content);
 372              //echo "process_exec($this->name) merge(changes,content) ="; _debug_array($content);
 373  
 374              if ($GLOBALS['egw_info']['etemplate']['loop'])
 375              {
 376                  if ($session_data['hooked'] != '')    // set previous phpgw_body if we are called as hook
 377                  {
 378                      if (!$this->xslt)
 379                      {
 380                          $GLOBALS['egw_info']['etemplate']['hook_content'] = $session_data['hooked'];
 381                          $GLOBALS['egw_info']['flags']['currentapp'] = $GLOBALS['egw_info']['etemplate']['hook_app'] = $session_data['hook_app'];
 382                      }
 383                      else
 384                      {
 385                          $GLOBALS['egw']->xslttpl->set_var('phpgw',array('body_data' => $session_data['hooked']));
 386                      }
 387                  }
 388                  if (!empty($session_data['app_header']))
 389                  {
 390                      $GLOBALS['egw_info']['flags']['app_header'] = $session_data['app_header'];
 391                  }
 392                  
 393                  $GLOBALS['egw_info']['flags']['java_script'] .= $session_data['java_script_from_flags'];
 394                  if (!empty($session_data['java_script_body_tags']))
 395                  {
 396                      if( !is_object($GLOBALS['phpgw']->js))
 397                      {
 398                          $GLOBALS['phpgw']->js = CreateObject('phpgwapi.javascript');
 399                      }
 400                      foreach ($session_data['java_script_body_tags'] as $tag => $code)
 401                      {
 402                          error_log($GLOBALS['egw']->js->body[$tag]);
 403                          $GLOBALS['egw']->js->body[$tag] .= $code;
 404                      }
 405                  }
 406                  
 407                  //echo "<p>process_exec($this->name): <font color=red>loop is set</font>, content=</p>\n"; _debug_array($content);
 408                  return $this->exec($session_data['method'],$session_data['content'],$session_data['sel_options'],
 409                      $session_data['readonlys'],$session_data['preserv'],$session_data['output_mode'],
 410                      $session_data['ignore_validation'],$content);
 411              }
 412              else
 413              {
 414                  return ExecMethod($session_data['method'],$this->complete_array_merge($session_data['preserv'],$content));
 415              }
 416          }
 417  
 418          /**
 419           * process the values transfered with the javascript function values2url
 420           *
 421           * The returned array contains the preserved values overwritten (only!) with the variables named in values2url
 422           *
 423           * @return array/boolean content array or false on error
 424           */
 425  		function process_values2url()
 426          {
 427              //echo "process_exec: _GET ="; _debug_array($_GET);
 428              $session_data = $this->get_appsession($_GET['etemplate_exec_id']);
 429              //echo "<p>process_exec: session_data ="; _debug_array($session_data);
 430  
 431              if (!$_GET['etemplate_exec_id'] || !is_array($session_data) || count($session_data) < 10)
 432              {
 433                  return false;
 434              }
 435              $GLOBALS['egw_info']['etemplate']['extension_data'] = $session_data['extension_data'];
 436  
 437              $content = $_GET['exec'];
 438              if (!is_array($content))
 439              {
 440                  $content = array();
 441              }
 442              $this->process_show($content,$session_data['to_process'],'exec');
 443  
 444              return $this->complete_array_merge($session_data['preserv'],$content);
 445          }
 446  
 447          /**
 448           * creates HTML from an eTemplate
 449           *
 450           * This is done by calling show_cell for each cell in the form. show_cell itself
 451           * calls show recursivly for each included eTemplate.
 452           * You could use it in the UI-layer of an app, just make shure to call process_show !!!
 453           * This is intended as internal function and should NOT be called by new app's direct,
 454           * as it deals with HTML and is so UI-dependent, use exec instead.
 455           *
 456           * @internal
 457           * @param array $content with content for the cells, keys are the names given in the cells/form elements
 458           * @param array $sel_options with options for the selectboxes, keys are the name of the selectbox
 459           * @param array $readonlys with names of cells/form-elements to be not allowed to change
 460           *         This is to facilitate complex ACL's which denies access on field-level !!!
 461           * @param string $cname basename of names for form-elements, means index in $_POST
 462           *         eg. $cname='cont', element-name = 'name' returned content in $_POST['cont']['name']
 463           * @param string $show_c name/index for name expansion
 464           * @param string $show_row name/index for name expansion
 465           * @return string the generated HTML
 466           */
 467  		function show($content,$sel_options='',$readonlys='',$cname='',$show_c=0,$show_row=0)
 468          {
 469              if (!$sel_options)
 470              {
 471                  $sel_options = array();
 472              }
 473              // make it globaly availible for show_cell and show_grid, or extensions
 474              $this->sel_options =& $sel_options;
 475  
 476              if (!$readonlys)
 477              {
 478                  $readonlys = array();
 479              }
 480              if (++$this->already_showed > 1) return '';    // prefens infinit self-inclusion
 481  
 482              if (is_int($this->debug) && $this->debug >= 1 || $this->name && $this->debug == $this->name)
 483              {
 484                  echo "<p>etemplate.show($this->name): $cname =\n"; _debug_array($content);
 485                  echo "readonlys="; _debug_array($readonlys);
 486              }
 487              if (!is_array($content))
 488              {
 489                  $content = array();    // happens if incl. template has no content
 490              }
 491              // make the content availible as class-var for extensions
 492              $this->content =& $content;
 493  
 494              $html = "\n\n<!-- BEGIN eTemplate $this->name -->\n\n";
 495              if (!$GLOBALS['egw_info']['etemplate']['styles_included'][$this->name])
 496              {
 497                  $GLOBALS['egw_info']['etemplate']['styles_included'][$this->name] = True;
 498                  $html .= $this->html->style($this->style)."\n\n";
 499              }
 500              $path = '/';
 501              foreach ($this->children as $n => $child)
 502              {
 503                  $h = $this->show_cell($child,$content,$readonlys,$cname,$show_c,$show_row,$nul,$class,$path.$n);
 504                  $html .= $class || $child['align'] ? $this->html->div($h,$this->html->formatOptions(array(
 505                      $class,
 506                      $child['align'],
 507                  ),'class,align')) : $h;
 508              }
 509              return $html."<!-- END eTemplate $this->name -->\n\n";
 510          }
 511              
 512          /**
 513           * creates HTML from an eTemplate
 514           *
 515           * This is done by calling show_cell for each cell in the form. show_cell itself
 516           * calls show recursivly for each included eTemplate.
 517           * You can use it in the UI-layer of an app, just make shure to call process_show !!!
 518           * This is intended as internal function and should NOT be called by new app's direct,
 519           * as it deals with HTML and is so UI-dependent, use exec instead.
 520           *
 521           * @internal
 522           * @param array $grid representing a grid
 523           * @param array $content with content for the cells, keys are the names given in the cells/form elements
 524           * @param array $readonlys with names of cells/form-elements to be not allowed to change
 525           *         This is to facilitate complex ACL's which denies access on field-level !!!
 526           * @param string $cname basename of names for form-elements, means index in $_POST
 527           *        eg. $cname='cont', element-name = 'name' returned content in $_POST['cont']['name']
 528           * @param string $show_c name/index for name expansion
 529           * @param string $show_row name/index for name expansion
 530           * @param string $path path in the widget tree
 531           * @return string the generated HTML
 532           */
 533  		function show_grid(&$grid,$content,$readonlys='',$cname='',$show_c=0,$show_row=0,$path='')
 534          {
 535              if (!$readonlys)
 536              {
 537                  $readonlys = array();
 538              }
 539              if (is_int($this->debug) && $this->debug >= 2 || $grid['name'] && $this->debug == $grid['name'] ||
 540                  $this->name && $this->debug == $this->name)
 541              {
 542                  echo "<p>etemplate.show_grid($grid[name]): $cname =\n"; _debug_array($content);
 543              }
 544              if (!is_array($content))
 545              {
 546                  $content = array();    // happens if incl. template has no content
 547              }
 548              $content += array(    // for var-expansion in names in show_cell
 549                  '.c' => $show_c,
 550                  '.col' => $this->num2chrs($show_c-1),
 551                  '.row' => $show_row
 552              );
 553              $rows = array();
 554  
 555              $data = &$grid['data'];
 556              reset($data);
 557              if (isset($data[0]))
 558              {
 559                  list(,$opts) = each($data);
 560              }
 561              else
 562              {
 563                  $opts = array();
 564              }
 565              $max_cols = $grid['cols'];
 566              for ($r = 0; $row = 1+$r /*list($row,$cols) = each($data)*/; ++$r)
 567              {
 568                  if (!(list($r_key) = each($data)))    // no further row
 569                  {
 570                      if (!(($this->autorepeat_idx($cols['A'],0,$r,$idx,$idx_cname) && $idx_cname) ||
 571                              (substr($cols['A']['type'],1) == 'box' && $this->autorepeat_idx($cols['A'][1],0,$r,$idx,$idx_cname) && $idx_cname) ||
 572                          ($this->autorepeat_idx($cols['B'],1,$r,$idx,$idx_cname) && $idx_cname)) ||
 573                          !$this->isset_array($content,$idx_cname))
 574                      {
 575                          break;                         // no auto-row-repeat
 576                      }
 577                  }
 578                  else
 579                  {
 580                      $cols = &$data[$r_key];
 581                      list($height,$disabled) = explode(',',$opts["h$row"]);
 582                      $class = /*TEST-RB$no_table_tr ? $tr_class :*/ $opts["c$row"];
 583                  }
 584                  if ($disabled != '' && $this->check_disabled($disabled,$content))
 585                  {
 586                      continue;    // row is disabled
 587                  }
 588                  $rows[".$row"] .= $this->html->formatOptions($height,'height');
 589                  list($cl) = explode(',',$class);
 590                  if ($cl == '@' || strstr($cl,'$') !== false)
 591                  {
 592                      $cl = $this->expand_name($cl,0,$r,$content['.c'],$content['.row'],$content);
 593                  }
 594                  if ($cl == 'nmr' || $cl == 'row')
 595                  {
 596                      $cl = 'row_'.($nmr_alternate++ & 1 ? 'off' : 'on'); // alternate color
 597                  }
 598                  $cl = isset($this->class_conf[$cl]) ? $this->class_conf[$cl] : $cl;
 599                  $rows[".$row"] .= $this->html->formatOptions($cl,'class');
 600                  $rows[".$row"] .= $this->html->formatOptions($class,',valign');
 601                  reset ($cols);
 602                  $row_data = array();
 603                  for ($c = 0; True /*list($col,$cell) = each($cols)*/; ++$c)
 604                  {
 605                      $col = $this->num2chrs($c);
 606                      if (!(list($c_key) = each($cols)))        // no further cols
 607                      {
 608                          // only check if the max. column-number reached so far is exeeded
 609                          // otherwise the rows have a differen number of cells and it saved a lot checks
 610                          if ($c >= $max_cols)
 611                          {
 612                              if (!$this->autorepeat_idx($cell,$c,$r,$idx,$idx_cname,True) ||
 613                                  !$this->isset_array($content,$idx))
 614                              {
 615                                  break;    // no auto-col-repeat
 616                              }
 617                              $max_cols = $c+1;
 618                          }
 619                      }
 620                      else
 621                      {
 622                          $cell = &$cols[$c_key];
 623                          list($col_width,$col_disabled) = explode(',',$opts[$col]);
 624  
 625                          if (!$cell['height'])    // if not set, cell-height = height of row
 626                          {
 627                              $cell['height'] = $height;
 628                          }
 629                          if (!$cell['width'])    // if not set, cell-width = width of column or table
 630                          {
 631                              list($col_span) = explode(',',$cell['span']);
 632                              if ($col_span == 'all' && !$c)
 633                              {
 634                                  list($cell['width']) = explode(',',$this->size);
 635                              }
 636                              else
 637                              {
 638                                  $cell['width'] = $col_width;
 639                              }
 640                          }
 641                      }
 642                      /*TEST-RB
 643                      if ($cell['type'] == 'template' && $cell['onchange'])
 644                      {
 645                          $cell['tr_class'] = $cl;
 646                      }*/
 647                      if ($col_disabled != '' && $this->check_disabled($col_disabled,$content))
 648                      {
 649                          continue;    // col is disabled
 650                      }
 651                      $row_data[$col] = $this->show_cell($cell,$content,$readonlys,$cname,$c,$r,$span,$cl,$path.'/'.$r_key.$c_key);
 652  
 653                      if ($row_data[$col] == '' && $this->rows == 1)
 654                      {
 655                          unset($row_data[$col]);    // omit empty/disabled cells if only one row
 656                          continue;
 657                      }
 658                      // can only be set via source at the moment
 659                      if (strlen($cell['onclick']) > 1 && $cell['type'] != 'button')
 660                      {
 661                          $row_data[".$col"] .= ' onclick="'.$cell['onclick'].'"' .
 662                              ($cell['id'] ? ' id="'.$cell['id'].'"' : '');
 663                      }
 664                      $colspan = $span == 'all' ? $this->cols-$c : 0+$span;
 665                      if ($colspan > 1)
 666                      {
 667                          $row_data[".$col"] .= " colspan=\"$colspan\"";
 668                          for ($i = 1; $i < $colspan; ++$i,++$c)
 669                          {
 670                              each($cols);    // skip next cell(s)
 671                          }
 672                      }
 673                      else
 674                      {
 675                          list($width,$disable) = explode(',',$opts[$col]);
 676                          if ($width)        // width only once for a non colspan cell
 677                          {
 678                              $row_data[".$col"] .= " width=\"$width\"";
 679                              $opts[$col] = "0,$disable";
 680                          }
 681                      }
 682                      $row_data[".$col"] .= $this->html->formatOptions($cell['align']?$cell['align']:'left','align');
 683                      // allow to set further attributes in the tablecell, beside the class
 684                      if (is_array($cl))
 685                      {
 686                          foreach($cl as $attr => $val)
 687                          {
 688                              if ($attr != 'class' && $val)
 689                              {
 690                                  $row_data['.'.$col] .= ' '.$attr.'="'.$val.'"';
 691                              }
 692                          }
 693                          $cl = $cl['class'];
 694                      }                                        
 695                      $cl = $this->expand_name(isset($this->class_conf[$cl]) ? $this->class_conf[$cl] : $cl,
 696                          $c,$r,$show_c,$show_row,$content);
 697                      // else the class is set twice, in the table and the table-cell, which is not good for borders
 698                      if ($cl && $cell['type'] != 'template' && $cell['type'] != 'grid')
 699                      {
 700                          $row_data[".$col"] .= $this->html->formatOptions($cl,'class');
 701                      }
 702                  }
 703                  $rows[$row] = $row_data;
 704              }
 705  
 706              list($width,$height,,,,,$overflow) = $options = explode(',',$grid['size']);
 707              if ($overflow && $height)
 708              {
 709                  $options[1] = '';    // set height in div only
 710              }
 711              $html = $this->html->table($rows,$this->html->formatOptions($options,'width,height,border,class,cellspacing,cellpadding').
 712                  $this->html->formatOptions($grid['span'],',class')/*TEST-RB,$no_table_tr*/);
 713  
 714              if (!empty($overflow)) {
 715                  if (is_numeric($height)) $height .= 'px';
 716                  if (is_numeric($width)) $width .= 'px';
 717                  $div_style=' style="'.($width?"width: $width; ":'').($height ? "height: $height; ":'')."overflow: $overflow;\"";
 718                  $html = $this->html->div($html,$div_style);
 719              }
 720              return "\n\n<!-- BEGIN grid $grid[name] -->\n$html<!-- END grid $grid[name] -->\n\n";
 721          }
 722          
 723          /**
 724           * build the name of a form-element from a basename and name
 725           *
 726           * name and basename can contain sub-indices in square bracets, eg. basename="base[basesub1][basesub2]" 
 727           * and name = "name[sub]" gives "base[basesub1][basesub2][name][sub]"
 728           *
 729           * @param string $cname basename
 730           * @param string $name name
 731           * @return string complete form-name
 732           */
 733  		function form_name($cname,$name)
 734          {
 735              if(is_object($name)) return '';
 736  
 737              $name_parts = explode('[',str_replace(']','',$name));
 738              if (!empty($cname))
 739              {
 740                  array_unshift($name_parts,$cname);
 741              }
 742              $form_name = array_shift($name_parts);
 743              if (count($name_parts))
 744              {
 745                  $form_name .= '['.implode('][',$name_parts).']';
 746              }
 747              return $form_name;
 748          }
 749  
 750          /**
 751           * generates HTML for one widget (input-field / cell)
 752           *
 753           * calls show to generate included eTemplates. Again only an INTERMAL function.
 754           *
 755           * @internal
 756           * @param array $cell with data of the cell: name, type, ...
 757           * @param array $content with content for the cells, keys are the names given in the cells/form elements
 758           * @param array $readonlys with names of cells/form-elements to be not allowed to change
 759           *         This is to facilitate complex ACL's which denies access on field-level !!!
 760           * @param string $cname basename of names for form-elements, means index in $_POST
 761           *        eg. $cname='cont', element-name = 'name' returned content in $_POST['cont']['name']
 762           * @param string $show_c name/index for name expansion
 763           * @param string $show_row name/index for name expansion
 764           * @param string &$span on return number of cells to span or 'all' for the rest (only used for grids)
 765           * @param string &$class on return the css class of the cell, to be set in the <td> tag
 766           * @param string $path path in the widget tree
 767           * @return string the generated HTML
 768          */
 769  		function show_cell($cell,$content,$readonlys,$cname,$show_c,$show_row,&$span,&$class,$path='')
 770          {
 771              if ($this->debug && (is_int($this->debug) && $this->debug >= 3 || $this->debug == $cell['type']))
 772              {
 773                  echo "<p>etemplate.show_cell($this->name,name='$cell['name']}',type='$cell['type']}',cname='$cname')</p>\n";
 774              }
 775              list($span) = explode(',',$cell['span']);    // evtl. overriten later for type template
 776  
 777              if ($cell['name']{0} == '@' && $cell['type'] != 'template')
 778              {
 779                  $cell['name'] = $this->get_array($content,$this->expand_name(substr($cell['name'],1),
 780                      $show_c,$show_row,$content['.c'],$content['.row'],$content));
 781              }
 782              $name = $this->expand_name($cell['name'],$show_c,$show_row,$content['.c'],$content['.row'],$content);
 783  
 784              $form_name = $this->form_name($cname,$name);
 785  
 786              $value = $this->get_array($content,$name);
 787  
 788              $options = '';
 789              if ($readonly = $cell['readonly'] || @$readonlys[$name] && !is_array($readonlys[$name]) || $readonlys['__ALL__'])
 790              {
 791                  $options .= ' readonly="readonly"';
 792              }
 793              if ((int) $cell['tabindex']) $options .= ' tabindex="'.(int)$cell['tabindex'].'"';
 794              if ($cell['accesskey']) $options .= ' accesskey="'.$this->html->htmlspecialchars($cell['accesskey']).'"';
 795  
 796              if ($cell['disabled'] && $readonlys[$name] !== false || $readonly && $cell['type'] == 'button' && !strstr($cell['size'],','))
 797              {
 798                  if ($this->rows == 1) {
 799                      return '';    // if only one row omit cell
 800                  }
 801                  $cell = $this->empty_cell(); // show nothing
 802                  $value = '';
 803              }
 804              $extra_label = True;
 805  
 806              // the while loop allows to build extensions from other extensions
 807              // please note: only the first extension's post_process function is called !!!
 808              list($type,$sub_type) = explode('-',$cell['type']);
 809              while ((!$this->types[$cell['type']] || !empty($sub_type)) && $this->haveExtension($type,'pre_process'))
 810              {
 811                  //echo "<p>pre_process($cell[name]/$cell[type])</p>\n";
 812                  if (strchr($cell['size'],'$') || $cell['size']{0} == '@')
 813                  {
 814                      $cell['size'] = $this->expand_name($cell['size'],$show_c,$show_row,$content['.c'],$content['.row'],$content);
 815                  }
 816                  if (!$ext_type) $ext_type = $type;
 817                  $extra_label = $this->extensionPreProcess($type,$form_name,$value,$cell,$readonlys[$name]);
 818  
 819                  $readonly = $readonly || $cell['readonly'];    // might be set by extension
 820                  $this->set_array($content,$name,$value);
 821  
 822                  if ($cell['type'] == $type.'-'.$sub_type) break;    // stop if no further type-change
 823  
 824                  list($type,$sub_type) = explode('-',$cell['type']);                
 825              }
 826              list(,$class) = explode(',',$cell['span']);    // might be set by extension
 827              if (strchr($class,'$') || $class{0} == '@')
 828              {
 829                  $class = $this->expand_name($class,$show_c,$show_row,$content['.c'],$content['.row'],$content);
 830              }
 831              $cell_options = $cell['size'];
 832              if (strchr($cell_options,'$') || $cell_options{0} == '@')
 833              {
 834                  $cell_options = $this->expand_name($cell_options,$show_c,$show_row,$content['.c'],$content['.row'],$content);
 835              }
 836              $label = $cell['label'];
 837              if (strchr($label,'$') || $label{0} == '@')
 838              {
 839                  $label = $this->expand_name($label,$show_c,$show_row,$content['.c'],$content['.row'],$content);
 840              }
 841              $help = $cell['help'];
 842              if (strchr($help,'$') || $help{0} == '@')
 843              {
 844                  $no_lang_on_help = true;
 845                  $help = $this->expand_name($help,$show_c,$show_row,$content['.c'],$content['.row'],$content);
 846              }
 847              $blur = $cell['blur']{0} == '@' ? $this->get_array($content,substr($cell['blur'],1)) :
 848                  (strlen($cell['blur']) <= 1 ? $cell['blur'] : lang($cell['blur']));
 849  
 850              if ($this->java_script())
 851              {
 852                  if ($blur)
 853                  {
 854                      if (empty($value))
 855                      {
 856                          $value = $blur;
 857                      }
 858                      $onFocus .= "if(this.value=='".addslashes($this->html->htmlspecialchars($blur))."') this.value='';";
 859                      $onBlur  .= "if(this.value=='') this.value='".addslashes($this->html->htmlspecialchars($blur))."';";
 860                  }
 861                  if ($help)
 862                  {
 863                      if ((int)$cell['no_lang'] < 2 && !$no_lang_on_help)
 864                      {
 865                          $help = lang($help);
 866                      }
 867                      if (($use_tooltip_for_help = strstr($help,'<') && strip_tags($help) != $help))    // helptext is html => use a tooltip
 868                      {
 869                          $options .= $this->html->tooltip($help);
 870                      }
 871                      else    // "regular" help-text in the statusline
 872                      {
 873                          $onFocus .= "self.status='".addslashes($this->html->htmlspecialchars($help))."'; return true;";
 874                          $onBlur  .= "self.status=''; return true;";
 875                          if ($cell['type'] == 'button' || $cell['type'] == 'file')    // for button additionally when mouse over button
 876                          {
 877                              $options .= " onMouseOver=\"self.status='".addslashes($this->html->htmlspecialchars($help))."'; return true;\"";
 878                              $options .= " onMouseOut=\"self.status=''; return true;\"";
 879                          }
 880                      }
 881                  }
 882                  if ($onBlur)
 883                  {
 884                      $options .= " onFocus=\"$onFocus\" onBlur=\"$onBlur\"";
 885                  }
 886                  if ($cell['onchange'] && $cell['type'] != 'button') // values != '1' can only set by a program (not in the editor so fa
 887                  {
 888                      if (strchr($cell['onchange'],'$') || $cell['onchange']{0} == '@')
 889                      {
 890                          $cell['onchange'] = $this->expand_name($cell['onchange'],$show_c,$show_row,$content['.c'],$content['.row'],$content);
 891                      }
 892                      $options .= ' onChange="'.($cell['onchange']=='1'?'this.form.submit();':$cell['onchange']).'"';
 893                  }
 894              }
 895              if ($form_name != '')
 896              {
 897                  $options = 'id="'.($cell['id'] ? $cell['id'] : $form_name).'" '.$options;
 898              }
 899              switch ($type)
 900              {
 901                  case 'label':    //  size: [b[old]][i[talic]],[link],[activate_links],[label_for],[link_target],[link_popup_size]
 902                      if (is_array($value))
 903                          break;
 904                      list($style,$extra_link,$activate_links,$label_for,$extra_link_target,$extra_link_popup) = explode(',',$cell_options);
 905                      $value = strlen($value) > 1 && !$cell['no_lang'] ? lang($value) : $value;
 906                      $value = nl2br($this->html->htmlspecialchars($value));
 907                      if ($activate_links) $value = $this->html->activate_links($value);
 908                      if ($value != '' && strstr($style,'b')) $value = $this->html->bold($value);
 909                      if ($value != '' && strstr($style,'i')) $value = $this->html->italic($value);
 910                      $html .= $value;
 911                      if ($help)
 912                      {
 913                          $class = array(
 914                              'class'       => $class,
 915                              'onmouseover' => "self.status='".addslashes($this->html->htmlspecialchars($help))."'; return true;",
 916                              'onmouseout'  => "self.status=''; return true;",
 917                          );
 918                      }
 919                      break;
 920                  case 'html':    //  size: [link],[link_target],[link_popup_size]
 921                      list($extra_link,$extra_link_target,$extra_link_popup) = explode(',',$cell_options);
 922                      $html .= $value;
 923                      break;
 924                  case 'int':        // size: [min],[max],[len],[precission (only float)]
 925                  case 'float':
 926                      list($min,$max,$cell_options,$pre) = explode(',',$cell_options);
 927                      if ($cell_options == '')
 928                      {
 929                          $cell_options = $cell['type'] == 'int' ? 5 : 8;
 930                      }
 931                      if ($type == 'float' && $value && $pre)
 932                      {
 933                          $value = round($value,$pre);
 934                      }
 935                      $cell_options .= ',,'.($cell['type'] == 'int' ? '/^-?[0-9]*$/' : '/^-?[0-9]*[,.]?[0-9]*$/');
 936                      // fall-through
 937                  case 'text':        // size: [length][,maxLength[,preg]]
 938                      if ($readonly)
 939                      {
 940                          $html .= strlen($value) ? $this->html->bold($this->html->htmlspecialchars($value)) : '';
 941                      }
 942                      else
 943                      {
 944                          $html .= $this->html->input($form_name,$value,'',
 945                              $options.$this->html->formatOptions($cell_options,'SIZE,MAXLENGTH'));
 946                          $cell_options = explode(',',$cell_options,3);
 947                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] =  array(
 948                              'type'      => $cell['type'],
 949                              'maxlength' => $cell_options[1],
 950                              'needed'    => $cell['needed'],
 951                              'preg'      => $cell_options[2],
 952                              'min'       => $min,    // int and float only
 953                              'max'       => $max,
 954                          );
 955                      }
 956                      break;
 957                  case 'textarea':    // Multiline Text Input, size: [rows][,cols]
 958                      if ($readonly && !$cell_options)
 959                      {
 960                          $html .= '<pre style="margin-top: 0px;">'.$this->html->htmlspecialchars($value)."</pre>\n";
 961                      }
 962                      else
 963                      {
 964                          $html .= $this->html->textarea($form_name,$value,
 965                              $options.$this->html->formatOptions($cell_options,'ROWS,COLS'));
 966                      }
 967                      if (!$readonly)
 968                      {
 969                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] =  array(
 970                              'type'      => $cell['type'],
 971                              'needed'    => $cell['needed'],
 972                          );
 973                      }
 974                      break;
 975                  case 'htmlarea':    // Multiline formatted Text Input, size: [inline styles for the widget][,plugins (comma-sep.)]
 976                      list($styles,$plugins) = explode(',',$cell_options,2);
 977                      if (!$styles) $styles = 'width: 100%; min-width: 500px; height: 300px;';    // default HTMLarea style in html-class
 978                      if (!$readonly)
 979                      {
 980                          $html .= $this->html->tinymce($form_name,$value,$styles,$plugins);
 981                          
 982                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] =  array(
 983                              'type'      => $cell['type'],
 984                              'needed'    => $cell['needed'],
 985                          );
 986                      }
 987                      else
 988                      {
 989                          $html .= $this->html->div($this->html->activate_links($value),'style="overflow: auto; border: thin inset black;'.$styles.'"');
 990                      }
 991                      break;
 992                  case 'checkbox':
 993                      $set_val = 1; $unset_val = 0;
 994                      if (!empty($cell_options))
 995                      {
 996                          list($set_val,$unset_val,$ro_true,$ro_false) = explode(',',$cell_options);
 997                          if (!$set_val && !$unset_val) $set_val = 1;
 998                          $value = $value == $set_val;
 999                      }
1000                      if ($readonly)
1001                      {
1002                          if (count(explode(',',$cell_options)) < 3)
1003                          {
1004                              $ro_true = 'x';
1005                              $ro_false = '';
1006                          }
1007                          if (!$value && $ro_false == 'disable') return '';
1008  
1009                          $html .= $value ? $this->html->bold($ro_true) : $ro_false;
1010                      }
1011                      else
1012                      {
1013                          if ($value) $options .= ' checked="checked"';
1014  
1015                          if (($multiple = substr($cell['name'],-2) == '[]'))
1016                          {
1017                              // add the set_val to the id to make it unique
1018                              $options = str_replace('id="'.$form_name,'id="'.substr($form_name,0,-2)."[$set_val]",$options);
1019                          }
1020                          $html .= $this->html->input($form_name,$set_val,'checkbox',$options);
1021                          
1022                          if ($multiple) $form_name = $this->form_name($cname,substr($cell['name'],0,-2));
1023  
1024                          if (!isset($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]))
1025                          {
1026                              $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = array(
1027                                  'type'        => $cell['type'],
1028                                  'unset_value' => $unset_val,
1029                                  'multiple'    => $multiple,
1030                              );
1031                          }
1032                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name]['values'][] = $set_val;
1033                          if (!$multiple) unset($set_val);    // otherwise it will be added to the label
1034                      }
1035                      break;
1036                  case 'radio':        // size: value if checked
1037                      $set_val = $this->expand_name($cell_options,$show_c,$show_row,$content['.c'],$content['.row'],$content);
1038  
1039                      if ($value == $set_val)
1040                      {
1041                          $options .= ' checked="checked"';
1042                      }
1043                      // add the set_val to the id to make it unique
1044                      $options = str_replace('id="'.$form_name,'id="'.$form_name."[$set_val]",$options);
1045  
1046                      if ($readonly)
1047                      {
1048                          $html .= $value == $set_val ? $this->html->bold('x') : '';
1049                      }
1050                      else
1051                      {
1052                          $html .= $this->html->input($form_name,$set_val,'RADIO',$options);
1053                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = $cell['type'];
1054                      }
1055                      break;
1056                  case 'button':
1057                  case 'cancel':    // cancel button
1058                      list($app) = explode('.',$this->name);
1059                      list($img,$ro_img) = explode(',',$cell_options);
1060                      $title = strlen($label) <= 1 || $cell['no_lang'] ? $label : lang($label);
1061                      if ($cell['onclick'] &&
1062                          ($onclick = $this->expand_name($cell['onclick'],$show_c,$show_row,$content['.c'],$content['.row'],$content)))
1063                      {
1064                          
1065                          if (preg_match("/egw::link\\('([^']+)','([^']+)'\\)/",$onclick,$matches))
1066                          {
1067                              $url = $GLOBALS['egw']->link($matches[1],$matches[2]);
1068                              $onclick = preg_replace('/egw::link\(\'([^\']+)\',\'([^\']+)\'\)/','\''.$url.'\'',$onclick);
1069                          }
1070                          elseif (preg_match("/form::name\\('([^']+)'\\)/",$onclick,$matches))
1071                          {
1072                              $onclick = preg_replace("/form::name\\('([^']+)'\\)/",'\''.$this->form_name($cname,$matches[1]).'\'',$onclick);
1073                          }
1074                          elseif (preg_match('/confirm\(["\']{1}(.*)["\']{1}\)/',$cell['onclick'],$matches))
1075                          {
1076                              $question = lang($matches[1]).(substr($matches[1],-1) != '?' ? '?' : '');    // add ? if not there, saves extra phrase
1077                              $onclick = preg_replace('/confirm\(["\']{1}(.*)["\']{1}\)/','confirm(\''.addslashes($question).'\')',$onclick);
1078                              //$onclick = "return confirm('".str_replace('\'','\\\'',$this->html->htmlspecialchars($question))."');";
1079                          }
1080                      }
1081                      if ($this->java_script() && ($cell['onchange'] != '' || $img && !$readonly) && !$cell['needed']) // use a link instead of a button
1082                      {
1083                          $onclick = ($onclick ? preg_replace('/^return(.*);$/','if (\\1) ',$onclick) : '').
1084                              (($cell['onchange'] == 1 || $img) ? "return submitit($this->name_form,'$form_name');" : $cell['onchange']).'; return false;';
1085                          
1086                          if (!$this->html->netscape4 && substr($img,-1) == '%' && is_numeric($percent = substr($img,0,-1)))
1087                          {
1088                              $html .= $this->html->progressbar($percent,$title,'onclick="'.$onclick.'" '.$options);
1089                          }
1090                          else
1091                          {
1092                              $html .= '<a href="" onClick="'.$onclick.'" '.$options.'>' .
1093                                  ($img ? $this->html->image($app,$img,$title,'border="0"') : $title) . '</a>';
1094                          }
1095                      }
1096                      else
1097                      {
1098                          if (!empty($img))
1099                          {
1100                              $options .= ' title="'.$title.'"';
1101                          }
1102                          if ($cell['onchange'] && $cell['onchange'] != 1)
1103                          {
1104                              $onclick = ($onclick ? preg_replace('/^return(.*);$/','if (\\1) ',$onclick) : '').$cell['onchange'];
1105                          }
1106                          $html .= !$readonly ? $this->html->submit_button($form_name,$label,$onclick,
1107                              strlen($label) <= 1 || $cell['no_lang'],$options,$img,$app) :
1108                              $this->html->image($app,$ro_img);
1109                      }
1110                      $extra_label = False;
1111                      if (!$readonly)
1112                      {
1113                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = $cell['type'];
1114                          if (strtolower($name) == 'cancel')
1115                          {
1116                              $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = 'cancel';
1117                          }
1118                      }
1119                      break;
1120                  case 'hrule':
1121                      $html .= $this->html->hr($cell_options);
1122                      break;
1123                  case 'grid':
1124                      if ($readonly && !$readonlys['__ALL__'])
1125                      {
1126                          if (!is_array($readonlys)) $readonlys = array();
1127                          $set_readonlys_all = $readonlys['__ALL__'] = True;
1128                      }
1129                      if ($name != '')
1130                      {
1131                          $cname .= $cname == '' ? $name : '['.str_replace('[','][',str_replace(']','',$name)).']';
1132                      }
1133                      $html .= $this->show_grid($cell,$name ? $value : $content,$readonlys,$cname,$show_c,$show_row,$path);
1134                      if ($set_readonlys_all) unset($readonlys['__ALL__']);
1135                      break;
1136                  case 'template':    // size: index in content-array (if not full content is past further on)
1137                      if (is_object($cell['name']))
1138                      {
1139                          $cell['obj'] = &$cell['name'];
1140                          unset($cell['name']);
1141                          $cell['name'] = 'was Object';
1142                          echo "<p>Object in Name in tpl '$this->name': "; _debug_array($grid);
1143                      }
1144                      $obj_read = 'already loaded';
1145                      if (is_array($cell['obj']))
1146                      {
1147                          $obj =& new etemplate();
1148                          $obj->init($cell['obj']);
1149                          $cell['obj'] =& $obj;
1150                          unset($obj);
1151                      }
1152                      if (!is_object($cell['obj']))
1153                      {
1154                          if ($cell['name']{0} == '@')
1155                          {
1156                              $cell['obj'] = $this->get_array($content,substr($cell['name'],1));
1157                              $obj_read = is_object($cell['obj']) ? 'obj from content' : 'obj read, obj-name from content';
1158                              if (!is_object($cell['obj']))
1159                              {
1160                                  $cell['obj'] =& new etemplate($cell['obj'],$this->as_array());
1161                              }
1162                          }
1163                          else
1164                          {  $obj_read = 'obj read';
1165                              $cell['obj'] =& new etemplate($name,$this->as_array());
1166                          }
1167                      }
1168                      if (is_int($this->debug) && $this->debug >= 3 || $this->debug == $cell['type'])
1169                      {
1170                          echo "<p>show_cell::template(tpl=$this->name,name=$cell[name]): $obj_read</p>\n";
1171                      }
1172                      if ($this->autorepeat_idx($cell,$show_c,$show_row,$idx,$idx_cname) || $cell_options != '')
1173                      {
1174                          if ($span == '' && isset($content[$idx]['span']))
1175                          {    // this allows a colspan in autorepeated cells like the editor
1176                              list($span) = explode(',',$content[$idx]['span']);
1177                              if ($span == 'all')
1178                              {
1179                                  $span = 1 + $content['cols'] - $show_c;
1180                              }
1181                          }
1182                          $readonlys = $this->get_array($readonlys,$idx);
1183                          $content = $this->get_array($content,$idx);
1184                          if ($idx_cname != '')
1185                          {
1186                              $cname .= $cname == '' ? $idx_cname : '['.str_replace('[','][',str_replace(']','',$idx_cname)).']';
1187                          }
1188                          //echo "<p>show_cell-autorepeat($name,$show_c,$show_row,cname='$cname',idx='$idx',idx_cname='$idx_cname',span='$span'): content ="; _debug_array($content);
1189                      }
1190                      if ($readonly && !$readonlys['__ALL__'])
1191                      {
1192                          if (!is_array($readonlys)) $readonlys = array();
1193                          $set_readonlys_all = $readonlys['__ALL__'] = True;
1194                      }
1195                      // propagate our onclick handler to embeded templates, if they dont have their own
1196                      if (!isset($cell['obj']->onclick_handler)) $cell['obj']->onclick_handler = $this->onclick_handler;
1197                      if ($cell['obj']->no_onclick)
1198                      {
1199                          $cell['obj']->onclick_proxy = $this->onclick_proxy ? $this->onclick_proxy : $this->name.':'.$this->version.':'.$path;
1200                      }
1201                      // propagate the CSS class to the template
1202                      if ($class)
1203                      {
1204                          $grid_size = array_pad(explode(',',$cell['obj']->size),4,'');
1205                          $grid_size[3] = ($grid_size[3] ? $grid_size[3].' ' : '') . $class;
1206                          $cell['obj']->size = implode(',',$grid_size);
1207                      }
1208                      $html = $cell['obj']->show($content,$this->sel_options,$readonlys,$cname,$show_c,$show_row);
1209                      
1210                      if ($set_readonlys_all) unset($readonlys['__ALL__']);
1211                      break;
1212                  case 'select':    // size:[linesOnMultiselect|emptyLabel,extraStyleMulitselect]
1213                      $sels = array();
1214                      list($multiple,$extraStyleMultiselect) = explode(',',$cell_options,2);
1215                      if (!empty($multiple) && 0+$multiple <= 0)
1216                      {
1217                          $sels[''] = $multiple < 0 ? 'all' : $multiple;
1218                          // extra-option: no_lang=0 gets translated later and no_lang=1 gets translated too (now), only no_lang>1 gets not translated
1219                          if ((int)$cell['no_lang'] == 1)
1220                          {
1221                              $sels[''] = substr($sels[''],-3) == '...' ? lang(substr($sels[''],0,-3)).'...' : lang($sels['']);
1222                          }
1223                          $multiple = 0;
1224                      }
1225                      if (!empty($cell['sel_options']))
1226                      {
1227                          if (!is_array($cell['sel_options']))
1228                          {
1229                              $opts = explode(',',$cell['sel_options']);
1230                              while (list(,$opt) = each($opts))
1231                              {
1232                                  list($k,$v) = explode('=',$opt);
1233                                  $sels[$k] = $v;
1234                              }
1235                          }
1236                          else
1237                          {
1238                              $sels += $cell['sel_options'];
1239                          }
1240                      }
1241                      if (isset($this->sel_options[$name]) && is_array($this->sel_options[$name]))
1242                      {
1243                          $sels += $this->sel_options[$name];
1244                      }
1245                      else
1246                      {
1247                          $name_parts = explode('[',str_replace(']','',$name));
1248                          if (count($name_parts))
1249                          {
1250                              $org_name = $name_parts[count($name_parts)-1];
1251                              if (isset($this->sel_options[$org_name]) && is_array($this->sel_options[$org_name]))
1252                              {
1253                                  $sels += $this->sel_options[$org_name];
1254                              }
1255                              elseif (isset($this->sel_options[$name_parts[0]]) && is_array($this->sel_options[$name_parts[0]]))
1256                              {
1257                                  $sels += $this->sel_options[$name_parts[0]];
1258                              }
1259                          }
1260                      }
1261                      if (isset($content["options-$name"]))
1262                      {
1263                          $sels += $content["options-$name"];
1264                      }
1265                      if ($multiple && !is_array($value)) $value = explode(',',$value);
1266                      if ($readonly || $cell['noprint'])
1267                      {
1268                          foreach($multiple ? $value : array($value) as $val)
1269                          {
1270                              if (is_array($sels[$val]))
1271                              {
1272                                  $option_label = $sels[$val]['label'];
1273                                  $option_title = $sels[$val]['title'];
1274                              }
1275                              else
1276                              {
1277                                  $option_label = $sels[$val];
1278                                  $option_title = '';
1279                              }
1280                              if (!$cell['no_lang']) $option_label = lang($option_label);
1281                              
1282                              if ($html) $html .= "<br>\n";
1283  
1284                              if ($option_title)
1285                              {
1286                                  $html .= '<span title="'.$this->html->htmlspecialchars($option_title).'">'.$this->html->htmlspecialchars($option_label).'</span>';
1287                              }
1288                              else
1289                              {
1290                                  $html .= $this->html->htmlspecialchars($option_label);
1291                              }
1292                          }
1293                      }
1294                      if (!$readonly)
1295                      {
1296                          if ($cell['noprint'])
1297                          {
1298                              $html = '<span class="onlyPrint">'.$html.'</span>';
1299                              $options .= ' class="noPrint"';
1300                          }
1301                          if ($multiple && is_numeric($multiple))    // eg. "3+" would give a regular multiselectbox
1302                          {
1303                              $html .= $this->html->checkbox_multiselect($form_name.($multiple > 1 ? '[]' : ''),$value,$sels,
1304                                  $cell['no_lang'],$options,$multiple,true,$extraStyleMultiselect);
1305                          }
1306                          else
1307                          {
1308                              $html .= $this->html->select($form_name.($multiple > 1 ? '[]' : ''),$value,$sels,
1309                                  $cell['no_lang'],$options,$multiple);
1310                          }
1311                          if (!isset($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]))
1312                          {
1313                              $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = $cell['type'];
1314                          }
1315                      }
1316                      break;
1317                  case 'image':    // size: [link],[link_target],[imagemap],[link_popup]
1318                      $image = $value != '' ? $value : $name;
1319                      list($app,$img) = explode('/',$image,2);
1320                      if (!$app || !$img || !is_dir(EGW_SERVER_ROOT.'/'.$app) || strstr($img,'/'))
1321                      {
1322                          $img = $image;
1323                          list($app) = explode('.',$this->name);
1324                      }
1325                      if (!$readonly)
1326                      {
1327                          list($extra_link,$extra_link_target,$imagemap,$extra_link_popup) = explode(',',$cell['size']);
1328                      }
1329                      $html .= $this->html->image($app,$img,strlen($label) > 1 && !$cell['no_lang'] ? lang($label) : $label,
1330                          'border="0"'.($imagemap?' usemap="'.$this->html->htmlspecialchars($imagemap).'"':''));
1331                      $extra_label = False;
1332                      break;
1333                  case 'file':    // size: size of the filename field
1334                      if (!$readonly)
1335                      {
1336                          if ((int) $cell_options) $options .= ' size="'.(int)$cell_options.'"';
1337                          $html .= $this->html->input_hidden($path_name = str_replace($name,$name.'_path',$form_name),'.');
1338                          $html .= $this->html->input($form_name,'','file',$options);
1339                          $GLOBALS['egw_info']['etemplate']['form_options'] =
1340                              "enctype=\"multipart/form-data\" onsubmit=\"set_element2(this,'$path_name','$form_name')\"";
1341                          $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = $cell['type'];
1342                      }
1343                      break;
1344                  case 'vbox':
1345                  case 'hbox':
1346                  case 'groupbox':
1347                  case 'box':
1348                      $rows = array();
1349                      $box_row = 1;
1350                      $box_col = 'A';
1351                      $box_anz = 0;
1352                      list($num,$orient) = explode(',',$cell_options);
1353                      if (!$orient) $orient = $type == 'hbox' ? 'horizontal' : ($type == 'box' ? false : 'vertical');
1354                      for ($n = 1; $n <= (int) $num; ++$n)
1355                      {
1356                          $h = $this->show_cell($cell[$n],$content,$readonlys,$cname,$show_c,$show_row,$nul,$cl,$path.'/'.$n);
1357                          if ($h != '' && $h != '&nbsp;')
1358                          {
1359                              if ($orient != 'horizontal')
1360                              {
1361                                  $box_row = $n;
1362                              }
1363                              else
1364                              {
1365                                  $box_col = $this->num2chrs($n);
1366                              }
1367                              if (!$orient)
1368                              {
1369                                  $html .= $cl ? $this->html->div($h," class=\"$cl\"") : $h;
1370                              }
1371                              else
1372                              {
1373                                  $rows[$box_row][$box_col] = $html = $h;
1374                              }
1375                              $box_anz++;
1376                              if ($cell[$n]['align'])
1377                              {
1378                                  $rows[$box_row]['.'.$box_col] = $this->html->formatOptions($cell[$n]['align'],'align');
1379                                  $sub_cell_has_align = true;
1380                              }
1381                              // can only be set via source at the moment
1382                              if (strlen($cell[$n]['onclick']) > 1 && $cell[$n]['type'] != 'button')
1383                              {
1384                                  $rows[$box_row]['.'.$box_col] .= ' onclick="'.$cell[$n]['onclick'].'"'.
1385                                      ($cell[$n]['id'] ? ' id="'.$cell[$n]['id'].'"' : '');
1386                              }
1387                              // allow to set further attributes in the tablecell, beside the class
1388                              if (is_array($cl))
1389                              {
1390                                  foreach($cl as $attr => $val)
1391                                  {
1392                                      if ($attr != 'class' && $val)
1393                                      {
1394                                          $rows[$box_row]['.'.$box_col] .= ' '.$attr.'="'.$val.'"';
1395                                      }
1396                                  }
1397                                  $cl = $cl['class'];
1398                              }                                        
1399                              $box_item_class = $this->expand_name(isset($this->class_conf[$cl]) ? $this->class_conf[$cl] : $cl,
1400                                  $show_c,$show_row,$content['.c'],$content['.row'],$content);
1401                              $rows[$box_row]['.'.$box_col] .= $this->html->formatOptions($box_item_class,'class');
1402                          }
1403                      }
1404                      if ($box_anz > 1 && $orient)    // a single cell is NOT placed into a table
1405                      {
1406                          $html = $this->html->table($rows,$this->html->formatOptions($cell_options,',,cellpadding,cellspacing').
1407                              $this->html->formatOptions($cell['span'],',class').
1408                              ($cell['align'] && $orient != 'horizontal' || $sub_cell_has_align ? ' width="100%"' : ''));    // alignment only works if table has full width
1409                      }
1410                      // put the class of the box-cell, into the the class of this cell
1411                      elseif ($box_item_class)
1412                      {
1413                          $class = ($class ? $class . ' ' : '') . $box_item_class;
1414                      }
1415                      if ($type == 'groupbox')
1416                      {
1417                          if (strlen($label) > 1 && $cell['label'] == $label)
1418                          {
1419                              $label = lang($label);
1420                          }
1421                          $html = $this->html->fieldset($html,$label);
1422                      }
1423                      elseif (!$orient)
1424                      {
1425                          $html = $this->html->div($html,$this->html->formatOptions(array(
1426                                  $cell['height'],
1427                                  $cell['width'],
1428                                  $cell['class'],
1429                                  $cell['name']
1430                              ),'height,widht,class,id')). ($html ? '' : '</div>');
1431                      }
1432                      if ($box_anz > 1)    // small docu in the html-source
1433                      {
1434                          $html = "\n\n<!-- BEGIN $cell[type] -->\n\n".$html."\n\n<!-- END $cell[type] -->\n\n";
1435                      }
1436                      $extra_label = False;
1437                      break;
1438                  case 'deck':
1439                      for ($n = 1; $n <= $cell_options && (empty($value) || $value != $cell[$n]['name']); ++$n) ;
1440                      if ($n > $cell_options)
1441                      {
1442                          $value = $cell[1]['name'];
1443                      }
1444                      if ($s_width = $cell['width'])
1445                      {
1446                          $s_width = "width: $s_width".(substr($s_width,-1) != '%' ? 'px' : '').';';
1447                      }
1448                      if ($s_height = $cell['height'])
1449                      {
1450                          $s_height = "height: $s_height".(substr($s_height,-1) != '%' ? 'px' : '').';';
1451                      }
1452                      $html = $this->html->input_hidden($form_name,$value);
1453                      $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] =  $cell['type'];
1454                              
1455                      for ($n = 1; $n <= $cell_options; ++$n)
1456                      {
1457                          $html .= $this->html->div($this->show_cell($cell[$n],$content,$readonlys,$cname,$show_c,
1458                              $show_row,$nul,$cl,$path.'/'.$n),$this->html->formatOptions(array(
1459                              'display: '.($value == $cell[$n]['name'] ? 'inline' : 'none').';',
1460                              $cell[$n]['name']
1461                          ),'style,id'));
1462                      }
1463                      break;
1464                  default:
1465                      if ($ext_type && $this->haveExtension($ext_type,'render'))
1466                      {
1467                          $html .= $this->extensionRender($ext_type,$form_name,$value,$cell,$readonly);
1468                      }
1469                      else
1470                      {
1471                          $html .= "<i>unknown type '$cell[type]'</i>";
1472                      }
1473                      break;
1474              }
1475              // extension-processing need to be after all other and only with diff. name
1476              if ($ext_type && !$readonly && $this->haveExtension($ext_type,'post_process'))    
1477              {    // unset it first, if it is already set, to be after the other widgets of the ext.
1478                  $to_process = 'ext-'.$ext_type;
1479                  if (is_array($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]))
1480                  {
1481                      $to_process = $GLOBALS['egw_info']['etemplate']['to_process'][$form_name];
1482                      $to_process['type'] = 'ext-'.$ext_type;
1483                  }
1484                  unset($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]);
1485                  $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = $to_process;
1486              }
1487              // save blur-value to strip it in process_exec
1488              if (!empty($blur) && isset($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]))
1489              {
1490                  if (!is_array($GLOBALS['egw_info']['etemplate']['to_process'][$form_name]))
1491                  {
1492                      $GLOBALS['egw_info']['etemplate']['to_process'][$form_name] = array(
1493                          'type' => $GLOBALS['egw_info']['etemplate']['to_process'][$form_name]
1494                      );
1495                  }
1496                  $GLOBALS['egw_info']['etemplate']['to_process'][$form_name]['blur'] = $blur;
1497              }
1498              if ($extra_label && ($label != '' || $html == ''))
1499              {
1500                  if (strlen($label) > 1 && !($cell['no_lang'] && $cell['label'] != $label || (int)$cell['no_lang'] == 2))
1501                  {
1502                      $label = lang($label);
1503                  }
1504                  $accesskey = false;
1505                  if (($accesskey = strstr($label,'&')) && $accesskey[1] != ' ' && $form_name != '' &&
1506                          (($pos = strpos($accesskey,';')) === False || $pos > 5))
1507                  {
1508                      $label = str_replace('&'.$accesskey[1],'<u>'.$accesskey[1].'</u>',$label);
1509                      $accesskey = $accesskey[1];
1510                  }
1511                  if ($label && !$readonly && ($accesskey || $label_for || $type != 'label' && $cell['name']))
1512                  {
1513                      $label = $this->html->label($label,$label_for ? $this->form_name($cname,$label_for) : 
1514                          $form_name.($set_val?"[$set_val]":''),$accesskey);
1515                  }
1516                  if ($type == 'radio' || $type == 'checkbox' || strstr($label,'%s'))    // default for radio is label after the button
1517                  {
1518                      $html = strstr($label,'%s') ? str_replace('%s',$html,$label) : $html.' '.$label;
1519                  }
1520                  elseif (($html = $label . ' ' . $html) == ' ')
1521                  {
1522                      $html = '&nbsp;';
1523                  }
1524              }
1525              if ($extra_link && (($extra_link = $this->expand_name($extra_link,$show_c,$show_row,$content['.c'],$content['.row'],$content))))
1526              {
1527                  $options = $help ? ' onmouseover="self.status=\''.addslashes($this->html->htmlspecialchars($help)).'\'; return true;"' .
1528                      ' onmouseout="self.status=\'\'; return true;"' : '';
1529  
1530                  if ($extra_link_target && (($extra_link_target = $this->expand_name($extra_link_target,$show_c,$show_row,$content['.c'],$content['.row'],$content))))
1531                  {
1532                      $options .= ' target="'.addslashes($extra_link_target).'"';
1533                  }
1534                  if ($extra_link_popup && (($extra_link_popup = $this->expand_name($extra_link_popup,$show_c,$show_row,$content['.c'],$content['.row'],$content))))
1535                  {
1536                      list($w,$h) = explode('x',$extra_link_popup);
1537                      $options .= ' onclick="window.open(this,this.target,\'width='.(int)$w.',height='.(int)$h.',location=no,menubar=no,toolbar=no,scrollbars=yes,status=yes\'); return false;"';
1538                  }
1539                  return $this->html->a_href($html,$extra_link,'',$options);
1540              }
1541              // if necessary show validation-error behind field
1542              if (isset($GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name]))
1543              {
1544                  $html .= ' <span style="color: red; white-space: nowrap;">'.$GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name].'</span>';
1545              }
1546              // generate an extra div, if we have an onclick handler and NO children or it's an extension
1547              //echo "<p>$this->name($this->onclick_handler:$this->no_onclick:$this->onclick_proxy): $cell[type]/$cell[name]</p>\n";
1548              if ($this->onclick_handler && !isset($this->widgets_with_children[$cell['type']]))
1549              {
1550                  $handler = str_replace('%p',$this->no_onclick ? $this->onclick_proxy : $this->name.':'.$this->version.':'.$path,
1551                      $this->onclick_handler);
1552                  if ($type == 'button' || !$label)    // add something to click on
1553                  {
1554                      $html = (substr($html,-1) == "\n" ? substr($html,0,-1) : $html).'&nbsp;';
1555                  }
1556                  return $this->html->div($html,' ondblclick="'.$handler.'"','clickWidgetToEdit');
1557              }
1558              return $html;
1559          }
1560  
1561          /**
1562           * applies stripslashes recursivly on each element of an array
1563           * 
1564           * @param array &$var 
1565           * @return array
1566           */
1567  		function array_stripslashes($var)
1568          {
1569              if (!is_array($var))
1570              {
1571                  return stripslashes($var);
1572              }
1573              foreach($var as $key => $val)
1574              {
1575                  $var[$key] = is_array($val) ? $this->array_stripslashes($val) : stripslashes($val);
1576              }
1577              return $var;
1578          }
1579  
1580          /**
1581           * makes necessary adjustments on $_POST after a eTemplate / form gots submitted
1582           *
1583           * This is only an internal function, dont call it direct use only exec
1584           * Process_show uses a list of input-fields/widgets generated by show.
1585           *
1586           * @internal
1587           * @param array $content $_POST[$cname], on return the adjusted content
1588           * @param array $to_process list of widgets/form-fields to process
1589           * @param string $cname basename of our returnt content (same as in call to show)
1590           * @return int number of validation errors (the adjusted content is returned by the var-param &$content !)
1591          */
1592  		function process_show(&$content,$to_process,$cname='')
1593          {
1594              if (!isset($content) || !is_array($content) || !is_array($to_process))
1595              {
1596                  return;
1597              }
1598              if (is_int($this->debug) && $this->debug >= 1 || $this->debug == $this->name && $this->name)
1599              {
1600                  echo "<p>process_show($this->name) cname='$cname' start: content ="; _debug_array($content);
1601              }
1602              $content_in = $cname ? array($cname => $content) : $content;
1603              $content = array();
1604              if (get_magic_quotes_gpc())
1605              {
1606                  $content_in = $this->array_stripslashes($content_in);
1607              }
1608              $GLOBALS['egw_info']['etemplate']['validation_errors'] = array();
1609              $this->canceled = $this->button_pressed = False;
1610  
1611              foreach($to_process as $form_name => $type)
1612              {
1613                  if (is_array($type))
1614                  {
1615                      $attr = $type;
1616                      $type = $attr['type'];
1617                  }
1618                  else
1619                  {
1620                      $attr = array();
1621                  }
1622                  $value = $this->get_array($content_in,$form_name,True);
1623  
1624                  if (isset($attr['blur']) && $attr['blur'] == $value)
1625                  {
1626                      $value = '';    // blur-values is equal to emtpy
1627                  }
1628                  // echo "<p>process_show($this->name) $type: $form_name = '$value'</p>\n";
1629                  list($type,$sub) = explode('-',$type);
1630                  switch ($type)
1631                  {
1632                      case 'ext':
1633                          $_cont = &$this->get_array($content,$form_name,True);
1634                          if (!$this->extensionPostProcess($sub,$form_name,$_cont,$value))
1635                          {
1636                              //echo "\n<p><b>unsetting content[$form_name] !!!</b></p>\n";
1637                              $this->unset_array($content,$form_name);
1638                          }
1639                          // this else should NOT be unnecessary as $_cont is a reference to the index 
1640                          // $form_name of $content, but under some circumstances a set/changed $_cont
1641                          // does not result in a change in $content -- RalfBecker 2004/09/18
1642                          // seems to depend on the number of (not existing) dimensions of the array -- -- RalfBecker 2005/04/06
1643                          elseif (!$this->isset_array($content,$form_name))
1644                          {
1645                              //echo "<p>setting content[$form_name]='$_cont' because is was unset !!!</p>\n";
1646                              $this->set_array($content,$form_name,$_cont);
1647                          }
1648                          if ($_cont === '' && $attr['needed'] && !$attr['blur'])
1649                          {
1650                              $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang('Field must not be empty !!!',$value);
1651                          }
1652                          break;
1653                      case 'htmlarea':
1654                          $this->set_array($content,$form_name,$value);
1655                          break;
1656                      case 'int':
1657                      case 'float':
1658                      case 'text':
1659                      case 'textarea':
1660                          if ($value === '' && $attr['needed'] && !$attr['blur'])
1661                          {
1662                              $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang('Field must not be empty !!!',$value);
1663                          }
1664                          if ((int) $attr['maxlength'] > 0 && strlen($value) > (int) $attr['maxlength'])
1665                          {
1666                              $value = substr($value,0,(int) $attr['maxlength']);
1667                          }
1668                          if ($attr['preg'] && !preg_match($attr['preg'],$value))
1669                          {
1670                              switch($type)
1671                              {
1672                                  case 'int':
1673                                      $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang("'%1' is not a valid integer !!!",$value);
1674                                      break;
1675                                  case 'float':
1676                                      $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang("'%1' is not a valid floatingpoint number !!!",$value);
1677                                      break;
1678                                  default:
1679                                      $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang("'%1' has an invalid format !!!",$value);
1680                                      break;
1681                              }
1682                          }
1683                          elseif ($type == 'int' || $type == 'float')    // cast int and float and check range
1684                          {
1685                              if ($value !== '' || $attr['needed'])    // empty values are Ok if needed is not set
1686                              {
1687                                  $value = $type == 'int' ? (int) $value : (float) str_replace(',','.',$value);    // allow for german (and maybe other) format
1688  
1689                                  if (!empty($attr['min']) && $value < $attr['min'])
1690                                  {
1691                                      $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang("Value has to be at least '%1' !!!",$attr['min']);
1692                                      $value = $type == 'int' ? (int) $attr['min'] : (float) $attr['min'];
1693                                  }
1694                                  if (!empty($attr['max']) && $value > $attr['max'])
1695                                  {
1696                                      $GLOBALS['egw_info']['etemplate']['validation_errors'][$form_name] = lang("Value has to be at maximum '%1' !!!",$attr['max']);
1697                                      $value = $type == 'int' ? (int) $attr['max'] : (float) $attr['max'];
1698                                  }
1699                              }
1700                          }
1701                          $this->set_array($content,$form_name,$value);
1702                          break;
1703                      case 'cancel':    // cancel button ==> dont care for validation errors
1704                          if ($value)
1705                          {
1706                              $this->canceled = True;
1707                              $this->set_array($content,$form_name,$value);
1708                          }
1709                          break;
1710                      case 'button':
1711                          if ($value)
1712                          {
1713                              $this->button_pressed = True;
1714                              $this->set_array($content,$form_name,$value);
1715                          }
1716                          break;
1717                      case 'select':
1718                          $this->set_array($content,$form_name,is_array($value) ? implode(',',$value) : $value);
1719                          break;
1720                      case 'checkbox':
1721                          if (!isset($value))
1722                          {
1723                              $this->set_array($content,$form_name,$attr['multiple'] ? array() : $attr['unset_value']);    // need to be reported too
1724                          }
1725                          else
1726                          {
1727                              $value = array_intersect(is_array($value) ? $value : array($value),$attr['values']); // return only allowed values
1728                              $this->set_array($content,$form_name,$attr['multiple'] ? $value : $value[0]);
1729                          }
1730                          break;
1731                      case 'file':
1732                          $parts = explode('[',str_replace(']','',$form_name));
1733                          $name = array_shift($parts);
1734                          $index  = count($parts) ? '['.implode('][',$parts).']' : '';
1735                          $value = array();
1736                          foreach(array('tmp_name','type','size','name') as $part)
1737                          {
1738                              $value[$part] = is_array($_FILES[$name]) ? $this->get_array($_FILES[$name],$part.$index) : False;
1739                          }
1740                          $value['path'] = $this->get_array($content_in,substr($form_name,0,-1).'_path]');
1741                          $value['ip'] = get_var('REMOTE_ADDR',Array('SERVER'));
1742                          if (function_exists('is_uploaded_file') && !is_uploaded_file($value['tmp_name']))
1743                          {
1744                              $value = array();    // to be on the save side
1745                          }
1746                          //_debug_array($value);
1747                          // fall-throught
1748                      default:
1749                          $this->set_array($content,$form_name,$value);
1750                          break;
1751                  }
1752              }
1753              if ($cname)
1754              {
1755                  $content = $content[$cname];
1756              }
1757              if (is_int($this->debug) && $this->debug >= 2 || $this->debug == $this->name && $this->name)
1758              {
1759                  echo "<p>process_show($this->name) end: content ="; _debug_array($content);
1760                  if (count($GLOBALS['egw_info']['etemplate']['validation_errors']))
1761                  {
1762                      echo "<p>validation_errors = "; _debug_array($GLOBALS['egw_info']['etemplate']['validation_errors']);
1763                  }
1764              }
1765              return count($GLOBALS['egw_info']['etemplate']['validation_errors']);
1766          }
1767  
1768          /**
1769           * is javascript enabled?
1770           *
1771           * this should be tested by the api at login
1772           *
1773           * @return boolean true if javascript is enabled or not yet tested and $consider_not_tested_as_enabled 
1774          */
1775  		function java_script($consider_not_tested_as_enabled = True)
1776          {
1777              $ret = !!$GLOBALS['egw_info']['etemplate']['java_script'] ||
1778                  $consider_not_tested_as_enabled && !isset($GLOBALS['egw_info']['etemplate']['java_script']);
1779              //echo "<p>java_script($consider_not_tested_as_enabled)='$ret', java_script='".$GLOBALS['egw_info']['etemplate']['java_script']."', isset(java_script)=".isset($GLOBALS['egw_info']['etemplate']['java_script'])."</p>\n";
1780              
1781              return $ret;
1782              return !!$GLOBALS['egw_info']['etemplate']['java_script'] ||
1783                  $consider_not_tested_as_enabled &&
1784                  (!isset($GLOBALS['egw_info']['etemplate']['java_script']) ||
1785                  $GLOBALS['egw_info']['etemplate']['java_script'].'' == '');
1786          }
1787  
1788          /**
1789           * returns the javascript to be included by exec
1790           *
1791           * @param int $what &1 = returns the test, note: has to be included in the body, not the header, 
1792           *        &2 = returns the common functions, best to be included in the header
1793           * @return string javascript
1794           */
1795  		function include_java_script($what = 3)
1796          {
1797              // this is to test if javascript is enabled
1798              if ($what & 1 && !isset($GLOBALS['egw_info']['etemplate']['java_script']))
1799              {
1800                  $js = '<script language="javascript">
1801  document.write(\''.str_replace("\n",'',$this->html->input_hidden('java_script','1')).'\');
1802  if (document.getElementById) {
1803      document.write(\''.str_replace("\n",'',$this->html->input_hidden('dom_enabled','1')).'\');
1804  }
1805  </script>
1806  ';
1807              }
1808              // here are going all the necesarry functions if javascript is enabled
1809              if ($what & 2 && $this->java_script(True))
1810              {
1811                  $js .= '<script type="text/javascript" src="'.
1812                      $GLOBALS['egw_info']['server']['webserver_url'].'/etemplate/js/etemplate.js"></script>'."\n";
1813              }
1814              return $js;
1815          }
1816      };


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7