[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 /**************************************************************************\ 3 * eGroupWare - EditableTemplates - Business Objects * 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.boetemplate.inc.php 22824 2006-11-10 11:36:13Z ralfbecker $ */ 14 15 include_once (EGW_INCLUDE_ROOT . '/etemplate/inc/class.soetemplate.inc.php'); 16 17 /** 18 * Business Object for eTemplates, extending the Storage Object 19 * 20 * Not so much so far, as the most logic is still in the UI-class 21 * 22 * @package etemplate 23 * @subpackage api 24 * @author RalfBecker-AT-outdoor-training.de 25 * @license GPL 26 */ 27 class boetemplate extends soetemplate 28 { 29 var $extensions = array(); 30 31 var $types = array( 32 'label' => 'Label', // Label $cell['label'] is (to be translated) textual content 33 'text' => 'Text', // Textfield 1 Line (size = [length][,maxlength]) 34 'int' => 'Integer', // like text, but only numbers (size = [min][,max]) 35 'float' => 'Floating Point', // --------------- " -------------------------- 36 'textarea'=> 'Textarea', // Multiline Text Input (size = [rows][,cols]) 37 'htmlarea' => 'Formatted Text (HTML)', 38 'checkbox'=> 'Checkbox', 39 'radio' => 'Radiobutton', // Radiobutton (size = value if checked) 40 'button'=> 'Submitbutton', 41 'hrule' => 'Horizontal Rule', 42 'template' => 'Template', // $cell['name'] contains template-name, $cell['size'] index into $content,$cname,$readonlys 43 'image' => 'Image', // label = url, name=link or method, help=alt or title 44 'date' => '', // Datefield, size='' timestamp or size=format like 'm/d/Y' 45 'select'=> 'Selectbox', // Selectbox ($sel_options[$name] or $content[options-$name] is array with options) 46 // if size > 1 then multiple selections, size lines showed 47 'html' => 'Html', // Raw html in $content[$cell['name']] 48 'file' => 'FileUpload', // show an input type='file', set the local name as $name}_path 49 'vbox' => 'VBox', // a (vertical) box to contain widgets in rows, size = # of rows 50 'hbox' => 'HBox', // a (horizontal) box to contain widgets in cols, size = # of cols 51 'groupbox' => 'GroupBox', // a box with a label containing other elements to group them (html: fieldset) 52 'box' => 'Box', // just a container for widgets (html: div) 53 'grid' => 'Grid', // tabular widget containing rows with columns of widgets 54 'deck' => 'Deck' // a container of elements where only one is visible, size = # of elem. 55 ); 56 var $garbage_collection_done; 57 58 /** 59 * constructor of class 60 * 61 * Calls the constructor of soetemplate 62 * 63 * @param string/array $name name of etemplate or array with name and other keys 64 * @param string/array $load_via name or array with keys of other etemplate to load in order to get $name 65 */ 66 function boetemplate($name='',$load_via='') 67 { 68 $this->soetemplate(); 69 70 $tname = &$name; 71 if (is_array($name)) 72 { 73 $tname = &$name['name']; 74 } 75 $tname = (strstr($tname,'.') === False && !empty($tname) ? 76 (is_array($load_via) ? $load_via['name'] : $load_via).'.':'').$tname; 77 78 if (empty($tname) || !$this->read($name,'','',0,'',$load_via)) 79 { 80 $this->init($name); 81 } 82 $this->garbage_collection_done =& $GLOBALS['egw_info']['etemplate']['garbage_collection_done']; 83 } 84 85 /** 86 * checks if a grid row or column is disabled 87 * 88 * Expression: [!][@]val[=[@]check] 89 * Parts in square brackets are optional, a ! negates the expression, @val evaluates to $content['val'] 90 * if no =check is given all set non-empty and non-zero strings are true (standard php behavior) 91 * 92 * @param string $disabled expression to check, eg. "!@var" for !$content['var'] 93 * @param array $content the content-array in the context of the grid 94 * @return boolean true if the row/col is disabled or false if not 95 */ 96 function check_disabled($disabled,$content) 97 { 98 if ($this->onclick_handler && !$this->no_onclick) 99 { 100 return false; // we have an onclick handler 101 } 102 //return False; 103 if ($not = $disabled[0] == '!') 104 { 105 $disabled = substr($disabled,1); 106 } 107 list($val,$check_val) = $vals = explode('=',$disabled); 108 109 if ($val[0] == '@') 110 { 111 $val = $this->get_array($content,substr($val,1)); 112 } 113 if ($check_val[0] == '@') 114 { 115 $check_val = $this->get_array($content,substr($check_val,1)); 116 } 117 $result = count($vals) == 1 ? $val != '' : $val == $check_val; 118 if ($not) $result = !$result; 119 //echo "<p>check_disabled: '".($not?'!':'')."$disabled' = '$val' ".(count($vals) == 1 ? '' : ($not?'!':'=')."= '$check_val'")." = ".($result?'True':'False')."</p>\n"; 120 return $result; 121 } 122 123 /** 124 * allows a few variables (eg. row-number) to be used in field-names 125 * 126 * This is mainly used for autorepeat, but other use is possible. 127 * You need to be aware of the rules PHP uses to expand vars in strings, a name 128 * of "Row$row[length]" will expand to 'Row' as $row is scalar, you need to use 129 * "Row${row}[length]" instead. Only one indirection is allowd in a string by php !!! 130 * Out of that reason we have now the variable $row_cont, which is $cont[$row] too. 131 * Attention !!! 132 * Using only number as index in field-names causes a lot trouble, as depending 133 * on the variable type (which php determines itself) you used filling and later 134 * accessing the array it can by the index or the key of an array element. 135 * To make it short and clear, use "Row$row" or "$col$row" not "$row" or "$row$col" !!! 136 * 137 * @param sring $name the name to expand 138 * @param int $c is the column index starting with 0 (if you have row-headers, data-cells start at 1) 139 * @param int $row is the row number starting with 0 (if you have col-headers, data-cells start at 1) 140 * @param int $c_ is the value of the previous template-inclusion, 141 * eg. the column-headers in the eTemplate-editor are templates itself, 142 * to show the column-name in the header you can not use $col as it will 143 * be constant as it is always the same col in the header-template, 144 * what you want is the value of the previous template-inclusion. 145 * @param int $row_ is the value of the previous template-inclusion, 146 * @param array $cont content of the template, you might use it to generate button-names with id values in it: 147 * "del[$cont[id]]" expands to "del[123]" if $cont = array('id' => 123) 148 * @return string the expanded name 149 */ 150 function expand_name($name,$c,$row,$c_='',$row_='',$cont='') 151 { 152 $is_index_in_content = $name[0] == '@'; 153 if (strstr($name,'$') !== False) 154 { 155 if (!$cont) 156 { 157 $cont = array(); 158 } 159 $col = $this->num2chrs($c-1); // $c-1 to get: 0:'@', 1:'A', ... 160 $col_ = $this->num2chrs($c_-1); 161 $row_cont = $cont[$row]; 162 $col_row_cont = $cont[$col.$row]; 163 164 eval('$name = "'.$name.'";'); 165 } 166 if ($is_index_in_content) 167 { 168 $name = $this->get_array($cont,substr($name,1)); 169 } 170 return $name; 171 } 172 173 /** 174 * Checks if we have an row- or column autorepeat and sets the indexes for $content, etc. 175 * 176 * Autorepeat is important to allow a variable numer of rows or cols, eg. for a list. 177 * The eTemplate has only one (have to be the last) row or column, which gets 178 * automaticaly repeated as long as content is availible. To check this the content 179 * has to be in an sub-array of content. The index / subscript into content is 180 * determined by the content of size for templates or name for regular fields. 181 * An autorepeat is defined by an index which contains variables to expand. 182 * (vor variable expansion in names see expand_names). Usually I use the keys 183 * $row: 0, 1, 2, 3, ... for only rows, $col: '@', 'A', 'B', 'C', ... for only cols or 184 * $col$row: '@0','A0',... '@1','A1','B1',... '@2','A2','B2',... for both rows and cells. 185 * In general everything expand_names can generate is ok - see there. 186 * As you usually have col- and row-headers, data-cells start with '1' or 'A' !!! 187 * 188 * @param array $cell with data of cell: name, type, size, ... 189 * @param int $c,$r col/row index starting from 0 190 * @param string &$idx returns the index in $content and $readonlys (NOT $sel_options !!!) 191 * @param string &$idx_cname returns the basename for the form-name: is $idx if only one value 192 * (no ',') is given in size (name (not template-fields) are always only one value) 193 * @param boolean $check_col to check for col- or row-autorepeat 194 * @return boolean true if cell is autorepeat (has index with vars / '$') or false otherwise 195 */ 196 function autorepeat_idx($cell,$c,$r,&$idx,&$idx_cname,$check_col=False) 197 { 198 $org_idx = $idx = $cell[ $cell['type'] == 'template' ? 'size' : 'name' ]; 199 200 $idx = $this->expand_name($idx,$c,$r); 201 if (!($komma = strpos($idx,','))) 202 { 203 $idx_cname = $idx; 204 } 205 else 206 { 207 $idx_cname = substr($idx,1+$komma); 208 $idx = substr($idx,0,$komma); 209 } 210 $Ok = False; 211 $pat = $org_idx; 212 while (!$Ok && ($pat = strstr($pat,'$'))) 213 { 214 $pat = substr($pat,$pat[1] == '{' ? 2 : 1); 215 216 if ($check_col) 217 { 218 $Ok = $pat[0] == 'c' && !(substr($pat,0,4) == 'cont' || 219 substr($pat,0,2) == 'c_' || substr($pat,0,4) == 'col_'); 220 } 221 else 222 { 223 $Ok = $pat[0] == 'r' && !(substr($pat,0,2) == 'r_' || 224 substr($pat,0,4) == 'row_' && substr($pat,0,8) != 'row_cont'); 225 } 226 } 227 if ($this->name && $this->name == $this->debug) 228 { 229 echo "$this->name ".($check_col ? 'col' : 'row')."-check: c=$c, r=$r, idx='$org_idx'='$idx' idx_cname='$idx_cname' ==> ".($Ok?'True':'False')."<p>\n"; 230 } 231 return $Ok; 232 } 233 234 /** 235 * creates a new appsession-id via microtime() 236 */ 237 function appsession_id() 238 { 239 list($msec,$sec) = explode(' ',microtime()); 240 $time = 100 * $sec + (int)(100 * $msec); // gives precision of 1/100 sec 241 $id = $GLOBALS['egw_info']['flags']['currentapp'] .':'. $time; 242 //echo "<p>microtime()=".microtime().", sec=$sec, msec=$msec, id=$id</p>\n"; 243 return $id; 244 } 245 246 /** 247 * saves content,readonlys,template-keys, ... via the appsession function 248 * 249 * As a user may open several windows with the same content/template wie generate a location-id from microtime 250 * which is used as location for appsession to descriminate between the different windows. This location-id 251 * is then saved as a hidden-var in the form. The above mentions session-id has nothing to do / is different 252 * from the session-id which is constant for all windows opened in one session. 253 * 254 * @param array $data the data to save 255 * @param string $id the id to use or '' to generate a new id 256 * @return string location-id 257 */ 258 function save_appsession($data,$id='') 259 { 260 if (!$id) 261 { 262 $id = $this->appsession_id(); 263 } 264 $GLOBALS['egw']->session->appsession($id,'etemplate',$data); 265 266 if (substr($GLOBALS['egw_info']['server']['sessions_type'],0,4) == 'php4' && !$this->garbage_collection_done) 267 { 268 return $this->php4_session_garbage_collection(); 269 } 270 return $id; 271 } 272 273 /** 274 * gets content,readonlys,template-keys, ... back from the appsession function 275 * 276 * @param string $id the location-id 277 * @return array with session-data 278 */ 279 function get_appsession($id) 280 { 281 $data = $GLOBALS['egw']->session->appsession($id,'etemplate'); 282 //echo "boetemplate::get_appsession('$id')"; _debug_array($data); 283 284 if (substr($GLOBALS['egw_info']['server']['sessions_type'],0,4) == 'php4') 285 { 286 $this->php4_session_garbage_collection($id); 287 } 288 return $data; 289 } 290 291 /** 292 * a little bit of garbage collection for php4 sessions (their size is limited by memory_limit) 293 * 294 * With constant eTemplate use it can grow quite big and lead to unusable sessions (php terminates 295 * before any output with "Allowed memory size of ... exhausted"). 296 * We delete now sessions once used after 10min and sessions never or multiple used after 60min. 297 * 298 * @param string $id_used id of session just read by get_appsession to increment the usage counter 299 */ 300 function php4_session_garbage_collection($id_used='') 301 { 302 if (!defined('EGW_SESSION_VAR')) return; // for 1.0.0 compatibility 303 304 // now we are on php4 sessions and do a bit of garbage collection 305 $app_sessions =& $_SESSION[EGW_SESSION_VAR]['app_sessions']['etemplate']; 306 $session_used =& $app_sessions['session_used']; 307 308 if ($id_used) 309 { 310 //echo "session_used[$id_used]='".$session_used[$id_used]."'<br/>\n"; 311 ++$session_used[$id_used]; // count the number of times a session got used 312 } 313 $this->garbage_collection_done = true; 314 315 if (count($app_sessions) < 20) return $data; // we dont need to care 316 317 list($msec,$sec) = explode(' ',microtime()); 318 $now = 100 * $sec + (int)(100 * $msec); // gives precision of 1/100 sec 319 320 foreach(array_keys($app_sessions) as $id) 321 { 322 list($app,$time) = explode(':',$id); 323 324 if (!$time) continue; // other data, no session 325 326 //echo ++$n.') '.$id.': '.(($now-$time)/100.0)."secs old, used=".$session_used[$id].", size=".strlen($app_sessions[$id])."<br>\n"; 327 328 if ($session_used[$id] == 1 && $time < $now - 10*6000 || // session used and older then 10min 329 $time < $now - 60*6000) // session not used and older then 1h 330 { 331 //echo "<p>boetemplate::php4_session_garbage_collection('$id_used'): unsetting session '$id' (now=$now)</p>\n"; 332 unset($app_sessions[$id]); 333 unset($session_used[$id]); 334 } 335 } 336 } 337 338 /** 339 * gets an attribute in a named cell 340 * 341 * @static 342 * @param string $name cell-name 343 * @param string $attr attribute-name 344 * @return mixed the attribute or False if named cell not found 345 */ 346 function &get_cell_attribute($name,$attr) 347 { 348 return $this->set_cell_attribute($name,$attr,NULL); 349 } 350 351 /** 352 * set an attribute in a named cell if val is not NULL else return the attribute 353 * 354 * @static 355 * @param string $name cell-name 356 * @param string $attr attribute-name 357 * @param mixed $val if not NULL sets attribute else returns it 358 * @return mixed number of changed cells or False, if none changed 359 */ 360 function &set_cell_attribute($name,$attr,$val) 361 { 362 //echo "<p>set_cell_attribute(tpl->name=$this->name, name='$name', attr='$attr',val='$val')</p>\n"; 363 364 $extra = array(false,$name,$attr,$val); 365 $result =& $this->widget_tree_walk('set_cell_attribute_helper',$extra); 366 367 if (is_null($val)) 368 { 369 return $result; 370 } 371 return $extra[0]; 372 } 373 374 /** 375 * disables all cells with name == $name 376 * 377 * @param sting $name cell-name 378 * @param boolean $disabled=true disable or enable a cell, default true=disable 379 * @return mixed number of changed cells or False, if none changed 380 */ 381 function disable_cells($name,$disabled=True) 382 { 383 return $this->set_cell_attribute($name,'disabled',$disabled); 384 } 385 386 /** 387 * set one or more attibutes for row $n 388 * 389 * @deprecated as it uses this->data 390 * @param int $n numerical row-number starting with 1 (!) 391 * @param string $height percent or pixel or '' for no height 392 * @param string $class name of css class (without the leading '.') or '' for no class 393 * @param string $valign alignment (top,middle,bottom) or '' for none 394 * @param boolean $disabled True or expression or False to disable or enable the row (Only the number 0 means dont change the attribute !!!) 395 */ 396 function set_row_attributes($n,$height=0,$class=0,$valign=0,$disabled=0) 397 { 398 list($old_height,$old_disabled) = explode(',',$this->data[0]["h$n"]); 399 $disabled = $disabled !== 0 ? $disabled : $old_disabled; 400 $this->data[0]["h$n"] = ($height !== 0 ? $height : $old_height). 401 ($disabled ? ','.$disabled : ''); 402 list($old_class,$old_valign) = explode(',',$this->data[0]["c$n"]); 403 $valign = $valign !== 0 ? $valign : $old_valign; 404 $this->data[0]["c$n"] = ($class !== 0 ? $class : $old_class). 405 ($valign ? ','.$valign : ''); 406 } 407 408 /** 409 * disables row $n 410 * 411 * @deprecated as it uses this->data 412 * @param int $n numerical row-number starting with 1 (!) 413 * @param boolean $enable=false can be used to re-enable a row if set to True 414 */ 415 function disable_row($n,$enable=False) 416 { 417 $this->set_row_attributes($n,0,0,0,!$enable); 418 } 419 420 /** 421 * set one or more attibutes for column $c 422 * 423 * @deprecated as it uses this->data 424 * @param int/string $c numerical column-number starting with 0 (!), or the char-code starting with 'A' 425 * @param string $width percent or pixel or '' for no height 426 * @param mixed $disabled=0 True or expression or False to disable or enable the column (Only the number 0 means dont change the attribute !!!) 427 */ 428 function set_column_attributes($c,$width=0,$disabled=0) 429 { 430 if (is_numeric($c)) 431 { 432 $c = $this->num2chrs($c); 433 } 434 list($old_width,$old_disabled) = explode(',',$this->data[0][$c]); 435 $disabled = $disabled !== 0 ? $disabled : $old_disabled; 436 $this->data[0][$c] = ($width !== 0 ? $width : $old_width). 437 ($disabled ? ','.$disabled : ''); 438 } 439 440 /** 441 * disables column $c 442 * 443 * @deprecated as it uses this->data 444 * @param int/string $c numerical column-number starting with 0 (!), or the char-code starting with 'A' 445 * @param boolean $enable can be used to re-enable a column if set to True 446 */ 447 function disable_column($c,$enable=False) 448 { 449 $this->set_column_attributes($c,0,!$enable); 450 } 451 452 /** 453 * trys to load the Extension / Widget-class from the app or etemplate 454 * 455 * @param string $name name of the extension, the classname should be class.${name}_widget.inc.php 456 * the $name might be "$name.$app" to give a app-name (default is the current app,or template-name) 457 * @return string/boolean human readable name or false if not found/loadable 458 */ 459 function loadExtension($type) 460 { 461 list($class,$app) = explode('.',$type); 462 $class .= '_widget'; 463 464 if (!$app) $app = $GLOBALS['egw_info']['flags']['current_app']; 465 466 if (!file_exists(EGW_SERVER_ROOT."/$app/inc/class.$class.inc.php")) 467 { 468 list($app) = explode('_',$type); 469 } 470 if (!file_exists(EGW_SERVER_ROOT."/$app/inc/class.$class.inc.php")) 471 { 472 list($app) = explode('.',$this->name); 473 } 474 if (!file_exists(EGW_SERVER_ROOT."/$app/inc/class.$class.inc.php")) 475 { 476 $app = 'etemplate'; 477 } 478 if (!file_exists(EGW_SERVER_ROOT."/$app/inc/class.$class.inc.php")) 479 { 480 //echo "<p>boetemplate::loadExtension($type) extension not found</p>\n"; 481 return $GLOBALS['egw_info']['etemplate']['extension'][$type] = False; 482 } 483 $GLOBALS['egw_info']['etemplate']['extension'][$type] =& CreateObject($app.'.'.$class,$ui='html'); 484 485 //echo "<p>boetemplate::loadExtension($type) extension found in App. $app</p>\n"; 486 return $GLOBALS['egw_info']['etemplate']['extension'][$type]->human_name; 487 } 488 489 /** 490 * checks if extension is loaded (load it if it isnt) and optional checks if it has a given method 491 * 492 * @param string $name name of the extension, the classname should be class.${name}_widget.inc.php 493 * the $name might be "$name.$app" to give a app-name (default is the current app,or template-name) 494 * @param string $function 'pre_process', 'post_process' or 'render' 495 * @return boolean true if the extension (incl. method) exists, else false 496 */ 497 function haveExtension($type,$function='') 498 { 499 return ($GLOBALS['egw_info']['etemplate']['extension'][$type] || $this->loadExtension($type,$ui)) && 500 ($function == '' || $GLOBALS['egw_info']['etemplate']['extension'][$type]->public_functions[$function]); 501 } 502 503 /** 504 * executes the pre_process-function of the extension $cell[type] 505 * 506 * @param string $type type of the extension 507 * @param string $name form-name of this widget/field (used as a unique index into extension_data) 508 * @param mixed &$value value of the extensions content(-array) 509 * @param array &$cell table-cell on which the extension operates 510 * @param array &$readonlys value of the extensions readonly-setting(-array) 511 * @return mixed the return-value of the extensions preprocess function 512 */ 513 function extensionPreProcess($type,$name,&$value,&$cell,&$readonlys) 514 { 515 if (!$this->haveExtension($type)) 516 { 517 return False; 518 } 519 return $GLOBALS['egw_info']['etemplate']['extension'][$type]->pre_process($name,$value,$cell,$readonlys, 520 $GLOBALS['egw_info']['etemplate']['extension_data'][$name],$this); 521 } 522 523 /** 524 * executes the post_process-function of the extension $cell[type] 525 * 526 * @param string $type name of the extension 527 * @param string $name form-name of this widget/field (used as a unique index into extension_data) 528 * @param mixed &$value returns the value of the extensions content(-array) 529 * @param mixed $value_in unprocessed value, eg. as posted by the browser 530 * @return boolean True if a value should be returned (default for no postprocess fkt.), else False 531 */ 532 function extensionPostProcess($type,$name,&$value,$value_in) 533 { 534 if (!$this->haveExtension($type,'post_process')) 535 { 536 return True; 537 } 538 return $GLOBALS['egw_info']['etemplate']['extension'][$type]->post_process($name,$value, 539 $GLOBALS['egw_info']['etemplate']['extension_data'][$name], 540 $GLOBALS['egw_info']['etemplate']['loop'],$this,$value_in); 541 } 542 543 /** 544 * executes the render-function of the extension $cell[type] 545 * 546 * @param string $type name of the extension 547 * @param string $name form-name of this widget/field (used as a unique index into extension_data) 548 * @param mixed &$value value of the extensions content(-array) 549 * @param array &$cell table-cell on which the extension operates 550 * @param array &$readonlys value of the extensions readonly-setting(-array) 551 * @return mixed return-value of the render function 552 */ 553 function extensionRender($type,$name,&$value,&$cell,$readonly) 554 { 555 if (!$this->haveExtension($type,'render')) 556 { 557 return False; 558 } 559 return $GLOBALS['egw_info']['etemplate']['extension'][$type]->render($cell,$name,$value,$readonly, 560 $GLOBALS['egw_info']['etemplate']['extension_data'][$name],$this); 561 } 562 563 /** 564 * checks if $idx is set in array $arr 565 * 566 * for one level of subindes identical to isset($arr[$idx]) 567 * 568 * @static 569 * @param array $arr array to check 570 * @param string $idx may contain multiple subindex (eg.'x[y][z]') 571 * @return boolean true if set, else false 572 */ 573 function isset_array($arr,$idx) 574 { 575 $idxs = explode('[',str_replace(']','',$idx)); 576 $last_idx = array_pop($idxs); 577 $pos = &$arr; 578 foreach($idxs as $idx) 579 { 580 if (!is_array($pos)) 581 { 582 return False; 583 } 584 $pos = &$pos[$idx]; 585 } 586 return isset($pos[$last_idx]); 587 } 588 589 /** 590 * sets $arr[$idx] = $val 591 * 592 * This works for non-trival indexes like 'a[b][c]' too: $arr['a']['b']['c'] = $val; 593 * 594 * @static 595 * @param array &$arr the array to search 596 * @param string $idx the index, may contain sub-indices like a[b], see example below 597 * @param mixed $val value to set 598 */ 599 function set_array(&$arr,$idx,$val) 600 { 601 if (!is_array($arr)) 602 { 603 die('set_array() $arr is no array<br>'.function_backtrace()); 604 } 605 $idxs = explode('[',str_replace(']','',$idx)); 606 $pos = &$arr; 607 foreach($idxs as $idx) 608 { 609 $pos = &$pos[$idx]; 610 } 611 $pos = $val; 612 } 613 614 /** 615 * return a reference to $arr[$idx] 616 * 617 * This works for non-trival indexes like 'a[b][c]' too: it returns &$arr[a][b][c] 618 * $sub = get_array($arr,'a[b]'); $sub = 'c'; is equivalent to $arr['a']['b'] = 'c'; 619 * 620 * @static 621 * @param array $arr the array to search, referenz as a referenz gets returned 622 * @param string $idx the index, may contain sub-indices like a[b], see example below 623 * @param boolean $reference_into default False, if True none-existing sub-arrays/-indices get created to be returned as referenz, else False is returned 624 * @return mixed reference to $arr[$idx] or false if $idx is not set and not $reference_into 625 */ 626 function &get_array(&$arr,$idx,$reference_into=False) 627 { 628 if (!is_array($arr)) 629 { 630 die('set_array() $arr is no array<br>'.function_backtrace()); 631 } 632 if (is_object($idx)) return false; // given an error in php5.2 633 634 $idxs = explode('[',str_replace(']','',$idx)); 635 $pos = &$arr; 636 foreach($idxs as $idx) 637 { 638 if (!is_array($pos) && !$referenz_info) 639 { 640 return False; 641 } 642 $pos = &$pos[$idx]; 643 } 644 return $pos; 645 } 646 647 /** 648 * unsets $arr[$idx] 649 * 650 * This works for non-trival indexes like 'a[b][c]' too 651 * unset_array($arr,'a[b]'); is equivalent to unset($arr['a']['b']); 652 * 653 * @static 654 * @param array $arr the array to search, referenz as a referenz gets returned 655 * @param string $idx the index, may contain sub-indices like a[b], see example below 656 */ 657 function unset_array(&$arr,$idx) 658 { 659 if (!is_array($arr)) 660 { 661 die('set_array() $arr is no array<br>'.function_backtrace()); 662 } 663 $idxs = explode('[',str_replace(']','',$idx)); 664 $last_idx = array_pop($idxs); 665 $pos = &$arr; 666 foreach($idxs as $idx) 667 { 668 $pos = &$pos[$idx]; 669 } 670 unset($pos[$last_idx]); 671 } 672 673 /** 674 * merges $old and $new, content of $new has precedence over $old 675 * 676 * THIS IS NOT THE SAME AS PHP4's functions: 677 * - array_merge, as it calls itself recursive for values which are arrays. 678 * - array_merge_recursive accumulates values with the same index and $new does NOT overwrite $old 679 * 680 * @static 681 * @param array $old 682 * @param array $new 683 * @return array the merged array 684 */ 685 function complete_array_merge($old,$new) 686 { 687 if (is_array($new)) 688 { 689 if (!is_array($old)) $old = (array) $old; 690 691 foreach($new as $k => $v) 692 { 693 if (!is_array($v) || !isset($old[$k])) 694 { 695 $old[$k] = $v; 696 } 697 else 698 { 699 $old[$k] = $this->complete_array_merge($old[$k],$v); 700 } 701 } 702 } 703 return $old; 704 } 705 706 /** 707 * returns a reference to a widget in the widget's children tree spezified by a path 708 * 709 * The path get's generated by the widget_tree_walk() methode and consists of the keys of the children arrays. 710 * For the 3. Column in the 2. row of a grid which is the only widget in the children-tree it is eg.: "/0/2C" 711 * 712 * @param string $path path in the widget tree 713 * @param int $ancestor=0 0: widget itself, 1: parent, 2: grand-parent, ... 714 * @return array referenz to the widget spezified or null, if it's not found 715 */ 716 function &get_widget_by_path($path,$ancestor=0) 717 { 718 //echo "<p>boetemplate::get_widget_by_path('$path',$ancestor)</p>\n"; 719 $path_parts = explode('/',$path); 720 while($ancestor-- > 0) 721 { 722 if (array_pop($path_parts) === '') return null; 723 } 724 $path = implode('/',$path_parts); 725 if ($path == '/' || $path === '') return $this->children; 726 727 return $this->widget_tree_walk('get_widget_by_path_helper',$path); 728 } 729 730 /** 731 * returns a reference to a widget in the widget's children tree spezified it's name 732 * 733 * It returns the first match! 734 * 735 * @param string $name name of the widget 736 * @return array referenz to the widget spezified or null, if it's not found 737 */ 738 function &get_widget_by_name($name) 739 { 740 return $this->widget_tree_walk('get_widget_by_name_helper',$name); 741 } 742 743 /** 744 * generated a file-name from an eTemplates, name, template(-set) and lang 745 * 746 * @param string/array $name name of template or array('name'=>$name,'template'=>$template,'lang'=>$lang) 747 * @param string $template template-set 748 * @param string $lang language to use 749 * @return string 750 */ 751 function cache_name($name='',$template='default',$lang='default') 752 { 753 if (empty($name)) 754 { 755 $name = $this->name; 756 $template = $this->template; 757 $lang = $this->lang; 758 } 759 elseif (is_array($name)) 760 { 761 $template = $name['template']; 762 $lang = $name['lang']; 763 $name = $name['name']; 764 } 765 if (empty($template)) 766 { 767 $template = 'default'; 768 } 769 $cname = $template . '/' . $name . (!empty($lang) && $lang != 'default' ? '.' . $lang : ''); 770 //echo "cache_name('$name','$template','$lang') = '$cname'"; 771 772 return $cname; 773 } 774 775 /** 776 * stores the etemplate in the cache in phpgw_info 777 */ 778 function store_in_cache() 779 { 780 //echo "<p>store_in_cache('$this->name','$this->template','$this->lang','$this->version')</p>\n"; 781 $GLOBALS['egw_info']['etemplate']['cache'][$this->cache_name()] = $this->as_array(1); 782 } 783 784 /** 785 * deletes the etemplate in the cache in phpgw_info 786 */ 787 function delete_in_cache() 788 { 789 //echo "<p>delete_in_cache('$this->name','$this->template','$this->lang','$this->version')</p>\n"; 790 unset($GLOBALS['egw_info']['etemplate']['cache'][$this->cache_name()]); 791 } 792 793 /* 794 * returns true if a given eTemplate is in the cache 795 * 796 * @param string/array $name name of template or array('name'=>$name,'template'=>$template,'lang'=>$lang) 797 * @param string $template template-set 798 * @param string $lang language to use 799 * @param int $group to use the template for 800 * @param string $version of the template 801 * @return boolean 802 */ 803 function in_cache($name,$template='default',$lang='default',$group=0,$version='') 804 { 805 $cname = $this->cache_name($name,$template,$lang); 806 if (is_array($name)) 807 { 808 $version = $name['version']; 809 $name = $name['name']; 810 } 811 if (!isset($GLOBALS['egw_info']['etemplate']['cache'][$cname]) || 812 !empty($version) && $GLOBALS['egw_info']['etemplate']['cache'][$cname]['version'] != $version) 813 { 814 //echo " NOT found in cache</p>\n"; 815 return False; 816 } 817 //echo " found in cache</p>\n"; 818 return $cname; 819 } 820 821 /* 822 * reads the content of an eTemplate from the cache into the current object 823 * 824 * same as read but only via the cache 825 * 826 * @param string/array $name name of template or array('name'=>$name,'template'=>$template,'lang'=>$lang) 827 * @param string $template template-set 828 * @param string $lang language to use 829 * @param int $group to use the template for 830 * @param string $version of the template 831 * @return boolean true if the eTemplate was found in the cache 832 */ 833 function read_from_cache($name,$template='default',$lang='default',$group=0,$version='') 834 { 835 //if (is_array($name)) $version = $name['version']; echo "<p>read_from_cache(,,,version='$version'): "; 836 if ($cname = $this->in_cache($name,$template,$lang,$group)) 837 { 838 $this->init($GLOBALS['egw_info']['etemplate']['cache'][$cname]); 839 840 return True; 841 } 842 return False; 843 } 844 845 /** 846 * reads an eTemplate from the cache or database / filesystem (and updates the cache) 847 * 848 * reimplementation of soetemplate::read to use and/or update the cache 849 * 850 * @param string $name name of the eTemplate or array with the values for all keys 851 * @param string $template template-set, '' loads the prefered template of the user, 'default' loads the default one '' in the db 852 * @param string $lang language, '' loads the pref. lang of the user, 'default' loads the default one '' in the db 853 * @param int $group id of the (primary) group of the user or 0 for none, not used at the moment !!! 854 * @param string $version version of the eTemplate 855 * @param mixed $load_via name/array of keys of etemplate to load in order to get $name (only as second try!) 856 * @return boolean True if a fitting template is found, else False 857 */ 858 function read($name,$template='default',$lang='default',$group=0,$version='',$load_via='') 859 { 860 if (is_array($name)) { 861 $pname = &$name['name']; 862 } 863 else 864 { 865 $pname = &$name; 866 } 867 if (empty($pname)) 868 { 869 return False; 870 } 871 $parent = is_array($load_via) ? $load_via['name'] : $load_via; 872 873 if (strstr($pname,'.') === False && !empty($parent)) 874 { 875 $pname = $parent . '.' . $pname; 876 } 877 if (!$this->read_from_cache($name,$template,$lang,$group,$version)) 878 { 879 if (!soetemplate::read($name,$template,$lang,$group,$version)) 880 { 881 if ($load_via && (is_string($load_via) || 882 !isset($load_via['tpls_in_file']) || $load_via['tpls_in_file'] > 1)) 883 { 884 soetemplate::read($load_via); 885 return $this->read_from_cache($name,$template,$lang,$group,$version); 886 } 887 return False; 888 } 889 $this->store_in_cache(); 890 } 891 return True; 892 } 893 894 /** 895 * saves eTemplate-object to db and update the cache 896 * 897 * reimplementation of soetemplate::save to update the cache 898 * 899 * @param string $name name of the eTemplate or array with the values for all keys 900 * @param string $template template-set or '' for the default one 901 * @param string $lang language or '' for the default one 902 * @param int $group id of the (primary) group of the user or 0 for none, not used at the moment !!! 903 * @param string $version version of the eTemplate 904 * @return the number of affected rows, 1 should be ok, 0 somethings wrong 905 */ 906 function save($name='',$template='.',$lang='.',$group=0,$version='.') 907 { 908 if ($result = soetemplate::save($name,$template,$lang,$group,$version)) 909 { 910 $this->store_in_cache(); 911 } 912 return $result; 913 } 914 915 /** 916 * Deletes the eTemplate from the db, object itself is unchanged 917 * 918 * reimplementation of soetemplate::delete to update the cache 919 * 920 * @return int number of affected rows, 1 should be ok, 0 somethings wrong 921 */ 922 function delete() 923 { 924 $this->delete_in_cache(); 925 926 return soetemplate::delete(); 927 } 928 929 } 930 931 if (!function_exists('set_cell_attribute_helper')) 932 { 933 function &set_cell_attribute_helper(&$widget,&$extra) 934 { 935 // extra = array(0=>n,1=>name,2=>attr,3=>value) 936 if ($widget['name'] == $extra[1]) 937 { 938 if (is_null($extra[3])) 939 { 940 $extra['__RETURN_NOW__'] = true; // wouldnt work otherwise, if attr is not yet set == null 941 return $widget[$extra[2]]; 942 } 943 $widget[$extra[2]] = $extra[3]; 944 ++$extra[0]; 945 } 946 } 947 948 function &get_widget_by_name_helper(&$widget,$extra) 949 { 950 if ($widget['name'] == $extra) return $widget; 951 } 952 953 function &get_widget_by_path_helper(&$widget,$extra,$path) 954 { 955 //echo "<p>path_searched='$extra', widget-path($widget[type]:$widget[name])='$path'</p>\n"; 956 if ($path == $extra) return $widget; 957 } 958 }
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 |