Re: Config plans was: Config recursion error

From: Date: Sun, 06 Oct 2002 14:59:44 +0000
Subject: Re: Config plans was: Config recursion error
References: 1  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-9884@lists.php.net to get a copy of this message
<mike@blueroot.net> wrote : > >> >> I choose (2) because it's more fun. > > for the record - i think you are mad ;) > > Can you explain briefly how you intend to implement the HTML forms? I > wrote a function that generates a Gtk Form from configuration variables, as > well as methods to extract the data when the form is submitted. > > I would like to do the same for this version of Config, but would like to > know how you are proceeding so that I can make a similar API. How do you > plan to detect what type of widget each directive should have? I proposed > a patch to Config-0.3 which stores datatypes along with the key/value pairs > (by using a special comment format). This could be extended to provide a > way to store multiple config values to be used in select boxes. Hi Mike, I have only made a few tests but that was with a too much complex configuration file (mnogosearch indexer.conf file) which has too many groups and config options to be displayed automatically in a HTML form. But I believe it can be done with easy config files. I use the same strategy as the one used by Charles Hagenbuch in the Horde project. Look here for a reference: http://marc.theaimsgroup.com/?l=pear-dev&m=102762342826471&w=2 I use a XML file to define what options are available and if the field is a boolean, a string, a string list or a number. Then I map these types with form elements. For instance, booleans are mapped to radio, strings to text, string lists to checkboxes... Then, I've made a subclass of QuickForm which parses the xml file and get the values from the conf file by calling the toArray() method of the given config_container object. I have had some problems with groups in QuickForm and didn't have the time to get the values back in a config_container. This makes my work useless for now (it took me only half a day, so it's ok). But I would like to have it to work one of these days. My next steps will be to think more about groups in QuickForm and the way we handle them (as opposed to thematic sections). Anyway, you will find attached the QuickForm subclass and the xml file. I haven't got a DTD yet but it could be interesting to have one so we can go in the same direction. Tell me what you think about all this. Thanks, Bertrand Mansion Mamasam

