From e9be751ce72d775e57d6e5b116c2c60c148641e1 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 20 Feb 2002 01:26:03 +0000 Subject: [PATCH] initial import of gtk user-interface --- etemplate/inc/class.etemplate.inc.php | 9 +- etemplate/inc/class.uietemplate_gtk.inc.php | 918 ++++++++++++++++++++ 2 files changed, 924 insertions(+), 3 deletions(-) create mode 100644 etemplate/inc/class.uietemplate_gtk.inc.php diff --git a/etemplate/inc/class.etemplate.inc.php b/etemplate/inc/class.etemplate.inc.php index aafe1009d7..25f982385d 100644 --- a/etemplate/inc/class.etemplate.inc.php +++ b/etemplate/inc/class.etemplate.inc.php @@ -12,6 +12,9 @@ /* $Id$ */ - $ui = 'ui'; // html UI, which UI to use, should come from api and be in $GLOBALS['phpgw']??? - - include(PHPGW_API_INC . "/../../etemplate/inc/class.${ui}etemplate.inc.php"); + $ui = ''; // html UI, which UI to use, should come from api and be in $GLOBALS['phpgw']??? + if ($_ENV['DISPLAY']) + { + $ui = '_gtk'; + } + include(PHPGW_API_INC . "/../../etemplate/inc/class.uietemplate$ui.inc.php"); diff --git a/etemplate/inc/class.uietemplate_gtk.inc.php b/etemplate/inc/class.uietemplate_gtk.inc.php new file mode 100644 index 0000000000..fad3f97693 --- /dev/null +++ b/etemplate/inc/class.uietemplate_gtk.inc.php @@ -0,0 +1,918 @@ + * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + include(PHPGW_API_INC . '/../../etemplate/inc/class.boetemplate.inc.php'); + + /*! + @class etemplate + @abstract creates dialogs / HTML-forms from eTemplate descriptions + @discussion etemplate or uietemplate extends boetemplate, all vars and public functions are inherited + @example $tmpl = CreateObject('etemplate.etemplate','app.template.name'); + @example $tmpl->exec('app.class.callback',$content_to_show); + @example This creates a form from the eTemplate 'app.template.name' and takes care that + @example the method / public function 'callback' in (bo)class 'class' of 'app' gets called + @example if the user submitts the form. Vor the complete param's see the description of exec. + @param $debug enables debug messages: 0=no, 1=calls to show and process_show, 2=content of process_show + @param 3=calls to show_cell OR template- or cell-type name + @param $html,$sbox instances of html and sbox2 class used to generate the html + */ + class etemplate extends boetemplate + { + var $debug;//='etemplate.editor.edit'; // 1=calls to show and process_show, 2=content after process_show, + // 3=calls to show_cell and process_show_cell, or template-name or cell-type + + /*! + @function etemplate + @abstract constructor of etemplate class, reads an eTemplate if $name is given + @param as soetemplate.read + */ + function etemplate($name='',$template='default',$lang='default',$group=0,$version='',$rows=2,$cols=2) + { + $this->public_functions += array( + 'exec' => True, + 'process_exec' => True, + 'show' => True, + 'process_show' => True, + ); + $this->boetemplate(); + + if (!$this->read($name,$template,$lang,$group,$version)) + { + $this->init($name,$template,$lang,$group,$version,$rows,$cols); + return False; + } + return True; + } + + /*! + @function exec + @abstract Generats a Dialog from an eTemplate - abstract the UI-layer + @discussion This is the only function an application should use, all other are INTERNAL and + @discussion do NOT abstract the UI-layer, because they return HTML. + @discussion Generates a webpage with a form from the template and puts process_exec in the + @discussion form as submit-url to call process_show for the template before it + @discussion ExecuteMethod's the given $methode of the caller. + @param $methode Methode (e.g. 'etemplate.editor.edit') to be called if form is submitted + @param $content Array with content to fill the input-fields of template, eg. the text-field + @param with name 'name' gets its content from $content['name'] + @param $sel_options Array or arrays with the options for each select-field, keys are the + @param field-names, eg. array('name' => array(1 => 'one',2 => 'two')) set the + @param options for field 'name'. ($content['options-name'] is possible too !!!) + @param $readonlys Array with field-names as keys for fields with should be readonly + @param (eg. to implement ACL grants on field-level or to remove buttons not applicable) + @param $preserv Array with vars which should be transported to the $method-call (eg. an id) array('id' => $id) sets $HTTP_POST_VARS['id'] for the $method-call + @returns nothing + */ + function exec($method,$content,$sel_options='',$readonlys='',$preserv='') + { + if (!$sel_options) + { + $sel_options = array(); + } + if (!$readonlys) + { + $readonlys = array(); + } + if (!$preserv) + { + $preserv = array(); + } + if (!class_exists('gtk')) // load the gtk extension + { + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') + { + dl('php_gtk.dll'); + } + else + { + dl('php_gtk.so'); + } + } + /* + * Create a new top-level window and connect the signals to the appropriate + * functions. Note that all constructors must be assigned by reference. + */ + $this->window = &new GtkWindow(); + $this->window->connect('destroy',array('etemplate','destroy')); + $this->window->connect('delete-event',array('etemplate','delete_event')); + $this->window->set_title('phpGroupware & GTK'); + $this->window->set_border_width(10); + + $result = array(); + $this->window->add($this->show($result,$content,$sel_options,$readonlys)); + /* + * Show the window and all its child widgets. + */ + $this->window->show_all(); + + /* Run the main loop. */ + Gtk::main(); + + $this->collect_results(); + + $this->window->hide(); + unset($this->window); + unset($this->widgets); + + // set application name so that lang, etc. works + list($GLOBALS['phpgw_info']['flags']['currentapp']) = explode('.',$method); + + //echo "

