* @author Shohei Nakajima * @link http://www.netcommons.org NetCommons Project * @license http://www.netcommons.org/license.txt NetCommons License * @copyright Copyright 2014, NetCommons Project */ App::uses('AppHelper', 'View/Helper'); /** * NetCommonsでFormHelperをOverrideしたHelper * * @property FormHelper $Form * @property HtmlHelper $Html * @property FilesFormHelper $FilesForm * @property ButtonHelper $Button * @property FormInputHelper $FormInput * @property NetCommonsHtmlHelper $NetCommonsHtml * @property NetCommonsTimeHelper $NetCommonsTime * @property DatetimePickerHelper $DatetimePicker * * @package NetCommons\NetCommons\View\Helper */ class NetCommonsFormHelper extends AppHelper { /** * 使用するHelpers * * - [FormHelper](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html) * - [HtmlHelper](http://book.cakephp.org/2.0/ja/core-libraries/helpers/html.html) * - [Files.FilesFormHelper](../../Files/classes/FilesFormHelper.html) * - [NetCommons.ButtonHelper](../../NetCommons/classes/ButtonHelper.html) * - [NetCommons.FormInputHelper](../../NetCommons/classes/FormInputHelper.html) * - [NetCommons.NetCommonsHtmlHelper](../../NetCommons/classes/NetCommonsHtmlHelper.html) * - [NetCommons.NetCommonsTimeHelper](../../NetCommons/classes/NetCommonsTimeHelper.html) * - [NetCommons.DatetimePickerHelper](../../NetCommons/classes/DatetimePickerHelper.html) * * @var array */ public $helpers = array( 'Form', 'Html', 'Files.FilesForm', 'NetCommons.Button', 'NetCommons.FormInput', 'NetCommons.NetCommonsHtml', 'NetCommons.NetCommonsTime', 'NetCommons.DatetimePicker', ); /** * 各プラグインFormHelperラップ用マジックメソッド * * 指定されたメソッドにより、各プラグインのFormHelperのメソッドを呼び出します。 * * #### $method による出力内容 * - * NetCommonsForm::uploadFile()
* [Files.FilesFormHelper::uploadFile()](../../Files/classes/FilesFormHelper.html#method_uploadFile) * の結果を出力する。 * * - * NetCommonsForm::checkbox()
* [NetCommons.FormInputHelper::checkbox()](./FormInputHelper.html#method_checkbox) * の結果を出力する。 * * - * NetCommonsForm::radio()
* [NetCommons.FormInputHelper::radio()](./FormInputHelper.html#method_radio) * の結果を出力する。 * * - * NetCommonsForm::wysiwyg()
* [Wysiwyg.WysiwygHelper::wysiwyg()](../../Wysiwyg/classes/WysiwygHelper.html#method_wysiwyg) * の結果を出力する。 * * - * NetCommonsForm::inlineCheckbox()
* $paramsに以下を追加して、 * [NetCommons.FormInputHelper::checkbox()](./FormInputHelper.html#method_checkbox) * の結果を出力する。ただし、すでに$paramsにあれば、無視する。 * ``` * $params[1] = array( * 'class' => false, * 'div' => array('class' => 'form-group') * ) * ``` * * - * NetCommonsForm::inputWithTitleIcon()
* [NetCommons.TitleIconHelper::inputWithTitleIcon()](./TitleIconHelper.html#method_inputWithTitleIcon) * の結果を出力する。 * * - * NetCommonsForm::titleIconPicker()
* [NetCommons.TitleIconHelper::titleIconPicker()](./TitleIconHelper.html#method_titleIconPicker) * の結果を出力する。 * * - * NetCommonsForm::ngTitleIconPicker()
* [NetCommons.TitleIconHelper::ngTitleIconPicker()](./TitleIconHelper.html#method_ngTitleIconPicker) * の結果を出力する。 * * - * NetCommonsForm::ngTitleIconPicker()
* [NetCommons.DisplayNumber::select()](./DisplayNumberHelper.html#method_select) * の結果を出力する。 * * - * それ以外
* [FormHelper](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#formhelper) * の各メソッドの結果を出力する。 * * @param string $method メソッド * @param array $params パラメータ * @return mixed */ public function __call($method, $params) { if ($method === 'uploadFile') { //アップロード $helper = $this->FilesForm; } elseif (in_array($method, ['hidden', 'checkbox', 'radio', 'select', 'email'], true)) { $helper = $this->FormInput; } elseif ($method === 'wysiwyg') { //WYSIWYG $helper = $this->_View->loadHelper('Wysiwyg.Wysiwyg'); } elseif ($method === 'inlineCheckbox') { //checkbox、radioのインライン $helper = $this->FormInput; $method = 'checkbox'; $params = Hash::insert($params, '1.class', false); $params = Hash::insert($params, '1.div', array('class' => 'form-group')); } elseif (in_array($method, ['inputWithTitleIcon', 'titleIconPicker', 'ngTitleIconPicker'], true)) { //タイトルアイコン $this->NetCommonsHtml->script('/net_commons/js/title_icon_picker.js'); $helper = $this->_View->loadHelper('NetCommons.TitleIcon'); } elseif ($method === 'selectNumber') { //表示件数 $helper = $this->_View->loadHelper('NetCommons.DisplayNumber'); $method = 'select'; } elseif ($method === 'selectDays') { //表示件数 $helper = $this->_View->loadHelper('NetCommons.DisplayNumber'); $method = 'selectDays'; } elseif ($method === 'button') { //ボタン $helper = $this->_View->loadHelper('NetCommons.Button'); } else { //それ以外 $helper = $this->Form; } return call_user_func_array(array($helper, $method), $params); } /** * 共通のオプションをセットして、FormHelper->create()の結果を出力する * * - 二重submit防止のため、ng-submit=submit($event)をセットする * - エラー出力をNetCommons用の表示をするため、novalidateをOffにする * * #### return サンプル * ``` *
* ``` * * @param mixed $model モデル名 * @param array $options オプション * @return string * @see http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#FormHelper::create FormHelper::create() */ public function create($model = null, $options = array()) { $options['ng-submit'] = Hash::get($options, 'ng-submit', 'submit($event)'); $options['novalidate'] = Hash::get($options, 'novalidate', true); $output = $this->Form->create($model, $options); if (Hash::get($options, 'type') === 'file') { $output .= $this->FilesForm->setupFileUploadForm(); } return $output; } /** * NetCommons用Htmlを付加して、FormHelper::input()の結果を出力する。 * * ##### 下記の$optionsに指定した内容に基づきHTMLを出力する。 * * - * help=メッセージ(NCオリジナル)
* このオプションは、ヘルプブロックを出力するオプション。
* - 入力 * ``` * echo $this->NetCommonsForm->input('Bbs.name', * array( * 'type' => 'text', * 'label' => __d('bbses', 'Bbs name'), * 'required' => true, * 'help' => '掲示板名を入力してください。', * ) * ); * ``` * - 出力 * ``` *
* * *
掲示板名を入力してください。
*
*
* ``` * * - * type=text (typeを省略した場合、デフォルト値)
* [FormHelper::input()](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#formhelper) * の結果を出力する。
* - 入力 * ``` * echo $this->NetCommonsForm->input('Bbs.name', * array( * 'type' => 'text', * 'label' => __d('bbses', 'Bbs name'), * 'required' => true, * ) * ); * ``` * - 出力 * ``` *
* * *
*
* ``` * * - * type=textarea
* [FormHelper::input()](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#formhelper) * の結果を出力する。
* - 入力 * ``` * echo $this->NetCommonsForm->input('Bbs.name', * array( * 'type' => 'textarea', * 'label' => '内容', * 'required' => true, * ) * ); * ``` * - 出力 * ``` *
* * *
*
* ``` * * - * type=radio
* [FormInputHelper::radio()](./FormInputHelper.html#method_radio) * の結果を出力する。 * * - * type=select, multiple=checkbox
* [FormInputHelper::multipleCheckbox()](./FormInputHelper.html#method_multipleCheckbox) * の結果を出力する。 * * - * type=checkbox
* [FormInputHelper::checkbox()](./FormInputHelper.html#method_checkbox) * の結果を出力する。 * * - * type=select
* [FormInputHelper::select()](./FormInputHelper.html#method_select) * の結果を出力する。 * * - * type=hidden
* [FormInputHelper::hidden()](./FormInputHelper.html#method_hidden) * の結果を出力する。 * * - * type=datetime
* [datetimepicker](./DatetimePickerHelper.html) * の結果を出力する。
* - 入力 * ``` * echo $this->NetCommonsForm->input('publish_start', * array( * 'type' => 'datetime', * 'required' => 'required', * 'label' => __d('blogs', 'Published datetime') * ) * ); * ``` * - 出力 * ``` *
* * *
*
* ``` *
* * ##### $optionsの内容の他に、下記のHTMLを強制的に出力する。 * - TimeZone関係のHTML * ``` * * * ``` * - エラー発生時、入力ボックスの色を変えるためのdiv * ``` *
* ・・・ *
* ``` * * @param string $fieldName フィールド名("Modelname.fieldname"形式) * @param array $options オプション配列 * ##### $optionsの初期値 * - 共通 * ``` * array( * 'error' => false, * 'required' => null, * 'label' => null, * ); * ``` * - type=number の場合 * ``` * array( * 'error' => false, * 'required' => null, * 'label' => null, * 'min' => 0, * 'div' => array('class' => 'form-group') * ); * ``` * * ##### $optionsの値
* 基本的なオプションについては、[FormHelperのオプション](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#id5)を参照。 * そのうち、下記が良く使われるオプションである。 * * - 必須マークを付ける場合 * ``` * array( * 'required' => true, * ); * ``` * - * プレースホルダーテキストを表示する場合 * ``` * array( * 'placeholder' => 'アンケートを入力してください。', * ); * ``` * - ヘルプブロックを表示する場合(NetCommonsのみのオプション)
* 出力内容については、[こちら](#method_input_help) を参照。 * ``` * array( * 'help' => 'アンケートを入力してください。', * ); * ``` * * @return string */ public function input($fieldName, $options = array()) { if (Hash::get($options, 'type') === 'hidden') { return $this->FormInput->hidden($fieldName, $options); } //DatetimePicker用処理 $options = $this->DatetimePicker->beforeFormInput($fieldName, $options); //TimeZoneのコンバートするinputのセットアップ $this->NetCommonsTime->beforeFormInput($fieldName, $options); $options = Hash::merge(array( 'error' => array(), ), $options); $help = Hash::get($options, 'help', false); $options = Hash::remove($options, 'help'); $helpOptions = Hash::get($options, 'helpOptions', null); $options = Hash::remove($options, 'helpOptions'); $type = Hash::get($options, 'type', 'text'); $inputOptions = $this->_inputOptions($type, $options); //Form->inputには含めないため、divの設定を取得しておく $divOption = $this->FormInput->getDivOption( $type, $inputOptions, 'div', array('class' => 'form-group') ); $inputOptions = Hash::remove($inputOptions, 'div'); $inputOptions = Hash::insert( $inputOptions, 'div', $this->FormInput->getDivOption($type, $inputOptions, 'childDiv', false) ); $inputOptions = Hash::remove($inputOptions, 'childDiv'); //errorの有無 $error = (bool)$this->Form->error($fieldName); if (in_array(Hash::get($options, 'type'), ['password', 'email'], true)) { $error = $error || (bool)$this->Form->error($fieldName . '_again'); } //Form->input $input = ''; if ($error && Hash::get($inputOptions, 'error') !== false) { $input .= '
'; $input .= $this->_input($fieldName, $inputOptions); $input .= '
'; } else { $input .= $this->_input($fieldName, $inputOptions); } //ヘルプブロックの追加 $input .= $this->help($help, $helpOptions); //error出力 if (is_array($options['error'])) { $options['error']['current'] = Hash::get($options, 'type') === 'password'; $options['error']['again'] = Hash::get($options, 'type') === 'password'; $input .= $this->error($fieldName, null, $options['error']); } if ($divOption) { return $this->NetCommonsHtml->div(null, $input, $divOption); } else { return $input; } } /** * のオプション * このメソッドは、NetCommonsFormHelper->input()から実行される。 * * @param string $type タイプ * @param array $options オプション配列 * @return array */ protected function _inputOptions($type, $options) { $defaultOptions = array( 'error' => false, //'class' => 'form-control', 'required' => null, 'label' => null, ); if ($type === 'number') { $defaultOptions['min'] = 0; $defaultOptions['placeholder'] = __d('net_commons', 'Only numbers are allowed.'); } if ($type === 'url') { $defaultOptions['placeholder'] = 'http://'; } $inputOptions = Hash::merge($defaultOptions, $options); $inputOptions['error'] = false; return $inputOptions; } /** * の出力 * このメソッドは、NetCommonsFormHelper->input()から実行される。 * * @param string $fieldName フィールド名("Modelname.fieldname"形式) * @param array $options inputのオプション配列 * @return string HTML */ protected function _input($fieldName, $options = array()) { $input = ''; $label = ''; $type = Hash::get($options, 'type'); if (Hash::get($options, 'multiple') === 'checkbox') { $type = 'multiple'; } //ラベルの表示 if (Hash::get($options, 'label')) { $label = $this->label($fieldName, $options['label'], ['required' => $options['required']]); } if ($type === 'radio') { //ラジオボタン $options = Hash::remove($options, 'required'); $options = Hash::insert($options, 'label', false); $options['outer'] = (bool)$label; $attributes = Hash::remove($options, 'options'); $input = $this->FormInput->radio( $fieldName, Hash::get($options, 'options', array()), $attributes ); } elseif ($type === 'multiple') { //複数チェックボックス $options = Hash::remove($options, 'required'); $options = Hash::insert($options, 'label', false); $options['outer'] = (bool)$label; $input = $this->FormInput->multipleCheckbox($fieldName, $options); } elseif ($type === 'checkbox') { //チェックボックス $options = Hash::remove($options, 'required'); $options = Hash::insert($options, 'label', false); $options['outer'] = (bool)$label; $input = $this->FormInput->$type($fieldName, $options); } elseif (in_array($type, ['password', 'email', 'label', 'handle'], true)) { //パスワード、eメール $options = Hash::remove($options, 'required'); $options = Hash::insert($options, 'label', false); $input = $this->FormInput->$type($fieldName, $options); } else { $options = Hash::remove($options, 'required'); $options = Hash::insert($options, 'label', false); if ($type !== 'file' && ! Hash::get($options, 'class')) { $options = Hash::insert($options, 'class', 'form-control'); } $input = $this->Form->input($fieldName, $options); } return $label . $input; } /** * Timezone変換の準備を組み込んだForm::end * * [FormHelper::end()](http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#FormHelper::end)と * [DatetimePickerHelper::beforeFormEnd()](./DatetimePickerHelper.html#method_beforeFormEnd)と * [NetCommonsTimeHelper::beforeFormEnd()](./NetCommonsTimeHelper.html#method_beforeFormEnd)の内容を出力する * * @param null|array $options オプション * @param array $secureAttributes secureAttributes * @return string * @see http://book.cakephp.org/2.0/ja/core-libraries/helpers/form.html#FormHelper::end FormHelper::end() */ public function end($options = null, $secureAttributes = array()) { $out = ''; $this->DatetimePicker->beforeFormEnd(); $out .= $this->NetCommonsTime->beforeFormEnd(); $out .= $this->Form->end($options, $secureAttributes); return $out; } /** * エラーの出力 * * #### サンプル * - 入力 * ``` * ``` * - 出力 * ``` * ``` * * @param string $fieldName フィールド名 "Modelname.fieldname" * @param string|array $text エラーメッセージ * @param array $options
の属性オプション * @return string */ public function error($fieldName, $text = null, $options = array()) { $output = ''; $current = Hash::get($options, 'current', false); $options = Hash::remove($options, 'current'); $again = Hash::get($options, 'again', false); $options = Hash::remove($options, 'again'); $output .= '
'; $output .= $this->Form->error( $fieldName, $text, Hash::merge(['class' => 'help-block'], $options) ); if ($current) { $output .= $this->Form->error( $fieldName . '_current', $text, Hash::merge(['class' => 'help-block'], $options) ); } if ($again) { $output .= $this->Form->error( $fieldName . '_again', $text, Hash::merge(['class' => 'help-block'], $options) ); } $output .= '
'; return $output; } /** * ヘルプブロックの表示 * * #### サンプル * - 入力 * ``` * ``` * - 出力 * ``` * ``` * * @param string $helpText ヘルプテキスト * @param array|null $helpOptions ヘルプテキストのオプション * @return string */ public function help($helpText, $helpOptions = null) { $output = ''; if (! $helpOptions) { $helpOptions = array('class' => 'help-block', 'escape' => false); } if ($helpText) { $output .= $this->NetCommonsHtml->div(null, $helpText, $helpOptions); } return $output; } /** *