[Solar-svn] Revision 2818
pmjones at solarphp.com
pmjones at solarphp.com
Sat Oct 6 10:43:25 CDT 2007
Solar_Form
----------
* [CHG] In populate(), do not set values for "submit", "button", or "reset"
elements. This keeps values from previous submit buttons from overwriting
those on new forms.
* [BRK] Many BC breaks related to using the new Filter mechanism, where
sanitizing and validation are wrapped into the same class.
* [BRK] Element-specific messages are now keyed on 'invalid' (not 'feedback'),
although overall form-level messages are still called feedback.
* [ADD] New config key 'filter' is a Solar_Filter dependency injection.
* [BRK] Methods addFilter() and addFilters() are now related to the new
Solar_Filter class, and so handle both validation and sanitizing. Removed
addValid() method entirely.
* [BRK] Methods addInvalid() and addInvalids() to invalidation messages to one
or more elements. This replaces addFeedback(), which has been removed.
* [ADD] Methods setValue() and setValues() to more reliably set the value on
one or more elements manually.
* [CHG] Method validate() now uses the Solar_Filter filter-chain instead of a
custom internal sanitize/validate routine.
* [BRK] Renamed method values() to getValues(), to be more consistent with
coding standards.
* [FIX] Added default 'filters' attribute.
* [CHG] Method addInvald() no longer throws an exception when the element does not exist; instead, ignores it.
* [CHG] Method setValue() no longer throws an exception when the element does not exist; instead, ignores it.
Copied: trunk/Solar/Form/Load/Model.php (from rev 2801, branches/orm/Solar/Form/Load/Model.php)
===================================================================
--- trunk/Solar/Form/Load/Model.php (rev 0)
+++ trunk/Solar/Form/Load/Model.php 2007-10-06 15:43:25 UTC (rev 2818)
@@ -0,0 +1,256 @@
+<?php
+/**
+ *
+ * Class for loading form definitions from Solar_Sql_Model columns.
+ *
+ * @category Solar
+ *
+ * @package Solar_Form
+ *
+ * @author Paul M. Jones <pmjones at solarphp.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id: Table.php 2646 2007-07-29 15:49:30Z pmjones $
+ *
+ */
+
+/**
+ *
+ * Class for loading form definitions from Solar_Sql_Model columns.
+ *
+ * @category Solar
+ *
+ * @package Solar_Form
+ *
+ */
+class Solar_Form_Load_Model extends Solar_Base {
+
+ /**
+ *
+ * Loads Solar_Form elements based on Solar_Sql_Table columns.
+ *
+ * @param Solar_Sql_Table $model Load form elements from this model object.
+ *
+ * @param array $list Which model columns to load as form elements, default '*'.
+ *
+ * @param string $array_name Load the model columns as elements of this
+ * array-name within the form.
+ *
+ * @return Solar_Form|false Solar_Form object, or boolean false on error.
+ *
+ */
+ public function fetch($model, $list = '*', $array_name = null)
+ {
+ // make sure it's a Model
+ if (! $model instanceof Solar_Sql_Model) {
+ throw $this->_exception('ERR_NOT_MODEL_OBJECT');
+ }
+
+ // if not specified, set the array_name to the model name
+ if (empty($array_name)) {
+ $array_name = $model->model_name;
+ }
+
+ // table columns in the model
+ $cols = $model->table_cols;
+
+ // special condition: if looking for '*' columns,
+ // set the list to all the model columns.
+ if ($list == '*') {
+ $list = array_keys($cols);
+ } else {
+ settype($list, 'array');
+ }
+
+ // default values
+ $default = $model->fetchNew();
+
+ // loop through the list of requested columns and collect elements
+ $elements = array();
+ foreach ($list as $name => $info) {
+
+ // if $name is integer, $info is just a column name,
+ // and there is no added element info.
+ if (is_int($name)) {
+ $name = $info;
+ $info = array();
+ } else {
+ settype($info, 'array');
+ }
+
+ // is the column name in the model table?
+ if (empty($cols[$name])) {
+ // not in the table, fake some elements
+ $cols[$name] = array(
+ 'primary' => false,
+ 'require' => false,
+ 'type' => 'text',
+ 'size' => false,
+ );
+ }
+
+ // initial set of element info based on the model column
+ $base = array(
+ 'name' => $array_name . '[' . $name . ']',
+ 'type' => null,
+ 'label' => $model->locale(strtoupper("LABEL_$name")),
+ 'descr' => $model->locale(strtoupper("DESCR_$name")),
+ 'value' => $default[$name],
+ 'require' => $cols[$name]['require'],
+ 'disable' => $cols[$name]['primary'],
+ 'options' => array(),
+ 'attribs' => array(),
+ 'filters' => array(),
+ 'invalid' => array(),
+ );
+
+ $info = array_merge($base, $info);
+
+ // use the filters here
+ if (! empty($model->filters[$name])) {
+ $filters = $model->filters[$name];
+ } else {
+ $filters = array();
+ }
+
+ // make primary keys hidden and disabled
+ if ($cols[$name]['primary']) {
+ $info['type'] = 'hidden';
+ $info['disable'] = true;
+ }
+
+ // pick an element type based on the column type
+ if (empty($info['type'])) {
+ // base the element type on the column type.
+ switch ($cols[$name]['type']) {
+
+ case 'bool':
+ $info['type'] = 'checkbox';
+ break;
+
+ case 'clob':
+ $info['type'] = 'textarea';
+ break;
+
+ case 'date':
+ case 'time':
+ case 'timestamp':
+ $info['type'] = $cols[$name]['type'];
+ break;
+
+ default:
+
+ // make 'id' and '*_id' columns hidden
+ if ($name == 'id' || substr($name, -3) == '_id') {
+ $info['type'] = 'hidden';
+ }
+
+ // if there is a filter to 'validateInList' or 'validateInKeys',
+ // make this a select element.
+ foreach ($filters as $v) {
+ if ($v[0] == 'validateInKeys' || $v[0] == 'validateInList') {
+ $info['type'] = 'select';
+ break;
+ }
+ }
+
+ // if type is still empty, make it text.
+ if (empty($info['type'])) {
+ $info['type'] = 'text';
+ }
+ break;
+ }
+ }
+
+ // set up options for checkboxes if none specified
+ if ($info['type'] == 'checkbox' && empty($info['options'])) {
+ // look for 'validateInKeys' or 'validateInList' validation.
+ foreach ($filters as $v) {
+ if ($v[0] == 'validateInKeys' || $v[0] == 'validateInList') {
+ $info['options'] = $this->_autoOptions($v[0], $v[2]);
+ break;
+ }
+ }
+ // if still empty, set to 1,0
+ if (empty($info['options'])) {
+ $info['options'] = array(1,0);
+ }
+ }
+
+ // set up options for select and radio if none specified
+ if (($info['type'] == 'select' || $info['type'] == 'radio') &&
+ empty($info['options'])) {
+ // look for 'validateInKeys' or 'validateInList'
+ foreach ($filters as $v) {
+ if ($v[0] == 'validateInKeys' || $v[0] == 'validateInList') {
+ $info['options'] = $this->_autoOptions($v[0], $v[2]);
+ break;
+ }
+ }
+ }
+
+ // for text elements, set up maxlength if none specified
+ if ($info['type'] == 'text' &&
+ empty($info['attribs']['maxlength']) &&
+ $cols[$name]['size'] > 0) {
+ /** @todo Add +1 or +2 to 'size' for numeric types? */
+ $info['attribs']['maxlength'] = $cols[$name]['size'];
+ }
+
+ // if no label specified, set up based on element name
+ if (empty($info['label'])) {
+ $info['label'] = $info['name'];
+ }
+
+ // if there is a validateNotBlank filter, mark to require
+ foreach ($filters as $v) {
+ if ($v[0] == 'validateNotBlank') {
+ $info['require'] = true;
+ break;
+ }
+ }
+
+ // keep the element
+ $elements[$info['name']] = $info;
+ }
+
+ // done!
+ $result = array(
+ 'attribs' => array(),
+ 'elements' => $elements
+ );
+
+ return $result;
+ }
+
+ /**
+ *
+ * Builds an option list from validateInKeys and validateInList values.
+ *
+ * The 'validateInKeys' options are not changed.
+ *
+ * The 'validateInList' options are generally sequential, so the label
+ * and the value are made to be identical (based on the label).
+ *
+ * @param string $type The validation type, 'validateInKeys' or 'validateInList'.
+ *
+ * @param array $opts The options provided by the validation.
+ *
+ * @return array
+ *
+ */
+ protected function _autoOptions($type, $opts)
+ {
+ // leave the labels and values alone
+ if ($type == 'validateInKeys') {
+ return $opts;
+ }
+
+ // make the form display the labels as both labels and values
+ if ($type == 'validateInList') {
+ $vals = array_values($opts);
+ return array_combine($vals, $vals);
+ }
+ }
+}
Modified: trunk/Solar/Form/Load/Table.php
===================================================================
--- trunk/Solar/Form/Load/Table.php 2007-10-06 14:41:17 UTC (rev 2817)
+++ trunk/Solar/Form/Load/Table.php 2007-10-06 15:43:25 UTC (rev 2818)
@@ -94,7 +94,7 @@
'disable' => $table->col[$name]['primary'],
'options' => array(),
'attribs' => array(),
- 'feedback' => array(),
+ 'invalid' => array(),
'valid' => array(),
);
$info = array_merge($base, $info);
Modified: trunk/Solar/Form/Load/Xml.php
===================================================================
--- trunk/Solar/Form/Load/Xml.php 2007-10-06 14:41:17 UTC (rev 2817)
+++ trunk/Solar/Form/Load/Xml.php 2007-10-06 15:43:25 UTC (rev 2818)
@@ -41,7 +41,7 @@
'require',
'disable',
);
-
+
/**
*
* Loads a Solar_Form definition from an XML file.
@@ -63,11 +63,11 @@
$args = func_get_args();
$filename = array_shift($args);
$param = array_shift($args);
-
+
if (! file_exists($filename)) {
throw $this->_exception('ERR_FILE_NOT_FOUND');
}
-
+
// load the XML file data
$xml = simplexml_load_file($filename);
if (false === $xml) {
@@ -92,14 +92,14 @@
// ... otherwise, get element name and initialize array
$name = (string) $element['name'];
$elementInfo = array();
-
+
// Get element attributes
foreach ($this->elementAttribs as $attrib) {
if (isset($element[$attrib])) {
$elementInfo[$attrib] = (string) $element[$attrib];
}
}
-
+
// Get element label/description, if present
if (!empty($element->label)) {
$elementInfo['label'] = (string) $element->label;
@@ -107,7 +107,7 @@
if (!empty($element->descr)) {
$elementInfo['descr'] = (string) $element->descr;
}
-
+
// Get attribs and options
foreach (array('attribs', 'options') as $opt) {
if (!empty($element->$opt)) {
@@ -119,7 +119,7 @@
$elementInfo[$opt] = $info;
}
}
-
+
// Get element filters
if (! empty($element->filters)) {
$filters = array();
@@ -127,10 +127,10 @@
if (empty($filter['method'])) continue;
$method = (string) $filter['method'];
-
+
$params = array();
$tmpFilter = array($method);
-
+
// Were any arguments passed?
if (!empty($filter->params)) {
$params = $this->getParams($filter->params->param);
@@ -140,7 +140,7 @@
foreach ($params as $param) {
array_push($tmpFilter, $param);
}
-
+
// Add filter to element
$filters[] = $tmpFilter;
}
@@ -163,28 +163,28 @@
$params = array();
$tmpRule = array($method, $message);
-
+
// Were any arguments passed?
if (! empty($rule->args)) {
$params = $this->getParams($rule->args->arg);
}
-
+
// Add arguments to validation array
foreach ($params as $param) {
array_push($tmpRule, $param);
}
-
+
// Add validation to element
$validate[] = $tmpRule;
}
-
+
$elementInfo['valid'] = $validate;
}
// Add element to formElements array
$elements[$name] = $elementInfo;
}
-
+
return array(
'attribs' => array(),
'elements' => $elements
@@ -211,7 +211,7 @@
if (!empty($param['type'])) {
$argType = (string) $param['type'];
}
-
+
if ('array' == $argType) {
if (empty($param->item)) {
$param = (array) $param;
@@ -234,10 +234,10 @@
$param = (string) $param->item;
}
}
-
+
array_push($final, $param);
}
-
+
return $final;
}
}
Modified: trunk/Solar/Form.php
===================================================================
--- trunk/Solar/Form.php 2007-10-06 14:41:17 UTC (rev 2817)
+++ trunk/Solar/Form.php 2007-10-06 15:43:25 UTC (rev 2818)
@@ -9,7 +9,7 @@
*
* @author Paul M. Jones <pmjones at solarphp.com>
*
- * @author Contributions from Matthew Weier O'Phinney <mweierophinney at gmail.com>
+ * @author Matthew Weier O'Phinney <mweierophinney at gmail.com>
*
* @license http://opensource.org/licenses/bsd-license.php BSD
*
@@ -50,18 +50,19 @@
* : (string) The overall "failure" message when validating form
* input. Default is Solar locale key FAILURE_FORM.
*
+ * `filter`
+ * : (dependency) A Solar_Filter dependency injection; default is empty,
+ * which creates a standard Solar_Filter object on the fly.
+ *
* @var array
*
*/
protected $_Solar_Form = array(
'request' => 'request',
- 'attribs' => array(
- 'action' => null,
- 'method' => 'post',
- 'enctype' => 'multipart/form-data',
- ),
+ 'filter' => null,
'success' => null,
'failure' => null,
+ 'attribs' => array(),
);
/**
@@ -70,11 +71,25 @@
*
* @var bool Null if validation has not occurred yet, true if
* valid, false if not valid.
+ *
*/
protected $_status = null;
/**
*
+ * Default <form> tag attributes.
+ *
+ * @var array
+ *
+ */
+ protected $_default_attribs = array(
+ 'action' => null,
+ 'method' => 'post',
+ 'enctype' => 'multipart/form-data',
+ );
+
+ /**
+ *
* Attributes for the form tag itself.
*
* The `$attribs` array holds HTML attributes for the
@@ -93,8 +108,8 @@
* The array of elements in this form.
*
* The `$elements` array contains all elements in the form,
- * including their names, types, values, any feedback messages,
- * validation and filter callbacks, and so on.
+ * including their names, types, values, any invalidation messages,
+ * filter callbacks, and so on.
*
* In general, you should not try to set $elements yourself;
* instead, Solar_Form::setElement() and Solar_Form::setElements().
@@ -115,8 +130,8 @@
*
* Note that the $feedback property pertains to the form as a
* whole, not the individual elements. This is as opposed to
- * the 'feedback' key in each of the elements, which contains
- * feedback specific to that element.
+ * the 'invalid' key in each of the elements, which contains
+ * invalidation messages specific to that element.
*
* @var array
*
@@ -125,24 +140,15 @@
/**
*
- * The array of pre-filters for the form elements.
+ * The array of filters for the form elements.
*
* @var array
*
*/
- protected $_filter = array();
+ protected $_filters = array();
/**
*
- * The array of validations for the form elements.
- *
- * @var array
- *
- */
- protected $_valid = array();
-
- /**
- *
* Array of submitted values.
*
* Populated on the first call to [[_populate()]], which itself uses
@@ -175,13 +181,13 @@
* : (string) The default or selected value(s) for the element.
*
* `descr`
- * : (string) A longer description of the element, for example a tooltip
+ * : (string) A longer description of the element, such as a tooltip
* or help text.
*
* `status`
- * : (bool) Whether or not the particular elements has
- * passed or failed validation (true or false), or null if there
- * has been no attempt at validation.
+ * : (bool) Whether or not the particular element has passed or failed
+ * validation (true or false), or null if there has been no attempt at
+ * validation.
*
* `require`
* : (bool) Whether or not the element is required.
@@ -198,47 +204,38 @@
* : (array) Additional XHTML attributes for the element in the
* form (attribute => value).
*
- * `feedback`
- * : (array) An array of feedback messages for this element,
- * generally based on validation of previous user input.
+ * `invalid`
+ * : (array) An array of messages if the value is invalid.
*
* @var array
*
*/
- protected $_default = array(
- 'name' => null,
- 'type' => null,
- 'label' => null,
- 'descr' => null,
- 'value' => null,
- 'status' => null,
- 'require' => false,
- 'disable' => false,
- 'options' => array(),
- 'attribs' => array(),
- 'feedback' => array(),
+ protected $_default_element = array(
+ 'name' => null,
+ 'type' => null,
+ 'label' => null,
+ 'descr' => null,
+ 'value' => null,
+ 'status' => null,
+ 'require' => false,
+ 'disable' => false,
+ 'options' => array(),
+ 'attribs' => array(),
+ 'filters' => array(),
+ 'invalid' => array(),
);
/**
*
- * A Solar_Filter object for internal filtering needs.
+ * A Solar_Filter object for filtering form values.
*
* @var Solar_Filter
*
*/
- protected $_obj_filter;
+ protected $_filter;
/**
*
- * A Solar_Valid object for internal validation needs.
- *
- * @var Solar_Valid
- *
- */
- protected $_obj_valid;
-
- /**
- *
* Request environment object.
*
* @var Solar_Request
@@ -268,21 +265,24 @@
$this->_config['request']
);
- // make sure we have an action. normally we try not to change $_config
- // from what the user set, but in this case, we need $_config values
- // so that reset() works properly.
- if (empty($this->_config['attribs']['action'])) {
- $this->_config['attribs']['action'] = $this->_request->server('REQUEST_URI');
- }
+ // filter object
+ $this->_filter = Solar::dependency(
+ 'Solar_Filter',
+ $this->_config['filter']
+ );
- // retain setups, create validator/filter objects
- $this->attribs = array_merge(
- $this->_Solar_Form['attribs'],
+ // set the default action attribute
+ $action = $this->_request->server('REQUEST_URI');
+ $this->_default_attribs['action'] = $action;
+
+ // now merge attribute configs
+ $this->_config['attribs'] = array_merge(
+ $this->_default_attribs,
$this->_config['attribs']
);
- $this->_obj_filter = Solar::factory('Solar_Filter');
- $this->_obj_valid = Solar::factory('Solar_Valid');
+ // reset all the properties based on config now
+ $this->reset();
}
// -----------------------------------------------------------------
@@ -299,7 +299,7 @@
* $info['name'].
*
* @param array $info Element information using the same keys as
- * in Solar_Form::$_default.
+ * in Solar_Form::$_default_element.
*
* @param string $array Rename the element as a key in this array.
*
@@ -312,48 +312,22 @@
$name = $this->_prepareName($name, $array);
// prepare the element info
- $info = array_merge($this->_default, $info);
+ $info = array_merge($this->_default_element, $info);
// forcibly cast each of the keys into the elements array
$this->elements[$name] = array (
- 'name' => $name,
- 'type' => (string) $info['type'],
- 'label' => (string) $info['label'],
- 'value' => $info['value'], // mixed
- 'descr' => (string) $info['descr'],
- 'require' => (bool) $info['require'],
- 'disable' => (bool) $info['disable'],
- 'options' => (array) $info['options'],
- 'attribs' => (array) $info['attribs'],
- 'feedback' => (array) $info['feedback'],
+ 'name' => (string) $name,
+ 'type' => (string) $info['type'],
+ 'label' => (string) $info['label'],
+ 'value' => $info['value'], // mixed
+ 'descr' => (string) $info['descr'],
+ 'require' => (bool) $info['require'],
+ 'disable' => (bool) $info['disable'],
+ 'options' => (array) $info['options'],
+ 'attribs' => (array) $info['attribs'],
+ 'filters' => (array) $info['filters'],
+ 'invalid' => (array) $info['invalid'],
);
-
- // add filters
- if (array_key_exists('filter', $info)) {
- foreach ( (array) $info['filter'] as $args) {
- $this->_filter[$name][] = $args;
- }
- }
-
- // add validations
- if (array_key_exists('valid', $info)) {
-
- foreach ( (array) $info['valid'] as $args) {
-
- // make sure $args is an array
- settype($args, 'array');
-
- // shift the name onto the top of the args
- array_unshift($args, $name);
-
- // add the validation to the element
- call_user_func_array(
- array($this, 'addValid'),
- $args
- );
-
- }
- }
}
/**
@@ -361,7 +335,7 @@
* Sets multiple elements in the form. Appends if they do not exist.
*
* @param array $list Element information as array(name => info), where
- * each info value is an array like Solar_Form::$_default.
+ * each info value is an array like Solar_Form::$_default_element.
*
* @param string $array Rename each element as a key in this array.
*
@@ -406,95 +380,103 @@
/**
*
- * Adds a Solar_Filter method callback for an element.
+ * Adds one filter to an element.
*
- * All pre-filters are applied via
- * Solar_Filter::multiple() and should conform to the
- * specifications for that method.
+ * @param string $name The element name.
*
- * All parameters after $method are treated as added parameters
- * for the Solar_Filter method call.
+ * @param array|string $spec The filter specification; either a
+ * Solar_Filter method name (string), or an array where the first element
+ * is a method name and remaining elements are parameters to that method.
*
+ * @return void
+ *
+ */
+ public function addFilter($name, $spec, $array)
+ {
+ // make sure the element exists
+ $name = $this->_prepareName($name, $array);
+ if (empty($this->elements[$name])) {
+ throw $this->_exception('ERR_NO_SUCH_ELEMENT', array(
+ 'name' => $name,
+ ));
+ }
+
+ // add the filter
+ $this->elements[$name]['filters'][] = (array) $spec;
+ }
+
+ /**
+ *
+ * Adds many filters to one element.
+ *
* @param string $name The element name.
*
- * @param string $method Solar_Filter method or PHP function to use
- * for filtering.
+ * @param array|string $spec The filter specification; either a
+ * Solar_Filter method name (string), or an array where the first element
+ * is a method name and remaining elements are parameters to that method.
*
+ * @param string $array Rename each element as a key in this array.
+ *
* @return void
*
*/
- public function addFilter($name, $method)
+ public function addFilters($name, $list, $array)
{
- // Get the arguments, drop the element name
- $args = func_get_args();
- array_shift($args);
-
- $this->_filter[$name][] = $args;
+ foreach ((array) $list as $spec) {
+ $this->addFilter($name, $spec, $array);
+ }
}
/**
*
- * Adds a Solar_Valid method callback as a validation for an element.
+ * Adds one or more invalid message to an element, sets the element status
+ * to false (invalid), and sets the form status to false (invalid).
*
* @param string $name The element name.
*
- * @param string $method The Solar_Valid callback method.
+ * @param string|array $spec The invalidation message(s).
*
- * @param string $message The feedback message to use if validation fails.
+ * @param string $array Rename each element as a key in this array.
*
* @return void
*
*/
- public function addValid($name, $method, $message = null)
+ public function addInvalid($name, $spec, $array = null)
{
- // get the arguments, drop the element name
- $args = func_get_args();
- $name = array_shift($args);
+ // make sure the element exists
+ $name = $this->_prepareName($name, $array);
+ if (! empty($this->elements[$name])) {
+ // add the messages
+ foreach ((array) $spec as $text) {
+ $this->elements[$name]['invalid'][] = $text;
+ }
- // add a default validation message (args[0] is the method,
- // args[1] is the message)
- if (empty($args[1]) || trim($args[1]) == '') {
-
- // see if we have an method-specific validation message
- $key = 'VALID_' . strtoupper($method);
- $args[1] = $this->locale($key);
-
- // if the message is the same as the key,
- // there was no method-specific validation
- // message. revert to the generic default.
- if ($key == $args[1]) {
- $args[1] = $this->locale('ERR_INVALID');
- }
+ // mark the status of the element, and of the form
+ $this->elements[$name]['status'] = false;
+ $this->_status = false;
}
-
- // add to the validation array
- $this->_valid[$name][] = $args;
}
/**
*
- * Adds multiple feedback messages to elements.
+ * Adds invalidation messages to multiple elements, sets their status to
+ * false (invalid) and sets the form status to false (invalid).
*
- * @param array $list An associative array where the key is an element
- * name and the value is a string or sequential array of feedback messages.
+ * @param array $list An array where the key is the element name, and the
+ * value is a string or array of invalidation messages for that element.
*
* @param string $array Rename each element as a key in this array.
*
* @return void
*
*/
- public function addFeedback($list, $array = null)
+ public function addInvalids($list, $array = null)
{
- foreach ($list as $name => $feedback) {
- $name = $this->_prepareName($name, $array);
- settype($feedback, 'array');
- foreach ($feedback as $text) {
- $this->elements[$name]['feedback'][] = $text;
- }
+ foreach ((array) $list as $name => $spec) {
+ $this->addInvalid($name, $spec, $array);
}
}
-
// -----------------------------------------------------------------
//
// Value-management methods
@@ -503,8 +485,61 @@
/**
*
- * Populates form elements with specified values.
+ * Manually set the value of one element.
*
+ * Note that this is subtly different from [[populate()]]. This method
+ * takes full name of the element, whereas populate() takes a "natural"
+ * hierarchical array like $_POST.
+ *
+ * @param string $name The element name.
+ *
+ * @param mixes $value Set the element to this value.
+ *
+ * @param string $array Rename the element as a key in this array.
+ *
+ * @return void
+ *
+ */
+ public function setValue($name, $value, $array = null)
+ {
+ // make sure the element exists
+ $name = $this->_prepareName($name, $array);
+ if (! empty($this->elements[$name])) {
+ $this->elements[$name]['value'] = $value;
+ }
+
+ }
+
+ /**
+ *
+ * Manually set the value of several elements.
+ *
+ * Note that this is subtly different from [[populate()]]. This method
+ * takes a flat array where the full name of the element is the key,
+ * whereas populate() takes a "natural" hierarchical array like $_POST.
+ *
+ * @param array $data An associative array where the key is the element
+ * name and the value is the element value to set.
+ *
+ * @param string $array Rename each element as a key in this array.
+ *
+ * @return void
+ *
+ * @throws Solar_Form_Exception_NoSuchElement when the named element does
+ * not exist in the form.
+ *
+ */
+ public function setValues($data, $array = null)
+ {
+ foreach ((array) $data as $name => $value) {
+ $this->setValue($name, $value, $array);
+ }
+ }
+
+ /**
+ *
+ * Automatically populates form elements with specified values.
+ *
* @param array $submit The source data array for populating form
* values as array(name => value); if null, will populate from POST
* or GET vars as determined from the Solar_Form::$attribs['method']
@@ -540,19 +575,17 @@
/**
*
- * Performs filtering and validation on each form element.
+ * Applies the filter chain to the form element values; in particular,
+ * checks validation and updates the 'invalid' keys for each element that
+ * fails.
*
- * Updates the feedback keys for each element that fails validation.
- * Values are either pulled from the submitted form or from the array
- * passed in $submit.
- *
* This method cycles through each element in the form, where it ...
*
* 1. Applies the filters to populated user input for the element,
*
* 2. Validates the filtered value against the validation rules for the element,
*
- * 3. Adds feedback messages to the element if it does not pass validation.
+ * 3. Adds invalidation messages to the element if it does not pass validation.
*
* If all populated values pass validation, the method returns boolean
* true, indicating the form as a whole it valid; if even one validation on
@@ -566,74 +599,46 @@
* please see those pages for more information on how to add filters and
* validation to an element.
*
- * @param array $submit The source data array for populating form
- * values as array(name => info); if null, will populate from POST
- * or GET vars as determined from the 'method' attribute.
- *
* @return bool True if all elements are valid, false if not.
*
*/
- public function validate($submit = null)
+ public function validate()
{
- // Populate the form values.
- if (empty($this->_submitted)) {
- $this->populate($submit);
- }
-
- // Loop through each element to filter
- foreach ($this->_filter as $name => $filters) {
- $value = $this->elements[$name]['value'];
- $this->elements[$name]['value'] = $this->_obj_filter->multiple(
- $value, $filters
- );
- }
-
- $validated = true;
+ // reset the filter chain so we can rebuild it
+ $this->_filter->resetChain();
- // loop through each element to be validated
- foreach ($this->_valid as $name => $list) {
+ // build the filter chain and data values. note that the foreach()
+ // loop uses an info **reference**, not a copy.
+ $data = array();
+ foreach ($this->elements as $name => &$info) {
+ // keep a **reference** to the data (not a copy)
+ $data[$name] = &$info['value'];
- // loop through each validation for the element
- foreach ($list as $args) {
-
- // the name of the Solar_Valid method
- $method = array_shift($args);
-
- // the text of the error message
- $feedback = array_shift($args);
-
- // config is now the remaining arguments,
- // put the value on top of it.
- array_unshift($args, $this->elements[$name]['value']);
-
- // call the appropriate Solar_Valid method.
- $result = call_user_func_array(
- array($this->_obj_valid, $method),
- $args
- );
-
- // was it valid?
- if (! $result) {
- // no, add the feedback message
- $validated = false;
- $this->elements[$name]['feedback'][] = $feedback;
- $this->elements[$name]['status'] = false;
- } else {
- $this->elements[$name]['status'] = true;
- }
-
- } // inner loop of validations
+ // set the filters and require-flag, reference not needed
+ $this->_filter->addChainFilters($name, $info['filters']);
+ $this->_filter->setChainRequire($name, $info['require']);
- } // outer loop of elements
+ }
- if ($validated) {
+ // apply the filter chain to the data, which will modify the
+ // element data in place because of the references
+ $this->_status = $this->_filter->applyChain($data);
+
+ // set the main feedback message
+ if ($this->_status) {
$this->feedback = array($this->_config['success']);
} else {
$this->feedback = array($this->_config['failure']);
}
- $this->_status = $validated;
- return $validated;
+ // retain any invalidation messages
+ $invalid = $this->_filter->getChainInvalid();
+ foreach ((array) $invalid as $key => $val) {
+ $this->addInvalid($key, $val);
+ }
+
+ // done!
+ return $this->_status;
}
/**
@@ -647,7 +652,7 @@
* @return array An associative array of element values.
*
*/
- public function values($key = null)
+ public function getValues($key = null)
{
$values = array();
foreach ($this->elements as $name => $elem) {
@@ -686,8 +691,7 @@
$this->attribs = $this->_config['attribs'];
$this->elements = array();
$this->feedback = null;
- $this->_filter = array();
- $this->_valid = array();
+ $this->_filters = array();
$this->_submitted = null;
}
More information about the Solar-svn
mailing list