MultiCheckbox.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since CakePHP(tm) v3.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\View\Input;
  16. use Cake\Utility\Inflector;
  17. /**
  18. * Input widget class for generating multiple checkboxes.
  19. *
  20. */
  21. class MultiCheckbox {
  22. /**
  23. * Template instance to use.
  24. *
  25. * @var Cake\View\StringTemplate
  26. */
  27. protected $_templates;
  28. /**
  29. * Render multi-checkbox widget.
  30. *
  31. * @param Cake\View\StringTemplate $templates
  32. */
  33. public function __construct($templates) {
  34. $this->_templates = $templates;
  35. }
  36. /**
  37. * Render multi-checkbox widget.
  38. *
  39. * Data supports the following options.
  40. *
  41. * - `name` The name attribute of the inputs to create.
  42. * `[]` will be appended to the name.
  43. * - `options` An array of options to create checkboxes out of.
  44. * - `val` Either a string/integer or array of values that should be
  45. * checked. Can also be a complex options set.
  46. * - `disabled` Either a boolean or an array of checkboxes to disable.
  47. * - `escape` Set to false to disable HTML escaping.
  48. * - `options` An associative array of value=>labels to generate options for.
  49. *
  50. * ### Options format
  51. *
  52. * The options option can take a variety of data format depending on
  53. * the complexity of HTML you want generated.
  54. *
  55. * You can generate simple options using a basic associative array:
  56. *
  57. * {{{
  58. * 'options' => ['elk' => 'Elk', 'beaver' => 'Beaver']
  59. * }}}
  60. *
  61. * If you need to define additional attributes on your option elements
  62. * you can use the complex form for options:
  63. *
  64. * {{{
  65. * 'options' => [
  66. * ['value' => 'elk', 'text' => 'Elk', 'data-foo' => 'bar'],
  67. * ]
  68. * }}}
  69. *
  70. * This form **requires** that both the `value` and `text` keys be defined.
  71. * If either is not set options will not be generated correctly.
  72. *
  73. * @param array $data
  74. * @return string
  75. */
  76. public function render($data) {
  77. $data += [
  78. 'name' => '',
  79. 'escape' => true,
  80. 'options' => [],
  81. 'disabled' => null,
  82. 'val' => null,
  83. ];
  84. $out = [];
  85. foreach ($data['options'] as $key => $val) {
  86. $checkbox = [
  87. 'value' => $key,
  88. 'text' => $val,
  89. ];
  90. if (is_array($val) && isset($val['text'], $val['value'])) {
  91. $checkbox = $val;
  92. }
  93. $checkbox['name'] = $data['name'];
  94. $checkbox['escape'] = $data['escape'];
  95. if ($this->_isSelected($key, $data['val'])) {
  96. $checkbox['checked'] = true;
  97. }
  98. if ($this->_isDisabled($key, $data['disabled'])) {
  99. $checkbox['disabled'] = true;
  100. }
  101. if (empty($checkbox['id'])) {
  102. $checkbox['id'] = mb_strtolower(Inflector::slug($checkbox['name'] . $checkbox['value'], '-'));
  103. }
  104. $out[] = $this->_renderInput($checkbox);
  105. }
  106. return implode('', $out);
  107. }
  108. /**
  109. * Render a single checkbox & wrapper.
  110. *
  111. * @return string
  112. */
  113. protected function _renderInput($checkbox) {
  114. $input = $this->_templates->format('checkbox', [
  115. 'name' => $checkbox['name'] . '[]',
  116. 'value' => $checkbox['escape'] ? h($checkbox['value']) : $checkbox['value'],
  117. 'attrs' => $this->_templates->formatAttributes(
  118. $checkbox,
  119. ['name', 'value', 'text']
  120. )
  121. ]);
  122. $labelAttrs = [
  123. 'for' => $checkbox['id'],
  124. 'escape' => $checkbox['escape']
  125. ];
  126. $label = $this->_templates->format('label', [
  127. 'text' => $checkbox['escape'] ? h($checkbox['text']) : $checkbox['text'],
  128. 'input' => $input,
  129. 'attrs' => $this->_templates->formatAttributes($labelAttrs)
  130. ]);
  131. return $this->_templates->format('checkboxContainer', [
  132. 'label' => $label,
  133. 'input' => $input
  134. ]);
  135. }
  136. /**
  137. * Helper method for deciding what options are selected.
  138. *
  139. * @param string $key The key to test.
  140. * @param array|string|null The selected values.
  141. * @return boolean
  142. */
  143. protected function _isSelected($key, $selected) {
  144. if ($selected === null) {
  145. return false;
  146. }
  147. $isArray = is_array($selected);
  148. if (!$isArray) {
  149. return (string)$key === (string)$selected;
  150. }
  151. $strict = !is_numeric($key);
  152. return in_array((string)$key, $selected, $strict);
  153. }
  154. /**
  155. * Helper method for deciding what options are disabled.
  156. *
  157. * @param string $key The key to test.
  158. * @param array|null The disabled values.
  159. * @return boolean
  160. */
  161. protected function _isDisabled($key, $disabled) {
  162. if ($disabled === null || $disabled === false) {
  163. return false;
  164. }
  165. if ($disabled === true) {
  166. return true;
  167. }
  168. $strict = !is_numeric($key);
  169. return in_array((string)$key, $disabled, $strict);
  170. }
  171. }