Skip to content

Commit

Permalink
Update FormHelper::error() to reflect current implementation.
Browse files Browse the repository at this point in the history
Use templates for HTML generation instead of attribute/array smashing.
This will break existing use cases, but I honestly doubt people use many
different kinds of error formatting and probably ended up accepting
defaults, or copy and pasting formatting options everywhere.
  • Loading branch information
markstory committed Feb 20, 2014
1 parent 5aea924 commit 8de9a27
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 125 deletions.
83 changes: 29 additions & 54 deletions src/View/Helper/FormHelper.php
Expand Up @@ -172,6 +172,9 @@ class FormHelper extends Helper {
'button' => '<button{{attrs}}>{{text}}</button>',
'checkbox' => '<input type="checkbox" name="{{name}}" value="{{value}}"{{attrs}}>',
'checkboxContainer' => '<div class="checkbox">{{input}}{{label}}</div>',
'error' => '<div class="error-message">{{content}}</div>',
'errorList' => '<ul>{{content}}</ul>',
'errorItem' => '<li>{{text}}</li>',
'file' => '<input type="file" name="{{name}}"{{attrs}}>',
'formstart' => '<form{{attrs}}>',
'formend' => '</form>',
Expand Down Expand Up @@ -597,38 +600,34 @@ public function isFieldError($field) {
}

/**
* Returns a formatted error message for given FORM field, NULL if no errors.
* Returns a formatted error message for given form field, '' if no errors.
*
* Uses the `error`, `errorList` and `errorItem` templates. The errorList and
* errorItem templates are used to format multiple error messages per field.
*
* ### Options:
*
* - `escape` boolean - Whether or not to html escape the contents of the error.
* - `wrap` mixed - Whether or not the error message should be wrapped in a div. If a
* string, will be used as the HTML tag to use.
* - `class` string - The class name for the error message
*
* @param string $field A field name, like "Modelname.fieldname"
* @param string|array $text Error message as string or array of messages.
* If array contains `attributes` key it will be used as options for error container
* @param array $options Rendering options for <div /> wrapper tag
* @return string If there are errors this method returns an error message, otherwise null.
* @param string|array $text Error message as string or array of messages. If an array,
* it should be a hash of key names => messages.
* @param array $options See above.
* @return string Formatted errors or ''.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::error
*/
public function error($field, $text = null, $options = array()) {
$defaults = array('wrap' => true, 'class' => 'error-message', 'escape' => true);
$options = array_merge($defaults, $options);
$this->setEntity($field);
public function error($field, $text = null, $options = []) {
$options += ['escape' => true];

$error = $this->tagIsInvalid();
if ($error === false) {
return null;
$context = $this->_getContext();
if (!$context->hasError($field)) {
return '';
}
$error = (array)$context->error($field);

if (is_array($text)) {
if (isset($text['attributes']) && is_array($text['attributes'])) {
$options = array_merge($options, $text['attributes']);
unset($text['attributes']);
}
$tmp = array();
foreach ($error as &$e) {
$tmp = [];
foreach ($error as $e) {
if (isset($text[$e])) {
$tmp[] = $text[$e];
} else {
Expand All @@ -641,50 +640,26 @@ public function error($field, $text = null, $options = array()) {
if ($text !== null) {
$error = $text;
}
if (is_array($error)) {
foreach ($error as &$e) {
if (is_numeric($e)) {
$e = __d('cake', 'Error in field %s', Inflector::humanize($this->field()));
}
}
}

if ($options['escape']) {
$error = h($error);
unset($options['escape']);
}

if (is_array($error)) {
if (count($error) > 1) {
$listParams = array();
if (isset($options['listOptions'])) {
if (is_string($options['listOptions'])) {
$listParams[] = $options['listOptions'];
} else {
if (isset($options['listOptions']['itemOptions'])) {
$listParams[] = $options['listOptions']['itemOptions'];
unset($options['listOptions']['itemOptions']);
} else {
$listParams[] = array();
}
if (isset($options['listOptions']['tag'])) {
$listParams[] = $options['listOptions']['tag'];
unset($options['listOptions']['tag']);
}
array_unshift($listParams, $options['listOptions']);
}
unset($options['listOptions']);
$errorText = [];
foreach ($error as $err) {
$errorText[] = $this->formatTemplate('errorItem', ['text' => $err]);
}
array_unshift($listParams, $error);
$error = call_user_func_array(array($this->Html, 'nestedList'), $listParams);
$error = $this->formatTemplate('errorList', [
'content' => implode('', $errorText)
]);
} else {
$error = array_pop($error);
}
}
if ($options['wrap']) {
$tag = is_string($options['wrap']) ? $options['wrap'] : 'div';
unset($options['wrap']);
return $this->Html->tag($tag, $error, $options);
}
return $error;
return $this->formatTemplate('error', ['content' => $error]);
}

/**
Expand Down
124 changes: 53 additions & 71 deletions tests/TestCase/View/Helper/FormHelperTest.php
Expand Up @@ -4009,45 +4009,70 @@ public function testTextDefaultValue() {
* @return void
*/
public function testError() {
$this->markTestIncomplete('Need to revisit once models work again.');
$Contact->validationErrors['field'] = array(1);
$result = $this->Form->error('Contact.field');
$this->assertTags($result, array('div' => array('class' => 'error-message'), 'Error in field Field', '/div'));

$result = $this->Form->error('Contact.field', null, array('wrap' => false));
$this->assertEquals('Error in field Field', $result);

$Contact->validationErrors['field'] = array("This field contains invalid input");
$result = $this->Form->error('Contact.field', null, array('wrap' => false));
$this->assertEquals('This field contains invalid input', $result);

$Contact->validationErrors['field'] = array("This field contains invalid input");
$result = $this->Form->error('Contact.field', null, array('wrap' => 'span'));
$this->assertTags($result, array('span' => array('class' => 'error-message'), 'This field contains invalid input', '/span'));
$this->article['errors'] = [
'Article' => ['field' => 'email']
];
$this->Form->create($this->article);

$result = $this->Form->error('Contact.field', 'There is an error fool!', array('wrap' => 'span'));
$this->assertTags($result, array('span' => array('class' => 'error-message'), 'There is an error fool!', '/span'));
$result = $this->Form->error('Article.field');
$expected = [
['div' => ['class' => 'error-message']],
'email',
'/div',
];
$this->assertTags($result, $expected);

$result = $this->Form->error('Contact.field', "<strong>Badness!</strong>", array('wrap' => false));
$this->assertEquals('&lt;strong&gt;Badness!&lt;/strong&gt;', $result);
$result = $this->Form->error('Article.field', "<strong>Badness!</strong>");
$expected = [
['div' => ['class' => 'error-message']],
'&lt;strong&gt;Badness!&lt;/strong&gt;',
'/div',
];
$this->assertTags($result, $expected);

$result = $this->Form->error('Contact.field', "<strong>Badness!</strong>", array('wrap' => false, 'escape' => true));
$this->assertEquals('&lt;strong&gt;Badness!&lt;/strong&gt;', $result);
$result = $this->Form->error('Article.field', "<strong>Badness!</strong>", ['escape' => false]);
$expected = [
['div' => ['class' => 'error-message']],
'<strong', 'Badness!', '/strong',
'/div',
];
$this->assertTags($result, $expected);
}

$result = $this->Form->error('Contact.field', "<strong>Badness!</strong>", array('wrap' => false, 'escape' => false));
$this->assertEquals('<strong>Badness!</strong>', $result);
/**
* Test error with nested lists.
*
* @return void
*/
public function testErrorMessages() {
$this->article['errors'] = [
'Article' => ['field' => 'email']
];
$this->Form->create($this->article);

$Contact->validationErrors['field'] = array("email");
$result = $this->Form->error('Contact.field', array('attributes' => array('class' => 'field-error'), 'email' => 'No good!'));
$result = $this->Form->error('Article.field', array(
'email' => 'No good!'
));
$expected = array(
'div' => array('class' => 'field-error'),
'div' => array('class' => 'error-message'),
'No good!',
'/div'
);
$this->assertTags($result, $expected);
}

$Contact->validationErrors['field'] = array('notEmpty', 'email', 'Something else');
$result = $this->Form->error('Contact.field', array(
/**
* test error() with multiple messages.
*
* @return void
*/
public function testErrorMultipleMessages() {
$this->article['errors'] = [
'field' => ['notEmpty', 'email', 'Something else']
];
$this->Form->create($this->article);

$result = $this->Form->error('field', array(
'notEmpty' => 'Cannot be empty',
'email' => 'No good!'
));
Expand All @@ -4061,49 +4086,6 @@ public function testError() {
'/div'
);
$this->assertTags($result, $expected);

// Testing error messages list options
$Contact->validationErrors['field'] = array('notEmpty', 'email');

$result = $this->Form->error('Contact.field', null, array('listOptions' => 'ol'));
$expected = array(
'div' => array('class' => 'error-message'),
'ol' => array(),
'<li', 'notEmpty', '/li',
'<li', 'email', '/li',
'/ol',
'/div'
);
$this->assertTags($result, $expected);

$result = $this->Form->error('Contact.field', null, array('listOptions' => array('tag' => 'ol')));
$expected = array(
'div' => array('class' => 'error-message'),
'ol' => array(),
'<li', 'notEmpty', '/li',
'<li', 'email', '/li',
'/ol',
'/div'
);
$this->assertTags($result, $expected);

$result = $this->Form->error('Contact.field', null, array(
'listOptions' => array(
'class' => 'ul-class',
'itemOptions' => array(
'class' => 'li-class'
)
)
));
$expected = array(
'div' => array('class' => 'error-message'),
'ul' => array('class' => 'ul-class'),
array('li' => array('class' => 'li-class')), 'notEmpty', '/li',
array('li' => array('class' => 'li-class')), 'email', '/li',
'/ul',
'/div'
);
$this->assertTags($result, $expected);
}

/**
Expand Down

0 comments on commit 8de9a27

Please sign in to comment.