PageRenderTime 82ms CodeModel.GetById 4ms RepoModel.GetById 3ms app.codeStats 0ms

/vendor/sonata-project/admin-bundle/Twig/Extension/SonataAdminExtension.php

https://gitlab.com/freebird/WebApp
PHP | 315 lines | 176 code | 40 blank | 99 comment | 8 complexity | 7ad93c99f741cc6fde856153ea4ed32e MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\AdminBundle\Twig\Extension;
  11. use Doctrine\Common\Util\ClassUtils;
  12. use Psr\Log\LoggerInterface;
  13. use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
  14. use Sonata\AdminBundle\Admin\Pool;
  15. use Sonata\AdminBundle\Exception\NoValueException;
  16. use Symfony\Component\PropertyAccess\PropertyAccess;
  17. use Twig_Environment;
  18. class SonataAdminExtension extends \Twig_Extension
  19. {
  20. /**
  21. * @var Pool
  22. */
  23. protected $pool;
  24. /**
  25. * @var LoggerInterface
  26. */
  27. protected $logger;
  28. /**
  29. * @param Pool $pool
  30. * @param LoggerInterface $logger
  31. */
  32. public function __construct(Pool $pool, LoggerInterface $logger = null)
  33. {
  34. $this->pool = $pool;
  35. $this->logger = $logger;
  36. }
  37. /**
  38. * {@inheritdoc}
  39. */
  40. public function getFilters()
  41. {
  42. return array(
  43. new \Twig_SimpleFilter('render_list_element', array($this, 'renderListElement'), array('is_safe' => array('html'), 'needs_environment' => true)),
  44. new \Twig_SimpleFilter('render_view_element', array($this, 'renderViewElement'), array('is_safe' => array('html'), 'needs_environment' => true)),
  45. new \Twig_SimpleFilter('render_view_element_compare', array($this, 'renderViewElementCompare'), array('is_safe' => array('html'))),
  46. new \Twig_SimpleFilter('render_relation_element', array($this, 'renderRelationElement')),
  47. new \Twig_SimpleFilter('sonata_urlsafeid', array($this, 'getUrlsafeIdentifier')),
  48. new \Twig_SimpleFilter('sonata_xeditable_type', array($this, 'getXEditableType')),
  49. );
  50. }
  51. /**
  52. * {@inheritdoc}
  53. */
  54. public function getName()
  55. {
  56. return 'sonata_admin';
  57. }
  58. /**
  59. * Get template.
  60. *
  61. * @param FieldDescriptionInterface $fieldDescription
  62. * @param string $defaultTemplate
  63. *
  64. * @return \Twig_Template
  65. */
  66. protected function getTemplate(FieldDescriptionInterface $fieldDescription, $defaultTemplate, Twig_Environment $environment)
  67. {
  68. $templateName = $fieldDescription->getTemplate() ?: $defaultTemplate;
  69. try {
  70. $template = $environment->loadTemplate($templateName);
  71. } catch (\Twig_Error_Loader $e) {
  72. $template = $environment->loadTemplate($defaultTemplate);
  73. if (null !== $this->logger) {
  74. $this->logger->warning(sprintf('An error occured trying to load the template "%s" for the field "%s", the default template "%s" was used instead: "%s". ', $templateName, $fieldDescription->getFieldName(), $defaultTemplate, $e->getMessage()));
  75. }
  76. }
  77. return $template;
  78. }
  79. /**
  80. * render a list element from the FieldDescription.
  81. *
  82. * @param mixed $object
  83. * @param FieldDescriptionInterface $fieldDescription
  84. * @param array $params
  85. *
  86. * @return string
  87. */
  88. public function renderListElement(Twig_Environment $environment, $object, FieldDescriptionInterface $fieldDescription, $params = array())
  89. {
  90. $template = $this->getTemplate($fieldDescription, $fieldDescription->getAdmin()->getTemplate('base_list_field'), $environment);
  91. return $this->output($fieldDescription, $template, array_merge($params, array(
  92. 'admin' => $fieldDescription->getAdmin(),
  93. 'object' => $object,
  94. 'value' => $this->getValueFromFieldDescription($object, $fieldDescription),
  95. 'field_description' => $fieldDescription,
  96. )), $environment);
  97. }
  98. /**
  99. * @param FieldDescriptionInterface $fieldDescription
  100. * @param \Twig_Template $template
  101. * @param array $parameters
  102. *
  103. * @return string
  104. */
  105. public function output(FieldDescriptionInterface $fieldDescription, \Twig_Template $template, array $parameters = array(), Twig_Environment $environment)
  106. {
  107. $content = $template->render($parameters);
  108. if ($environment->isDebug()) {
  109. return sprintf("\n<!-- START \n fieldName: %s\n template: %s\n compiled template: %s\n -->\n%s\n<!-- END - fieldName: %s -->",
  110. $fieldDescription->getFieldName(),
  111. $fieldDescription->getTemplate(),
  112. $template->getTemplateName(),
  113. $content,
  114. $fieldDescription->getFieldName()
  115. );
  116. }
  117. return $content;
  118. }
  119. /**
  120. * return the value related to FieldDescription, if the associated object does no
  121. * exists => a temporary one is created.
  122. *
  123. * @param object $object
  124. * @param FieldDescriptionInterface $fieldDescription
  125. * @param array $params
  126. *
  127. * @throws \RuntimeException
  128. *
  129. * @return mixed
  130. */
  131. public function getValueFromFieldDescription($object, FieldDescriptionInterface $fieldDescription, array $params = array())
  132. {
  133. if (isset($params['loop']) && $object instanceof \ArrayAccess) {
  134. throw new \RuntimeException('remove the loop requirement');
  135. }
  136. $value = null;
  137. try {
  138. $value = $fieldDescription->getValue($object);
  139. } catch (NoValueException $e) {
  140. if ($fieldDescription->getAssociationAdmin()) {
  141. $value = $fieldDescription->getAssociationAdmin()->getNewInstance();
  142. }
  143. }
  144. return $value;
  145. }
  146. /**
  147. * render a view element.
  148. *
  149. * @param FieldDescriptionInterface $fieldDescription
  150. * @param mixed $object
  151. *
  152. * @return string
  153. */
  154. public function renderViewElement(Twig_Environment $environment, FieldDescriptionInterface $fieldDescription, $object)
  155. {
  156. $template = $this->getTemplate($fieldDescription, 'SonataAdminBundle:CRUD:base_show_field.html.twig', $environment);
  157. try {
  158. $value = $fieldDescription->getValue($object);
  159. } catch (NoValueException $e) {
  160. $value = null;
  161. }
  162. return $this->output($fieldDescription, $template, array(
  163. 'field_description' => $fieldDescription,
  164. 'object' => $object,
  165. 'value' => $value,
  166. 'admin' => $fieldDescription->getAdmin(),
  167. ), $environment);
  168. }
  169. /**
  170. * render a compared view element.
  171. *
  172. * @param FieldDescriptionInterface $fieldDescription
  173. * @param mixed $baseObject
  174. * @param mixed $compareObject
  175. *
  176. * @return string
  177. */
  178. public function renderViewElementCompare(Twig_Environment $environment, FieldDescriptionInterface $fieldDescription, $baseObject, $compareObject)
  179. {
  180. $template = $this->getTemplate($fieldDescription, 'SonataAdminBundle:CRUD:base_show_field.html.twig', $environment);
  181. try {
  182. $baseValue = $fieldDescription->getValue($baseObject);
  183. } catch (NoValueException $e) {
  184. $baseValue = null;
  185. }
  186. try {
  187. $compareValue = $fieldDescription->getValue($compareObject);
  188. } catch (NoValueException $e) {
  189. $compareValue = null;
  190. }
  191. $baseValueOutput = $template->render(array(
  192. 'admin' => $fieldDescription->getAdmin(),
  193. 'field_description' => $fieldDescription,
  194. 'value' => $baseValue,
  195. ));
  196. $compareValueOutput = $template->render(array(
  197. 'field_description' => $fieldDescription,
  198. 'admin' => $fieldDescription->getAdmin(),
  199. 'value' => $compareValue,
  200. ));
  201. // Compare the rendered output of both objects by using the (possibly) overridden field block
  202. $isDiff = $baseValueOutput !== $compareValueOutput;
  203. return $this->output($fieldDescription, $template, array(
  204. 'field_description' => $fieldDescription,
  205. 'value' => $baseValue,
  206. 'value_compare' => $compareValue,
  207. 'is_diff' => $isDiff,
  208. 'admin' => $fieldDescription->getAdmin(),
  209. ), $environment);
  210. }
  211. /**
  212. * @throws \RunTimeException
  213. *
  214. * @param mixed $element
  215. * @param FieldDescriptionInterface $fieldDescription
  216. *
  217. * @return mixed
  218. */
  219. public function renderRelationElement($element, FieldDescriptionInterface $fieldDescription)
  220. {
  221. if (!is_object($element)) {
  222. return $element;
  223. }
  224. $propertyPath = $fieldDescription->getOption('associated_property');
  225. if (null === $propertyPath) {
  226. // For BC kept associated_tostring option behavior
  227. $method = $fieldDescription->getOption('associated_tostring', '__toString');
  228. if (!method_exists($element, $method)) {
  229. throw new \RuntimeException(sprintf(
  230. 'You must define an `associated_property` option or create a `%s::__toString` method to the field option %s from service %s is ',
  231. get_class($element),
  232. $fieldDescription->getName(),
  233. $fieldDescription->getAdmin()->getCode()
  234. ));
  235. }
  236. return call_user_func(array($element, $method));
  237. }
  238. return PropertyAccess::createPropertyAccessor()->getValue($element, $propertyPath);
  239. }
  240. /**
  241. * Get the identifiers as a string that is save to use in an url.
  242. *
  243. * @param object $model
  244. *
  245. * @return string string representation of the id that is save to use in an url
  246. */
  247. public function getUrlsafeIdentifier($model)
  248. {
  249. $admin = $this->pool->getAdminByClass(ClassUtils::getClass($model));
  250. return $admin->getUrlsafeIdentifier($model);
  251. }
  252. /**
  253. * @param $type
  254. *
  255. * @return string|bool
  256. */
  257. public function getXEditableType($type)
  258. {
  259. $mapping = array(
  260. 'boolean' => 'select',
  261. 'text' => 'text',
  262. 'textarea' => 'textarea',
  263. 'email' => 'email',
  264. 'string' => 'text',
  265. 'smallint' => 'text',
  266. 'bigint' => 'text',
  267. 'integer' => 'number',
  268. 'decimal' => 'number',
  269. 'currency' => 'number',
  270. 'percent' => 'number',
  271. 'url' => 'url',
  272. );
  273. return isset($mapping[$type]) ? $mapping[$type] : false;
  274. }
  275. }