| [ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
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 != ' ') 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 = ' '; 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).' '; 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 };
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |