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
* @return array
* @access publice
* @access public
* @static
*/
function utf8($string) {

View file

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

View file

@ -36,18 +36,18 @@
*/
class FormHelper extends AppHelper {
/**
* Enter description here...
* Other helpers used by FormHelper
*
* @var unknown_type
*/
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')
*
* @access public
*/
var $fieldset = array('fields'=> array(), 'sizes'=> array(), 'key'=> 'id', 'validates'=> array());
var $fieldset = array('fields' => array(), 'sizes' => array(), 'key' => 'id', 'validates' => array());
/**
* Enter description here...
*
@ -60,9 +60,15 @@ class FormHelper extends AppHelper {
/**
* Enter description here...
*
* @var unknown_type
* @var 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.
*
@ -188,6 +194,7 @@ class FormHelper extends AppHelper {
$htmlAttributes['method'] = 'post';
break;
}
$this->requestType = low($options['type']);
$htmlAttributes['action'] = $this->url($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;
}
/**
* 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.
* @access public
*/
function end($options = null) {
if (!empty($this->params['models'])) {
@ -255,6 +263,14 @@ class FormHelper extends AppHelper {
$out .= $this->Html->tags['formend'];
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) {
if (!empty($fields)) {
$append = '<p style="display: inline; margin: 0px; padding: 0px;">';
@ -271,6 +287,14 @@ class FormHelper extends AppHelper {
}
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) {
if (!$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
*
* @access public
* @param string $field This should be "Modelname.fieldname", "Modelname/fieldname" is deprecated
* @return bool If there are errors this method returns true, else false.
* @access public
*/
function isFieldError($field) {
$this->setFormTag($field);
@ -323,6 +347,7 @@ class FormHelper extends AppHelper {
* @param string $text Error message
* @param array $options Rendering options for <div /> wrapper tag
* @return string If there are errors this method returns an error message, otherwise null.
* @access public
*/
function error($field, $text = null, $options = array()) {
$this->setFormTag($field);
@ -722,36 +747,30 @@ class FormHelper extends AppHelper {
$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);
}
/**
* Creates a set of radio widgets.
*
* @param string $fieldName Name of a field, like this "Modelname/fieldname"
* @param array $options Radio button options array
* @param array $inbetween String that separates the radio buttons.
* @param array $attributes Array of HTML attributes.
* @param string $fieldName Name of a field, like this "Modelname.fieldname"
* @param array $options Radio button options array.
* @param array $attributes Array of HTML attributes. Use the 'separator' key to
* define the string in between the radio buttons
* @return string
*/
function radio($fieldName, $options, $inbetween = null, $attributes = array()) {
function radio($fieldName, $options = array(), $attributes = array()) {
$this->setFormTag($fieldName);
$attributes = $this->domId((array)$attributes);
$attributes = $this->__initInputField($fieldName, $attributes);
$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();
$inbetween = null;
if (isset($attributes['separator'])) {
$inbetween = $attributes['separator'];
unset($attributes['separator']);
}
if (isset($attributes['label'])) {
$label = $attributes['label'];
unset($attributes['label']);
@ -765,16 +784,16 @@ class FormHelper extends AppHelper {
$optionsHere = array('value' => $optValue);
if (isset($value) && $optValue == $value) {
$optionsHere['checked'] = 'checked';
}
$parsedOptions = $this->_parseAttributes(array_merge($attributes, $optionsHere), null, '', ' ');
$optionsHere['checked'] = 'checked';
}
$parsedOptions = $this->_parseAttributes(array_merge($attributes, $optionsHere), array('name', 'type', 'id'), '', ' ');
$fieldName = $this->field() . '_'.Inflector::underscore($optValue);
$tagName = Inflector::camelize($fieldName);
if($label) {
$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++;
}
@ -791,7 +810,7 @@ class FormHelper extends AppHelper {
function text($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, am(array('type' => 'text'), $options));
$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.
@ -803,7 +822,7 @@ class FormHelper extends AppHelper {
function password($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options);
$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.
@ -815,14 +834,13 @@ class FormHelper extends AppHelper {
function textarea($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options);
$this->__secure();
unset($options['type']);
$value = null;
if (array_key_exists('value', $options)) {
$value = $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.
@ -835,21 +853,21 @@ class FormHelper extends AppHelper {
function hidden($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options);
$model = $this->model();
unset($options['class']);
$value = '';
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') {
$value = $options['value'];
}
$this->__secure($model, $value);
if (in_array($fieldName, array('_method', '_fields'))) {
/*if (in_array($fieldName, array('_method', '_fields'))) {
$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.
@ -862,7 +880,7 @@ class FormHelper extends AppHelper {
function file($fieldName, $options = array()) {
$options = $this->__initInputField($fieldName, $options);
$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.
@ -971,13 +989,8 @@ class FormHelper extends AppHelper {
$escapeOptions = $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])) {
$options = $this->__generateOptions($options);
} elseif (!is_array($options)) {
@ -992,7 +1005,7 @@ class FormHelper extends AppHelper {
}
if (!isset($selected)) {
$selected = $this->value($fieldName);
$selected = $attributes['value'];
}
if (isset($attributes) && array_key_exists('multiple', $attributes)) {
@ -1001,7 +1014,7 @@ class FormHelper extends AppHelper {
$tag = $this->Html->tags['selectstart'];
$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 === true) {
@ -1290,6 +1303,40 @@ class FormHelper extends AppHelper {
}
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
*

View file

@ -50,21 +50,21 @@ class HtmlHelper extends AppHelper {
'mailto' => '<a href="mailto:%s" %s>%s</a>',
'form' => '<form %s>',
'formend' => '</form>',
'input' => '<input name="data[%s][%s]" %s/>',
'textarea' => '<textarea name="data[%s][%s]" %s>%s</textarea>',
'hidden' => '<input type="hidden" name="data[%s][%s]" %s/>',
'textarea' => '<textarea name="data[%s][%s]" %s>%s</textarea>',
'checkbox' => '<input type="checkbox" name="data[%s][%s]" %s/>',
'radio' => '<input type="radio" name="data[%s][%s]" id="%s" %s />%s',
'selectstart' => '<select name="data[%s][%s]"%s>',
'selectmultiplestart' => '<select name="data[%s][%s][]"%s>',
'input' => '<input name="%s" %s/>',
'textarea' => '<textarea name="%s" %s>%s</textarea>',
'hidden' => '<input type="hidden" name="%s" %s/>',
'textarea' => '<textarea name="%s" %s>%s</textarea>',
'checkbox' => '<input type="checkbox" name="%s" %s/>',
'radio' => '<input type="radio" name="%s" id="%s" %s />%s',
'selectstart' => '<select name="%s"%s>',
'selectmultiplestart' => '<select name="%s[]"%s>',
'selectempty' => '<option value=""%s>&nbsp;</option>',
'selectoption' => '<option value="%s"%s>%s</option>',
'selectend' => '</select>',
'optiongroup' => '<optgroup label="%s"%s>',
'optiongroupend' => '</optgroup>',
'password' => '<input type="password" name="data[%s][%s]" %s/>',
'file' => '<input type="file" name="data[%s][%s]" %s/>',
'password' => '<input type="password" name="%s" %s/>',
'file' => '<input type="file" name="%s" %s/>',
'file_no_model' => '<input type="file" name="%s" %s/>',
'submit' => '<input type="submit" %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('/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="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="Field0".*checked="checked"/', $result);
}
@ -780,7 +783,7 @@ class FormHelperTest extends CakeTestCase {
$result = $this->Form->submit('Next >');
$this->assertPattern('/^<div\s+class="submit"><input type="submit"[^<>]+value="Next &gt;"[^<>]+\/><\/div>$/', $result);
$result = $this->Form->submit('Next >', array('escape'=>false));
$result = $this->Form->submit('Next >', array('escape' => false));
$this->assertPattern('/^<div\s+class="submit"><input type="submit"[^<>]+value="Next >"[^<>]+\/><\/div>$/', $result);
}
@ -823,6 +826,29 @@ class FormHelperTest extends CakeTestCase {
$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() {
$result = $this->Form->create('Contact');
$this->assertPattern('/^<form\s+id="ContactAddForm"\s+method="post"\s+action="\/contacts\/add\/"\s*>$/', $result);