Admin.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  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. namespace Sonata\BaseApplicationBundle\Admin;
  11. use Symfony\Component\DependencyInjection\ContainerAware;
  12. use Symfony\Component\Form\Form;
  13. use Sonata\BaseApplicationBundle\Tool\Datagrid;
  14. abstract class Admin extends ContainerAware
  15. {
  16. protected $class;
  17. protected $listFields = false;
  18. protected $formFields = false;
  19. protected $filterFields = array(); // by default there is no filter
  20. protected $filterDatagrid;
  21. protected $maxPerPage = 25;
  22. protected $baseRouteName = '';
  23. protected $baseRoutePattern;
  24. protected $baseControllerName;
  25. protected $formGroups = false;
  26. // note : don't like this, but havn't find a better way to do it
  27. protected $configurationPool;
  28. protected $code;
  29. protected $label;
  30. protected $urls = array();
  31. protected $subject;
  32. /**
  33. * Reference the parent FieldDescription related to this admin
  34. * only set for FieldDescription which is associated to an Sub Admin instance
  35. *
  36. * FieldDescription
  37. */
  38. protected $parentFieldDescription;
  39. protected $loaded = array(
  40. 'form_fields' => false,
  41. 'form_groups' => false,
  42. 'list_fields' => false,
  43. 'urls' => false,
  44. );
  45. /**
  46. * todo: put this in the DIC
  47. *
  48. * @var array
  49. */
  50. protected $formFieldClasses = array(
  51. 'string' => 'Symfony\\Component\\Form\\TextField',
  52. 'text' => 'Symfony\\Component\\Form\\TextareaField',
  53. 'boolean' => 'Symfony\\Component\\Form\\CheckboxField',
  54. 'integer' => 'Symfony\\Component\\Form\\IntegerField',
  55. 'tinyint' => 'Symfony\\Component\\Form\\IntegerField',
  56. 'smallint' => 'Symfony\\Component\\Form\\IntegerField',
  57. 'mediumint' => 'Symfony\\Component\\Form\\IntegerField',
  58. 'bigint' => 'Symfony\\Component\\Form\\IntegerField',
  59. 'decimal' => 'Symfony\\Component\\Form\\NumberField',
  60. 'datetime' => 'Symfony\\Component\\Form\\DateTimeField',
  61. 'date' => 'Symfony\\Component\\Form\\DateField',
  62. 'choice' => 'Symfony\\Component\\Form\\ChoiceField',
  63. 'array' => 'Symfony\\Component\\Form\\FieldGroup',
  64. );
  65. protected $choicesCache = array();
  66. /**
  67. * return the entity manager
  68. *
  69. * @return EntityManager
  70. */
  71. abstract public function getEntityManager();
  72. /**
  73. * build the fields to use in the form
  74. *
  75. * @throws RuntimeException
  76. * @return
  77. */
  78. abstract protected function buildFormFields();
  79. /**
  80. * build the field to use in the list view
  81. *
  82. * @return void
  83. */
  84. abstract protected function buildListFields();
  85. abstract protected function getChoices(FieldDescription $description);
  86. abstract public function getForm($object, $fields);
  87. public function configure()
  88. {
  89. }
  90. /**
  91. * return the baseRoutePattern used to generate the routing information
  92. *
  93. * @throws RuntimeException
  94. * @return string the baseRoutePattern used to generate the routing information
  95. */
  96. public function getBaseRoutePattern()
  97. {
  98. if (!$this->baseRoutePattern) {
  99. if (preg_match('@(Application|Bundle)\\\([A-Za-z]*)\\\([A-Za-z]*)Bundle\\\(Entity|Document)\\\([A-Za-z]*)@', $this->getClass(), $matches)) {
  100. $this->baseRoutePattern = sprintf('/%s/%s/%s',
  101. $this->urlize($matches[2], '-'),
  102. $this->urlize($matches[3], '-'),
  103. $this->urlize($matches[5], '-')
  104. );
  105. } else {
  106. throw new \RuntimeException(sprintf('Please define a default `baseRoutePattern` value for the admin class `%s`', get_class($this)));
  107. }
  108. }
  109. return $this->baseRoutePattern;
  110. }
  111. /**
  112. * return the baseRouteName used to generate the routing information
  113. *
  114. * @throws RuntimeException
  115. * @return string the baseRouteName used to generate the routing information
  116. */
  117. public function getBaseRouteName()
  118. {
  119. if (!$this->baseRouteName) {
  120. if (preg_match('@(Application|Bundle)\\\([A-Za-z]*)\\\([A-Za-z]*)Bundle\\\(Entity|Document)\\\([A-Za-z]*)@', $this->getClass(), $matches)) {
  121. $this->baseRouteName = sprintf('admin_%s_%s_%s',
  122. $this->urlize($matches[2]),
  123. $this->urlize($matches[3]),
  124. $this->urlize($matches[5])
  125. );
  126. } else {
  127. throw new \RuntimeException(sprintf('Please define a default `baseRouteName` value for the admin class `%s`', get_class($this)));
  128. }
  129. }
  130. return $this->baseRouteName;
  131. }
  132. public function urlize($word, $sep = '_') {
  133. return strtolower(preg_replace('~(?<=\\w)([A-Z])~', $sep.'$1', $word));
  134. }
  135. /**
  136. * return the class name handled by the Admin instance
  137. *
  138. * @return string the class name handled by the Admin instance
  139. */
  140. public function getClass()
  141. {
  142. return $this->class;
  143. }
  144. /**
  145. * return the doctrine class metadata handled by the Admin instance
  146. *
  147. * @return ClassMetadataInfo the doctrine class metadata handled by the Admin instance
  148. */
  149. public function getClassMetaData()
  150. {
  151. return $this->getEntityManager()
  152. ->getClassMetaData($this->getClass());
  153. }
  154. /**
  155. * return the list of batchs actions
  156. *
  157. * @return array the list of batchs actions
  158. */
  159. public function getBatchActions()
  160. {
  161. return array(
  162. 'delete' => 'action_delete'
  163. );
  164. }
  165. /**
  166. * return the list of available urls
  167. *
  168. * @return array the list of available urls
  169. */
  170. public function getUrls()
  171. {
  172. $this->buildUrls();
  173. return $this->urls;
  174. }
  175. public function buildUrls()
  176. {
  177. if ($this->loaded['urls']) {
  178. return;
  179. }
  180. $this->urls = array(
  181. 'list' => array(
  182. 'name' => $this->getBaseRouteName().'_list',
  183. 'pattern' => $this->getBaseRoutePattern().'/list',
  184. 'defaults' => array(
  185. '_controller' => $this->getBaseControllerName().':list'
  186. ),
  187. 'requirements' => array(),
  188. 'options' => array(),
  189. 'params' => array(),
  190. ),
  191. 'create' => array(
  192. 'name' => $this->getBaseRouteName().'_create',
  193. 'pattern' => $this->getBaseRoutePattern().'/create',
  194. 'defaults' => array(
  195. '_controller' => $this->getBaseControllerName().':create'
  196. ),
  197. 'requirements' => array(),
  198. 'options' => array(),
  199. 'params' => array(),
  200. ),
  201. 'edit' => array(
  202. 'name' => $this->getBaseRouteName().'_edit',
  203. 'pattern' => $this->getBaseRoutePattern().'/{id}/edit',
  204. 'defaults' => array(
  205. '_controller' => $this->getBaseControllerName().':edit'
  206. ),
  207. 'requirements' => array(),
  208. 'options' => array(),
  209. 'params' => array(),
  210. ),
  211. 'update' => array(
  212. 'name' => $this->getBaseRouteName().'_update',
  213. 'pattern' => $this->getBaseRoutePattern().'/update',
  214. 'defaults' => array(
  215. '_controller' => $this->getBaseControllerName().':update'
  216. ),
  217. 'requirements' => array(),
  218. 'options' => array(),
  219. 'params' => array(),
  220. ),
  221. 'batch' => array(
  222. 'name' => $this->getBaseRouteName().'_batch',
  223. 'pattern' => $this->getBaseRoutePattern().'/batch',
  224. 'defaults' => array(
  225. '_controller' => $this->getBaseControllerName().':batch'
  226. ),
  227. 'requirements' => array(),
  228. 'options' => array(),
  229. 'params' => array(),
  230. )
  231. );
  232. $this->configureUrls();
  233. }
  234. public function configureUrls()
  235. {
  236. }
  237. /**
  238. * return the url defined by the $name
  239. *
  240. * @param $name
  241. * @return bool
  242. */
  243. public function getUrl($name)
  244. {
  245. $urls = $this->getUrls();
  246. if (!isset($urls[$name])) {
  247. return false;
  248. }
  249. return $urls[$name];
  250. }
  251. /**
  252. * generate the url with the given $name
  253. *
  254. * @throws RuntimeException
  255. * @param $name
  256. * @param array $params
  257. *
  258. * @return return a complete url
  259. */
  260. public function generateUrl($name, $params = array())
  261. {
  262. $url = $this->getUrl($name);
  263. if (!$url) {
  264. throw new \RuntimeException(sprintf('unable to find the url `%s`', $name));
  265. }
  266. if (!is_array($params)) {
  267. $params = array();
  268. }
  269. return $this->container->get('router')->generate($url['name'], array_merge($url['params'], $params));
  270. }
  271. /**
  272. * return the list template
  273. *
  274. * @return string the list template
  275. */
  276. public function getListTemplate()
  277. {
  278. return 'SonataBaseApplicationBundle:CRUD:list.twig.html';
  279. }
  280. /**
  281. * return the edit template
  282. *
  283. * @return string the edit template
  284. */
  285. public function getEditTemplate()
  286. {
  287. return 'SonataBaseApplicationBundle:CRUD:edit.twig.html';
  288. }
  289. public function getReflectionFields()
  290. {
  291. return $this->getClassMetaData()->reflFields;
  292. }
  293. public function getNewInstance()
  294. {
  295. $class = $this->getClass();
  296. return new $class;
  297. }
  298. /**
  299. * attach an admin instance to the given FieldDescription
  300. *
  301. */
  302. public function attachAdminClass(FieldDescription $fieldDescription)
  303. {
  304. $pool = $this->getConfigurationPool();
  305. $admin = $pool->getAdminByClass($fieldDescription->getTargetEntity());
  306. if (!$admin) {
  307. throw new \RuntimeException(sprintf('You must define an Admin class for the `%s` field', $fieldDescription->getFieldName()));
  308. }
  309. $fieldDescription->setAssociationAdmin($admin);
  310. }
  311. /**
  312. * return the target objet
  313. *
  314. * @param $id
  315. * @return
  316. */
  317. public function getObject($id)
  318. {
  319. return $this->getEntityManager()
  320. ->find($this->getClass(), $id);
  321. }
  322. public function buildFormGroups()
  323. {
  324. if ($this->loaded['form_groups']) {
  325. return;
  326. }
  327. $this->loaded['form_groups'] = true;
  328. if (!$this->formGroups) {
  329. $this->formGroups = array(
  330. false => array('fields' => array_keys($this->formFields))
  331. );
  332. }
  333. // normalize array
  334. foreach ($this->formGroups as $name => $group) {
  335. if (!isset($this->formGroups[$name]['collapsed'])) {
  336. $this->formGroups[$name]['collapsed'] = false;
  337. }
  338. }
  339. }
  340. public function preUpdate($object)
  341. {
  342. }
  343. public function postUpdate($object)
  344. {
  345. }
  346. public function preInsert($object)
  347. {
  348. }
  349. public function postInsert($object)
  350. {
  351. }
  352. public function configureListFields()
  353. {
  354. }
  355. public function configureFilterFields()
  356. {
  357. }
  358. public function configureFormFields()
  359. {
  360. }
  361. public function getFilterDatagrid()
  362. {
  363. if (!$this->filterDatagrid) {
  364. $this->filterDatagrid = new Datagrid(
  365. $this->getClass(),
  366. $this->getEntityManager()
  367. );
  368. $this->filterDatagrid->setMaxPerPage($this->maxPerPage);
  369. // first pass, configure and normalize the filterFields array
  370. $this->filterDatagrid->setFilterFields($this->filterFields);
  371. $this->filterDatagrid->buildFilterFields();
  372. // update the current filterFields array and apply admin custom code
  373. $this->filterFields = $this->filterDatagrid->getFilterFields();
  374. $this->configureFilterFields();
  375. // set the final value to the datagrid
  376. $this->filterDatagrid->setFilterFields($this->filterFields);
  377. }
  378. return $this->filterDatagrid;
  379. }
  380. /**
  381. *
  382. */
  383. public function getRootCode()
  384. {
  385. return $this->getRoot()->getCode();
  386. }
  387. /**
  388. * return the master admin
  389. *
  390. */
  391. public function getRoot()
  392. {
  393. $parentFieldDescription = $this->getParentFieldDescription();
  394. if (!$parentFieldDescription) {
  395. return $this;
  396. }
  397. return $parentFieldDescription->getAdmin()->getRoot();
  398. }
  399. /**
  400. * Construct and build the form field definitions
  401. *
  402. * @return list form field definition
  403. */
  404. public function getFormFields()
  405. {
  406. $this->buildFormFields();
  407. return $this->formFields;
  408. }
  409. public function getListFields()
  410. {
  411. $this->buildListFields();
  412. return $this->listFields;
  413. }
  414. public function setBaseControllerName($baseControllerName)
  415. {
  416. $this->baseControllerName = $baseControllerName;
  417. }
  418. public function getBaseControllerName()
  419. {
  420. return $this->baseControllerName;
  421. }
  422. public function setConfigurationPool($configurationPool)
  423. {
  424. $this->configurationPool = $configurationPool;
  425. }
  426. public function getConfigurationPool()
  427. {
  428. return $this->configurationPool;
  429. }
  430. public function setCode($code)
  431. {
  432. $this->code = $code;
  433. }
  434. public function getCode()
  435. {
  436. return $this->code;
  437. }
  438. public function setLabel($label)
  439. {
  440. $this->label = $label;
  441. }
  442. public function getLabel()
  443. {
  444. return $this->label;
  445. }
  446. public function setFilterFields($filterFields)
  447. {
  448. $this->filterFields = $filterFields;
  449. }
  450. public function getFilterFields()
  451. {
  452. return $this->filterFields;
  453. }
  454. public function setMaxPerPage($maxPerPage)
  455. {
  456. $this->maxPerPage = $maxPerPage;
  457. }
  458. public function getMaxPerPage()
  459. {
  460. return $this->maxPerPage;
  461. }
  462. public function setFormGroups($formGroups)
  463. {
  464. $this->formGroups = $formGroups;
  465. }
  466. public function getFormGroups()
  467. {
  468. $this->buildFormGroups();
  469. return $this->formGroups;
  470. }
  471. public function setParentFieldDescription($parentFieldDescription)
  472. {
  473. $this->parentFieldDescription = $parentFieldDescription;
  474. }
  475. public function getParentFieldDescription()
  476. {
  477. return $this->parentFieldDescription;
  478. }
  479. public function setSubject($subject)
  480. {
  481. $this->subject = $subject;
  482. }
  483. public function getSubject()
  484. {
  485. return $this->subject;
  486. }
  487. }