<?php // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2002 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Bertrand Mansion <bmansion@mamasam.com> | // +----------------------------------------------------------------------+ // // $Id: Form.php,v 1.7 2002/06/03 15:16:17 uw Exp $ // TODO : /* - Fix problem with grouped elements in QuickForm - Parse back the submitted values into a config_container */ require_once('HTML/QuickForm.php'); /** * Creates a form object from a xml file. * * @author Bertrand Mansion <bmansion@mamasam.com> * @package Config */ class HTML_QuickForm_Config extends HTML_QuickForm { var $contentData; var $selectOptions = array(); var $elementDescription = ''; var $elementAttributes = array(); var $elementRules = array(); var $elementName = ''; var $elementType = ''; var $append = ''; /** * Returns a form object build from the given xml file. * @param string xml filename (full path) * @return mixed object form on success, otherwise PEAR ERROR */ function HTML_QuickForm_Config($file, $formName='', $method='POST', $action='', $target='_self', $attributes=null) { $this->registeredRules['string'] = array('regex', '/[a-zA-Z0-9]*/'); $this->registeredRules['stringlist'] = array('regex', '/([a-zA-Z0-9]*\s*)*/'); $this->registeredRules['number'] = array('regex', '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/'); $this->registeredRules['boolean'] = array('regex', '/^(true|false|0|1)$/'); if (!($xml = implode('', file($file)))) { return PEAR::raiseError("Can't read xml file in Config_Form.", null, PEAR_ERROR_TRIGGER, E_USER_WARNING); } HTML_QuickForm::HTML_QuickForm($formName, $method, $action, $target, $attributes); $this->parse($xml); } // end constructor /** * Run the XML parser. * @param string XML content */ function parse($xml) { $parser = xml_parser_create(); xml_set_object($parser, $this); xml_set_element_handler($parser, 'startElement', 'endElement'); xml_set_character_data_handler($parser, 'cdata'); xml_parse($parser, $xml); xml_parser_free($parser); } // end func parse /* * XML Parser opening tag handler * * @param resource xmlparser * @param string tag name * @param array tag attributes */ function startElement($parser, $name, $attrs) { $name = strtolower($name); foreach ($attrs as $k => $v) { $k = strtolower($k); switch ($k) { case 'desc': // description $this->elementDescription = $v; break; case 'rule': // rules $this->elementRules[$v] = ''; break; case 'ruledata': // rules data $this->elementRules[count($this->elementRules)-1] = $v; break; case 'name': // element name $this->elementName = $v; break; case 'type': // config element type $this->elementType = $v; break; default: // standard html attribute $this->elementAttributes[$k] = $v; break; } } switch ($name) { case 'confsection': $this->addHeader($this->elementDescription); $this->elementDescription = ''; $this->append .= $this->elementName.'__'; break; case 'options': $this->selectOptions = array(); break; case 'option': $this->selectOptions[$this->elementDescription] = $this->elementDescription; break; default: break; } } // end func startElement /** * XML parser closing tag handler * @param resource xmlparser * @param string tag name */ function endElement($parser, $name) { static $currentSection; $name = strtolower($name); if (!isset($this->defaultValues[$this->elementName])) { } switch ($name) { case 'confsection': $append = explode('__', $this->append); array_pop($append); $this->append = implode('__', $append); break; case 'conftext': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = $this->contentData; } $this->addElement('text', $this->append.$this->elementName, $this->elementName.':', $this->elementAttributes); $this->elementDescription = ''; break; case 'confradio': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = preg_split('/[\s]+/', $this->contentData); } foreach ($this->selectOptions as $key => $value) { $radio[] =& HTML_QuickForm::createElement('radio', null, null, $value, $key); } $this->addElementGroup($radio, $this->elementName.':', $this->append.$this->elementName, '<br/>'); $this->selectOptions = array(); break; case 'confselect': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = preg_split('/[\s]+/', $this->contentData); } $this->addElement('select', $this->append.$this->elementName, $this->elementName.':', $this->selectOptions, $this->elementAttributes); $this->selectOptions = array(); break; case 'confmultiselect': if ($this->elementType == 'stringlist') { if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = preg_split('/[\s]+/', $this->contentData); } $this->addElement('select', $this->append.$this->elementName, $this->elementName.':', $this->selectOptions, $this->elementAttributes); $select =& $this->getElement($this->append.$this->elementName); $select->setMultiple(true); if ($this->elementType == 'stringlist') { $this->addElement('text', $this->append.$this->elementName.'[]', '... :', $this->elementAttributes); } } $this->selectOptions = array(); break; case 'confcheckbox': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $valArray = preg_split('/[\s]+/', $this->contentData); foreach ($valArray as $value) { $defArray[$value] = true; } $this->_defaultValues[$this->append.$this->elementName] = $defArray; } foreach ($this->selectOptions as $key => $value) { $checkbox[] =& HTML_QuickForm::createElement('checkbox', $key, null, $value); } $this->addElementGroup($checkbox, $this->elementName.':', $this->append.$this->elementName, '<br/>'); $this->selectOptions = array(); break; case 'confpassword': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = $this->contentData; } $this->addElement('password', $this->append.$this->elementName, $this->elementName.':', $this->elementAttributes); $this->elementDescription = ''; break; case 'conftextarea': if (!isset($this->defaultValues[$this->append.$this->elementName])) { $this->_defaultValues[$this->append.$this->elementName] = $this->contentData; } $this->addElement('textarea', $this->append.$this->elementName, $this->elementName.':', $this->elementAttributes); $this->elementDescription = ''; break; case 'option': $this->selectOptions[$this->elementDescription] = $this->contentData; break; default: break; } } // end func endElement /** * XML parser character data (= content) handler * @param resource xml parser * @param string cdata */ function cdata($parser, $cdata) { $this->contentData = htmlentities(trim($cdata)); } // end func cdata /** * Import values from the conf object * @param mixed conf object or conf array */ function importConf($conf) { if (is_a($conf, 'config_container')) { $conf = $conf->toArray(); } if (is_array($conf)) { $array = $this->_formizeArray($conf); foreach ($array as $key => $value) { $element = $this->getElement($key); $type = $element->getType($key); switch ($type) { case 'group' : switch ($element->getGroupType()) { case 'checkbox' : $valArray = preg_split('/[\s]+/', $value); foreach ($valArray as $val) { $defArray[$val] = true; } $this->setElementValue($key, $defArray); break; case 'radio' : $this->setElementValue($key, $value); break; } break; case 'select' : if ($element->getAttributes('multiple')) { $valArray = preg_split('/[\s]+/', $value); $this->setElementValue($key, $valArray); } else { $this->setElementValue($key, $value); } break; default : $this->setElementValue($key, $value); } } return true; } return PEAR::raiseError('HTML_QuickForm_Config::importConf only accept instances of Config_Container or conf arrays as arguments.', null, PEAR_ERROR_RETURN); } // end func importConf /** * Set the element value and override default values * * @param string $element Element name * @param string $value Element value * @since 2.0 * @access public * @return void */ function setElementValue($element, $value) { if (isset($this->_elementIndex[$element])) { $this->_elements[$this->_elementIndex[$element]]->setValue($value); } else { return PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true); } } // end func setElementValue /** * Converts a PHP multi-dimensional array into an array that is works with HTML. * i.e. if you pass it an array : * $foo = array ('input' => array(0 => 'bar')) * it will retun : * $foo['input[0]'] => 'bar' * which allows HTML arrays to be loaded correctly. * * @param array $array The multi-dimensional array to be converted * * @access private * @return array The converted array */ function _formizeArray($array) { //echo '<pre>'; var_dump($array); echo '</pre>'; if (is_array($array)) { foreach ($array as $key => $val) { if (is_array($val)) { foreach ($val as $key2 => $val2) { $array[$key.'__'.$key2] = $val2; } // now take out the array element $key_index = array_keys(array_keys($array), $key); array_splice($array, $key_index[0], 1); } } } return $array; } // end func _formizeArray function toConfArray() { } // end func toConfArray } // end class Config_Form ?>
« previous php.pear.dev (#9884) next »