BaseGroupedMapper.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <?php
  2. /*
  3. * This file is part of the Sonata 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. */
  11. namespace Sonata\AdminBundle\Mapper;
  12. /**
  13. * This class is used to simulate the Form API
  14. *
  15. */
  16. abstract class BaseGroupedMapper extends BaseMapper
  17. {
  18. protected $currentGroup;
  19. protected $currentTab;
  20. protected $apply;
  21. abstract protected function getGroups();
  22. abstract protected function getTabs();
  23. abstract protected function setGroups(array $groups);
  24. abstract protected function setTabs(array $tabs);
  25. /**
  26. * @param string $name
  27. * @param array $options
  28. *
  29. * @return \Sonata\AdminBundle\Mapper\BaseGroupedMapper
  30. */
  31. public function with($name, array $options = array())
  32. {
  33. /**
  34. * The current implementation should work with the following workflow:
  35. *
  36. * $formMapper
  37. * ->with('group1')
  38. * ->add('username')
  39. * ->add('password')
  40. * ->end()
  41. * ->with('tab1', array('tab' => true))
  42. * ->with('group1')
  43. * ->add('username')
  44. * ->add('password')
  45. * ->end()
  46. * ->with('group2', array('collapsed' => true))
  47. * ->add('enabled')
  48. * ->add('createdAt')
  49. * ->end()
  50. * ->end();
  51. *
  52. */
  53. $defaultOptions = array(
  54. 'collapsed' => false,
  55. 'class' => false,
  56. 'description' => false,
  57. 'translation_domain' => null,
  58. 'name' => $name,
  59. );
  60. $code = $name;
  61. // Open
  62. if (array_key_exists("tab", $options) && $options["tab"]) {
  63. $tabs = $this->getTabs();
  64. if ($this->currentTab) {
  65. throw new \RuntimeException($tabs[$this->currentTab]["auto_created"] ?
  66. "New tab was added automatically when you have added field or group. You should close current tab before adding new one OR add tabs before adding groups and fields" :
  67. "You should close previous tab with end() before adding new tab"
  68. );
  69. } elseif ($this->currentGroup) {
  70. throw new \RuntimeException("You should open tab before adding new groups");
  71. }
  72. if (!isset($tabs[$name])) {
  73. $tabs[$name] = array();
  74. }
  75. $tabs[$code] = array_merge($defaultOptions, array(
  76. 'auto_created' => false,
  77. 'groups' => array(),
  78. ), $tabs[$code], $options);
  79. $this->currentTab = $code;
  80. } else {
  81. if ($this->currentGroup) {
  82. throw new \RuntimeException("You should close previous group with end() before adding new tab");
  83. }
  84. if (!$this->currentTab) {
  85. // no tab define
  86. $this->with("default", array(
  87. 'tab' => true,
  88. 'auto_created' => true,
  89. 'translation_domain' => isset($options['translation_domain']) ? $options['translation_domain'] : null
  90. )); // add new tab automatically
  91. }
  92. // if no tab is selected, we go the the main one named '_' ..
  93. if ($this->currentTab !== "default") {
  94. $code = $this->currentTab.".".$name; // groups with the same name can be on different tabs, so we prefix them in order to make unique group name
  95. }
  96. $groups = $this->getGroups();
  97. if (!isset($groups[$code])) {
  98. $groups[$code] = array();
  99. }
  100. $groups[$code] = array_merge($defaultOptions, array(
  101. 'fields' => array(),
  102. ), $groups[$code], $options);
  103. $this->currentGroup = $code;
  104. $this->setGroups($groups);
  105. $tabs = $this->getTabs();
  106. }
  107. if ($this->currentGroup && isset($tabs[$this->currentTab]) && !in_array($this->currentGroup, $tabs[$this->currentTab]["groups"])) {
  108. $tabs[$this->currentTab]["groups"][] = $this->currentGroup;
  109. }
  110. $this->setTabs($tabs);
  111. return $this;
  112. }
  113. /**
  114. * Only nested add if the condition match FALSE
  115. *
  116. * @param $bool
  117. *
  118. * @return $this
  119. * @throws \RuntimeException
  120. */
  121. public function if_true($bool)
  122. {
  123. if (!$this->apply == null) {
  124. throw new \RuntimeException('Cannot nest ifTrue call');
  125. }
  126. $this->apply = ($bool === true);
  127. return $this;
  128. }
  129. /**
  130. * Only nested add if the condition match FALSE
  131. *
  132. * @param $bool
  133. *
  134. * @return $this
  135. * @throws \RuntimeException
  136. */
  137. public function if_false($bool)
  138. {
  139. if (!$this->apply == null) {
  140. throw new \RuntimeException('Cannot nest ifTrue call');
  141. }
  142. $this->apply = ($bool === false);
  143. return $this;
  144. }
  145. /**
  146. * @return $this
  147. */
  148. public function end_if()
  149. {
  150. $this->apply = null;
  151. return $this;
  152. }
  153. /**
  154. * @param $name
  155. * @param array $options
  156. *
  157. * @return BaseGroupedMapper
  158. */
  159. public function tab($name, array $options = array())
  160. {
  161. return $this->with($name, array_merge($options, array('tab' => true)));
  162. }
  163. /**
  164. * @return \Sonata\AdminBundle\Mapper\BaseGroupedMapper
  165. */
  166. public function end()
  167. {
  168. if ($this->currentGroup !== null) {
  169. $this->currentGroup = null;
  170. } elseif ($this->currentTab !== null) {
  171. $this->currentTab = null;
  172. } else {
  173. throw new \Exception("No open tabs or groups, you cannot use end()");
  174. }
  175. return $this;
  176. }
  177. /**
  178. * Add the fieldname to the current group
  179. *
  180. * @param string $fieldName
  181. */
  182. protected function addFieldToCurrentGroup($fieldName)
  183. {
  184. // Note this line must happen before the next line.
  185. // See https://github.com/sonata-project/SonataAdminBundle/pull/1351
  186. $currentGroup = $this->getCurrentGroupName();
  187. $groups = $this->getGroups();
  188. $groups[$currentGroup]['fields'][$fieldName] = $fieldName;
  189. $this->setGroups($groups);
  190. return $groups[$currentGroup];
  191. }
  192. /**
  193. * Return the name of the currently selected group. The method also makes
  194. * sure a valid group name is currently selected
  195. *
  196. * Note that this can have the side effect to change the "group" value
  197. * returned by the getGroup function
  198. *
  199. * @return string
  200. */
  201. protected function getCurrentGroupName()
  202. {
  203. if (!$this->currentGroup) {
  204. $this->with($this->admin->getLabel(), array('auto_created' => true));
  205. }
  206. return $this->currentGroup;
  207. }
  208. }