Skip to content

Commit

Permalink
General refactoring of the automatic input type selection
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Feb 23, 2014
1 parent 8c536d1 commit ecfd4cf
Showing 1 changed file with 74 additions and 91 deletions.
165 changes: 74 additions & 91 deletions src/View/Helper/FormHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ class FormHelper extends Helper {
* @var array
*/
public $settings = [
'errorClass' => 'form-error'
'errorClass' => 'form-error',
'typeMap' => [
'string' => 'text', 'datetime' => 'datetime', 'boolean' => 'checkbox',
'timestamp' => 'datetime', 'text' => 'textarea', 'time' => 'time',
'date' => 'date', 'float' => 'number', 'integer' => 'number',
'decimal' => 'number', 'binary' => 'file', 'uuid' => 'string'
]
];

/**
Expand Down Expand Up @@ -856,7 +862,7 @@ public function input($fieldName, $options = array()) {
'options' => null,
'templates' => []
];
$options = $this->_parseOptions($options);
$options = $this->_parseOptions($fieldName, $options);

$label = $this->_getLabel($fieldName, $options);
if ($options['type'] !== 'radio') {
Expand Down Expand Up @@ -924,18 +930,12 @@ protected function _getInput($args) {
* @param array $options
* @return array Options
*/
protected function _parseOptions($options) {
protected function _parseOptions($fieldName, $options) {
if (!empty($options['type'])) {
$options = $this->_magicOptions($options);
$options['type'] = $this->_inputType($fieldName, $options);
}

if (in_array($options['type'], ['radio', 'select'])) {
$options = $this->_optionsOptions($options);
}

if (isset($options['rows']) || isset($options['cols'])) {
$options['type'] = 'textarea';
}
$options = $this->_magicOptions($fieldName, $options);

if (in_array(['datetime', 'date', 'time', 'select'], $options['type'])) {
$options += ['empty' => false];
Expand All @@ -944,18 +944,53 @@ protected function _parseOptions($options) {
return $options;
}

protected function _inputType($fieldName, $options) {
$context = $this->_getContext();
$primaryKey = $context->primaryKey();

if (in_array($fieldName, $primaryKey)) {
return 'hidden';
}

if (substr($fieldName, -3) === '_id') {
return 'select';
}

$internalType = $context->type($fieldName);
$map = $this->settings['typeMap'];
$type = isset($map[$internalType]) ? $map[$internalType] : 'text';

switch (true) {
case isset($options['checked']) :
return 'checkbox';
case isset($options['options']) :
return 'select';
case in_array($fieldName, ['passwd', 'password']) :
return 'password';
case in_array($fieldName, ['tel', 'telephone', 'phone']) :
return 'tel';
case $fieldName === 'email':
return 'email';
case isset($options['rows']) || isset($options['cols']) :
return 'textarea';
}

return $type;
}

/**
* Generates list of options for multiple select
*
* @param array $options
* @return array
*/
protected function _optionsOptions($options) {
protected function _optionsOptions($fieldName, $options) {
if (isset($options['options'])) {
return $options;
}

$varName = Inflector::variable(
Inflector::pluralize(preg_replace('/_id$/', '', $this->field()))
Inflector::pluralize(preg_replace('/_id$/', '', $fieldName))
);
$varOptions = $this->_View->get($varName);
if (!is_array($varOptions)) {
Expand All @@ -974,70 +1009,40 @@ protected function _optionsOptions($options) {
* @param array $options
* @return array
*/
protected function _magicOptions($options) {
$modelKey = $this->model();
$fieldKey = $this->field();
$options['type'] = 'text';
if (isset($options['options'])) {
$options['type'] = 'select';
} elseif (in_array($fieldKey, array('psword', 'passwd', 'password'))) {
$options['type'] = 'password';
} elseif (in_array($fieldKey, array('tel', 'telephone', 'phone'))) {
$options['type'] = 'tel';
} elseif ($fieldKey === 'email') {
$options['type'] = 'email';
} elseif (isset($options['checked'])) {
$options['type'] = 'checkbox';
} elseif ($fieldDef = $this->_introspectModel($modelKey, 'fields', $fieldKey)) {
$type = $fieldDef['type'];
$primaryKey = $this->fieldset[$modelKey]['key'];
$map = array(
'string' => 'text', 'datetime' => 'datetime',
'boolean' => 'checkbox', 'timestamp' => 'datetime',
'text' => 'textarea', 'time' => 'time',
'date' => 'date', 'float' => 'number',
'integer' => 'number', 'decimal' => 'number',
'binary' => 'file'
);

if (isset($this->map[$type])) {
$options['type'] = $this->map[$type];
} elseif (isset($map[$type])) {
$options['type'] = $map[$type];
}
if ($fieldKey == $primaryKey) {
$options['type'] = 'hidden';
}
if (
$options['type'] === 'number' &&
!isset($options['step'])
) {
if ($type === 'decimal') {
$decimalPlaces = substr($fieldDef['length'], strpos($fieldDef['length'], ',') + 1);
$options['step'] = sprintf('%.' . $decimalPlaces . 'F', pow(10, -1 * $decimalPlaces));
} elseif ($type === 'float') {
$options['step'] = 'any';
}
protected function _magicOptions($fieldName, $options) {
$context = $this->_getContext();
$type = $context->type($fieldName);
$fielDef = $context->attributes($fieldName);

if ($options['type'] === 'number' && !isset($options['step'])) {
if ($type === 'decimal') {
$decimalPlaces = substr($fieldDef['length'], strpos($fieldDef['length'], ',') + 1);
$options['step'] = sprintf('%.' . $decimalPlaces . 'F', pow(10, -1 * $decimalPlaces));
} elseif ($type === 'float') {
$options['step'] = 'any';
}
}

if (preg_match('/_id$/', $fieldKey) && $options['type'] !== 'hidden') {
$options['type'] = 'select';
}
// Missing HABTM
//...

if ($modelKey === $fieldKey) {
$options['type'] = 'select';
if (!isset($options['multiple'])) {
$options['multiple'] = 'multiple';
}
}
if (in_array($options['type'], array('text', 'number'))) {
$options = $this->_optionsOptions($options);
if (in_array($options['type'], ['text', 'number', 'radio', 'select'])) {
$options = $this->_optionsOptions($fieldName, $options);
}

if ($options['type'] === 'select' && array_key_exists('step', $options)) {
unset($options['step']);
}
$options = $this->_maxLength($options);

$autoLength = !array_key_exists('maxlength', $options)
&& !empty($fieldDef['length'])
&& $options['type'] !== 'select';

$allowedTypes = ['text', 'email', 'tel', 'url', 'search'];
if ($autoLength && in_array($options['type'], $allowedTypes)) {
$options['maxlength'] = $fieldDef['length'];
}

return $options;
}

Expand All @@ -1064,28 +1069,6 @@ protected function _getLabel($fieldName, $options) {
return $this->_inputLabel($fieldName, $label, $options);
}

/**
* Calculates maxlength option
*
* @param array $options
* @return array
*/
protected function _maxLength($options) {
$fieldDef = $this->_introspectModel($this->model(), 'fields', $this->field());
$autoLength = (
!array_key_exists('maxlength', $options) &&
isset($fieldDef['length']) &&
is_scalar($fieldDef['length']) &&
$options['type'] !== 'select'
);
if ($autoLength &&
in_array($options['type'], array('text', 'email', 'tel', 'url', 'search'))
) {
$options['maxlength'] = $fieldDef['length'];
}
return $options;
}

/**
* Extracts a single option from an options array.
*
Expand Down

0 comments on commit ecfd4cf

Please sign in to comment.