uietemplate.process_exec: ExecMethod('${exec['method']}')

\n"; + ExecMethod($method,array_merge($result,$preserv)); + } + + /* + * Called when delete-event happens. Returns false to indicate that the event + * should proceed. + */ + function delete_event() + { + return false; + } + + /* + * Called when the window is being destroyed. Simply quit the main loop. + */ + function destroy() + { + Gtk::main_quit(); + exit(); + } + + function button_clicked(&$data) + { + $data = 'pressed'; + echo "button pressed\n"; + Gtk::main_quit(); + } + + function collect_results() + { + for($i=0; isset($this->widgets[$i]); ++$i) + { + $set = &$this->widgets[$i]; + $widget = &$set['widget']; + + echo "$i: $set[name]/$set[type]/".Gtk::type_name($widget->get_type()); + switch ($set['type']) + { + case 'int': + case 'float': + case 'text': + $set['var'] = $widget->get_chars(0,-1); + break; + case 'checkbox': + $set['var'] = $widget->get_active(); + break; + case 'radio': + if ($widget->get_active()) + { + $set['var'] = $set['set_val']; + } + break; + case 'select': + $entry = $widget->entry; + $selected = $entry->get_chars(0,-1); + $options = $set['set_val']; + reset($options); + while (list($key,$val) = each($options)) + { + if ($val == $selected) + { + $set['var'] = $key; + break; + } + } + break; + case 'textarea': + case 'date': + case 'button': + } + echo " = '$set[var]'\n"; + } + } + + /*! + @function isset_array($idx,$arr) + @abstract checks if idx, which may contain ONE subindex is set in array + */ + function isset_array($idx,$arr) + { + if (ereg('^([^[]*)\\[(.*)\\]$',$idx,$regs)) + { + return $regs[2] && isset($arr[$regs[1]][$regs[2]]); + } + return isset($arr[$idx]); + } + + /*! + @function show + @abstract creates HTML from an eTemplate + @discussion This is done by calling show_cell for each cell in the form. show_cell itself + @discussion calls show recursivly for each included eTemplate. + @discussion You can use it in the UI-layer of an app, just make shure to call process_show !!! + @discussion This is intended as internal function and should NOT be called by new app's direct, + @discussion as it deals with HTML and is so UI-dependent, use exec instead. + @param $content array with content for the cells, keys are the names given in the cells/form elements + @param $sel_options array with options for the selectboxes, keys are the name of the selectbox + @param $readonlys array with names of cells/form-elements to be not allowed to change + @param This is to facilitate complex ACL's which denies access on field-level !!! + @param $cname basename of names for form-elements, means index in $HTTP_POST_VARS + @param eg. $cname='cont', element-name = 'name' returned content in $HTTP_POST_VARS['cont']['name'] + @param $show_xxx row,col name/index for name expansion + @returns the generated HTML + */ + function show(&$result,$content,$sel_options='',$readonlys='',$show_c=0,$show_row=0) + { + if (!$sel_options) + { + $sel_options = array(); + } + if (!$readonlys) + { + $readonlys = array(); + } + if ($this->debug >= 1 || $this->debug == $this->name && $this->name) + { + echo "

