Permalink
Browse files

Merge pull request #2980 from ADmad/3.0-form-idprefix

3.0 form idprefix

Fixes #2952
  • Loading branch information...
markstory committed Mar 10, 2014
2 parents 83a54a9 + 17bcaf3 commit e54ffbc335cc0b484d1b73bc77f5fde4b80f7c4d
@@ -26,6 +26,7 @@
use Cake\View\Form\EntityContext;
use Cake\View\Form\NullContext;
use Cake\View\Helper;
+use Cake\View\Helper\IdGeneratorTrait;
use Cake\View\Helper\StringTemplateTrait;
use Cake\View\StringTemplate;
use Cake\View\View;
@@ -43,6 +44,7 @@
*/
class FormHelper extends Helper {
+ use IdGeneratorTrait;
use StringTemplateTrait;
/**
@@ -256,6 +258,7 @@ protected function _isRequiredField($validationRules) {
* - `encoding` Set the accept-charset encoding for the form. Defaults to `Configure::read('App.encoding')`
* - `context` Additional options for the context class. For example the EntityContext accepts a 'table'
* option that allows you to set the specific Table class the form should be based on.
+ * - `idPrefix` Prefix for generated ID attributes.
*
* @param mixed $model The context for which the form is being defined. Can
* be an ORM entity, ORM resultset, or an array of meta data. You can use false or null
@@ -281,10 +284,12 @@ public function create($model = null, $options = []) {
'action' => null,
'url' => null,
'encoding' => strtolower(Configure::read('App.encoding')),
+ 'idPrefix' => null
];
+ $this->_idPrefix = $options['idPrefix'];
$action = $this->url($this->_formUrl($context, $options));
- unset($options['url'], $options['action']);
+ unset($options['url'], $options['action'], $options['idPrefix']);
$htmlAttributes = [];
switch (strtolower($options['type'])) {
@@ -414,6 +419,7 @@ public function end($secureAttributes = []) {
$this->requestType = null;
$this->_context = null;
+ $this->_idPrefix = null;
return $out;
}
@@ -696,16 +702,6 @@ public function label($fieldName, $text = null, $options = array()) {
return $this->widget('label', $attrs);
}
-/**
- * Generate an ID suitable for use in an ID attribute.
- *
- * @param string $value The value to convert into an ID.
- * @return string The generated id.
- */
- protected function _domId($value) {
- return mb_strtolower(Inflector::slug($value, '-'));
- }
-
/**
* Generate a set of inputs for `$fields`. If $fields is null the fields of current model
* will be used.
@@ -1186,6 +1182,7 @@ public function radio($fieldName, $options = [], $attributes = []) {
]);
}
$attributes['options'] = $options;
+ $attributes['idPrefix'] = $this->_idPrefix;
return $hidden . $this->widget('radio', $attributes);
}
@@ -1642,6 +1639,7 @@ public function multiCheckbox($fieldName, $options, $attributes = []) {
];
$attributes = $this->_initInputField($fieldName, $attributes);
$attributes['options'] = $options;
+ $attributes['idPrefix'] = $this->_idPrefix;
$hidden = '';
if ($attributes['hiddenField']) {
@@ -12,7 +12,7 @@
* @since CakePHP(tm) v3.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
-namespace Cake\View\Widget;
+namespace Cake\View\Helper;
use Cake\Utility\Inflector;
@@ -22,6 +22,13 @@
*/
trait IdGeneratorTrait {
+/**
+ * Prefix for id attribute.
+ *
+ * @var string
+ */
+ protected $_idPrefix = null;
+
/**
* A list of id suffixes used in the current rendering.
*
@@ -39,7 +46,7 @@ protected function _clearIds() {
}
/**
- * Generate an ID attribute for a radio button.
+ * Generate an ID attribute for an element.
*
* Ensures that id's for a given set of fields are unique.
*
@@ -48,7 +55,8 @@ protected function _clearIds() {
* @return string Generated id.
*/
protected function _id($name, $val) {
- $name = mb_strtolower(Inflector::slug($name, '-'));
+ $name = $this->_domId($name);
+
$idSuffix = mb_strtolower(str_replace(array('/', '@', '<', '>', ' ', '"', '\''), '-', $val));
$count = 1;
$check = $idSuffix;
@@ -58,4 +66,19 @@ protected function _id($name, $val) {
$this->_idSuffixes[] = $check;
return trim($name . '-' . $check, '-');
}
+
+/**
+ * Generate an ID suitable for use in an ID attribute.
+ *
+ * @param string $value The value to convert into an ID.
+ * @return string The generated id.
+ */
+ protected function _domId($value) {
+ $domId = mb_strtolower(Inflector::slug($value, '-'));
+ if (!empty($this->_idPrefix)) {
+ $domId = $this->_idPrefix . '-' . $domId;
+ }
+ return $domId;
+ }
+
}
@@ -170,7 +170,7 @@ public function formatAttributes($options, $exclude = null) {
$exclude = [];
}
- $exclude = ['escape' => true] + array_flip($exclude);
+ $exclude = ['escape' => true, 'idPrefix' => true] + array_flip($exclude);
$escape = $options['escape'];
$attributes = [];
@@ -14,7 +14,7 @@
*/
namespace Cake\View\Widget;
-use Cake\View\Widget\IdGeneratorTrait;
+use Cake\View\Helper\IdGeneratorTrait;
use Cake\View\Widget\WidgetInterface;
/**
@@ -71,6 +71,7 @@ public function __construct($templates, $label) {
* - `disabled` Either a boolean or an array of checkboxes to disable.
* - `escape` Set to false to disable HTML escaping.
* - `options` An associative array of value=>labels to generate options for.
+ * - `idPrefix` Prefix for generated ID attributes.
*
* ### Options format
*
@@ -105,8 +106,10 @@ public function render(array $data) {
'options' => [],
'disabled' => null,
'val' => null,
+ 'idPrefix' => null
];
$out = [];
+ $this->_idPrefix = $data['idPrefix'];
$this->_clearIds();
foreach ($data['options'] as $key => $val) {
$checkbox = [
@@ -14,7 +14,7 @@
*/
namespace Cake\View\Widget;
-use Cake\View\Widget\IdGeneratorTrait;
+use Cake\View\Helper\IdGeneratorTrait;
use Cake\View\Widget\WidgetInterface;
use Traversable;
@@ -75,6 +75,7 @@ public function __construct($templates, $label) {
* an array of attributes for all labels.
* - `required` - Set to true to add the required attribute
* on all generated radios.
+ * - `idPrefix` Prefix for generated ID attributes.
*
* @param array $data The data to build radio buttons with.
* @return string
@@ -88,6 +89,7 @@ public function render(array $data) {
'escape' => true,
'label' => true,
'empty' => false,
+ 'idPrefix' => null
];
if ($data['options'] instanceof Traversable) {
$options = iterator_to_array($data['options']);
@@ -101,6 +103,7 @@ public function render(array $data) {
}
unset($data['empty']);
+ $this->_idPrefix = $data['idPrefix'];
$this->_clearIds();
$opts = [];
foreach ($options as $val => $text) {
@@ -1973,6 +1973,100 @@ public function testInputCustomization() {
$this->assertTags($result, $expected);
}
+/**
+ * Test id prefix
+ *
+ * @return void
+ */
+ public function testCreateIdPrefix() {
+ $this->Form->create(false, ['idPrefix' => 'prefix']);
+
+ $result = $this->Form->input('field');
+ $expected = [
+ 'div' => ['class' => 'input text'],
+ 'label' => ['for' => 'prefix-field'],
+ 'Field',
+ '/label',
+ 'input' => ['type' => 'text', 'name' => 'field', 'id' => 'prefix-field'],
+ '/div'
+ ];
+ $this->assertTags($result, $expected);
+
+ $result = $this->Form->input('field', ['id' => 'custom-id']);
+ $expected = [
+ 'div' => ['class' => 'input text'],
+ 'label' => ['for' => 'custom-id'],
+ 'Field',
+ '/label',
+ 'input' => ['type' => 'text', 'name' => 'field', 'id' => 'custom-id'],
+ '/div'
+ ];
+ $this->assertTags($result, $expected);
+
+ $result = $this->Form->radio('Model.field', ['option A']);
+ $expected = [
+ 'input' => ['type' => 'hidden', 'name' => 'Model[field]', 'value' => ''],
+ ['input' => [
+ 'type' => 'radio',
+ 'name' => 'Model[field]',
+ 'value' => '0',
+ 'id' => 'prefix-model-field-0'
+ ]],
+ 'label' => ['for' => 'prefix-model-field-0'],
+ 'option A',
+ '/label'
+ ];
+ $this->assertTags($result, $expected);
+
+ $result = $this->Form->radio('Model.field', ['option A', 'option']);
+ $expected = [
+ 'input' => ['type' => 'hidden', 'name' => 'Model[field]', 'value' => ''],
+ ['input' => [
+ 'type' => 'radio',
+ 'name' => 'Model[field]',
+ 'value' => '0',
+ 'id' => 'prefix-model-field-0'
+ ]],
+ 'label' => ['for' => 'prefix-model-field-0'],
+ 'option A',
+ '/label'
+ ];
+ $this->assertTags($result, $expected);
+
+ $result = $this->Form->select(
+ 'Model.multi_field',
+ ['first'],
+ ['multiple' => 'checkbox']
+ );
+ $expected = [
+ 'input' => [
+ 'type' => 'hidden', 'name' => 'Model[multi_field]', 'value' => ''
+ ],
+ ['div' => ['class' => 'checkbox']],
+ ['input' => [
+ 'type' => 'checkbox', 'name' => 'Model[multi_field][]',
+ 'value' => '0', 'id' => 'prefix-model-multi-field-0'
+ ]],
+ ['label' => ['for' => 'prefix-model-multi-field-0']],
+ 'first',
+ '/label',
+ '/div',
+ ];
+ $this->assertTags($result, $expected);
+
+ $this->Form->end();
+ $result = $this->Form->input('field');
+ $expected = [
+ 'div' => ['class' => 'input text'],
+ 'label' => ['for' => 'field'],
+ 'Field',
+ '/label',
+ 'input' => ['type' => 'text', 'name' => 'field', 'id' => 'field'],
+ '/div'
+ ];
+ $this->assertTags($result, $expected);
+ }
+
/**
* Test that inputs with 0 can be created.
*
@@ -2088,6 +2182,48 @@ public function testInputDatetime() {
$this->assertTags($result, $expected);
}
+/**
+ * test form->input() with datetime with id prefix
+ *
+ * @return void
+ */
+ public function testInputDatetimeIdPrefix() {
+ $this->Form = $this->getMock(
+ 'Cake\View\Helper\FormHelper',
+ ['datetime'],
+ [new View(null)]
+ );
+
+ $this->Form->create(false, ['idPrefix' => 'prefix']);
+
+ $this->Form->expects($this->once())->method('datetime')
+ ->with('prueba', [
+ 'type' => 'datetime',
+ 'timeFormat' => 24,
+ 'minYear' => 2008,
+ 'maxYear' => 2011,
+ 'interval' => 15,
+ 'options' => null,
+ 'empty' => false,
+ 'id' => 'prefix-prueba',
+ 'required' => false,
+ ])
+ ->will($this->returnValue('This is it!'));
+ $result = $this->Form->input('prueba', array(
+ 'type' => 'datetime', 'timeFormat' => 24, 'minYear' => 2008,
+ 'maxYear' => 2011, 'interval' => 15
+ ));
+ $expected = array(
+ 'div' => array('class' => 'input datetime'),
+ 'label' => array('for' => 'prefix-prueba'),
+ 'Prueba',
+ '/label',
+ 'This is it!',
+ '/div'
+ );
+ $this->assertTags($result, $expected);
+ }
+
/**
* Test generating checkboxes with disabled elements.
*

0 comments on commit e54ffbc

Please sign in to comment.