1. sfWidgetFormSchemaFormatter.class.php
  2. /** * sfWidgetFormSchemaFormatter allows to format a form schema with HTML formats. * * @package symfony * @subpackage widget * @author Fabien Potencier * @version SVN: $Id: sfWidgetFormSchemaFormatter.class.php 21908 2009-09-11 12:06:21Z fabien $ */
  3. abstract class sfWidgetFormSchemaFormatter
  4. {
  5. protected static
  6. $translationCallable = null;
  7. protected
  8. $rowFormat = '',
  9. $helpFormat = '%help%',
  10. $errorRowFormat = '%errors%',
  11. $errorListFormatInARow = " <ul class=\"error_list\">\n%errors% </ul>\n",
  12. $errorRowFormatInARow = " <li>%error%</li>\n",
  13. $namedErrorRowFormatInARow = " <li>%name%: %error%</li>\n",
  14. $decoratorFormat = '',
  15. $widgetSchema = null,
  16. $translationCatalogue = null;
  17. /**
  18. * Constructor
  19. *
  20. * @param sfWidgetFormSchema $widgetSchema
  21. */
  22. public function __construct(sfWidgetFormSchema $widgetSchema)
  23. {
  24. $this->setWidgetSchema($widgetSchema);
  25. }
  26. public function formatRow($label, $field, $errors = array(), $help = '', $hiddenFields = null)
  27. {
  28. return strtr($this->getRowFormat(), array(
  29. '%label%' => $label,
  30. '%field%' => $field,
  31. '%error%' => $this->formatErrorsForRow($errors),
  32. '%help%' => $this->formatHelp($help),
  33. '%hidden_fields%' => null === $hiddenFields ? '%hidden_fields%' : $hiddenFields,
  34. ));
  35. }
  36. /**
  37. * Translates a string using an i18n callable, if it has been provided
  38. *
  39. * @param mixed $subject The subject to translate
  40. * @param array $parameters Additional parameters to pass back to the callable
  41. * @return string
  42. */
  43. public function translate($subject, $parameters = array())
  44. {
  45. if (false === $subject)
  46. {
  47. return false;
  48. }
  49. if (null === self::$translationCallable)
  50. {
  51. // replace object with strings
  52. foreach ($parameters as $key => $value)
  53. {
  54. if (is_object($value) && method_exists($value, '__toString'))
  55. {
  56. $parameters[$key] = $value->__toString();
  57. }
  58. }
  59. return strtr($subject, $parameters);
  60. }
  61. $catalogue = $this->getTranslationCatalogue();
  62. if (self::$translationCallable instanceof sfCallable)
  63. {
  64. return self::$translationCallable->call($subject, $parameters, $catalogue);
  65. }
  66. return call_user_func(self::$translationCallable, $subject, $parameters, $catalogue);
  67. }
  68. /**
  69. * Returns the current i18n callable
  70. *
  71. * @return mixed
  72. */
  73. static public function getTranslationCallable()
  74. {
  75. return self::$translationCallable;
  76. }
  77. /**
  78. * Sets a callable which aims to translate form labels, errors and help messages
  79. *
  80. * @param mixed $callable
  81. *
  82. * @throws InvalidArgumentException if an invalid php callable or sfCallable has been provided
  83. */
  84. static public function setTranslationCallable($callable)
  85. {
  86. if (!$callable instanceof sfCallable && !is_callable($callable))
  87. {
  88. throw new InvalidArgumentException('Provided i18n callable should be either an instance of sfCallable or a valid PHP callable');
  89. }
  90. self::$translationCallable = $callable;
  91. }
  92. public function formatHelp($help)
  93. {
  94. if (!$help)
  95. {
  96. return '';
  97. }
  98. return strtr($this->getHelpFormat(), array('%help%' => $this->translate($help)));
  99. }
  100. public function formatErrorRow($errors)
  101. {
  102. if (null === $errors || !$errors)
  103. {
  104. return '';
  105. }
  106. return strtr($this->getErrorRowFormat(), array('%errors%' => $this->formatErrorsForRow($errors)));
  107. }
  108. public function formatErrorsForRow($errors)
  109. {
  110. if (null === $errors || !$errors)
  111. {
  112. return '';
  113. }
  114. if (!is_array($errors))
  115. {
  116. $errors = array($errors);
  117. }
  118. return strtr($this->getErrorListFormatInARow(), array('%errors%' => implode('', $this->unnestErrors($errors))));
  119. }
  120. /**
  121. * Generates a label for the given field name.
  122. *
  123. * @param string $name The field name
  124. * @param array $attributes Optional html attributes for the label tag
  125. *
  126. * @return string The label tag
  127. */
  128. public function generateLabel($name, $attributes = array())
  129. {
  130. $labelName = $this->generateLabelName($name);
  131. if (false === $labelName)
  132. {
  133. return '';
  134. }
  135. if (!isset($attributes['for']))
  136. {
  137. $attributes['for'] = $this->widgetSchema->generateId($this->widgetSchema->generateName($name));
  138. }
  139. return $this->widgetSchema->renderContentTag('label', $labelName, $attributes);
  140. }
  141. /**
  142. * Generates the label name for the given field name.
  143. *
  144. * @param string $name The field name
  145. *
  146. * @return string The label name
  147. */
  148. public function generateLabelName($name)
  149. {
  150. $label = $this->widgetSchema->getLabel($name);
  151. if (!$label && false !== $label)
  152. {
  153. $label = str_replace('_', ' ', ucfirst('_id' == substr($name, -3) ? substr($name, 0, -3) : $name));
  154. }
  155. return $this->translate($label);
  156. }
  157. /**
  158. * Get i18n catalogue name
  159. *
  160. * @return string
  161. */
  162. public function getTranslationCatalogue()
  163. {
  164. return $this->translationCatalogue;
  165. }
  166. /**
  167. * Set an i18n catalogue name
  168. *
  169. * @param string $catalogue
  170. *
  171. * @throws InvalidArgumentException when the catalogue is not a string
  172. */
  173. public function setTranslationCatalogue($catalogue)
  174. {
  175. if (!is_string($catalogue))
  176. {
  177. throw new InvalidArgumentException('Catalogue name must be a string');
  178. }
  179. $this->translationCatalogue = $catalogue;
  180. }
  181. protected function unnestErrors($errors, $prefix = '')
  182. {
  183. $newErrors = array();
  184. foreach ($errors as $name => $error)
  185. {
  186. if ($error instanceof ArrayAccess || is_array($error))
  187. {
  188. $newErrors = array_merge($newErrors, $this->unnestErrors($error, ($prefix ? $prefix.' > ' : '').$name));
  189. }
  190. else
  191. {
  192. if ($error instanceof sfValidatorError)
  193. {
  194. $err = $this->translate($error->getMessageFormat(), $error->getArguments());
  195. }
  196. else
  197. {
  198. $err = $this->translate($error);
  199. }
  200. if (!is_integer($name))
  201. {
  202. $newErrors[] = strtr($this->getNamedErrorRowFormatInARow(), array('%error%' => $err, '%name%' => ($prefix ? $prefix.' > ' : '').$name));
  203. }
  204. else
  205. {
  206. $newErrors[] = strtr($this->getErrorRowFormatInARow(), array('%error%' => $err));
  207. }
  208. }
  209. }
  210. return $newErrors;
  211. }
  212. public function setRowFormat($format)
  213. {
  214. $this->rowFormat = $format;
  215. }
  216. public function getRowFormat()
  217. {
  218. return $this->rowFormat;
  219. }
  220. public function setErrorRowFormat($format)
  221. {
  222. $this->errorRowFormat = $format;
  223. }
  224. public function getErrorRowFormat()
  225. {
  226. return $this->errorRowFormat;
  227. }
  228. public function setErrorListFormatInARow($format)
  229. {
  230. $this->errorListFormatInARow = $format;
  231. }
  232. public function getErrorListFormatInARow()
  233. {
  234. return $this->errorListFormatInARow;
  235. }
  236. public function setErrorRowFormatInARow($format)
  237. {
  238. $this->errorRowFormatInARow = $format;
  239. }
  240. public function getErrorRowFormatInARow()
  241. {
  242. return $this->errorRowFormatInARow;
  243. }
  244. public function setNamedErrorRowFormatInARow($format)
  245. {
  246. $this->namedErrorRowFormatInARow = $format;
  247. }
  248. public function getNamedErrorRowFormatInARow()
  249. {
  250. return $this->namedErrorRowFormatInARow;
  251. }
  252. public function setDecoratorFormat($format)
  253. {
  254. $this->decoratorFormat = $format;
  255. }
  256. public function getDecoratorFormat()
  257. {
  258. return $this->decoratorFormat;
  259. }
  260. public function setHelpFormat($format)
  261. {
  262. $this->helpFormat = $format;
  263. }
  264. public function getHelpFormat()
  265. {
  266. return $this->helpFormat;
  267. }
  268. /**
  269. * Sets the widget schema associated with this formatter instance.
  270. *
  271. * @param sfWidgetFormSchema $widgetSchema A sfWidgetFormSchema instance
  272. */
  273. public function setWidgetSchema(sfWidgetFormSchema $widgetSchema)
  274. {
  275. $this->widgetSchema = $widgetSchema;
  276. }
  277. public function getWidgetSchema()
  278. {
  279. return $this->widgetSchema;
  280. }
  281. }

Debug toolbar