etemplate.show($this->name): $cname =\n"; _debug_array($content); + } + if (!is_array($content)) + { + $content = array(); // happens if incl. template has no content + } + $content += array( // for var-expansion in names in show_cell + '.c' => $show_c, + '.col' => $this->num2chrs($show_c-1), + '.row' => $show_row + ); + + $table = &new GtkTable($this->rows,$this->cols,False); + $table->set_row_spacings(2); + $table->set_col_spacings(5); + $table->show(); + + reset($this->data); + if (isset($this->data[0])) + { + list($nul,$width) = each($this->data); + } + else + { + $width = array(); + } + for ($r = 0; $row = 1+$r /*list($row,$cols) = each($this->data)*/; ++$r) + { + $old_cols = $cols; $old_class = $class; $old_height = $height; + if (!(list($nul,$cols) = each($this->data))) // no further row + { + $cols = $old_cols; $class = $old_class; $height = $old_height; + list($nul,$cell) = each($cols); reset($cols); + if (!($this->autorepeat_idx($cols['A'],0,$r,$idx,$idx_cname) && $idx_cname) && + !($this->autorepeat_idx($cols['B'],1,$r,$idx,$idx_cname) && $idx_cname) || + !$this->isset_array($idx,$content)) + { + break; // no auto-row-repeat + } + } + else + { + $height = $this->data[0]["h$row"]; + $class = $this->data[0]["c$row"]; + } + $row_data = array(); + for ($c = 0; True /*list($col,$cell) = each($cols)*/; ++$c) + { + $old_cell = $cell; + if (!(list($nul,$cell) = each($cols))) // no further cols + { + $cell = $old_cell; + if (!$this->autorepeat_idx($cell,$c,$r,$idx,$idx_cname,True) || + !$this->isset_array($idx,$content)) + { + break; // no auto-col-repeat + } + } + $col = $this->num2chrs($c); + + //$row_data[$col] = $this->show_cell($cell,$content,$sel_options,$readonlys,$cname,$c,$r,$span); + $widget = $this->show_cell($cell,$content,$sel_options,$readonlys,$cname,$c,$r,$span,$result); + if (($colspan = $span == 'all' ? $this->cols-$c : 0+$span) < 1) + { + $colspan = 1; + } + if ($widget) + { + $widget->show(); + $table->attach($widget, $c, $c+$colspan, $r, $r+1,GTK_FILL,GTK_FILL,0,0); + } + if ($row_data[$col] == '' && $this->rows == 1) + { + unset($row_data[$col]); // omit empty/disabled cells if only one row + continue; + } + if ($colspan > 1) + { + $row_data[".$col"] .= " COLSPAN=$colspan"; + for ($i = 1; $i < $colspan; ++$i,++$c) + { + each($cols); // skip next cell(s) + } + } + elseif ($width[$col]) // width only once for a non colspan cell + { + $row_data[".$col"] .= ' WIDTH='.$width[$col]; + $width[$col] = 0; + } +// $row_data[".$col"] .= $this->html->formatOptions($cell['align'],'ALIGN'); +// $row_data[".$col"] .= $this->html->formatOptions($cell['span'],',CLASS'); + } + $rows[$row] = $row_data; + +// $rows[".$row"] .= $this->html->formatOptions($height,'HEIGHT'); + list($cl) = explode(',',$class); + if ($cl == 'nmr') + { + $cl .= $nmr_alternate++ & 1; // alternate color + } +// $rows[".$row"] .= $this->html->formatOptions($cl,'CLASS'); +// $rows[".$row"] .= $this->html->formatOptions($class,',VALIGN'); + } + if (!$GLOBALS['phpgw_info']['etemplate']['styles_included'][$this->name]) + { +// $style = $this->html->style($this->style); + $GLOBALS['phpgw_info']['etemplate']['styles_included'][$this->name] = True; + } + return $table; + } + + /*! + @function show_cell + @abstract generates HTML for 1 input-field / cell + @discussion calls show to generate included eTemplates. Again only an INTERMAL function. + @param $cell array with data of the cell: name, type, ... + @param for rest see show + @returns the generated HTML + */ + function show_cell($cell,$content,$sel_options,$readonlys,$cname,$show_c,$show_row,&$span,&$result) + { + if ($this->debug >= 3 || $this->debug == $cell['type']) + { + echo "

