Refactoring Helper/FormHelper to actually use dynamically generated name attributes; refactoring out extra parameter in FormHelper::radio(), per gwoo

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@5744 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2007-10-09 20:44:28 +00:00
parent d13b0323a9
commit 736ab28b0b
5 changed files with 140 additions and 67 deletions

View file

@ -124,7 +124,7 @@ class String extends Object {
* *
* @param multi-byte string $string * @param multi-byte string $string
* @return array * @return array
* @access publice * @access public
* @static * @static
*/ */
function utf8($string) { function utf8($string) {

View file

@ -314,8 +314,10 @@ class Helper extends Overloadable {
$parts = preg_split('/\/|\./', $tagValue); $parts = preg_split('/\/|\./', $tagValue);
$view->association = null; $view->association = null;
if (count($parts) == 1) { if (count($parts) == 1) {
$view->field = $parts[0]; $view->field = $parts[0];
//} elseif (count($parts) == 2 && !ClassRegistry::isKeySet($parts[0]) && !ClassRegistry::isKeySet($parts[0])) {
} elseif (count($parts) == 2 && is_numeric($parts[0])) { } elseif (count($parts) == 2 && is_numeric($parts[0])) {
$view->modelId = $parts[0]; $view->modelId = $parts[0];
$view->field = $parts[1]; $view->field = $parts[1];
@ -422,7 +424,6 @@ class Helper extends Overloadable {
} }
switch($field) { switch($field) {
case 'method':
case '_method': case '_method':
$name = $field; $name = $field;
break; break;
@ -506,7 +507,6 @@ class Helper extends Overloadable {
if ($this->tagIsInvalid()) { if ($this->tagIsInvalid()) {
$options = $this->addClass($options, 'form-error'); $options = $this->addClass($options, 'form-error');
} }
unset($options['name']); // Temporary
return $options; return $options;
} }
/** /**

View file

@ -36,13 +36,13 @@
*/ */
class FormHelper extends AppHelper { class FormHelper extends AppHelper {
/** /**
* Enter description here... * Other helpers used by FormHelper
* *
* @var unknown_type * @var unknown_type
*/ */
var $helpers = array('Html'); var $helpers = array('Html');
/** /**
* holds the fields array('field_name'=>'type'), sizes array('field_name'=>'size'), * Holds the fields array('field_name' => 'type'), sizes array('field_name' => 'size'),
* primaryKey and validates array('field_name') * primaryKey and validates array('field_name')
* *
* @access public * @access public
@ -60,9 +60,15 @@ class FormHelper extends AppHelper {
/** /**
* Enter description here... * Enter description here...
* *
* @var unknown_type * @var array
*/ */
var $fields = array(); var $fields = array();
/**
* Defines the type of form being created. Set by FormHelper::create().
*
* @var string
*/
var $requestType = null;
/** /**
* Returns an HTML FORM element. * Returns an HTML FORM element.
* *
@ -188,6 +194,7 @@ class FormHelper extends AppHelper {
$htmlAttributes['method'] = 'post'; $htmlAttributes['method'] = 'post';
break; break;
} }
$this->requestType = low($options['type']);
$htmlAttributes['action'] = $this->url($options['action']); $htmlAttributes['action'] = $this->url($options['action']);
unset($options['type'], $options['action']); unset($options['type'], $options['action']);
@ -211,10 +218,11 @@ class FormHelper extends AppHelper {
return $this->output(sprintf($this->Html->tags['form'], $this->Html->_parseAttributes($htmlAttributes, null, ''))) . $append; return $this->output(sprintf($this->Html->tags['form'], $this->Html->_parseAttributes($htmlAttributes, null, ''))) . $append;
} }
/** /**
* Closes an HTML form. * Closes an HTML form, cleans up values set by FormHelper::create(), and writes hidden
* input fields where appropriate.
* *
* @access public
* @return string A closing FORM tag. * @return string A closing FORM tag.
* @access public
*/ */
function end($options = null) { function end($options = null) {
if (!empty($this->params['models'])) { if (!empty($this->params['models'])) {
@ -255,6 +263,14 @@ class FormHelper extends AppHelper {
$out .= $this->Html->tags['formend']; $out .= $this->Html->tags['formend'];
return $this->output($out); return $this->output($out);
} }
/**
* Generates a hidden field with a security hash based on the fields used in the form.
*
* @param array $fields The list of fields to use when generating the hash
* @return string A hidden input field with a security hash
* @access public
*/
function secure($fields) { function secure($fields) {
if (!empty($fields)) { if (!empty($fields)) {
$append = '<p style="display: inline; margin: 0px; padding: 0px;">'; $append = '<p style="display: inline; margin: 0px; padding: 0px;">';
@ -271,6 +287,14 @@ class FormHelper extends AppHelper {
} }
return null; return null;
} }
/**
* Generates a field list
*
* @param string $model Model name
* @param array $options Options
* @return void
* @access private
*/
function __secure($model = null, $options = null) { function __secure($model = null, $options = null) {
if (!$model) { if (!$model) {
$model = $this->model(); $model = $this->model();
@ -308,9 +332,9 @@ class FormHelper extends AppHelper {
/** /**
* Returns true if there is an error for the given field, otherwise false * Returns true if there is an error for the given field, otherwise false
* *
* @access public
* @param string $field This should be "Modelname.fieldname", "Modelname/fieldname" is deprecated * @param string $field This should be "Modelname.fieldname", "Modelname/fieldname" is deprecated
* @return bool If there are errors this method returns true, else false. * @return bool If there are errors this method returns true, else false.
* @access public
*/ */
function isFieldError($field) { function isFieldError($field) {
$this->setFormTag($field); $this->setFormTag($field);
@ -323,6 +347,7 @@ class FormHelper extends AppHelper {
* @param string $text Error message * @param string $text Error message
* @param array $options Rendering options for <div /> wrapper tag * @param array $options Rendering options for <div /> wrapper tag
* @return string If there are errors this method returns an error message, otherwise null. * @return string If there are errors this method returns an error message, otherwise null.
* @access public
*/ */
function error($field, $text = null, $options = array()) { function error($field, $text = null, $options = array()) {
$this->setFormTag($field); $this->setFormTag($field);
@ -722,36 +747,30 @@ class FormHelper extends AppHelper {
$options['value'] = $value; $options['value'] = $value;
} }
$output .= sprintf($this->Html->tags['checkbox'], $this->model(), $this->field(), $this->_parseAttributes($options, null, null, ' ')); $output .= sprintf($this->Html->tags['checkbox'], $options['name'], $this->_parseAttributes($options, array('name'), null, ' '));
return $this->output($output); return $this->output($output);
} }
/** /**
* Creates a set of radio widgets. * Creates a set of radio widgets.
* *
* @param string $fieldName Name of a field, like this "Modelname/fieldname" * @param string $fieldName Name of a field, like this "Modelname.fieldname"
* @param array $options Radio button options array * @param array $options Radio button options array.
* @param array $inbetween String that separates the radio buttons. * @param array $attributes Array of HTML attributes. Use the 'separator' key to
* @param array $attributes Array of HTML attributes. * define the string in between the radio buttons
* @return string * @return string
*/ */
function radio($fieldName, $options, $inbetween = null, $attributes = array()) { function radio($fieldName, $options = array(), $attributes = array()) {
$this->setFormTag($fieldName); $attributes = $this->__initInputField($fieldName, $attributes);
$attributes = $this->domId((array)$attributes);
$this->__secure(); $this->__secure();
if ($this->tagIsInvalid()) {
$attributes = $this->addClass($attributes, 'form-error');
}
if (isset($attributes['type'])) {
unset($attributes['type']);
}
if (isset($attributes['id'])) {
unset($attributes['id']);
}
$label = $this->field(); $label = $this->field();
$inbetween = null;
if (isset($attributes['separator'])) {
$inbetween = $attributes['separator'];
unset($attributes['separator']);
}
if (isset($attributes['label'])) { if (isset($attributes['label'])) {
$label = $attributes['label']; $label = $attributes['label'];
unset($attributes['label']); unset($attributes['label']);
@ -767,14 +786,14 @@ class FormHelper extends AppHelper {
if (isset($value) && $optValue == $value) { if (isset($value) && $optValue == $value) {
$optionsHere['checked'] = 'checked'; $optionsHere['checked'] = 'checked';
} }
$parsedOptions = $this->_parseAttributes(array_merge($attributes, $optionsHere), null, '', ' '); $parsedOptions = $this->_parseAttributes(array_merge($attributes, $optionsHere), array('name', 'type', 'id'), '', ' ');
$fieldName = $this->field() . '_'.Inflector::underscore($optValue); $fieldName = $this->field() . '_'.Inflector::underscore($optValue);
$tagName = Inflector::camelize($fieldName); $tagName = Inflector::camelize($fieldName);
if($label) { if($label) {
$optTitle = sprintf($this->Html->tags['label'], $tagName, null, $optTitle); $optTitle = sprintf($this->Html->tags['label'], $tagName, null, $optTitle);
} }
$out[] = sprintf($this->Html->tags['radio'], $this->model(), $this->field(), $tagName, $parsedOptions, $optTitle); $out[] = sprintf($this->Html->tags['radio'], $attributes['name'], $tagName, $parsedOptions, $optTitle);
$count++; $count++;
} }
@ -791,7 +810,7 @@ class FormHelper extends AppHelper {
function text($fieldName, $options = array()) { function text($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, am(array('type' => 'text'), $options)); $options = $this->__initInputField($fieldName, am(array('type' => 'text'), $options));
$this->__secure(); $this->__secure();
return $this->output(sprintf($this->Html->tags['input'], $this->model(), $this->field(), $this->_parseAttributes($options, null, null, ' '))); return $this->output(sprintf($this->Html->tags['input'], $options['name'], $this->_parseAttributes($options, array('name'), null, ' ')));
} }
/** /**
* Creates a password input widget. * Creates a password input widget.
@ -803,7 +822,7 @@ class FormHelper extends AppHelper {
function password($fieldName, $options = array()) { function password($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options); $options = $this->__initInputField($fieldName, $options);
$this->__secure(); $this->__secure();
return $this->output(sprintf($this->Html->tags['password'], $this->model(), $this->field(), $this->_parseAttributes($options, null, null, ' '))); return $this->output(sprintf($this->Html->tags['password'], $options['name'], $this->_parseAttributes($options, array('name'), null, ' ')));
} }
/** /**
* Creates a textarea widget. * Creates a textarea widget.
@ -815,14 +834,13 @@ class FormHelper extends AppHelper {
function textarea($fieldName, $options = array()) { function textarea($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options); $options = $this->__initInputField($fieldName, $options);
$this->__secure(); $this->__secure();
unset($options['type']);
$value = null; $value = null;
if (array_key_exists('value', $options)) { if (array_key_exists('value', $options)) {
$value = $options['value']; $value = $options['value'];
unset($options['value']); unset($options['value']);
} }
return $this->output(sprintf($this->Html->tags['textarea'], $this->model(), $this->field(), $this->_parseAttributes($options, null, ' '), $value)); return $this->output(sprintf($this->Html->tags['textarea'], $options['name'], $this->_parseAttributes($options, array('type', 'name'), ' '), $value));
} }
/** /**
* Creates a hidden input field. * Creates a hidden input field.
@ -835,21 +853,21 @@ class FormHelper extends AppHelper {
function hidden($fieldName, $options = array()) { function hidden($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options); $options = $this->__initInputField($fieldName, $options);
$model = $this->model(); $model = $this->model();
unset($options['class']); $value = '';
if (isset($this->params['_Token']) && !empty($this->params['_Token'])) { if (isset($this->params['_Token']) && !empty($this->params['_Token'])) {
$model = '_' . $model; $options['name'] = str_replace($model, '_' . $model, $options['name']);
} }
$value = '';
if (!empty($options['value']) || $options['value'] === '0') { if (!empty($options['value']) || $options['value'] === '0') {
$value = $options['value']; $value = $options['value'];
} }
$this->__secure($model, $value); $this->__secure($model, $value);
if (in_array($fieldName, array('_method', '_fields'))) { /*if (in_array($fieldName, array('_method', '_fields'))) {
$model = null; $model = null;
} }*/
return $this->output(sprintf($this->Html->tags['hidden'], $model, $this->field(), $this->_parseAttributes($options, null, '', ' '))); return $this->output(sprintf($this->Html->tags['hidden'], $options['name'], $this->_parseAttributes($options, array('name', 'class'), '', ' ')));
} }
/** /**
* Creates file input widget. * Creates file input widget.
@ -862,7 +880,7 @@ class FormHelper extends AppHelper {
function file($fieldName, $options = array()) { function file($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options); $options = $this->__initInputField($fieldName, $options);
$this->__secure(); $this->__secure();
return $this->output(sprintf($this->Html->tags['file'], $this->model(), $this->field(), $this->_parseAttributes($options, null, '', ' '))); return $this->output(sprintf($this->Html->tags['file'], $options['name'], $this->_parseAttributes($options, array('name'), '', ' ')));
} }
/** /**
* Creates a button tag. * Creates a button tag.
@ -971,13 +989,8 @@ class FormHelper extends AppHelper {
$escapeOptions = $attributes['escape']; $escapeOptions = $attributes['escape'];
unset($attributes['escape']); unset($attributes['escape']);
} }
$attributes = $this->__initInputField($fieldName, $attributes);
$this->setFormTag($fieldName);
$attributes = $this->domId((array)$attributes);
if ($this->tagIsInvalid()) {
$attributes = $this->addClass($attributes, 'form-error');
}
if (is_string($options) && isset($this->__options[$options])) { if (is_string($options) && isset($this->__options[$options])) {
$options = $this->__generateOptions($options); $options = $this->__generateOptions($options);
} elseif (!is_array($options)) { } elseif (!is_array($options)) {
@ -992,7 +1005,7 @@ class FormHelper extends AppHelper {
} }
if (!isset($selected)) { if (!isset($selected)) {
$selected = $this->value($fieldName); $selected = $attributes['value'];
} }
if (isset($attributes) && array_key_exists('multiple', $attributes)) { if (isset($attributes) && array_key_exists('multiple', $attributes)) {
@ -1001,7 +1014,7 @@ class FormHelper extends AppHelper {
$tag = $this->Html->tags['selectstart']; $tag = $this->Html->tags['selectstart'];
$this->__secure(); $this->__secure();
} }
$select[] = sprintf($tag, $this->model(), $this->field(), $this->_parseAttributes($attributes)); $select[] = sprintf($tag, $attributes['name'], $this->_parseAttributes($attributes, array('name', 'value')));
if ($showEmpty !== null && $showEmpty !== false && !(empty($showEmpty) && (isset($attributes) && array_key_exists('multiple', $attributes)))) { if ($showEmpty !== null && $showEmpty !== false && !(empty($showEmpty) && (isset($attributes) && array_key_exists('multiple', $attributes)))) {
if ($showEmpty === true) { if ($showEmpty === true) {
@ -1290,6 +1303,40 @@ class FormHelper extends AppHelper {
} }
return $opt; return $opt;
} }
/**
* Gets the input field name for the current tag
*
* @param array $options
* @param string $key
* @return array
*/
function __name($options = array(), $field = null, $key = 'name') {
if ($this->requestType == 'get') {
if ($options === null) {
$options = array();
} elseif (is_string($options)) {
$field = $options;
$options = 0;
}
if (!empty($field)) {
$this->setFormTag($field);
}
if (is_array($options) && isset($options[$key])) {
return $options;
}
$name = $this->field();
if (is_array($options)) {
$options[$key] = $name;
return $options;
} else {
return $name;
}
}
return parent::__name($options, $field, $key);
}
/** /**
* Returns an array of formatted OPTION/OPTGROUP elements * Returns an array of formatted OPTION/OPTGROUP elements
* *

View file

@ -50,21 +50,21 @@ class HtmlHelper extends AppHelper {
'mailto' => '<a href="mailto:%s" %s>%s</a>', 'mailto' => '<a href="mailto:%s" %s>%s</a>',
'form' => '<form %s>', 'form' => '<form %s>',
'formend' => '</form>', 'formend' => '</form>',
'input' => '<input name="data[%s][%s]" %s/>', 'input' => '<input name="%s" %s/>',
'textarea' => '<textarea name="data[%s][%s]" %s>%s</textarea>', 'textarea' => '<textarea name="%s" %s>%s</textarea>',
'hidden' => '<input type="hidden" name="data[%s][%s]" %s/>', 'hidden' => '<input type="hidden" name="%s" %s/>',
'textarea' => '<textarea name="data[%s][%s]" %s>%s</textarea>', 'textarea' => '<textarea name="%s" %s>%s</textarea>',
'checkbox' => '<input type="checkbox" name="data[%s][%s]" %s/>', 'checkbox' => '<input type="checkbox" name="%s" %s/>',
'radio' => '<input type="radio" name="data[%s][%s]" id="%s" %s />%s', 'radio' => '<input type="radio" name="%s" id="%s" %s />%s',
'selectstart' => '<select name="data[%s][%s]"%s>', 'selectstart' => '<select name="%s"%s>',
'selectmultiplestart' => '<select name="data[%s][%s][]"%s>', 'selectmultiplestart' => '<select name="%s[]"%s>',
'selectempty' => '<option value=""%s>&nbsp;</option>', 'selectempty' => '<option value=""%s>&nbsp;</option>',
'selectoption' => '<option value="%s"%s>%s</option>', 'selectoption' => '<option value="%s"%s>%s</option>',
'selectend' => '</select>', 'selectend' => '</select>',
'optiongroup' => '<optgroup label="%s"%s>', 'optiongroup' => '<optgroup label="%s"%s>',
'optiongroupend' => '</optgroup>', 'optiongroupend' => '</optgroup>',
'password' => '<input type="password" name="data[%s][%s]" %s/>', 'password' => '<input type="password" name="%s" %s/>',
'file' => '<input type="file" name="data[%s][%s]" %s/>', 'file' => '<input type="file" name="%s" %s/>',
'file_no_model' => '<input type="file" name="%s" %s/>', 'file_no_model' => '<input type="file" name="%s" %s/>',
'submit' => '<input type="submit" %s/>', 'submit' => '<input type="submit" %s/>',
'submitimage' => '<input type="image" src="%s" %s/>', 'submitimage' => '<input type="image" src="%s" %s/>',

View file

@ -479,11 +479,14 @@ class FormHelperTest extends CakeTestCase {
$this->assertNoPattern('/id="ModelField"/', $result); $this->assertNoPattern('/id="ModelField"/', $result);
$this->assertNoPattern('/checked="checked"/', $result); $this->assertNoPattern('/checked="checked"/', $result);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), null, array('value' => '1')); $this->assertPattern('/^<fieldset><legend>field<\/legend>(<input[^<>]+><label[^<>]+>option [AB]<\/label>)+<\/fieldset>$/', $result);
$this->assertPattern('/(<input[^<>]+name="data\[Model\]\[field\]"[^<>]+>.+){2}/', $result);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '1'));
$this->assertPattern('/id="Field1".*checked="checked"/', $result); $this->assertPattern('/id="Field1".*checked="checked"/', $result);
$this->assertPattern('/id="Field0"/', $result); $this->assertPattern('/id="Field0"/', $result);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), null, array('value' => '0')); $result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0'));
$this->assertPattern('/id="Field1"/', $result); $this->assertPattern('/id="Field1"/', $result);
$this->assertPattern('/id="Field0".*checked="checked"/', $result); $this->assertPattern('/id="Field0".*checked="checked"/', $result);
} }
@ -823,6 +826,29 @@ class FormHelperTest extends CakeTestCase {
$this->assertNoPattern('/^<form[^<>]+[^method|action]=[^<>]*>/', $result); $this->assertNoPattern('/^<form[^<>]+[^method|action]=[^<>]*>/', $result);
} }
function testGetFormCreate() {
$result = $this->Form->create('Contact', array('type' => 'get'));
$this->assertPattern('/^<form [^<>]+>/', $result);
$this->assertPattern('/\s+id="ContactAddForm"/', $result);
$this->assertPattern('/\s+method="get"/', $result);
$this->assertPattern('/\s+action="\/contacts\/add\/"/', $result);
$this->assertNoPattern('/^<form[^<>]+[^method|action|id]=[^<>]*>/', $result);
$result = $this->Form->text('Contact.name');
$this->assertPattern('/^<input[^<>]+name="name"[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+type="text"[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+value=""[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+id="ContactName"[^<>]+\/>$/', $result);
$this->assertNoPattern('/<input[^<>]+[^id|name|type|value]=[^<>]*>$/', $result);
$result = $this->Form->password('password');
$this->assertPattern('/^<input[^<>]+name="password"[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+type="password"[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+value=""[^<>]+\/>$/', $result);
$this->assertPattern('/^<input[^<>]+id="ContactPassword"[^<>]+\/>$/', $result);
$this->assertNoPattern('/<input[^<>]+[^id|name|type|value]=[^<>]*>$/', $result);
}
function testFormMagicInput() { function testFormMagicInput() {
$result = $this->Form->create('Contact'); $result = $this->Form->create('Contact');
$this->assertPattern('/^<form\s+id="ContactAddForm"\s+method="post"\s+action="\/contacts\/add\/"\s*>$/', $result); $this->assertPattern('/^<form\s+id="ContactAddForm"\s+method="post"\s+action="\/contacts\/add\/"\s*>$/', $result);