Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jun 22nd, 2012  |  syntax: PHP  |  size: 30.35 KB  |  hits: 14  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.  
  2. <?php
  3.  
  4. App::uses('ClassRegistry', 'Utility');
  5. App::uses('AppHelper', 'View/Helper');
  6.  
  7. class FormHelper extends AppHelper {
  8.  
  9.  
  10.         public function create($model = null, $options = array()) {
  11.                 $created = $id = false;
  12.                 $append = '';
  13.  
  14.                 if (is_array($model) && empty($options)) {
  15.                         $options = $model;
  16.                         $model = null;
  17.                 }
  18.  
  19.                 if (empty($model) && $model !== false && !empty($this->request->params['models'])) {
  20.                         $model = key($this->request->params['models']);
  21.                 } elseif (empty($model) && empty($this->request->params['models'])) {
  22.                         $model = false;
  23.                 }
  24.                 $this->defaultModel = $model;
  25.  
  26.                 $key = null;
  27.                 if ($model !== false) {
  28.                         $object = $this->_getModel($model);
  29.                         $key = $this->_introspectModel($model, 'key');
  30.                         $this->setEntity($model, true);
  31.                 }
  32.  
  33.                 if ($model !== false && $key) {
  34.                         $recordExists = (
  35.                                 isset($this->request->data[$model]) &&
  36.                                 !empty($this->request->data[$model][$key]) &&
  37.                                 !is_array($this->request->data[$model][$key])
  38.                         );
  39.  
  40.                         if ($recordExists) {
  41.                                 $created = true;
  42.                                 $id = $this->request->data[$model][$key];
  43.                         }
  44.                 }
  45.  
  46.                 $options = array_merge(array(
  47.                         'type' => ($created && empty($options['action'])) ? 'put' : 'post',
  48.                         'action' => null,
  49.                         'url' => null,
  50.                         'default' => true,
  51.                         'encoding' => strtolower(Configure::read('App.encoding')),
  52.                         'inputDefaults' => array()),
  53.                 $options);
  54.                 $this->_inputDefaults = $options['inputDefaults'];
  55.                 unset($options['inputDefaults']);
  56.  
  57.                 if (!isset($options['id'])) {
  58.                         $domId = isset($options['action']) ? $options['action'] : $this->request['action'];
  59.                         $options['id'] = $this->domId($domId . 'Form');
  60.                 }
  61.  
  62.                 if ($options['action'] === null && $options['url'] === null) {
  63.                         $options['action'] = $this->request->here(false);
  64.                 } elseif (empty($options['url']) || is_array($options['url'])) {
  65.                         if (empty($options['url']['controller'])) {
  66.                                 if (!empty($model)) {
  67.                                         $options['url']['controller'] = Inflector::underscore(Inflector::pluralize($model));
  68.                                 } elseif (!empty($this->request->params['controller'])) {
  69.                                         $options['url']['controller'] = Inflector::underscore($this->request->params['controller']);
  70.                                 }
  71.                         }
  72.                         if (empty($options['action'])) {
  73.                                 $options['action'] = $this->request->params['action'];
  74.                         }
  75.  
  76.                         $plugin = null;
  77.                         if ($this->plugin) {
  78.                                 $plugin = Inflector::underscore($this->plugin);
  79.                         }
  80.                         $actionDefaults = array(
  81.                                 'plugin' => $plugin,
  82.                                 'controller' => $this->_View->viewPath,
  83.                                 'action' => $options['action'],
  84.                         );
  85.                         $options['action'] = array_merge($actionDefaults, (array)$options['url']);
  86.                         if (empty($options['action'][0]) && !empty($id)) {
  87.                                 $options['action'][0] = $id;
  88.                         }
  89.                 } elseif (is_string($options['url'])) {
  90.                         $options['action'] = $options['url'];
  91.                 }
  92.                 unset($options['url']);
  93.  
  94.                 switch (strtolower($options['type'])) {
  95.                         case 'get':
  96.                                 $htmlAttributes['method'] = 'get';
  97.                         break;
  98.                         case 'file':
  99.                                 $htmlAttributes['enctype'] = 'multipart/form-data';
  100.                                 $options['type'] = ($created) ? 'put' : 'post';
  101.                         case 'post':
  102.                         case 'put':
  103.                         case 'delete':
  104.                                 $append .= $this->hidden('_method', array(
  105.                                         'name' => '_method', 'value' => strtoupper($options['type']), 'id' => null,
  106.                                         'secure' => self::SECURE_SKIP
  107.                                 ));
  108.                         default:
  109.                                 $htmlAttributes['method'] = 'post';
  110.                         break;
  111.                 }
  112.                 $this->requestType = strtolower($options['type']);
  113.  
  114.                 $action = $this->url($options['action']);
  115.                 unset($options['type'], $options['action']);
  116.  
  117.                 if ($options['default'] == false) {
  118.                         if (!isset($options['onsubmit'])) {
  119.                                 $options['onsubmit'] = '';
  120.                         }
  121.                         $htmlAttributes['onsubmit'] = $options['onsubmit'] . 'event.returnValue = false; return false;';
  122.                 }
  123.                 unset($options['default']);
  124.  
  125.                 if (!empty($options['encoding'])) {
  126.                         $htmlAttributes['accept-charset'] = $options['encoding'];
  127.                         unset($options['encoding']);
  128.                 }
  129.  
  130.                 $htmlAttributes = array_merge($options, $htmlAttributes);
  131.  
  132.                 $this->fields = array();
  133.                 $append .= $this->_csrfField();
  134.  
  135.                 if (!empty($append)) {
  136.                         $append = $this->Html->useTag('block', ' style="display:none;"', $append);
  137.                 }
  138.  
  139.                 if ($model !== false) {
  140.                         $this->setEntity($model, true);
  141.                         $this->_introspectModel($model, 'fields');
  142.                 }
  143.                 return $this->Html->useTag('form', $action, $htmlAttributes) . $append;
  144.         }
  145.  
  146.         public function end($options = null) {
  147.                 $out = null;
  148.                 $submit = null;
  149.  
  150.                 if ($options !== null) {
  151.                         $submitOptions = array();
  152.                         if (is_string($options)) {
  153.                                 $submit = $options;
  154.                         } else {
  155.                                 if (isset($options['label'])) {
  156.                                         $submit = $options['label'];
  157.                                         unset($options['label']);
  158.                                 }
  159.                                 $submitOptions = $options;
  160.                         }
  161.                         $out .= $this->submit($submit, $submitOptions);
  162.                 }
  163.                 if (isset($this->request['_Token']) && !empty($this->request['_Token'])) {
  164.                         $out .= $this->secure($this->fields);
  165.                         $this->fields = array();
  166.                 }
  167.                 $this->setEntity(null);
  168.                 $out .= $this->Html->useTag('formend');
  169.  
  170.                 $this->_View->modelScope = false;
  171.                 return $out;
  172.         }
  173.  
  174.         public function secure($fields = array()) {
  175.                 if (!isset($this->request['_Token']) || empty($this->request['_Token'])) {
  176.                         return;
  177.                 }
  178.                 $locked = array();
  179.                 $unlockedFields = $this->_unlockedFields;
  180.  
  181.                 foreach ($fields as $key => $value) {
  182.                         if (!is_int($key)) {
  183.                                 $locked[$key] = $value;
  184.                                 unset($fields[$key]);
  185.                         }
  186.                 }
  187.  
  188.                 sort($unlockedFields, SORT_STRING);
  189.                 sort($fields, SORT_STRING);
  190.                 ksort($locked, SORT_STRING);
  191.                 $fields += $locked;
  192.  
  193.                 $locked = implode(array_keys($locked), '|');
  194.                 $unlocked = implode($unlockedFields, '|');
  195.                 $fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'));
  196.  
  197.                 $out = $this->hidden('_Token.fields', array(
  198.                         'value' => urlencode($fields . ':' . $locked),
  199.                         'id' => 'TokenFields' . mt_rand()
  200.                 ));
  201.                 $out .= $this->hidden('_Token.unlocked', array(
  202.                         'value' => urlencode($unlocked),
  203.                         'id' => 'TokenUnlocked' . mt_rand()
  204.                 ));
  205.                 return $this->Html->useTag('block', ' style="display:none;"', $out);
  206.         }
  207.  
  208. /**
  209.  * Generates a form input element complete with label and wrapper div
  210.  *
  211.  * ### Options
  212.  *
  213.  * See each field type method for more information. Any options that are part of
  214.  * $attributes or $options for the different **type** methods can be included in `$options` for input().i
  215.  * Additionally, any unknown keys that are not in the list below, or part of the selected type's options
  216.  * will be treated as a regular html attribute for the generated input.
  217.  *
  218.  * - `type` - Force the type of widget you want. e.g. `type => 'select'`
  219.  * - `label` - Either a string label, or an array of options for the label. See FormHelper::label()
  220.  * - `div` - Either `false` to disable the div, or an array of options for the div.
  221.  *      See HtmlHelper::div() for more options.
  222.  * - `options` - for widgets that take options e.g. radio, select
  223.  * - `error` - control the error message that is produced
  224.  * - `empty` - String or boolean to enable empty select box options.
  225.  * - `before` - Content to place before the label + input.
  226.  * - `after` - Content to place after the label + input.
  227.  * - `between` - Content to place between the label + input.
  228.  * - `format` - format template for element order. Any element that is not in the array, will not be in the output.
  229.  *      - Default input format order: array('before', 'label', 'between', 'input', 'after', 'error')
  230.  *      - Default checkbox format order: array('before', 'input', 'between', 'label', 'after', 'error')
  231.  *      - Hidden input will not be formatted
  232.  *      - Radio buttons cannot have the order of input and label elements controlled with these settings.
  233.  *
  234.  * @param string $fieldName This should be "Modelname.fieldname"
  235.  * @param array $options Each type of input takes different options.
  236.  * @return string Completed form widget.
  237.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#creating-form-elements
  238.  */
  239.         public function input($fieldName, $options = array()) {
  240.                 $this->setEntity($fieldName);
  241.  
  242.                 $options = array_merge(
  243.                         array('before' => null, 'between' => null, 'after' => null, 'format' => null),
  244.                         $this->_inputDefaults,
  245.                         $options
  246.                 );
  247.  
  248.                 $modelKey = $this->model();
  249.                 $fieldKey = $this->field();
  250.  
  251.                 if (!isset($options['type'])) {
  252.                         $magicType = true;
  253.                         $options['type'] = 'text';
  254.                         if (isset($options['options'])) {
  255.                                 $options['type'] = 'select';
  256.                         } elseif (in_array($fieldKey, array('psword', 'passwd', 'password'))) {
  257.                                 $options['type'] = 'password';
  258.                         } elseif (isset($options['checked'])) {
  259.                                 $options['type'] = 'checkbox';
  260.                         } elseif ($fieldDef = $this->_introspectModel($modelKey, 'fields', $fieldKey)) {
  261.                                 $type = $fieldDef['type'];
  262.                                 $primaryKey = $this->fieldset[$modelKey]['key'];
  263.                         }
  264.  
  265.                         if (isset($type)) {
  266.                                 $map = array(
  267.                                         'string' => 'text', 'datetime' => 'datetime',
  268.                                         'boolean' => 'checkbox', 'timestamp' => 'datetime',
  269.                                         'text' => 'textarea', 'time' => 'time',
  270.                                         'date' => 'date', 'float' => 'number',
  271.                                         'integer' => 'number'
  272.                                 );
  273.  
  274.                                 if (isset($this->map[$type])) {
  275.                                         $options['type'] = $this->map[$type];
  276.                                 } elseif (isset($map[$type])) {
  277.                                         $options['type'] = $map[$type];
  278.                                 }
  279.                                 if ($fieldKey == $primaryKey) {
  280.                                         $options['type'] = 'hidden';
  281.                                 }
  282.                                 if (
  283.                                         $options['type'] === 'number' &&
  284.                                         $type === 'float' &&
  285.                                         !isset($options['step'])
  286.                                 ) {
  287.                                         $options['step'] = 'any';
  288.                                 }
  289.                         }
  290.                         if (preg_match('/_id$/', $fieldKey) && $options['type'] !== 'hidden') {
  291.                                 $options['type'] = 'select';
  292.                         }
  293.  
  294.                         if ($modelKey === $fieldKey) {
  295.                                 $options['type'] = 'select';
  296.                                 if (!isset($options['multiple'])) {
  297.                                         $options['multiple'] = 'multiple';
  298.                                 }
  299.                         }
  300.                 }
  301.                 $types = array('checkbox', 'radio', 'select');
  302.  
  303.                 if (
  304.                         (!isset($options['options']) && in_array($options['type'], $types)) ||
  305.                         (isset($magicType) && $options['type'] == 'text')
  306.                 ) {
  307.                         $varName = Inflector::variable(
  308.                                 Inflector::pluralize(preg_replace('/_id$/', '', $fieldKey))
  309.                         );
  310.                         $varOptions = $this->_View->getVar($varName);
  311.                         if (is_array($varOptions)) {
  312.                                 if ($options['type'] !== 'radio') {
  313.                                         $options['type'] = 'select';
  314.                                 }
  315.                                 $options['options'] = $varOptions;
  316.                         }
  317.                 }
  318.  
  319.                 $autoLength = (!array_key_exists('maxlength', $options) && isset($fieldDef['length']));
  320.                 if ($autoLength && $options['type'] == 'text') {
  321.                         $options['maxlength'] = $fieldDef['length'];
  322.                 }
  323.                 if ($autoLength && $fieldDef['type'] == 'float') {
  324.                         $options['maxlength'] = array_sum(explode(',', $fieldDef['length'])) + 1;
  325.                 }
  326.  
  327.                 $divOptions = array();
  328.                 $div = $this->_extractOption('div', $options, true);
  329.                 unset($options['div']);
  330.  
  331.                 if (!empty($div)) {
  332.                         $divOptions['class'] = 'input';
  333.                         $divOptions = $this->addClass($divOptions, $options['type']);
  334.                         if (is_string($div)) {
  335.                                 $divOptions['class'] = $div;
  336.                         } elseif (is_array($div)) {
  337.                                 $divOptions = array_merge($divOptions, $div);
  338.                         }
  339.                         if ($this->_introspectModel($modelKey, 'validates', $fieldKey)) {
  340.                                 $divOptions = $this->addClass($divOptions, 'required');
  341.                         }
  342.                         if (!isset($divOptions['tag'])) {
  343.                                 $divOptions['tag'] = 'div';
  344.                         }
  345.                 }
  346.  
  347.                 $label = null;
  348.                 if (isset($options['label']) && $options['type'] !== 'radio') {
  349.                         $label = $options['label'];
  350.                         unset($options['label']);
  351.                 }
  352.  
  353.                 if ($options['type'] === 'radio') {
  354.                         $label = false;
  355.                         if (isset($options['options'])) {
  356.                                 $radioOptions = (array)$options['options'];
  357.                                 unset($options['options']);
  358.                         }
  359.                 }
  360.  
  361.                 if ($label !== false) {
  362.                         $label = $this->_inputLabel($fieldName, $label, $options);
  363.                 }
  364.  
  365.                 $error = $this->_extractOption('error', $options, null);
  366.                 unset($options['error']);
  367.  
  368.                 $selected = $this->_extractOption('selected', $options, null);
  369.                 unset($options['selected']);
  370.  
  371.                 if (isset($options['rows']) || isset($options['cols'])) {
  372.                         $options['type'] = 'textarea';
  373.                 }
  374.  
  375.                 if ($options['type'] === 'datetime' || $options['type'] === 'date' || $options['type'] === 'time' || $options['type'] === 'select') {
  376.                         $options += array('empty' => false);
  377.                 }
  378.                 if ($options['type'] === 'datetime' || $options['type'] === 'date' || $options['type'] === 'time') {
  379.                         $dateFormat = $this->_extractOption('dateFormat', $options, 'MDY');
  380.                         $timeFormat = $this->_extractOption('timeFormat', $options, 12);
  381.                         unset($options['dateFormat'], $options['timeFormat']);
  382.                 }
  383.  
  384.                 $type = $options['type'];
  385.                 $out = array_merge(
  386.                         array('before' => null, 'label' => null, 'between' => null, 'input' => null, 'after' => null, 'error' => null),
  387.                         array('before' => $options['before'], 'label' => $label, 'between' => $options['between'], 'after' => $options['after'])
  388.                 );
  389.                 $format = null;
  390.                 if (is_array($options['format']) && in_array('input', $options['format'])) {
  391.                         $format = $options['format'];
  392.                 }
  393.                 unset($options['type'], $options['before'], $options['between'], $options['after'], $options['format']);
  394.  
  395.                 switch ($type) {
  396.                         case 'hidden':
  397.                                 $input = $this->hidden($fieldName, $options);
  398.                                 $format = array('input');
  399.                                 unset($divOptions);
  400.                         break;
  401.                         case 'checkbox':
  402.                                 $input = $this->checkbox($fieldName, $options);
  403.                                 $format = $format ? $format : array('before', 'input', 'between', 'label', 'after', 'error');
  404.                         break;
  405.                         case 'radio':
  406.                                 if (isset($out['between'])) {
  407.                                         $options['between'] = $out['between'];
  408.                                         $out['between'] = null;
  409.                                 }
  410.                                 $input = $this->radio($fieldName, $radioOptions, $options);
  411.                         break;
  412.                         case 'file':
  413.                                 $input = $this->file($fieldName, $options);
  414.                         break;
  415.                         case 'select':
  416.                                 $options += array('options' => array(), 'value' => $selected);
  417.                                 $list = $options['options'];
  418.                                 unset($options['options']);
  419.                                 $input = $this->select($fieldName, $list, $options);
  420.                         break;
  421.                         case 'time':
  422.                                 $options['value'] = $selected;
  423.                                 $input = $this->dateTime($fieldName, null, $timeFormat, $options);
  424.                         break;
  425.                         case 'date':
  426.                                 $options['value'] = $selected;
  427.                                 $input = $this->dateTime($fieldName, $dateFormat, null, $options);
  428.                         break;
  429.                         case 'datetime':
  430.                                 $options['value'] = $selected;
  431.                                 $input = $this->dateTime($fieldName, $dateFormat, $timeFormat, $options);
  432.                         break;
  433.                         case 'textarea':
  434.                                 $input = $this->textarea($fieldName, $options + array('cols' => '30', 'rows' => '6'));
  435.                         break;
  436.                         case 'url':
  437.                                 $input = $this->text($fieldName, array('type' => 'url') + $options);
  438.                         break;
  439.                         default:
  440.                                 $input = $this->{$type}($fieldName, $options);
  441.                 }
  442.  
  443.                 if ($type != 'hidden' && $error !== false) {
  444.                         $errMsg = $this->error($fieldName, $error);
  445.                         if ($errMsg) {
  446.                                 $divOptions = $this->addClass($divOptions, 'error');
  447.                                 $out['error'] = $errMsg;
  448.                         }
  449.                 }
  450.  
  451.                 $out['input'] = $input;
  452.                 $format = $format ? $format : array('before', 'label', 'between', 'input', 'after', 'error');
  453.                 $output = '';
  454.                 foreach ($format as $element) {
  455.                         $output .= $out[$element];
  456.                         unset($out[$element]);
  457.                 }
  458.  
  459.                 if (!empty($divOptions['tag'])) {
  460.                         $tag = $divOptions['tag'];
  461.                         unset($divOptions['tag']);
  462.                         $output = $this->Html->tag($tag, $output, $divOptions);
  463.                 }
  464.                 return $output;
  465.         }
  466. /**
  467.  * Creates a checkbox input widget.
  468.  *
  469.  * ### Options:
  470.  *
  471.  * - `value` - the value of the checkbox
  472.  * - `checked` - boolean indicate that this checkbox is checked.
  473.  * - `hiddenField` - boolean to indicate if you want the results of checkbox() to include
  474.  *    a hidden input with a value of ''.
  475.  * - `disabled` - create a disabled input.
  476.  * - `default` - Set the default value for the checkbox.  This allows you to start checkboxes
  477.  *    as checked, without having to check the POST data.  A matching POST data value, will overwrite
  478.  *    the default value.
  479.  *
  480.  * @param string $fieldName Name of a field, like this "Modelname.fieldname"
  481.  * @param array $options Array of HTML attributes.
  482.  * @return string An HTML text input element.
  483.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs
  484.  */
  485.         public function checkbox($fieldName, $options = array()) {
  486.                 $valueOptions = array();
  487.                 if (isset($options['default'])) {
  488.                         $valueOptions['default'] = $options['default'];
  489.                         unset($options['default']);
  490.                 }
  491.  
  492.                 $options = $this->_initInputField($fieldName, $options) + array('hiddenField' => true);
  493.                 $value = current($this->value($valueOptions));
  494.                 $output = "";
  495.  
  496.                 if (empty($options['value'])) {
  497.                         $options['value'] = 1;
  498.                 }
  499.                 if (
  500.                         (!isset($options['checked']) && !empty($value) && $value == $options['value']) ||
  501.                         !empty($options['checked'])
  502.                 ) {
  503.                         $options['checked'] = 'checked';
  504.                 }
  505.                 if ($options['hiddenField']) {
  506.                         $hiddenOptions = array(
  507.                                 'id' => $options['id'] . '_',
  508.                                 'name' => $options['name'],
  509.                                 'value' => ($options['hiddenField'] !== true ? $options['hiddenField'] : '0'),
  510.                                 'secure' => false
  511.                         );
  512.                         if (isset($options['disabled']) && $options['disabled'] == true) {
  513.                                 $hiddenOptions['disabled'] = 'disabled';
  514.                         }
  515.                         $output = $this->hidden($fieldName, $hiddenOptions);
  516.                 }
  517.                 unset($options['hiddenField']);
  518.  
  519.                 return $output . $this->Html->useTag('checkbox', $options['name'], array_diff_key($options, array('name' => '')));
  520.         }
  521.  
  522. /**
  523.  * Creates a set of radio widgets. Will create a legend and fieldset
  524.  * by default.  Use $options to control this
  525.  *
  526.  * ### Attributes:
  527.  *
  528.  * - `separator` - define the string in between the radio buttons
  529.  * - `between` - the string between legend and input set
  530.  * - `legend` - control whether or not the widget set has a fieldset & legend
  531.  * - `value` - indicate a value that is should be checked
  532.  * - `label` - boolean to indicate whether or not labels for widgets show be displayed
  533.  * - `hiddenField` - boolean to indicate if you want the results of radio() to include
  534.  *    a hidden input with a value of ''. This is useful for creating radio sets that non-continuous
  535.  * - `disabled` - Set to `true` or `disabled` to disable all the radio buttons.
  536.  *
  537.  * @param string $fieldName Name of a field, like this "Modelname.fieldname"
  538.  * @param array $options Radio button options array.
  539.  * @param array $attributes Array of HTML attributes, and special attributes above.
  540.  * @return string Completed radio widget set.
  541.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs
  542.  */
  543.         public function radio($fieldName, $options = array(), $attributes = array()) {
  544.                 $attributes = $this->_initInputField($fieldName, $attributes);
  545.  
  546.                 $legend = false;
  547.                 if (isset($attributes['legend'])) {
  548.                         $legend = $attributes['legend'];
  549.                         unset($attributes['legend']);
  550.                 } elseif (count($options) > 1) {
  551.                         $legend = __(Inflector::humanize($this->field()));
  552.                 }
  553.  
  554.                 $label = true;
  555.                 if (isset($attributes['label'])) {
  556.                         $label = $attributes['label'];
  557.                         unset($attributes['label']);
  558.                 }
  559.  
  560.                 $separator = null;
  561.                 if (isset($attributes['separator'])) {
  562.                         $separator = $attributes['separator'];
  563.                         unset($attributes['separator']);
  564.                 }
  565.  
  566.                 $between = null;
  567.                 if (isset($attributes['between'])) {
  568.                         $between = $attributes['between'];
  569.                         unset($attributes['between']);
  570.                 }
  571.  
  572.                 $value = null;
  573.                 if (isset($attributes['value'])) {
  574.                         $value = $attributes['value'];
  575.                 } else {
  576.                         $value = $this->value($fieldName);
  577.                 }
  578.  
  579.                 $disabled = array();
  580.                 if (isset($attributes['disabled'])) {
  581.                         $disabled = $attributes['disabled'];
  582.                 }
  583.  
  584.                 $out = array();
  585.  
  586.                 $hiddenField = isset($attributes['hiddenField']) ? $attributes['hiddenField'] : true;
  587.                 unset($attributes['hiddenField']);
  588.  
  589.                 foreach ($options as $optValue => $optTitle) {
  590.                         $optionsHere = array('value' => $optValue);
  591.  
  592.                         if (isset($value) && $optValue == $value) {
  593.                                 $optionsHere['checked'] = 'checked';
  594.                         }
  595.                         if ($disabled && (!is_array($disabled) || in_array($optValue, $disabled))) {
  596.                                 $optionsHere['disabled'] = true;
  597.                         }
  598.                         $tagName = Inflector::camelize(
  599.                                 $attributes['id'] . '_' . Inflector::slug($optValue)
  600.                         );
  601.  
  602.                         if ($label) {
  603.                                 $optTitle = $this->Html->useTag('label', $tagName, '', $optTitle);
  604.                         }
  605.                         $allOptions = array_merge($attributes, $optionsHere);
  606.                         $out[] = $this->Html->useTag('radio', $attributes['name'], $tagName,
  607.                                 array_diff_key($allOptions, array('name' => '', 'type' => '', 'id' => '')),
  608.                                 $optTitle
  609.                         );
  610.                 }
  611.                 $hidden = null;
  612.  
  613.                 if ($hiddenField) {
  614.                         if (!isset($value) || $value === '') {
  615.                                 $hidden = $this->hidden($fieldName, array(
  616.                                         'id' => $attributes['id'] . '_', 'value' => '', 'name' => $attributes['name']
  617.                                 ));
  618.                         }
  619.                 }
  620.                 $out = $hidden . implode($separator, $out);
  621.  
  622.                 if ($legend) {
  623.                         $out = $this->Html->useTag('fieldset', '', $this->Html->useTag('legend', $legend) . $between . $out);
  624.                 }
  625.                 return $out;
  626.         }
  627.  
  628.         public function textarea($fieldName, $options = array()) {
  629.                 $options = $this->_initInputField($fieldName, $options);
  630.                 $value = null;
  631.  
  632.                 if (array_key_exists('value', $options)) {
  633.                         $value = $options['value'];
  634.                         if (!array_key_exists('escape', $options) || $options['escape'] !== false) {
  635.                                 $value = h($value);
  636.                         }
  637.                         unset($options['value']);
  638.                 }
  639.                 return $this->Html->useTag('textarea', $options['name'], array_diff_key($options, array('type' => '', 'name' => '')), $value);
  640.         }
  641.  
  642. /**
  643.  * Creates a hidden input field.
  644.  *
  645.  * @param string $fieldName Name of a field, in the form of "Modelname.fieldname"
  646.  * @param array $options Array of HTML attributes.
  647.  * @return string A generated hidden input
  648.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::hidden
  649.  */
  650.         public function hidden($fieldName, $options = array()) {
  651.                 $secure = true;
  652.  
  653.                 if (isset($options['secure'])) {
  654.                         $secure = $options['secure'];
  655.                         unset($options['secure']);
  656.                 }
  657.                 $options = $this->_initInputField($fieldName, array_merge(
  658.                         $options, array('secure' => self::SECURE_SKIP)
  659.                 ));
  660.  
  661.                 if ($secure && $secure !== self::SECURE_SKIP) {
  662.                         $this->_secure(true, null, '' . $options['value']);
  663.                 }
  664.  
  665.                 return $this->Html->useTag('hidden', $options['name'], array_diff_key($options, array('name' => '')));
  666.         }
  667.  
  668. /**
  669.  * Creates file input widget.
  670.  *
  671.  * @param string $fieldName Name of a field, in the form "Modelname.fieldname"
  672.  * @param array $options Array of HTML attributes.
  673.  * @return string A generated file input.
  674.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::file
  675.  */
  676.         public function file($fieldName, $options = array()) {
  677.                 $options += array('secure' => true);
  678.                 $secure = $options['secure'];
  679.                 $options['secure'] = self::SECURE_SKIP;
  680.  
  681.                 $options = $this->_initInputField($fieldName, $options);
  682.                 $field = $this->entity();
  683.  
  684.                 foreach (array('name', 'type', 'tmp_name', 'error', 'size') as $suffix) {
  685.                         $this->_secure($secure, array_merge($field, array($suffix)));
  686.                 }
  687.  
  688.                 return $this->Html->useTag('file', $options['name'], array_diff_key($options, array('name' => '')));
  689.         }
  690.  
  691. /**
  692.  * Creates a `<button>` tag.  The type attribute defaults to `type="submit"`
  693.  * You can change it to a different value by using `$options['type']`.
  694.  *
  695.  * ### Options:
  696.  *
  697.  * - `escape` - HTML entity encode the $title of the button. Defaults to false.
  698.  *
  699.  * @param string $title The button's caption. Not automatically HTML encoded
  700.  * @param array $options Array of options and HTML attributes.
  701.  * @return string A HTML button tag.
  702.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::button
  703.  */
  704.         public function button($title, $options = array()) {
  705.                 $options += array('type' => 'submit', 'escape' => false, 'secure' => false);
  706.                 if ($options['escape']) {
  707.                         $title = h($title);
  708.                 }
  709.                 if (isset($options['name'])) {
  710.                         $name = str_replace(array('[', ']'), array('.', ''), $options['name']);
  711.                         $this->_secure($options['secure'], $name);
  712.                 }
  713.                 return $this->Html->useTag('button', $options, $title);
  714.         }
  715.  
  716. /**
  717.  * Create a `<button>` tag with a surrounding `<form>` that submits via POST.
  718.  *
  719.  * This method creates a `<form>` element. So do not use this method in an already opened form.
  720.  * Instead use FormHelper::submit() or FormHelper::button() to create buttons inside opened forms.
  721.  *
  722.  * ### Options:
  723.  *
  724.  * - `data` - Array with key/value to pass in input hidden
  725.  * - Other options is the same of button method.
  726.  *
  727.  * @param string $title The button's caption. Not automatically HTML encoded
  728.  * @param mixed $url URL as string or array
  729.  * @param array $options Array of options and HTML attributes.
  730.  * @return string A HTML button tag.
  731.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::postButton
  732.  */
  733.         public function postButton($title, $url, $options = array()) {
  734.                 $out = $this->create(false, array('id' => false, 'url' => $url));
  735.                 if (isset($options['data']) && is_array($options['data'])) {
  736.                         foreach ($options['data'] as $key => $value) {
  737.                                 $out .= $this->hidden($key, array('value' => $value, 'id' => false));
  738.                         }
  739.                         unset($options['data']);
  740.                 }
  741.                 $out .= $this->button($title, $options);
  742.                 $out .= $this->end();
  743.                 return $out;
  744.         }
  745.  
  746. /**
  747.  * Creates an HTML link, but access the url using method POST.
  748.  * Requires javascript to be enabled in browser.
  749.  *
  750.  * This method creates a `<form>` element. So do not use this method inside an existing form.
  751.  * Instead you should add a submit button using FormHelper::submit()
  752.  *
  753.  * ### Options:
  754.  *
  755.  * - `data` - Array with key/value to pass in input hidden
  756.  * - `confirm` - Can be used instead of $confirmMessage.
  757.  * - Other options is the same of HtmlHelper::link() method.
  758.  * - The option `onclick` will be replaced.
  759.  *
  760.  * @param string $title The content to be wrapped by <a> tags.
  761.  * @param mixed $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
  762.  * @param array $options Array of HTML attributes.
  763.  * @param string $confirmMessage JavaScript confirmation message.
  764.  * @return string An `<a />` element.
  765.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::postLink
  766.  */
  767.         public function postLink($title, $url = null, $options = array(), $confirmMessage = false) {
  768.                 if (!empty($options['confirm'])) {
  769.                         $confirmMessage = $options['confirm'];
  770.                         unset($options['confirm']);
  771.                 }
  772.  
  773.                 $formName = uniqid('post_');
  774.                 $formUrl = $this->url($url);
  775.                 $out = $this->Html->useTag('form', $formUrl, array('name' => $formName, 'id' => $formName, 'style' => 'display:none;', 'method' => 'post'));
  776.                 $out .= $this->Html->useTag('hidden', '_method', ' value="POST"');
  777.                 $out .= $this->_csrfField();
  778.  
  779.                 $fields = array();
  780.                 if (isset($options['data']) && is_array($options['data'])) {
  781.                         foreach ($options['data'] as $key => $value) {
  782.                                 $fields[$key] = $value;
  783.                                 $out .= $this->hidden($key, array('value' => $value, 'id' => false));
  784.                         }
  785.                         unset($options['data']);
  786.                 }
  787.                 $out .= $this->secure($fields);
  788.                 $out .= $this->Html->useTag('formend');
  789.  
  790.                 $url = '#';
  791.                 $onClick = 'document.' . $formName . '.submit();';
  792.                 if ($confirmMessage) {
  793.                         $confirmMessage = str_replace(array("'", '"'), array("\'", '\"'), $confirmMessage);
  794.                         $options['onclick'] = "if (confirm('{$confirmMessage}')) { {$onClick} }";
  795.                 } else {
  796.                         $options['onclick'] = $onClick;
  797.                 }
  798.                 $options['onclick'] .= ' event.returnValue = false; return false;';
  799.  
  800.                 $out .= $this->Html->link($title, $url, $options);
  801.                 return $out;
  802.         }
  803.  
  804. /**
  805.  * Creates a submit button element.  This method will generate `<input />` elements that
  806.  * can be used to submit, and reset forms by using $options.  image submits can be created by supplying an
  807.  * image path for $caption.
  808.  *
  809.  * ### Options
  810.  *
  811.  * - `div` - Include a wrapping div?  Defaults to true.  Accepts sub options similar to
  812.  *   FormHelper::input().
  813.  * - `before` - Content to include before the input.
  814.  * - `after` - Content to include after the input.
  815.  * - `type` - Set to 'reset' for reset inputs.  Defaults to 'submit'
  816.  * - Other attributes will be assigned to the input element.
  817.  *
  818.  * ### Options
  819.  *
  820.  * - `div` - Include a wrapping div?  Defaults to true.  Accepts sub options similar to
  821.  *   FormHelper::input().
  822.  * - Other attributes will be assigned to the input element.
  823.  *
  824.  * @param string $caption The label appearing on the button OR if string contains :// or the
  825.  *  extension .jpg, .jpe, .jpeg, .gif, .png use an image if the extension
  826.  *  exists, AND the first character is /, image is relative to webroot,
  827.  *  OR if the first character is not /, image is relative to webroot/img.
  828.  * @param array $options Array of options.  See above.
  829.  * @return string A HTML submit button
  830.  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::submit
  831.  */
  832.         public function submit($caption = null, $options = array()) {
  833.                 if (!is_string($caption) && empty($caption)) {
  834.                         $caption = __d('cake', 'Submit');
  835.                 }
  836.                 $out = null;
  837.                 $div = true;
  838.  
  839.                 if (isset($options['div'])) {
  840.                         $div = $options['div'];
  841.                         unset($options['div']);
  842.                 }
  843.                 $options += array('type' => 'submit', 'before' => null, 'after' => null, 'secure' => false);
  844.                 $divOptions = array('tag' => 'div');
  845.  
  846.                 if ($div === true) {
  847.                         $divOptions['class'] = 'submit';
  848.                 } elseif ($div === false) {
  849.                         unset($divOptions);
  850.                 } elseif (is_string($div)) {
  851.                         $divOptions['class'] = $div;
  852.                 } elseif (is_array($div)) {
  853.                         $divOptions = array_merge(array('class' => 'submit', 'tag' => 'div'), $div);
  854.                 }
  855.  
  856.                 if (isset($options['name'])) {
  857.                         $name = str_replace(array('[', ']'), array('.', ''), $options['name']);
  858.                         $this->_secure($options['secure'], $name);
  859.                 }
  860.                 unset($options['secure']);
  861.  
  862.                 $before = $options['before'];
  863.                 $after = $options['after'];
  864.                 unset($options['before'], $options['after']);
  865.  
  866.                 $isUrl = strpos($caption, '://') !== false;
  867.                 $isImage = preg_match('/\.(jpg|jpe|jpeg|gif|png|ico)$/', $caption);
  868.  
  869.                 if ($isUrl || $isImage) {
  870.                         $unlockFields = array('x', 'y');
  871.                         if (isset($options['name'])) {
  872.                                 $unlockFields = array(
  873.                                         $options['name'] . '_x', $options['name'] . '_y'
  874.                                 );
  875.                         }
  876.                         foreach ($unlockFields as $ignore) {
  877.                                 $this->unlockField($ignore);
  878.                         }
  879.                 }
  880.  
  881.                 if ($isUrl) {
  882.                         unset($options['type']);
  883.                         $tag = $this->Html->useTag('submitimage', $caption, $options);
  884.                 } elseif ($isImage) {
  885.                         unset($options['type']);
  886.                         if ($caption{0} !== '/') {
  887.                                 $url = $this->webroot(IMAGES_URL . $caption);
  888.                         } else {
  889.                                 $url = $this->webroot(trim($caption, '/'));
  890.                         }
  891.                         $url = $this->assetTimestamp($url);
  892.                         $tag = $this->Html->useTag('submitimage', $url, $options);
  893.                 } else {
  894.                         $options['value'] = $caption;
  895.                         $tag = $this->Html->useTag('submit', $options);
  896.                 }
  897.                 $out = $before . $tag . $after;
  898.  
  899.                 if (isset($divOptions)) {
  900.                         $tag = $divOptions['tag'];
  901.                         unset($divOptions['tag']);
  902.                         $out = $this->Html->tag($tag, $out, $divOptions);
  903.                 }
  904.                 return $out;
  905.         }
  906.  
  907. }