etemplate.show_cell($this->name,name='${cell['name']}',type='${cell['type']}',cname='$cname')

\n"; + } + list($span) = explode(',',$cell['span']); // evtl. overriten later for type template + + $name = $this->expand_name($cell['name'],$show_c,$show_row,$content['.c'],$content['.row'],$content); + $value = $content[$name]; + $var = &$result[$name]; + + $org_name = $name; + if ($cname == '') // building the form-field-name depending on prefix $cname and possibl. Array-subscript in name + { + $form_name = $name; + } + elseif (ereg('^([^[]*)\\[(.*)\\]$',$name,$regs)) // name contains array-index + { + $form_name = $cname.'['.$regs[1].']['.$regs[2].']'; + $value = $content[$regs[1]][$regs[2]]; + $var = &$result[$regs[1]][$regs[2]]; + $org_name = $regs[2]; + } + else + { + $form_name = $cname.'['.$name.']'; + } + if ($readonly = $cell['readonly'] || $readonlys[$name] || $readonlys['__ALL__']) + { + $options .= ' READONLY'; + } + if ($cell['disabled'] || $cell['type'] == 'button' && $readonly) + { + if ($this->rows == 1) { + return ''; // if only one row omit cell + } + $cell = $this->empty_cell(); // show nothing + $value = ''; + } + if ($cell['onchange']) // values != '1' can only set by a program (not in the editor so far) + { + $options .= ' onChange="'.($cell['onchange']=='1'?'this.form.submit();':$cell['onchange']).'"'; + } + + if (strlen($label = $cell['label']) > 1) + { + $label = lang($label); + } + list($left_label,$right_label) = explode('%s',$label); + + $widget = False; + switch ($cell['type']) + { + case 'label': // size: [[b]old][[i]talic] + $value = strlen($value) > 1 && !$cell['no_lang'] ? lang($value) : $value; + + //if ($value != '' && strstr($cell['size'],'b')) $value = $this->html->bold($value); + //if ($value != '' && strstr($cell['size'],'i')) $value = $this->html->italic($value); + $html .= $value; + + if ($value) + { + $widget = &new GtkLabel($value); + } + break; + case 'raw': + //$html .= $value; + break; + case 'int': // size: [min][,[max][,len]] + case 'float': + list($min,$max,$cell['size']) = explode(',',$cell['size']); + if ($cell['size'] == '') + { + $cell['size'] = $cell['type'] == 'int' ? 5 : 8; + } + // fall-through + case 'text': // size: [length][,maxLength] + if ($readonly) + { + //$html .= $this->html->bold($value); + } + else + { + //$html .= $this->html->input($form_name,$value,'',$options.$this->html->formatOptions($cell['size'],'SIZE,MAXLENGTH')); + } + list($len,$max) = explode(',',$cell['size']); + $widget = &new GtkEntry(); + $widget->set_text($value); + if ($max) + { + $widget->set_max_length($max); + } + $widget->set_editable(!$readonly); + break; + case 'textarea': // Multiline Text Input, size: [rows][,cols] + //$html .= $this->html->textarea($form_name,$value,$options.$this->html->formatOptions($cell['size'],'ROWS,COLS')); + $widget = &new GtkText(null,null); + //$widget->set_text($value); + $widget->set_editable(!$readonly); + break; +/* case 'date': + if ($cell['size'] != '') + { + $date = split('[/.-]',$value); + $mdy = split('[/.-]',$cell['size']); + for ($value=array(),$n = 0; $n < 3; ++$n) + { + switch($mdy[$n]) + { + case 'Y': $value[0] = $date[$n]; break; + case 'm': $value[1] = $date[$n]; break; + case 'd': $value[2] = $date[$n]; break; + } + } + } + else + { + $value = array(date('Y',$value),date('m',$value),date('d',$value)); + } + if ($readonly) + { + $html .= $GLOBALS['phpgw']->common->dateformatorder($value[0],$value[1],$value[2]); + } + else + { + $html .= $this->sbox->getDate($name.'[Y]',$name.'[m]',$name.'[d]',$value,$options); + } + break; +*/ case 'checkbox': + if ($value) + { + $options .= ' CHECKED'; + } + //$html .= $this->html->input($form_name,'1','CHECKBOX',$options); + $widget = &new GtkCheckButton($right_label); + $right_label = ''; + $widget->set_active($value); + break; + case 'radio': // size: value if checked + if ($value == $cell['size']) + { + $options .= ' CHECKED'; + } + //$html .= $this->html->input($form_name,$cell['size'],'RADIO',$options); + if (isset($this->buttongroup[$form_name])) + { + $widget = &new GtkRadioButton($this->buttongroup[$form_name],$right_label); + } + else + { + $this->buttongroup[$form_name] = $widget = &new GtkRadioButton(null,$right_label); + } + $right_label = ''; + $widget->set_active($value == $cell['size']); + break; + case 'button': + //$html .= $this->html->submit_button($form_name,$cell['label'],'',strlen($cell['label']) <= 1 || $cell['no_lang'],$options); + $widget = &new GtkButton(strlen($cell['label']) > 1 ? lang($cell['label']) : $cell['label']); + $widget->connect_object('clicked', array('etemplate', 'button_clicked'),&$var); + break; + case 'hrule': + //$html .= $this->html->hr($cell['size']); + $widget = &new GtkHSeparator(); + break; + case 'template': // size: index in content-array (if not full content is past further on) + if ($this->autorepeat_idx($cell,$show_c,$show_row,$idx,$idx_cname) || $cell['size'] != '') + { + if ($span == '' && isset($content[$idx]['span'])) + { // this allows a colspan in autorepeated cells like the editor + $span = explode(',',$content[$idx]['span']); $span = $span[0]; + if ($span == 'all') + { + $span = 1 + $content['cols'] - $show_c; + } + } + $readonlys = $readonlys[$idx]; + $content = $content[$idx]; + $var = &$result[$idx]; + if ($idx_cname != '') + { + $cname .= $cname == '' ? $idx_cname : "[$idx_cname]"; + } + //echo "

