1. sfWidget.class.php
  2. /** * sfWidget is the base class for all widgets. * * @package symfony * @subpackage widget * @author Fabien Potencier * @version SVN: $Id: sfWidget.class.php 22933 2009-10-11 22:42:56Z Kris.Wallsmith $ */
  3. abstract class sfWidget
  4. {
  5. protected
  6. $requiredOptions = array(),
  7. $attributes = array(),
  8. $options = array();
  9. protected static
  10. $xhtml = true,
  11. $charset = 'UTF-8';
  12. /**
  13. * Constructor.
  14. *
  15. * @param array $options An array of options
  16. * @param array $attributes An array of default HTML attributes
  17. *
  18. * @throws InvalidArgumentException when a option is not supported
  19. * @throws RuntimeException when a required option is not given
  20. */
  21. public function __construct($options = array(), $attributes = array())
  22. {
  23. $this->configure($options, $attributes);
  24. $currentOptionKeys = array_keys($this->options);
  25. $optionKeys = array_keys($options);
  26. // check option names
  27. if ($diff = array_diff($optionKeys, array_merge($currentOptionKeys, $this->requiredOptions)))
  28. {
  29. throw new InvalidArgumentException(sprintf('%s does not support the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
  30. }
  31. // check required options
  32. if ($diff = array_diff($this->requiredOptions, array_merge($currentOptionKeys, $optionKeys)))
  33. {
  34. throw new RuntimeException(sprintf('%s requires the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
  35. }
  36. $this->options = array_merge($this->options, $options);
  37. $this->attributes = array_merge($this->attributes, $attributes);
  38. }
  39. /**
  40. * Configures the current widget.
  41. *
  42. * This method allows each widget to add options or HTML attributes
  43. * during widget creation.
  44. *
  45. * If some options and HTML attributes are given in the sfWidget constructor
  46. * they will take precedence over the options and HTML attributes you configure
  47. * in this method.
  48. *
  49. * @param array $options An array of options
  50. * @param array $attributes An array of HTML attributes
  51. *
  52. * @see __construct()
  53. */
  54. protected function configure($options = array(), $attributes = array())
  55. {
  56. }
  57. /**
  58. * Renders the widget as HTML.
  59. *
  60. * All subclasses must implement this method.
  61. *
  62. * @param string $name The name of the HTML widget
  63. * @param mixed $value The value of the widget
  64. * @param array $attributes An array of HTML attributes
  65. * @param array $errors An array of errors
  66. *
  67. * @return string A HTML representation of the widget
  68. */
  69. abstract public function render($name, $value = null, $attributes = array(), $errors = array());
  70. /**
  71. * Adds a required option.
  72. *
  73. * @param string $name The option name
  74. *
  75. * @return sfWidget The current widget instance
  76. */
  77. public function addRequiredOption($name)
  78. {
  79. $this->requiredOptions[] = $name;
  80. return $this;
  81. }
  82. /**
  83. * Returns all required option names.
  84. *
  85. * @return array An array of required option names
  86. */
  87. public function getRequiredOptions()
  88. {
  89. return $this->requiredOptions;
  90. }
  91. /**
  92. * Adds a new option value with a default value.
  93. *
  94. * @param string $name The option name
  95. * @param mixed $value The default value
  96. *
  97. * @return sfWidget The current widget instance
  98. */
  99. public function addOption($name, $value = null)
  100. {
  101. $this->options[$name] = $value;
  102. return $this;
  103. }
  104. /**
  105. * Changes an option value.
  106. *
  107. * @param string $name The option name
  108. * @param mixed $value The value
  109. *
  110. * @return sfWidget The current widget instance
  111. *
  112. * @throws InvalidArgumentException when a option is not supported
  113. */
  114. public function setOption($name, $value)
  115. {
  116. if (!in_array($name, array_merge(array_keys($this->options), $this->requiredOptions)))
  117. {
  118. throw new InvalidArgumentException(sprintf('%s does not support the following option: \'%s\'.', get_class($this), $name));
  119. }
  120. $this->options[$name] = $value;
  121. return $this;
  122. }
  123. /**
  124. * Gets an option value.
  125. *
  126. * @param string $name The option name
  127. *
  128. * @return mixed The option value
  129. */
  130. public function getOption($name)
  131. {
  132. return isset($this->options[$name]) ? $this->options[$name] : null;
  133. }
  134. /**
  135. * Returns true if the option exists.
  136. *
  137. * @param string $name The option name
  138. *
  139. * @return bool true if the option exists, false otherwise
  140. */
  141. public function hasOption($name)
  142. {
  143. return array_key_exists($name, $this->options);
  144. }
  145. /**
  146. * Gets all options.
  147. *
  148. * @return array An array of named options
  149. */
  150. public function getOptions()
  151. {
  152. return $this->options;
  153. }
  154. /**
  155. * Sets the options.
  156. *
  157. * @param array $options An array of options
  158. *
  159. * @return sfWidget The current widget instance
  160. */
  161. public function setOptions($options)
  162. {
  163. $this->options = $options;
  164. return $this;
  165. }
  166. /**
  167. * Returns the default HTML attributes.
  168. *
  169. * @param array An array of HTML attributes
  170. */
  171. public function getAttributes()
  172. {
  173. return $this->attributes;
  174. }
  175. /**
  176. * Sets a default HTML attribute.
  177. *
  178. * @param string $name The attribute name
  179. * @param string $value The attribute value
  180. *
  181. * @return sfWidget The current widget instance
  182. */
  183. public function setAttribute($name, $value)
  184. {
  185. $this->attributes[$name] = $value;
  186. return $this;
  187. }
  188. /**
  189. * Returns the HTML attribute value for a given attribute name.
  190. *
  191. * @param string $name The attribute name.
  192. *
  193. * @return string The attribute value, or null if the attribute does not exist
  194. */
  195. public function getAttribute($name)
  196. {
  197. return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
  198. }
  199. /**
  200. * Sets the HTML attributes.
  201. *
  202. * @param array $attributes An array of HTML attributes
  203. *
  204. * @return sfWidget The current widget instance
  205. */
  206. public function setAttributes($attributes)
  207. {
  208. $this->attributes = $attributes;
  209. return $this;
  210. }
  211. /**
  212. * Gets the stylesheet paths associated with the widget.
  213. *
  214. * The array keys are files and values are the media names (separated by a ,):
  215. *
  216. * array('/path/to/file.css' => 'all', '/another/file.css' => 'screen,print')
  217. *
  218. * @return array An array of stylesheet paths
  219. */
  220. public function getStylesheets()
  221. {
  222. return array();
  223. }
  224. /**
  225. * Gets the JavaScript paths associated with the widget.
  226. *
  227. * @return array An array of JavaScript paths
  228. */
  229. public function getJavaScripts()
  230. {
  231. return array();
  232. }
  233. /**
  234. * Sets the charset to use when rendering widgets.
  235. *
  236. * @param string $charset The charset
  237. */
  238. static public function setCharset($charset)
  239. {
  240. self::$charset = $charset;
  241. }
  242. /**
  243. * Returns the charset to use when rendering widgets.
  244. *
  245. * @return string The charset (defaults to UTF-8)
  246. */
  247. static public function getCharset()
  248. {
  249. return self::$charset;
  250. }
  251. /**
  252. * Sets the XHTML generation flag.
  253. *
  254. * @param bool $boolean true if widgets must be generated as XHTML, false otherwise
  255. */
  256. static public function setXhtml($boolean)
  257. {
  258. self::$xhtml = (boolean) $boolean;
  259. }
  260. /**
  261. * Returns whether to generate XHTML tags or not.
  262. *
  263. * @return bool true if widgets must be generated as XHTML, false otherwise
  264. */
  265. static public function isXhtml()
  266. {
  267. return self::$xhtml;
  268. }
  269. /**
  270. * Renders a HTML tag.
  271. *
  272. * @param string $tag The tag name
  273. * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes
  274. *
  275. * @param string An HTML tag string
  276. */
  277. public function renderTag($tag, $attributes = array())
  278. {
  279. if (empty($tag))
  280. {
  281. return '';
  282. }
  283. return sprintf('<%s%s%s', $tag, $this->attributesToHtml($attributes), self::$xhtml ? ' />' : (strtolower($tag) == 'input' ? '>' : sprintf('></%s>', $tag)));
  284. }
  285. /**
  286. * Renders a HTML content tag.
  287. *
  288. * @param string $tag The tag name
  289. * @param string $content The content of the tag
  290. * @param array $attributes An array of HTML attributes to be merged with the default HTML attributes
  291. *
  292. * @param string An HTML tag string
  293. */
  294. public function renderContentTag($tag, $content = null, $attributes = array())
  295. {
  296. if (empty($tag))
  297. {
  298. return '';
  299. }
  300. return sprintf('<%s%s>%s</%s>', $tag, $this->attributesToHtml($attributes), $content, $tag);
  301. }
  302. /**
  303. * Escapes a string.
  304. *
  305. * @param string $value string to escape
  306. * @return string escaped string
  307. */
  308. static public function escapeOnce($value)
  309. {
  310. return self::fixDoubleEscape(htmlspecialchars((string) $value, ENT_QUOTES, self::getCharset()));
  311. }
  312. /**
  313. * Fixes double escaped strings.
  314. *
  315. * @param string $escaped string to fix
  316. * @return string single escaped string
  317. */
  318. static public function fixDoubleEscape($escaped)
  319. {
  320. return preg_replace('/&amp;([a-z]+|(#\d+)|(#x[\da-f]+));/i', '&$1;', $escaped);
  321. }
  322. /**
  323. * Converts an array of attributes to its HTML representation.
  324. *
  325. * @param array $attributes An array of attributes
  326. *
  327. * @return string The HTML representation of the HTML attribute array.
  328. */
  329. public function attributesToHtml($attributes)
  330. {
  331. $attributes = array_merge($this->attributes, $attributes);
  332. return implode('', array_map(array($this, 'attributesToHtmlCallback'), array_keys($attributes), array_values($attributes)));
  333. }
  334. /**
  335. * Prepares an attribute key and value for HTML representation.
  336. *
  337. * It removes empty attributes, except for the value one.
  338. *
  339. * @param string $k The attribute key
  340. * @param string $v The attribute value
  341. *
  342. * @return string The HTML representation of the HTML key attribute pair.
  343. */
  344. protected function attributesToHtmlCallback($k, $v)
  345. {
  346. return false === $v || null === $v || ('' === $v && 'value' != $k) ? '' : sprintf(' %s="%s"', $k, $this->escapeOnce($v));
  347. }
  348. }

Debug toolbar