Location: PHPKode > scripts > HoinP > hoinp/hop_form_controller.php
<?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"

*/

?>
Return current item: HoinP