show_cell-autorepeat($name,$show_c,$show_row,cname='$cname',idx='$idx',idx_cname='$idx_cname',span='$span'): readonlys[$idx] ="; _debug_array($readonlys); + } + else + { + $var = &$result; + } + if ($readonly) + { + $readonlys['__ALL__'] = True; + } + $templ = is_object($cell['name']) ? $cell['name'] : new etemplate($name); + $templ->widgets = &$this->widgets; + //$html .= $templ->show($content,$sel_options,$readonlys,$cname,$show_c,$show_row); + $widget = $templ->show($var,$content,$sel_options,$readonlys,$cname,$show_c,$show_row); + break; + case 'select': // size:[linesOnMultiselect] + if (isset($sel_options[$name])) + { + $sel_options = $sel_options[$name]; + } + elseif (isset($sel_options[$org_name])) + { + $sel_options = $sel_options[$org_name]; + } elseif (isset($content["options-$name"])) + { + $sel_options = $content["options-$name"]; + } + //$html .= $this->sbox->getArrayItem($form_name.'[]',$value,$sel_options,$cell['no_lang'],$options,$cell['size']); + if (!$cell['no_lang']) + { + reset($sel_options); + while (list($key,$val) = each($sel_options)) + { + $sel_options[$key] = lang($val); + } + } + $widget = &new GtkCombo(); + $widget->set_popdown_strings($sel_options); + $entry = $widget->entry; + $entry->set_text($sel_options[$value]); + $entry->set_editable(False); + break; +/* case 'select-percent': + $html .= $this->sbox->getPercentage($form_name,$value,$options); + break; + case 'select-priority': + $html .= $this->sbox->getPriority($form_name,$value,$options); + break; + case 'select-access': + $html .= $this->sbox->getAccessList($form_name,$value,$options); + break; + case 'select-country': + $html .= $this->sbox->getCountry($form_name,$value,$options); + break; + case 'select-state': + $html .= $this->sbox->list_states($form_name,$value); // no helptext - old Function!!! + break; + case 'select-cat': + $html .= $this->sbox->getCategory($form_name.'[]',$value,$cell['size'] >= 0, + False,$cell['size'],$options); + break; + case 'select-account': + $type = substr(strstr($cell['size'],','),1); + if ($type == '') + { + $type = 'accounts'; // default is accounts + } + $html .= $this->sbox->getAccount($form_name.'[]',$value,2,$type,0+$cell['size'],$options); + break; + case 'image': + $image = $this->html->image(substr($this->name,0,strpos($this->name,'.')), + $cell['label'],lang($cell['help']),'BORDER=0'); + $html .= $name == '' ? $image : $this->html->a_href($image,$name); + break; +*/ default: + $html .= 'unknown type'; + $widget = &new GtkLabel('unknown type: '.$cell['type']); + break; + } + $no_result = array('label' => True,'hrule' => True,'image' => True,'raw' => True,'template' => True); + if ($widget && !$readonly && !$no_result[$cell['type']]) + { + $this->widgets[] = array( + 'widget' => &$widget, + 'type' => $cell['type'], + 'var' => &$var, + 'set_val' => $cell['type'] == 'radio' ? $cell['size'] : $sel_options, + 'name' => $form_name + ); + } + if ($cell['type'] != 'button' && $cell['type'] != 'image' && ($left_label || $right_label)) + { + if (!$widget && !$right_label) + { + $widget = &new GtkLabel($left_label); + } + else + { + $hbox = &new GtkHBox(False,5); + if ($left_label) + { + $left = &new GtkLabel($left_label); + $left->show(); + $hbox->add($left); + } + if ($widget) + { + $widget->show(); + $hbox->add($widget); + } + if ($right_label) + { + $right = &new GtkLabel($right_label); + $right->show(); + $hbox->add($right); + } + } + } + if ($cell['help'] && $widget) + { + if (!$this->tooltips) + { + $this->tooltips = &new GtkTooltips(); + } + $this->tooltips->set_tip($widget,lang($cell['help']),$this->name.'/'.$form_name); + } + return $hbox ? $hbox : $widget; + } + + /*! + @function process_show + @abstract makes necessary adjustments on HTTP_POST_VARS after a eTemplate / form gots submitted + @discussion This is only an internal function, dont call it direct use only exec + @discussion process_show recursivly calls itself for the included eTemplates. + @param $vars HTTP_POST_VARS on first call, later (deeper recursions) subscripts of it + @param $readonly array with cell- / var-names which should NOT return content (this is to workaround browsers who not understand READONLY correct) + @param $cname basename of our returnt content (same as in call to show) + @returns the adjusted content (in the simplest case that would be $vars[$cname]) + */ + function process_show(&$content,$readonlys='') + { + if (!$readonlys) + { + $readonlys = array(); + } + if (!isset($content) || !is_array($content)) + { + return; + } + if ($this->debug >= 1 || $this->debug == $this->name && $this->name) + { + echo "

