Browse Source

Merge pull request #2944 from markstory/3.0-form-inputs

3.0 Update FormHelper::inputs()
José Lorenzo Rodríguez 12 years ago
parent
commit
f3ccd7fcc7

+ 9 - 0
src/View/Form/ArrayContext.php

@@ -175,6 +175,15 @@ class ArrayContext implements ContextInterface {
 	}
 
 /**
+ * {@inheritDoc}
+ */
+	public function fieldNames() {
+		$schema = $this->_context['schema'];
+		unset($schema['_constraints'], $schema['_indexes']);
+		return array_keys($schema);
+	}
+
+/**
  * Get the abstract field type for a given field name.
  *
  * @param string $field A dot separated path to get a schema type for.

+ 7 - 0
src/View/Form/ContextInterface.php

@@ -62,6 +62,13 @@ interface ContextInterface {
 	public function isRequired($field);
 
 /**
+ * Get the fieldnames of the top level object in this context.
+ *
+ * @return array A list of the field names in the context.
+ */
+	public function fieldNames();
+
+/**
  * Get the abstract field type for a given field name.
  *
  * @param string $field A dot separated path to get a schema type for.

+ 12 - 0
src/View/Form/EntityContext.php

@@ -318,6 +318,18 @@ class EntityContext implements ContextInterface {
 	}
 
 /**
+ * Get the field names from the top level entity.
+ *
+ * If the context is for an array of entities, the 0th index will be used.
+ *
+ * @return array Array of fieldnames in the table/entity.
+ */
+	public function fieldNames() {
+		$table = $this->_getTable('0');
+		return $table->schema()->columns();
+	}
+
+/**
  * Get the validator associated to an entity based on naming
  * conventions.
  *

+ 7 - 0
src/View/Form/NullContext.php

@@ -80,6 +80,13 @@ class NullContext implements ContextInterface {
 /**
  * {@inheritDoc}
  */
+	public function fieldNames() {
+		return [];
+	}
+
+/**
+ * {@inheritDoc}
+ */
 	public function type($field) {
 		return null;
 	}

+ 38 - 49
src/View/Helper/FormHelper.php

