LoginSignup
7
7

More than 1 year has passed since last update.

[CakePHP2]Formヘルパーのmultiple->checkboxのdivをどうにかする

Last updated at Posted at 2014-07-15

コーダーさんに泣いて頼まれたのであのウザいdivをどうにかしてみた
空の値渡した場合の処理&classの貼っつけかたはかなーり適当なので修正必要かもー?

ソース

/app/View/Helper/CustomFormHelper.php
App::uses('FormHelper', 'View/Helper');

class CustomFormHelper extends FormHelper {

    public function select($fieldName, $options = array(), $attributes = array()) {
        $select = array();
        $style = null;
        $tag = null;
        $attributes += array(
            'class' => null,
            'escape' => true,
            'secure' => true,
            'empty' => '',
            'showParents' => false,
            'hiddenField' => true,
            'disabled' => false,
            'multipleOptionTag' => 'div'
        );

        $escapeOptions = $this->_extractOption('escape', $attributes);
        $secure = $this->_extractOption('secure', $attributes);
        $showEmpty = $this->_extractOption('empty', $attributes);
        $showParents = $this->_extractOption('showParents', $attributes);
        $hiddenField = $this->_extractOption('hiddenField', $attributes);
        unset($attributes['escape'], $attributes['secure'], $attributes['empty'], $attributes['showParents'], $attributes['hiddenField']);
        $id = $this->_extractOption('id', $attributes);

        $attributes = $this->_initInputField($fieldName, array_merge(
            (array)$attributes, array('secure' => self::SECURE_SKIP)
        ));

        if (is_string($options) && isset($this->_options[$options])) {
            $options = $this->_generateOptions($options);
        } elseif (!is_array($options)) {
            $options = array();
        }
        if (isset($attributes['type'])) {
            unset($attributes['type']);
        }

        if (!empty($attributes['multiple'])) {
            $style = ($attributes['multiple'] === 'checkbox') ? 'checkbox' : null;
            $template = ($style) ? 'checkboxmultiplestart' : 'selectmultiplestart';
            $tag = $template;
            if ($hiddenField) {
                $hiddenAttributes = array(
                    'value' => '',
                    'id' => $attributes['id'] . ($style ? '' : '_'),
                    'secure' => false,
                    'name' => $attributes['name']
                );
                $select[] = $this->hidden(null, $hiddenAttributes);
            }
        } else {
            $tag = 'selectstart';
        }

        if (!empty($tag) || isset($template)) {
            $hasOptions = (count($options) > 0 || $showEmpty);
            // Secure the field if there are options, or its a multi select.
            // Single selects with no options don't submit, but multiselects do.
            if (
                (!isset($secure) || $secure) &&
                empty($attributes['disabled']) &&
                (!empty($attributes['multiple']) || $hasOptions)
            ) {
                $this->_secure(true, $this->_secureFieldName($attributes));
            }
            $selectAttr = $attributes;
            unset($selectAttr['multipleOptionTag']);
            $select[] = $this->Html->useTag($tag, $selectAttr['name'], array_diff_key($selectAttr, array('name' => null, 'value' => null)));
        }
        $emptyMulti = (
            $showEmpty !== null && $showEmpty !== false && !(
                empty($showEmpty) && (isset($attributes) &&
                array_key_exists('multiple', $attributes))
            )
        );

        if ($emptyMulti) {
            $showEmpty = ($showEmpty === true) ? '' : $showEmpty;
            $options = array('' => $showEmpty) + $options;
        }

        if (!$id) {
            $attributes['id'] = Inflector::camelize($attributes['id']);
        }

        $select = array_merge($select, $this->_selectOptions(
            array_reverse($options, true),
            array(),
            $showParents,
            array(
                'escape' => $escapeOptions,
                'style' => $style,
                'name' => $attributes['name'],
                'value' => $attributes['value'],
                'class' => $attributes['class'],
                'id' => $attributes['id'],
                'disabled' => $attributes['disabled'],
                'multipleOptionTag' => $attributes['multipleOptionTag']
            )
        ));

        $template = ($style === 'checkbox') ? 'checkboxmultipleend' : 'selectend';
        $select[] = $this->Html->useTag($template);
        return implode("\n", $select);
    }