process_show($this->name) start: content ="; _debug_array($content); + } + reset($this->data); + if (isset($this->data[0])) + { + each($this->data); // skip width + } + for ($r = 0; True /*list($row,$cols) = each($this->data)*/; ++$r) + { + $old_cols = $cols; + if (!(list($nul,$cols) = each($this->data))) // no further row + { + $cols = $old_cols; + list($nul,$cell) = each($cols); reset($cols); + if ((!$this->autorepeat_idx($cols['A'],0,$r,$idx,$idx_cname) || + $idx_cname == '' || !$this->isset_array($idx,$content)) && + (!$this->autorepeat_idx($cols['B'],1,$r,$idx,$idx_cname) || + $idx_cname == '' || !$this->isset_array($idx,$content))) + { + break; // no auto-row-repeat + } + } + $row = 1+$r; + for ($c = 0; True /*list($col,$cell) = each($cols)*/; ++$c) + { + $old_cell = $cell; + if (!(list($nul,$cell) = each($cols))) // no further cols + { + $cell = $old_cell; + if (!$this->autorepeat_idx($cell,$c,$r,$idx,$idx_cname,True) || + $idx_cname == '' || !$this->isset_array($idx,$content)) + { + break; // no auto-col-repeat + } + } + else + { + $this->autorepeat_idx($cell,$c,$r,$idx,$idx_cname,True); // get idx_cname + } + $col = $this->num2chrs($c); + + $name = $this->expand_name($cell['name'],$c,$r); + $readonly = $cell['readonly'] || $readonlys[$name] || $readonlys['__ALL__'] || + $cell['type'] == 'label' || $cell['type'] == 'image' || $cell['type'] == 'raw' || + $cell['type'] == 'hrule'; + + if ($idx_cname == '' && $cell['type'] == 'template') // only templates + { + if ($readonly && !isset($readonlys['__ALL__'])) // can't unset whole content!!! + { + $readonlys['__ALL__'] = True; + $this->process_show_cell($cell,$name,$c,$r,$readonlys,$content); + unset($readonlys['__ALL__']); // unset it after or everything gets set readonly + } + else + { + $this->process_show_cell($cell,$name,$c,$r,$readonlys,$content); + } + } + elseif (ereg('^([^[]*)\\[(.*)\\]$',$idx_cname,$regs)) // name contains array-index + { + /* Attention: the unsets here and in the next else are vor two reasons: + * 1) some browsers does NOT understand the READONLY-tag and sent content back + * this has to be unset, as we only report no-readonly fields + * 2) php has a fault / feature :-) that it set unset array-elements passed as + * variable / changeable (&$var) to a function, this messes up a lot, as we + * depend on the fact variables are set or not for the autorepeat. To work + * around that, process_show_cell reports back if a variable is set or not + * via the returnvalue and we unset it or even the parent if is was not set. + */ + $parent_isset = isset($content[$regs[1]]); + + if ($readonly || !$this->process_show_cell($cell,$name,$c,$r, + $readonlys[$regs[1]][$regs[2]],$content[$regs[1]][$regs[2]])) + { + if (!$parent_isset) + { + unset($content[$regs[1]]); + } + else + { + unset($content[$regs[1]][$regs[2]]); + } + } + } + else + { + if ($readonly || !$this->process_show_cell($cell,$name,$c,$r, + $readonlys[$idx_cname],$content[$idx_cname])) + { + unset($content[$idx_cname]); + } + } + } + } + if ($this->debug >= 2 || $this->debug == $this->name && $this->name) + { + echo "

