<?php
/*
«Copyright 2007 Max Barel hide@address.com»
Release : 0.4 ($Rev: 49 $)
$Date: 2007-09-09 19:50:12 +0200 (Dim, 09 sep 2007) $
This file is part of HoP.
HoP is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
HoP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with HoP; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class Hop_form_controller
{
protected $controls = array(); //array of unstantiation functions
public $trigger = null; //value of trigger control
function __construct($definition = array()) {
// definition array must be of the form: array(
// array('id', "input(\$id)->set_type('text')", 'value'),
// array('ok', "input(\$id)->set_type('submit')", 'Submit data')
// )
// the second parameter is the hop function to instantiate the hop_element $id will be substituted at intantiation time
foreach ($definition as $c) {
$this->add_control($c);
}
}
public function add_control($cont_def = array()) {
if ($cont_def) {
$cont_def[] = null; $cont_def[] = null; // in case not all parameters have been specified
$this->controls[$cont_def[0]] = $cont_def[1]; //$this->controls['id'] = "function"
$this->{$cont_def[0]} = $cont_def[2]; // $this->control_id = control_value
}
return $this;
}
public function remove_control($id) {
//remove a control, given its id. This function must be used BEFORE the HoP elements are instantiated. It will NOT remove an already instantiated control.
unset($this->controls[$id]);
unset($this->$id);
return $this;
}
public function values_from_request($trigger , &$mode = null) { //$_REQUEST, $_POST, $_GET
if (!isset($mode)) $mode =& $_REQUEST;
$this->trigger = isset($mode[$trigger]);
if ($this->trigger) {
$this->trigger = $mode[$trigger];
foreach ($this->controls as $id => $f) $this->$id = (isset($mode[$id]) ? $mode[$id] : null);
}
return $this;
}
// public function trigger() {
// return $this->trigger;
// }
//
public function values_from_data($obj_or_array) {
if (is_array($obj_or_array)) $obj_or_array = (object) $obj_or_array;
foreach ($this->controls as $id => $f) $this->$id = (isset($obj_or_array->$id) ? $obj_or_array->$id : null);
return $this;
}
public function values_to_data(& $obj_or_array) {
foreach ($obj_or_array as $id => $val)
if (isset($this->$id)) {
if (is_array($obj_or_array)) $obj_or_array[$id] = $this->$id;
elseif ((is_object($obj_or_array))) $obj_or_array->$id = $this->$id;
}
return $this;
}
public function values($reg_exp = null, $def = null) {
foreach ($this->controls as $id => $f) {
if (is_null($reg_exp) or preg_match($reg_exp, $id)) $values[$id] = (isset($this->$id) ? $this->$id : $def);
}
return $values;
}
public function map($ho, $id) {
// map the control value to the existing hop_element oject
switch ($ho->type) {
case 'input' :
switch ($ho->attributes->type) {
case 'checkbox':
if ($this->$id == $ho->get_value()) $ho->set_checked('checked');
else $ho->remove_checked();
break;
case 'radio':
if ($this->{$ho->get_name()} == $ho->get_value()) $ho->set_checked('checked');
else $ho->remove_checked();
break;
case 'submit':
case 'reset':
case 'image':
case 'button':
break;
default:
if (isset($this->$id)) $ho->set_value($this->$id);
break;
}
break;
case 'select' :
$values = (is_array($this->$id) ? $this->$id : explode(',', $this->$id));
foreach($ho->content as $op) {
if (in_array($op->get_value(), $values)) $op->set_selected('selected');
else $op->remove_selected();
}
break;
case 'textarea' :
$ho->set_content($this->$id);
break;
default:
if (isset($this->$id)) $ho->set_value($this->$id);
break;
}
return $this;
}
public function hop($id) {
$hop = Hop::single(); //get the global hop factory
// instantiate and return the hop_element for this id
if ($f = $this->controls[$id]) eval ("\$hop_el = \$hop->$f;");
else throw new Exception("No instantiation function definition for $id");
if (!$hop_el->get_name()) $hop_el->set_name($id);
$this->map($hop_el, $id);
return $hop_el;
}
public function hop_all($wrapper = null, $f_container = null, $reg_exp = null) {
$hop = Hop::single(); //get the global hop factory
if ($f_container) eval("\$container = \$hop->$f_container;");
else $container = new Hop_node;
foreach ($this->controls as $id => $f) {
if ($f and (is_null($reg_exp) or preg_match($reg_exp, $id))) {
if ($wrapper) $container->add(eval("return \$hop->{$wrapper}->add(\$this->hop(\$id));"));
else $container->add($this->hop($id));
}
}
return $container;
}
public function map_global() {
foreach ($this->controls as $id => $f) {
if (isset(Hop_element::$pool->$id)) $this->map(Hop_element::$pool->$id, $id);
}
return $this;
}
}
/*
Example usage:
$fc = new Hop_form_controller( array(
array('txt1', "input()->set_type('text')", 'default text 1'), //object has automatic id, name is set to 'txt1' by controler
array('txt2', "input(\$id)->set_type('text')->set_value('default text 2')"), //object has id. Default value is set regardless of control value, null here
array('txt3', "input(\$id)->set_type('text')->auto_id()", 'default text 3'), //object has id, and it's propagated to html element. Default value is overwritten by values_from_* methods
array('check1', "input()->set_type('checkbox')->set_value(\$id)"),
array('check2', "input()->set_type('checkbox')->set_value(\$id)", 'check2'),
array('radio', null, 'rad1'),
array('rad1', "input()->set_type('radio')->set_value(\$id)->set_name('radio')"),
array('rad2', "input()->set_type('radio')->set_value(\$id)->set_name('radio')"),
array('ta1', "textarea(null, \$id)->auto_id()", 'default text area'), //beware, textarea in not an empty element so the id, if needed, must be the second parameter
array('sel1', "select()
->add(\$hop->option('option1')->set_value('op1'))
->add(\$hop->option('option2')->set_value('op2'))
->add(\$hop->option('option3')->set_value('op3'))", 'op2'),
array('defered_select', "pool('model_select')"), //This select wil be linked at instantiation time to a prgram built model.
array('clone_select', "clone_el(\$hop->pool('model_select'))", 'atelier'), //This select wil be cloned at instantiation time from a prgram built model. This is useful if you need several element with same base content. Attributes are cloned too, so they can differ.
array('ok', "input()->set_type('submit')->set_value('Send')") //declaration of button in controler has not utility beside grouping of controls
) );
$fc->values_from_request('ok'); // get values if submitted
$fc->values_from_data(array('radio'=>'rad2')); //set values from array (object is ok too and less memory consuming)
$ul = $fc->hop_all('li()', 'ul()'); // get form elements wrapped in a list
$fld = $fc->hop_all('p()', 'fieldset()'); // get form elements in a fieldset
$fc->txt3 = 'late modif'; // control value is modified after the hop object are generated
$fc->map_global(); //progagate the modif of every controls with id set
$fc->map($ul->content[0]->last(), 'txt3'); // set this control value to an arbitrary element, whith no id, accessed through its "path"
*/
?>