    protected function _selectOptions($elements = array(), $parents = array(), $showParents = null, $attributes = array()) {
        $select = array();
        $attributes = array_merge(
            array('escape' => true, 'style' => null, 'value' => null, 'class' => null, 'multipleOptionTag' => 'div'),
            $attributes
        );
        $selectedIsEmpty = ($attributes['value'] === '' || $attributes['value'] === null);
        $selectedIsArray = is_array($attributes['value']);

        foreach ($elements as $name => $title) {
            $htmlOptions = array();
            if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) {
                if (!empty($name)) {
                    if ($attributes['style'] === 'checkbox') {
                        $select[] = $this->Html->useTag('fieldsetend');
                    } else {
                        $select[] = $this->Html->useTag('optiongroupend');
                    }
                    $parents[] = $name;
                }
                $select = array_merge($select, $this->_selectOptions(
                    $title, $parents, $showParents, $attributes
                ));

                if (!empty($name)) {
                    $name = $attributes['escape'] ? h($name) : $name;
                    if ($attributes['style'] === 'checkbox') {
                        $select[] = $this->Html->useTag('fieldsetstart', $name);
                    } else {
                        $select[] = $this->Html->useTag('optiongroup', $name, '');
                    }
                }
                $name = null;
            } elseif (is_array($title)) {
                $htmlOptions = $title;
                $name = $title['value'];
                $title = $title['name'];
                unset($htmlOptions['name'], $htmlOptions['value']);
            }

            if ($name !== null) {
                $isNumeric = is_numeric($name);
                if (
                    (!$selectedIsArray && !$selectedIsEmpty && (string)$attributes['value'] == (string)$name) ||
                    ($selectedIsArray && in_array((string)$name, $attributes['value'], !$isNumeric))
                ) {
                    if ($attributes['style'] === 'checkbox') {
                        $htmlOptions['checked'] = true;
                    } else {
                        $htmlOptions['selected'] = 'selected';
                    }
                }

                if ($showParents || (!in_array($title, $parents))) {
                    $title = ($attributes['escape']) ? h($title) : $title;

                    $hasDisabled = !empty($attributes['disabled']);
                    if ($hasDisabled) {
                        $disabledIsArray = is_array($attributes['disabled']);
                        if ($disabledIsArray) {
                            $disabledIsNumeric = is_numeric($name);
                        }
                    }
                    if (
                        $hasDisabled &&
                        $disabledIsArray &&
                        in_array((string)$name, $attributes['disabled'], !$disabledIsNumeric)
                    ) {
                        $htmlOptions['disabled'] = 'disabled';
                    }
                    if ($hasDisabled && !$disabledIsArray && $attributes['style'] === 'checkbox') {
                        $htmlOptions['disabled'] = $attributes['disabled'] === true ? 'disabled' : $attributes['disabled'];
                    }

                    if ($attributes['style'] === 'checkbox') {
                        $htmlOptions['value'] = $name;

                        $tagName = $attributes['id'] . Inflector::camelize(Inflector::slug($name));
                        $htmlOptions['id'] = $tagName;
                        $label = array('for' => $tagName);

                        if (isset($htmlOptions['checked']) && $htmlOptions['checked'] === true) {
                            $label['class'] = 'selected';
                        }

                        $name = $attributes['name'];

                        if (empty($attributes['class'])) {
                            $attributes['class'] = 'checkbox';
                        } elseif ($attributes['class'] === 'form-error') {
                            $attributes['class'] = 'checkbox ' . $attributes['class'];
                        }
                        if (!strstr($attributes['class'], 'selected') && empty($attributes['multipleOptionTag'])) {
                            $label['class'] = (isset($label['class'])) ? $attributes['class'] . ' ' . $label['class'] : $attributes['class'];
                        }
                        $label = $this->label(null, $title, $label);
                        $item = $this->Html->useTag('checkboxmultiple', $name, $htmlOptions);
                        $select[] = $this->Html->tag($attributes['multipleOptionTag'], $item . $label, array('class' => $attributes['class']));
                    } else {
                        $select[] = $this->Html->useTag('selectoption', $name, $htmlOptions, $title);
                    }
                }
            }
        }

        return array_reverse($select, true);
    }
}

/app/Controller/AppController.php
class AppController extends Controller {
    public $helpers = array('Form' => array('className' => 'CustomForm'));
}
/app/View/Hoges/index.php
<?php echo $this->Form->input('hoge', array('type' => 'select', 'multiple' => 'checkbox',  'multipleOptionTag' => 'span', 'options' => array(1 => 'ほげ', 2 => 'ふが'))); ?>

結果

<div class="input select">
    <label for="hoge">Hoge</label>
    <input type="hidden" name="data[hoge]" value="" id="hoge">
    <span class="checkbox">
        <input type="checkbox" name="data[hoge][]" value="1" id="Hoge1">
        <label for="Hoge1">ほげ</label>
    </span>
    <span class="checkbox">
        <input type="checkbox" name="data[hoge][]" value="2" id="Hoge2">
        <label for="Hoge2">ふが</label>
    </span>
</div>
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7