process_show($this->name) end: content ="; _debug_array($content); + } + } + + /*! + @function process_show_cell($cell,$name,$c,$r,$readonlys,&$value) + @abstract makes necessary adjustments on $value eTemplate / form gots submitted + @discussion This is only an internal function, dont call it direct use only exec + @discussion process_show recursivly calls itself for the included eTemplates. + @param $cell processed cell + @param $name expanded name of cell + @param $c,$r col,row index + @param $readonlys readonlys-array to pass on for templates + @param &$value value to change + @returns if $value is set + */ + function process_show_cell($cell,$name,$c,$r,$readonlys,&$value) + { + if (is_array($cell['type'])) + { + $cell['type'] = $cell['type'][0]; + } + if ($this->debug >= 3 || $this->debug == $this->name || $this->debug == $cell['type']) + { + echo "

process_show_cell(c=$c, r=$r, name='$name',type='${cell['type']}) start: isset(value)=".(0+isset($value)).", value="; + if (is_array($value)) + { + _debug_array($value); + } + else + { + echo "'$value'

\n"; + } + } + switch ($cell['type']) + { + case 'int': + case 'float': + list($min,$max) = explode(',',$cell['size']); + /* + * TO DO: number- and range-check, if not enshured by java-script + */ + break; + case 'text': + case 'textarea': + if (isset($value)) + { + $value = stripslashes($value); + } + break; + case 'date': + if ($value['d']) + { + if (!$value['m']) + { + $value['m'] = date('m'); + } + if (!$value['Y']) + { + $value['Y'] = date('Y'); + } + if ($cell['size'] == '') + { + $value = mktime(0,0,0,$value['m'],$value['d'],$value['Y']); + } + else + { + for ($n = 0,$str = ''; $n < strlen($cell['size']); ++$n) + { + if (strstr('Ymd',$c = $cell['size'][$n])) + { + $str .= sprintf($c=='Y'?'%04d':'%02d',$value[$c]); + } + else + { + $str .= $c; + } + } + $value = $str; + } + } + else + { + $value = ''; + } + break; + case 'checkbox': + if (!isset($value)) // checkbox was not checked + { + $value = 0; // need to be reported too + } + break; + case 'template': + $templ = new etemplate($name); + $templ->process_show($value,$readonlys); + break; + case 'select': + case 'select-cat': + case 'select-account': + if (is_array($value)) + { + $value = count($value) <= 1 ? $value[0] : implode(',',$value); + } + break; + default: // do nothing, $value is correct as is + } + if ($this->debug >= 3 || $this->debug == $this->name || $this->debug == $cell['type']) + { + echo "

process_show_cell(name='$name',type='${cell['type']}) end: isset(value)=".(0+isset($value)).", value="; + if (is_array($value)) + { + _debug_array($value); + } + else + { + echo "'$value'

\n"; + } + } + return isset($value); + } + }; \ No newline at end of file