StringTemplate.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\View;
  16. use Cake\Configure\Engine\PhpConfig;
  17. use Cake\Core\InstanceConfigTrait;
  18. use Cake\Core\Plugin;
  19. use Cake\Error;
  20. /**
  21. * Provides an interface for registering and inserting
  22. * content into simple logic-less string templates.
  23. *
  24. * Used by several helpers to provide simple flexible templates
  25. * for generating HTML and other content.
  26. */
  27. class StringTemplate {
  28. use InstanceConfigTrait {
  29. config as add;
  30. config as get;
  31. }
  32. /**
  33. * List of attributes that can be made compact.
  34. *
  35. * @var array
  36. */
  37. protected $_compactAttributes = array(
  38. 'compact', 'checked', 'declare', 'readonly', 'disabled', 'selected',
  39. 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize',
  40. 'autoplay', 'controls', 'loop', 'muted', 'required', 'novalidate', 'formnovalidate'
  41. );
  42. /**
  43. * The default templates this instance holds.
  44. *
  45. * @var array
  46. */
  47. protected $_defaultConfig = [
  48. 'attribute' => '{{name}}="{{value}}"',
  49. 'compactAttribute' => '{{name}}="{{value}}"',
  50. ];
  51. /**
  52. * Constructor.
  53. *
  54. * @param array $templates A set of templates to add.
  55. */
  56. public function __construct(array $config = null) {
  57. $this->config($config);
  58. }
  59. /**
  60. * Load a config file containing templates.
  61. *
  62. * Template files should define a `$config` variable containing
  63. * all the templates to load. Loaded templates will be merged with existing
  64. * templates.
  65. *
  66. * @param string $file The file to load
  67. * @return void
  68. */
  69. public function load($file) {
  70. $loader = new PhpConfig(APP . 'Config/');
  71. $templates = $loader->read($file);
  72. $this->add($templates);
  73. }
  74. /**
  75. * Remove the named template.
  76. *
  77. * @param string $name The template to remove.
  78. * @return void
  79. */
  80. public function remove($name) {
  81. $this->config($name, null);
  82. }
  83. /**
  84. * Format a template string with $data
  85. *
  86. * @param string $name The template name.
  87. * @param array $data The data to insert.
  88. * @return string
  89. */
  90. public function format($name, array $data) {
  91. $template = $this->get($name);
  92. if ($template === null) {
  93. return '';
  94. }
  95. $replace = [];
  96. $keys = array_keys($data);
  97. foreach ($keys as $key) {
  98. $replace['{{' . $key . '}}'] = $data[$key];
  99. }
  100. return strtr($template, $replace);
  101. }
  102. /**
  103. * Returns a space-delimited string with items of the $options array. If a key
  104. * of $options array happens to be one of those listed
  105. * in `StringTemplate::$_compactAttributes` and its value is one of:
  106. *
  107. * - '1' (string)
  108. * - 1 (integer)
  109. * - true (boolean)
  110. * - 'true' (string)
  111. *
  112. * Then the value will be reset to be identical with key's name.
  113. * If the value is not one of these 4, the parameter is not output.
  114. *
  115. * 'escape' is a special option in that it controls the conversion of
  116. * attributes to their html-entity encoded equivalents. Set to false to disable html-encoding.
  117. *
  118. * If value for any option key is set to `null` or `false`, that option will be excluded from output.
  119. *
  120. * This method uses the 'attribute' and 'compactAttribute' templates. Each of
  121. * these templates uses the `name` and `value` variables. You can modify these
  122. * templates to change how attributes are formatted.
  123. *
  124. * @param array $options Array of options.
  125. * @param null|array $exclude Array of options to be excluded, the options here will not be part of the return.
  126. * @return string Composed attributes.
  127. */
  128. public function formatAttributes($options, $exclude = null) {
  129. $insertBefore = ' ';
  130. $options = (array)$options + ['escape' => true];
  131. if (!is_array($exclude)) {
  132. $exclude = [];
  133. }
  134. $exclude = ['escape' => true, 'idPrefix' => true] + array_flip($exclude);
  135. $escape = $options['escape'];
  136. $attributes = [];
  137. foreach ($options as $key => $value) {
  138. if (!isset($exclude[$key]) && $value !== false && $value !== null) {
  139. $attributes[] = $this->_formatAttribute($key, $value, $escape);
  140. }
  141. }
  142. $out = trim(implode(' ', $attributes));
  143. return $out ? $insertBefore . $out : '';
  144. }
  145. /**
  146. * Formats an individual attribute, and returns the string value of the composed attribute.
  147. * Works with minimized attributes that have the same value as their name such as 'disabled' and 'checked'
  148. *
  149. * @param string $key The name of the attribute to create
  150. * @param string $value The value of the attribute to create.
  151. * @param boolean $escape Define if the value must be escaped
  152. * @return string The composed attribute.
  153. */
  154. protected function _formatAttribute($key, $value, $escape = true) {
  155. if (is_array($value)) {
  156. $value = implode(' ', $value);
  157. }
  158. if (is_numeric($key)) {
  159. return $this->format('compactAttribute', [
  160. 'name' => $value,
  161. 'value' => $value
  162. ]);
  163. }
  164. $truthy = [1, '1', true, 'true', $key];
  165. $isMinimized = in_array($key, $this->_compactAttributes);
  166. if ($isMinimized && in_array($value, $truthy, true)) {
  167. return $this->format('compactAttribute', [
  168. 'name' => $key,
  169. 'value' => $key
  170. ]);
  171. }
  172. if ($isMinimized) {
  173. return '';
  174. }
  175. return $this->format('attribute', [
  176. 'name' => $key,
  177. 'value' => $escape ? h($value) : $value
  178. ]);
  179. }
  180. }