@@ -142,12 +142,14 @@ class FormHelper extends Helper {
 		'errorList' => '<ul>{{content}}</ul>',
 		'errorItem' => '<li>{{text}}</li>',
 		'file' => '<input type="file" name="{{name}}"{{attrs}}>',
+		'fieldset' => '<fieldset>{{content}}</fieldset>',
 		'formstart' => '<form{{attrs}}>',
 		'formend' => '</form>',
 		'hiddenblock' => '<div style="display:none;">{{content}}</div>',
 		'input' => '<input type="{{type}}" name="{{name}}"{{attrs}}>',
 		'inputsubmit' => '<input type="{{type}}"{{attrs}}>',
 		'label' => '<label{{attrs}}>{{text}}</label>',
+		'legend' => '<legend>{{text}}</legend>',
 		'option' => '<option value="{{value}}"{{attrs}}>{{text}}</option>',
 		'optgroup' => '<optgroup label="{{label}}"{{attrs}}>{{content}}</optgroup>',
 		'select' => '<select name="{{name}}"{{attrs}}>{{content}}</select>',
@@ -712,22 +714,28 @@ class FormHelper extends Helper {
  *
  * You can customize individual inputs through `$fields`.
  * {{{
- *	$this->Form->inputs(array(
- *		'name' => array('label' => 'custom label')
- *	));
+ * $this->Form->inputs([
+ *   'name' => ['label' => 'custom label']
+ * ]);
  * }}}
  *
+ * You can exclude fields using the `$blacklist` parameter:
+ *
+ * {{{
+ * $this->Form->inputs(null, ['title']);
+ * }}}
+ *
+ * In the above example, no field would be generated for the title field.
+ *
  * In addition to controller fields output, `$fields` can be used to control legend
  * and fieldset rendering.
  * `$this->Form->inputs('My legend');` Would generate an input set with a custom legend.
- * Passing `fieldset` and `legend` key in `$fields` array has been deprecated since 2.3,
- * for more fine grained control use the `fieldset` and `legend` keys in `$options` param.
  *
- * @param array $fields An array of fields to generate inputs for, or null.
- * @param array $blacklist A simple array of fields to not create inputs for.
+ * @param array $fields An array of customizations for the fields that will be
+ *   generated. This array allows you to set custom types, labels, or other options.
+ * @param array $blacklist A list of fields to not create inputs for.
  * @param array $options Options array. Valid keys are:
- * - `fieldset` Set to false to disable the fieldset. If a string is supplied it will be used as
- *    the class name for the fieldset element.
+ * - `fieldset` Set to false to disable the fieldset.
  * - `legend` Set to false to disable the legend for the generated input set. Or supply a string
  *    to customize the legend text.
  * @return string Completed form inputs.
@@ -735,29 +743,23 @@ class FormHelper extends Helper {
  */
 	public function inputs($fields = null, $blacklist = null, $options = array()) {
 		$fieldset = $legend = true;
-		$modelFields = array();
-		$model = $this->model();
-		if ($model) {
-			$modelFields = array_keys((array)$this->_introspectModel($model, 'fields'));
-		}
-		if (is_array($fields)) {
-			if (array_key_exists('legend', $fields) && !in_array('legend', $modelFields)) {
-				$legend = $fields['legend'];
-				unset($fields['legend']);
-			}
+		$context = $this->_getContext();
 
-			if (isset($fields['fieldset']) && !in_array('fieldset', $modelFields)) {
-				$fieldset = $fields['fieldset'];
-				unset($fields['fieldset']);
-			}
-		} elseif ($fields !== null) {
+		$modelFields = $context->fieldNames();
+
+		if (is_string($fields)) {
+			$legend = $fields;
+			$fields = [];
+		} elseif (is_bool($fields)) {
 			$fieldset = $legend = $fields;
-			if (!is_bool($fieldset)) {
-				$fieldset = true;
-			}
-			$fields = array();
+			$fields = [];
 		}
 
+		$fields = array_merge(
+			Hash::normalize($modelFields),
+			Hash::normalize((array)$fields)
+		);
+
 		if (isset($options['legend'])) {
 			$legend = $options['legend'];
 		}
@@ -765,28 +767,21 @@ class FormHelper extends Helper {
 			$fieldset = $options['fieldset'];
 		}
 
-		if (empty($fields)) {
-			$fields = $modelFields;
-		}
-
 		if ($legend === true) {
 			$actionName = __d('cake', 'New %s');
-			$isEdit = (
-				strpos($this->request->params['action'], 'update') !== false ||
-				strpos($this->request->params['action'], 'edit') !== false
-			);
-			if ($isEdit) {
+			$isCreate = $context->isCreate();
+			if (!$isCreate) {
 				$actionName = __d('cake', 'Edit %s');
 			}
-			$modelName = Inflector::humanize(Inflector::underscore($model));
-			$legend = sprintf($actionName, __($modelName));
+			$modelName = Inflector::humanize(Inflector::singularize($this->request->params['controller']));
+			$legend = sprintf($actionName, $modelName);
 		}
 
 		$out = null;
 		foreach ($fields as $name => $options) {
 			if (is_numeric($name) && !is_array($options)) {
 				$name = $options;
-				$options = array();
+				$options = [];
 			}
 			$entity = explode('.', $name);
 			$blacklisted = (
@@ -796,20 +791,14 @@ class FormHelper extends Helper {
 			if ($blacklisted) {
 				continue;
 			}
-			$out .= $this->input($name, $options);
-		}
-
-		if (is_string($fieldset)) {
-			$fieldsetClass = sprintf(' class="%s"', $fieldset);
-		} else {
-			$fieldsetClass = '';
+			$out .= $this->input($name, (array)$options);
 		}
 
 		if ($fieldset) {
 			if ($legend) {
-				$out = $this->Html->useTag('legend', $legend) . $out;
+				$out = $this->formatTemplate('legend', ['text' => $legend]) . $out;
 			}
-			$out = $this->Html->useTag('fieldset', $fieldsetClass, $out);
+			$out = $this->formatTemplate('fieldset', ['content' => $out]);
 		}
 		return $out;
 	}

+ 14 - 0
tests/TestCase/View/Form/EntityContextTest.php

@@ -819,4 +819,18 @@ class EntityContextTest extends TestCase {
 		$comments->validator('custom', $validator);
 	}
 
+/**
+ * Test the fieldnames method.
+ *
+ * @return void
+ */
+	public function testFieldNames() {
+		$context = new EntityContext($this->request, [
+			'entity' => new Entity(),
+			'table' => 'Articles',
+		]);
+		$articles = TableRegistry::get('Articles');
+		$this->assertEquals($articles->schema()->columns(), $context->fieldNames());
+	}
+
 }

+ 53 - 164
tests/TestCase/View/Helper/FormHelperTest.php

@@ -2498,9 +2498,8 @@ class FormHelperTest extends TestCase {
  *
  * @return void
  */
-	public function testFormInputs() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$this->Form->create('Cake\Test\TestCase\View\Helper\Contact');
+	public function testFormInputsLegendFieldset() {
+		$this->Form->create($this->article);
 		$result = $this->Form->inputs('The Legend');
 		$expected = array(
 			'<fieldset',
@@ -2511,210 +2510,100 @@ class FormHelperTest extends TestCase {
 		);
 		$this->assertTags($result, $expected);
 
-		$result = $this->Form->inputs(array('legend' => 'Field of Dreams', 'fieldset' => 'classy-stuff'));
-		$expected = array(
-			'fieldset' => array('class' => 'classy-stuff'),
-			'<legend',
-			'Field of Dreams',
-			'/legend',
-			'*/fieldset'
-		);
-		$this->assertTags($result, $expected);
+		$result = $this->Form->inputs(null, null, array('legend' => 'Field of Dreams', 'fieldset' => true));
+		$this->assertContains('<legend>Field of Dreams</legend>', $result);
+		$this->assertContains('<fieldset>', $result);
 
-		$result = $this->Form->inputs(null, null, array('legend' => 'Field of Dreams', 'fieldset' => 'classy-stuff'));
-		$this->assertTags($result, $expected);
+		$result = $this->Form->inputs('Field of Dreams', null, array('fieldset' => true));
+		$this->assertContains('<legend>Field of Dreams</legend>', $result);
+		$this->assertContains('<fieldset>', $result);
 
-		$result = $this->Form->inputs('Field of Dreams', null, array('fieldset' => 'classy-stuff'));
-		$this->assertTags($result, $expected);
+		$result = $this->Form->inputs(null, null, array('fieldset' => false, 'legend' => false));
+		$this->assertNotContains('<legend>', $result);
+		$this->assertNotContains('<fieldset>', $result);
 
-		$this->Form->create('Contact');
-		$this->Form->request['prefix'] = 'admin';
-		$this->Form->request['action'] = 'admin_edit';
+		$result = $this->Form->inputs(null, null, array('fieldset' => false, 'legend' => 'Hello'));
+		$this->assertNotContains('<legend>', $result);
+		$this->assertNotContains('<fieldset>', $result);
+
+		$this->Form->create($this->article);
+		$this->Form->request->params['prefix'] = 'admin';
+		$this->Form->request->params['action'] = 'admin_edit';
+		$this->Form->request->params['controller'] = 'articles';
 		$result = $this->Form->inputs();
-		$expected = array(
+		$expected = [
 			'<fieldset',
 			'<legend',
-			'Edit Contact',
+			'New Article',
 			'/legend',
 			'*/fieldset',
-		);
+		];
 		$this->assertTags($result, $expected);
+	}
 
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(false);
+/**
+ * Test the inputs() method.
+ *
+ * @return void
+ */
+	public function testFormInputs() {
+		$this->Form->create($this->article);
+		$result = $this->Form->inputs();
 		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
-			array('div' => array('class' => 'input text')),
-			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
-			'*/div',
-			array('div' => array('class' => 'input password')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input datetime')),
-			'*/div',
-			array('div' => array('class' => 'input number')),
+			'<fieldset',
+			'<legend', 'New Article', '/legend',
+			'input' => array('type' => 'hidden', 'name' => 'id', 'id' => 'id'),
+			array('div' => array('class' => 'input select required')),
 			'*/div',
-			array('div' => array('class' => 'input select')),
+			array('div' => array('class' => 'input text required')),
 			'*/div',
-		);
-		$this->assertTags($result, $expected);
-
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(array('fieldset' => false, 'legend' => false));
-		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
 			array('div' => array('class' => 'input text')),
 			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
-			'*/div',
-			array('div' => array('class' => 'input password')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input datetime')),
-			'*/div',
-			array('div' => array('class' => 'input number')),
-			'*/div',
-			array('div' => array('class' => 'input select')),
-			'*/div',
-		);
-		$this->assertTags($result, $expected);
-
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(null, null, array('fieldset' => false));
-		$this->assertTags($result, $expected);
-
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(array('fieldset' => true, 'legend' => false));
-		$expected = array(
-			'fieldset' => array(),
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
 			array('div' => array('class' => 'input text')),
 			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
-			'*/div',
-			array('div' => array('class' => 'input password')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input datetime')),
-			'*/div',
-			array('div' => array('class' => 'input number')),
-			'*/div',
-			array('div' => array('class' => 'input select')),
-			'*/div',
-			'/fieldset'
+			'/fieldset',
 		);
 		$this->assertTags($result, $expected);
 
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(array('fieldset' => false, 'legend' => 'Hello'));
+		$result = $this->Form->inputs([
+			'published' => ['type' => 'boolean']
+		]);
 		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
-			array('div' => array('class' => 'input text')),
-			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
-			'*/div',
-			array('div' => array('class' => 'input password')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
+			'<fieldset',
+			'<legend', 'New Article', '/legend',
+			'input' => array('type' => 'hidden', 'name' => 'id', 'id' => 'id'),
+			array('div' => array('class' => 'input select required')),
 			'*/div',
-			array('div' => array('class' => 'input datetime')),
+			array('div' => array('class' => 'input text required')),
 			'*/div',
-			array('div' => array('class' => 'input number')),
+			array('div' => array('class' => 'input text')),
 			'*/div',
-			array('div' => array('class' => 'input select')),
+			array('div' => array('class' => 'input boolean')),
 			'*/div',
+			'/fieldset',
 		);
 		$this->assertTags($result, $expected);
 
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(null, null, array('fieldset' => false, 'legend' => 'Hello'));
-		$this->assertTags($result, $expected);
-
-		$this->Form->create('Contact');
+		$this->Form->create($this->article);
 		$result = $this->Form->inputs('Hello');
 		$expected = array(
 			'fieldset' => array(),
 			'legend' => array(),
 			'Hello',
 			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
-			array('div' => array('class' => 'input text')),
-			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
+			'input' => array('type' => 'hidden', 'name' => 'id', 'id' => 'id'),
+			array('div' => array('class' => 'input select required')),
 			'*/div',
-			array('div' => array('class' => 'input password')),
+			array('div' => array('class' => 'input text required')),
 			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input datetime')),
-			'*/div',
-			array('div' => array('class' => 'input number')),
-			'*/div',
-			array('div' => array('class' => 'input select')),
-			'*/div',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(array('legend' => 'Hello'));
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Hello',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Contact[id]', 'id' => 'ContactId'),
 			array('div' => array('class' => 'input text')),
 			'*/div',
-			array('div' => array('class' => 'input email')),
-			'*/div',
-			array('div' => array('class' => 'input tel')),
-			'*/div',
-			array('div' => array('class' => 'input password')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input date')),
-			'*/div',
-			array('div' => array('class' => 'input datetime')),
-			'*/div',
-			array('div' => array('class' => 'input number')),
-			'*/div',
-			array('div' => array('class' => 'input select')),
+			array('div' => array('class' => 'input text')),
 			'*/div',
 			'/fieldset'
 		);
 		$this->assertTags($result, $expected);
 
-		$this->Form->create('Contact');
-		$result = $this->Form->inputs(null, null, array('legend' => 'Hello'));
-		$this->assertTags($result, $expected);
-		$this->Form->end();
-
 		$this->Form->create(false);
 		$expected = array(
 			'fieldset' => array(),