Admin.php 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272
  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\AdminBundle\Admin;
  11. use Symfony\Component\Form\Form;
  12. use Symfony\Component\Form\FormBuilder;
  13. use Symfony\Component\Validator\ValidatorInterface;
  14. use Symfony\Component\Routing\RouterInterface;
  15. use Symfony\Component\Translation\TranslatorInterface;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Security\Acl\Model\DomainObjectInterface;
  18. use Sonata\AdminBundle\Form\FormMapper;
  19. use Sonata\AdminBundle\Datagrid\ListMapper;
  20. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  21. use Sonata\AdminBundle\Show\ShowMapper;
  22. use Sonata\AdminBundle\Admin\Pool;
  23. use Sonata\AdminBundle\Validator\ErrorElement;
  24. use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
  25. use Sonata\AdminBundle\Builder\FormContractorInterface;
  26. use Sonata\AdminBundle\Builder\ListBuilderInterface;
  27. use Sonata\AdminBundle\Builder\DatagridBuilderInterface;
  28. use Sonata\AdminBundle\Builder\ShowBuilderInterface;
  29. use Sonata\AdminBundle\Builder\RouteBuilderInterface;
  30. use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
  31. use Sonata\AdminBundle\Route\RouteCollection;
  32. use Sonata\AdminBundle\Model\ModelManagerInterface;
  33. use Knp\Menu\FactoryInterface as MenuFactoryInterface;
  34. use Knp\Menu\ItemInterface as MenuItemInterface;
  35. use Knp\Menu\MenuItem;
  36. abstract class Admin implements AdminInterface, DomainObjectInterface
  37. {
  38. /**
  39. * The class name managed by the admin class
  40. *
  41. * @var string
  42. */
  43. private $class;
  44. /**
  45. * The list collection
  46. *
  47. * @var array
  48. */
  49. private $list;
  50. /**
  51. * The list FieldDescription constructed from the configureListField method
  52. *
  53. * @var array
  54. */
  55. protected $listFieldDescriptions = array();
  56. private $show;
  57. /**
  58. * The show FieldDescription constructed from the configureShowFields method
  59. *
  60. * @var array
  61. */
  62. protected $showFieldDescriptions = array();
  63. /**
  64. * @var Form
  65. */
  66. private $form;
  67. /**
  68. * The list FieldDescription constructed from the configureFormField method
  69. *
  70. * @var array
  71. */
  72. protected $formFieldDescriptions = array();
  73. /**
  74. * @var DatagridInterface
  75. */
  76. private $filter;
  77. /**
  78. * The filter FieldDescription constructed from the configureFilterField method
  79. *
  80. * @var array
  81. */
  82. protected $filterFieldDescriptions = array();
  83. /**
  84. * The number of result to display in the list
  85. *
  86. * @var integer
  87. */
  88. protected $maxPerPage = 25;
  89. /**
  90. * The base route name used to generate the routing information
  91. *
  92. * @var string
  93. */
  94. protected $baseRouteName;
  95. /**
  96. * The base route pattern used to generate the routing information
  97. *
  98. * @var string
  99. */
  100. protected $baseRoutePattern;
  101. /**
  102. * The base name controller used to generate the routing information
  103. *
  104. * @var string
  105. */
  106. protected $baseControllerName;
  107. /**
  108. * The form group disposition
  109. *
  110. * @var array|boolean
  111. */
  112. private $formGroups = false;
  113. /**
  114. * The view group disposition
  115. *
  116. * @var array|boolean
  117. */
  118. private $showGroups = false;
  119. /**
  120. * The label class name (used in the title/breadcrumb ...)
  121. *
  122. * @var string
  123. */
  124. protected $classnameLabel;
  125. /**
  126. * The translation domain to be used to translate messages
  127. *
  128. * @var string
  129. */
  130. protected $translationDomain = 'messages';
  131. /**
  132. * Options to set to the form (ie, validation_groups)
  133. *
  134. * @var array
  135. */
  136. protected $formOptions = array();
  137. /**
  138. * Default values to the datagrid
  139. *
  140. * @var array
  141. */
  142. protected $datagridValues = array(
  143. '_page' => 1,
  144. );
  145. /**
  146. * The code related to the admin
  147. *
  148. * @var string
  149. */
  150. protected $code;
  151. /**
  152. * The label
  153. *
  154. * @var string
  155. */
  156. protected $label;
  157. /**
  158. * Array of routes related to this admin
  159. *
  160. * @var \Sonata\AdminBundle\Route\RouteCollection
  161. */
  162. protected $routes;
  163. /**
  164. * The subject only set in edit/update/create mode
  165. *
  166. * @var object
  167. */
  168. protected $subject;
  169. /**
  170. * Define a Collection of child admin, ie /admin/order/{id}/order-element/{childId}
  171. *
  172. * @var array
  173. */
  174. protected $children = array();
  175. /**
  176. * Reference the parent collection
  177. *
  178. * @var Admin
  179. */
  180. protected $parent = null;
  181. /**
  182. * The base code route refer to the prefix used to generate the route name
  183. *
  184. * @var string
  185. */
  186. protected $baseCodeRoute = '';
  187. /**
  188. * The related field reflection, ie if OrderElement is linked to Order,
  189. * then the $parentReflectionProperty must be the ReflectionProperty of
  190. * the order (OrderElement::$order)
  191. *
  192. * @var \ReflectionProperty $parentReflectionProperty
  193. */
  194. protected $parentAssociationMapping = null;
  195. /**
  196. * Reference the parent FieldDescription related to this admin
  197. * only set for FieldDescription which is associated to an Sub Admin instance
  198. *
  199. * @var FieldDescription
  200. */
  201. protected $parentFieldDescription;
  202. /**
  203. * If true then the current admin is part of the nested admin set (from the url)
  204. *
  205. * @var boolean
  206. */
  207. protected $currentChild = false;
  208. /**
  209. * The uniqid is used to avoid clashing with 2 admin related to the code
  210. * ie: a Block linked to a Block
  211. *
  212. * @var string
  213. */
  214. protected $uniqid;
  215. /**
  216. * The Entity or Document manager
  217. *
  218. * @var \Sonata\AdminBundle\Model\ModelManagerInterface
  219. */
  220. protected $modelManager;
  221. /**
  222. * The current request object
  223. *
  224. * @var \Symfony\Component\HttpFoundation\Request
  225. */
  226. protected $request;
  227. /**
  228. * The translator component
  229. *
  230. * @var \Symfony\Component\Translation\TranslatorInterface
  231. */
  232. protected $translator;
  233. /**
  234. * The related form contractor
  235. *
  236. * @var \Sonata\AdminBundle\Builder\FormContractorInterface
  237. */
  238. protected $formContractor;
  239. /**
  240. * The related list builder
  241. *
  242. * @var \Sonata\AdminBundle\Builder\ListBuilderInterface
  243. */
  244. protected $listBuilder;
  245. /**
  246. * The related view builder
  247. *
  248. * @var \Sonata\AdminBundle\View\ShowBuilderInterface
  249. */
  250. protected $showBuilder;
  251. /**
  252. * The related datagrid builder
  253. *
  254. * @var \Sonata\AdminBundle\Builder\DatagridBuilderInterface
  255. */
  256. protected $datagridBuilder;
  257. /**
  258. * @var \Sonata\AdminBundle\Builder\RouteBuilderInterface
  259. */
  260. protected $routeBuilder;
  261. /**
  262. * The datagrid instance
  263. *
  264. * @var \Sonata\AdminBundle\Datagrid\DatagridInterface
  265. */
  266. protected $datagrid;
  267. /**
  268. * The router intance
  269. *
  270. * @var \Symfony\Component\Routing\RouterInterface
  271. */
  272. protected $router;
  273. /**
  274. * The generated breadcrumbs
  275. *
  276. * @var array
  277. */
  278. protected $breadcrumbs = array();
  279. protected $securityHandler = null;
  280. protected $validator = null;
  281. /**
  282. * The configuration pool
  283. *
  284. * @var Pool
  285. */
  286. protected $configurationPool;
  287. protected $menu;
  288. /**
  289. * @var \Knp\Menu\MenuFactoryInterface
  290. */
  291. protected $menuFactory;
  292. protected $loaded = array(
  293. 'view_fields' => false,
  294. 'view_groups' => false,
  295. 'routes' => false,
  296. 'side_menu' => false,
  297. );
  298. protected $formTheme = array();
  299. protected $filterTheme = array();
  300. protected $templates = array();
  301. protected $extensions = array();
  302. protected $labelTranslatorStrategy;
  303. /**
  304. * This method can be overwritten to tweak the form construction, by default the form
  305. * is built by reading the FieldDescription
  306. *
  307. * @param \Sonata\AdminBundle\Form\FormMapper $form
  308. * @return void
  309. */
  310. protected function configureFormFields(FormMapper $form)
  311. {
  312. }
  313. /**
  314. * overwrite this method to configure the list FormField definition
  315. *
  316. * @param \Sonata\AdminBundle\Datagrid\ListMapper $list
  317. * @return void
  318. */
  319. protected function configureListFields(ListMapper $list)
  320. {
  321. }
  322. /**
  323. * @param \Sonata\AdminBundle\Datagrid\DatagridMapper $filter
  324. * @return void
  325. */
  326. protected function configureDatagridFilters(DatagridMapper $filter)
  327. {
  328. }
  329. /**
  330. * @deprecated Use configureShowFields instead.
  331. * @param \Sonata\AdminBundle\Show\ShowMapper $filter
  332. * @return void
  333. */
  334. protected function configureShowField(ShowMapper $filter)
  335. {
  336. }
  337. /**
  338. * @param \Sonata\AdminBundle\Show\ShowMapper $filter
  339. * @return void
  340. */
  341. protected function configureShowFields(ShowMapper $filter)
  342. {
  343. }
  344. /**
  345. * configure the Admin routes
  346. *
  347. * @param \Sonata\AdminBundle\Route\RouteCollection $collection
  348. * @return void
  349. */
  350. protected function configureRoutes(RouteCollection $collection)
  351. {
  352. }
  353. /**
  354. * @param \Knp\Menu\ItemInterface $menu
  355. * @param $action
  356. * @param null|Admin $childAdmin
  357. * @return void
  358. */
  359. protected function configureSideMenu(MenuItemInterface $menu, $action, Admin $childAdmin = null)
  360. {
  361. }
  362. /**
  363. * @param \Sonata\AdminBundle\Validator\ErrorElement $errorElement
  364. * @param $object
  365. * @return void
  366. */
  367. public function validate(ErrorElement $errorElement, $object)
  368. {
  369. }
  370. /**
  371. * @param \Sonata\AdminBundle\Validator\ErrorElement $errorElement
  372. * @param $object
  373. * @return void
  374. */
  375. public function doValidate(ErrorElement $errorElement, $object)
  376. {
  377. $this->validate($errorElement, $object);
  378. foreach ($this->extensions as $extension) {
  379. $extension->validate($this, $errorElement, $object);
  380. }
  381. }
  382. /**
  383. * @param string $code
  384. * @param string $class
  385. * @param string $baseControllerName
  386. */
  387. public function __construct($code, $class, $baseControllerName)
  388. {
  389. $this->code = $code;
  390. $this->class = $class;
  391. $this->baseControllerName = $baseControllerName;
  392. }
  393. /**
  394. * define custom variable
  395. */
  396. public function initialize()
  397. {
  398. $this->uniqid = uniqid();
  399. if (!$this->classnameLabel) {
  400. $this->classnameLabel = substr($this->getClass(), strrpos($this->getClass(), '\\') + 1);
  401. }
  402. $this->baseCodeRoute = $this->getCode();
  403. $this->configure();
  404. }
  405. /**
  406. * Allows the user to define custom variables
  407. */
  408. public function configure()
  409. {
  410. }
  411. public function update($object)
  412. {
  413. $this->preUpdate($object);
  414. $this->getModelManager()->update($object);
  415. $this->postUpdate($object);
  416. }
  417. public function create($object)
  418. {
  419. $this->prePersist($object);
  420. $this->getModelManager()->create($object);
  421. $this->postPersist($object);
  422. }
  423. public function delete($object)
  424. {
  425. $this->preRemove($object);
  426. $this->getModelManager()->delete($object);
  427. $this->postRemove($object);
  428. }
  429. public function preUpdate($object)
  430. {
  431. }
  432. public function postUpdate($object)
  433. {
  434. }
  435. public function prePersist($object)
  436. {
  437. }
  438. public function postPersist($object)
  439. {
  440. }
  441. public function preRemove($object)
  442. {
  443. }
  444. public function postRemove($object)
  445. {
  446. }
  447. /**
  448. * build the view FieldDescription array
  449. *
  450. * @return void
  451. */
  452. protected function buildShow()
  453. {
  454. if ($this->show) {
  455. return;
  456. }
  457. $collection = new FieldDescriptionCollection();
  458. $mapper = new ShowMapper($this->showBuilder, $collection, $this);
  459. $this->configureShowField($mapper); // deprecated, use configureShowFields instead
  460. $this->configureShowFields($mapper);
  461. $this->show = $collection;
  462. }
  463. /**
  464. * build the list FieldDescription array
  465. *
  466. * @return void
  467. */
  468. protected function buildList()
  469. {
  470. if ($this->list) {
  471. return;
  472. }
  473. $this->list = $this->getListBuilder()->getBaseList();
  474. $mapper = new ListMapper($this->getListBuilder(), $this->list, $this);
  475. if (count($this->getBatchActions()) > 0) {
  476. $fieldDescription = $this->getModelManager()->getNewFieldDescriptionInstance($this->getClass(), 'batch', array(
  477. 'label' => 'batch',
  478. 'code' => '_batch',
  479. 'sortable' => false
  480. ));
  481. $fieldDescription->setAdmin($this);
  482. $fieldDescription->setTemplate('SonataAdminBundle:CRUD:list__batch.html.twig');
  483. $mapper->add($fieldDescription, 'batch');
  484. }
  485. $this->configureListFields($mapper);
  486. foreach($this->extensions as $extension) {
  487. $extension->configureListFields($mapper);
  488. }
  489. }
  490. /**
  491. * Get parameters that are currently bound to the filter.
  492. *
  493. * @return array
  494. */
  495. public function getFilterParameters()
  496. {
  497. $parameters = array();
  498. // build the values array
  499. if ($this->hasRequest()) {
  500. $parameters = array_merge(
  501. $this->getModelManager()->getDefaultSortValues($this->getClass()),
  502. $this->datagridValues,
  503. $this->request->query->get('filter', array())
  504. );
  505. // always force the parent value
  506. if ($this->isChild() && $this->getParentAssociationMapping()) {
  507. $parameters[$this->getParentAssociationMapping()] = array('value' => $this->request->get($this->getParent()->getIdParameter()));
  508. }
  509. }
  510. return $parameters;
  511. }
  512. /**
  513. * build the filter FieldDescription array
  514. *
  515. * @return void
  516. */
  517. public function buildDatagrid()
  518. {
  519. if ($this->datagrid) {
  520. return;
  521. }
  522. // initialize the datagrid
  523. $this->datagrid = $this->getDatagridBuilder()->getBaseDatagrid($this, $this->getFilterParameters());
  524. $this->datagrid->getPager()->setMaxPerPage($this->maxPerPage);
  525. $mapper = new DatagridMapper($this->getDatagridBuilder(), $this->datagrid, $this);
  526. // build the datagrid filter
  527. $this->configureDatagridFilters($mapper);
  528. // ok, try to limit to add parent filter
  529. if ($this->isChild() && $this->getParentAssociationMapping() && !$mapper->has($this->getParentAssociationMapping())) {
  530. $mapper->add($this->getParentAssociationMapping(), null, array(
  531. 'field_type' => 'sonata_type_model_reference',
  532. 'field_options' => array(
  533. 'model_manager' => $this->getModelManager()
  534. ),
  535. 'operator_type' => 'hidden'
  536. ));
  537. }
  538. foreach($this->extensions as $extension) {
  539. $extension->configureDatagridFilters($mapper);
  540. }
  541. }
  542. /**
  543. * Returns the name of the parent related field, so the field can be use to set the default
  544. * value (ie the parent object) or to filter the object
  545. *
  546. * @return string the name of the parent related field
  547. */
  548. public function getParentAssociationMapping()
  549. {
  550. return $this->parentAssociationMapping;
  551. }
  552. /**
  553. * Build the form FieldDescription collection
  554. *
  555. * @return void
  556. */
  557. protected function buildForm()
  558. {
  559. if ($this->form) {
  560. return;
  561. }
  562. // append parent object if any
  563. // todo : clean the way the Admin class can retrieve set the object
  564. if ($this->isChild() && $this->getParentAssociationMapping()) {
  565. $parent = $this->getParent()->getObject($this->request->get($this->getParent()->getIdParameter()));
  566. $propertyPath = new \Symfony\Component\Form\Util\PropertyPath($this->getParentAssociationMapping());
  567. $object = $this->getSubject();
  568. $propertyPath->setValue($object, $parent);
  569. }
  570. $this->form = $this->getFormBuilder()->getForm();
  571. }
  572. /**
  573. * Returns the baseRoutePattern used to generate the routing information
  574. *
  575. * @throws RuntimeException
  576. * @return string the baseRoutePattern used to generate the routing information
  577. */
  578. public function getBaseRoutePattern()
  579. {
  580. if (!$this->baseRoutePattern) {
  581. preg_match('@([A-Za-z0-9]*)\\\([A-Za-z0-9]*)Bundle\\\(Entity|Document|Model)\\\(.*)@', $this->getClass(), $matches);
  582. if (!$matches) {
  583. throw new \RuntimeException(sprintf('Please define a default `baseRoutePattern` value for the admin class `%s`', get_class($this)));
  584. }
  585. if ($this->isChild()) { // the admin class is a child, prefix it with the parent route name
  586. $this->baseRoutePattern = sprintf('%s/{id}/%s',
  587. $this->getParent()->getBaseRoutePattern(),
  588. $this->urlize($matches[4], '-')
  589. );
  590. } else {
  591. $this->baseRoutePattern = sprintf('/%s/%s/%s',
  592. $this->urlize($matches[1], '-'),
  593. $this->urlize($matches[2], '-'),
  594. $this->urlize($matches[4], '-')
  595. );
  596. }
  597. }
  598. return $this->baseRoutePattern;
  599. }
  600. /**
  601. * Returns the baseRouteName used to generate the routing information
  602. *
  603. * @throws RuntimeException
  604. * @return string the baseRouteName used to generate the routing information
  605. */
  606. public function getBaseRouteName()
  607. {
  608. if (!$this->baseRouteName) {
  609. preg_match('@([A-Za-z0-9]*)\\\([A-Za-z0-9]*)Bundle\\\(Entity|Document|Model)\\\(.*)@', $this->getClass(), $matches);
  610. if (!$matches) {
  611. throw new \RuntimeException(sprintf('Please define a default `baseRouteName` value for the admin class `%s`', get_class($this)));
  612. }
  613. if ($this->isChild()) { // the admin class is a child, prefix it with the parent route name
  614. $this->baseRouteName = sprintf('%s_%s',
  615. $this->getParent()->getBaseRouteName(),
  616. $this->urlize($matches[4])
  617. );
  618. } else {
  619. $this->baseRouteName = sprintf('admin_%s_%s_%s',
  620. $this->urlize($matches[1]),
  621. $this->urlize($matches[2]),
  622. $this->urlize($matches[4])
  623. );
  624. }
  625. }
  626. return $this->baseRouteName;
  627. }
  628. /**
  629. * urlize the given word
  630. *
  631. * @param string $word
  632. * @param string $sep the separator
  633. *
  634. * @return string
  635. */
  636. public function urlize($word, $sep = '_')
  637. {
  638. return strtolower(preg_replace('/[^a-z0-9_]/i', $sep.'$1', $word));
  639. }
  640. /**
  641. * Returns the class name handled by the Admin instance
  642. *
  643. * @return string the class name handled by the Admin instance
  644. */
  645. public function getClass()
  646. {
  647. return $this->class;
  648. }
  649. /**
  650. * Returns the list of batchs actions
  651. *
  652. * @return array the list of batchs actions
  653. */
  654. public function getBatchActions()
  655. {
  656. $actions = array();
  657. if ($this->isGranted('DELETE')) {
  658. $actions['delete'] = array(
  659. 'label' => $this->trans('action_delete', array(), 'SonataAdminBundle'),
  660. 'ask_confirmation' => true, // by default always true
  661. );
  662. }
  663. return $actions;
  664. }
  665. /**
  666. * Returns the list of available urls
  667. *
  668. * @return \Sonata\AdminBundle\Route\RouteCollection the list of available urls
  669. */
  670. public function getRoutes()
  671. {
  672. $this->buildRoutes();
  673. return $this->routes;
  674. }
  675. /**
  676. * Returns the parameter representing router id, ie: {id} or {childId}
  677. *
  678. * @return string
  679. */
  680. public function getRouterIdParameter()
  681. {
  682. return $this->isChild() ? '{childId}' : '{id}';
  683. }
  684. /**
  685. * Returns the parameter representing request id, ie: id or childId
  686. *
  687. * @return string
  688. */
  689. public function getIdParameter()
  690. {
  691. return $this->isChild() ? 'childId' : 'id';
  692. }
  693. /**
  694. * Build all the related urls to the current admin
  695. *
  696. * @return void
  697. */
  698. public function buildRoutes()
  699. {
  700. if ($this->loaded['routes']) {
  701. return;
  702. }
  703. $this->loaded['routes'] = true;
  704. $this->routes = new RouteCollection(
  705. $this->getBaseCodeRoute(),
  706. $this->getBaseRouteName(),
  707. $this->getBaseRoutePattern(),
  708. $this->getBaseControllerName()
  709. );
  710. $this->routeBuilder->build($this, $this->routes);
  711. $this->configureRoutes($this->routes);
  712. foreach($this->extensions as $extension) {
  713. $extension->configureRoutes($this, $this->routes);
  714. }
  715. }
  716. /**
  717. * Returns the url defined by the $name
  718. *
  719. * @param strinf $name
  720. * @return Route
  721. */
  722. public function getRoute($name)
  723. {
  724. $this->buildRoutes();
  725. if (!$this->routes->has($name)) {
  726. return false;
  727. }
  728. return $this->routes->get($name);
  729. }
  730. /**
  731. * @param $name
  732. * @return bool
  733. */
  734. public function hasRoute($name)
  735. {
  736. $this->buildRoutes();
  737. return $this->routes->has($name);
  738. }
  739. /**
  740. * generate the object url with the given $name
  741. *
  742. * @param string $name
  743. * @param $object
  744. * @param array $parameters
  745. *
  746. * @return return a complete url
  747. */
  748. public function generateObjectUrl($name, $object, array $parameters = array())
  749. {
  750. $parameters['id'] = $this->getNormalizedIdentifier($object);
  751. return $this->generateUrl($name, $parameters);
  752. }
  753. /**
  754. * generate the url with the given $name
  755. *
  756. * @throws RuntimeException
  757. * @param string $name
  758. * @param array $parameters
  759. *
  760. * @return return a complete url
  761. */
  762. public function generateUrl($name, array $parameters = array())
  763. {
  764. if (!$this->isChild()) {
  765. if (strpos($name, '.')) {
  766. $name = $this->getCode().'|'.$name;
  767. } else {
  768. $name = $this->getCode().'.'.$name;
  769. }
  770. }
  771. // if the admin is a child we automatically append the parent's id
  772. else if ($this->isChild()) {
  773. $name = $this->baseCodeRoute.'.'.$name;
  774. // twig template does not accept variable hash key ... so cannot use admin.idparameter ...
  775. // switch value
  776. if (isset($parameters['id'])) {
  777. $parameters[$this->getIdParameter()] = $parameters['id'];
  778. unset($parameters['id']);
  779. }
  780. $parameters[$this->getParent()->getIdParameter()] = $this->request->get($this->getParent()->getIdParameter());
  781. }
  782. // if the admin is linked to a parent FieldDescription (ie, embedded widget)
  783. if ($this->hasParentFieldDescription()) {
  784. // merge link parameter if any provided by the parent field
  785. $parameters = array_merge($parameters, $this->getParentFieldDescription()->getOption('link_parameters', array()));
  786. $parameters['uniqid'] = $this->getUniqid();
  787. $parameters['code'] = $this->getCode();
  788. $parameters['pcode'] = $this->getParentFieldDescription()->getAdmin()->getCode();
  789. $parameters['puniqid'] = $this->getParentFieldDescription()->getAdmin()->getUniqid();
  790. }
  791. if ($name == 'update' || substr($name, -7) == '|update') {
  792. $parameters['uniqid'] = $this->getUniqid();
  793. $parameters['code'] = $this->getCode();
  794. }
  795. // allows to define persistent parameters
  796. if ($this->hasRequest()) {
  797. $parameters = array_merge($this->getPersistentParameters(), $parameters);
  798. }
  799. $route = $this->getRoute($name);
  800. if (!$route) {
  801. throw new \RuntimeException(sprintf('unable to find the route `%s`', $name));
  802. }
  803. return $this->router->generate($route->getDefault('_sonata_name'), $parameters);
  804. }
  805. /**
  806. * Returns the list template
  807. *
  808. * @return string the list template
  809. */
  810. public function getListTemplate()
  811. {
  812. return $this->getTemplate('list');
  813. }
  814. /**
  815. * Returns the edit template
  816. *
  817. * @return string the edit template
  818. */
  819. public function getEditTemplate()
  820. {
  821. return $this->getTemplate('edit');
  822. }
  823. /**
  824. * Returns the view template
  825. *
  826. * @return string the view template
  827. */
  828. public function getShowTemplate()
  829. {
  830. return $this->getTemplate('show');
  831. }
  832. /**
  833. * @param array $templates
  834. * @return void
  835. */
  836. public function setTemplates(array $templates)
  837. {
  838. $this->templates = $templates;
  839. }
  840. /**
  841. * @return array
  842. */
  843. public function getTemplates()
  844. {
  845. return $this->templates;
  846. }
  847. /**
  848. * @param $name
  849. * @return null|string
  850. */
  851. public function getTemplate($name)
  852. {
  853. if (isset($this->templates[$name])) {
  854. return $this->templates[$name];
  855. }
  856. return null;
  857. }
  858. /**
  859. * Returns an instance of the related classname
  860. *
  861. * @return Object An instance of the related classname
  862. */
  863. public function getNewInstance()
  864. {
  865. return $this->getModelManager()->getModelInstance($this->getClass());
  866. }
  867. /**
  868. * @return \Symfony\Component\Form\FormBuilder the form builder
  869. */
  870. public function getFormBuilder()
  871. {
  872. // add the custom inline validation option
  873. $metadata = $this->validator->getMetadataFactory()->getClassMetadata($this->getClass());
  874. $metadata->addConstraint(new \Sonata\AdminBundle\Validator\Constraints\InlineConstraint(array(
  875. 'service' => $this,
  876. 'method' => 'doValidate'
  877. )));
  878. $this->formOptions['data_class'] = $this->getClass();
  879. $formBuilder = $this->getFormContractor()->getFormBuilder(
  880. $this->getUniqid(),
  881. $this->formOptions
  882. );
  883. $this->defineFormBuilder($formBuilder);
  884. return $formBuilder;
  885. }
  886. /**
  887. * @param \Symfony\Component\Form\FormBuilder $formBuilder
  888. * @return void
  889. */
  890. public function defineFormBuilder(FormBuilder $formBuilder)
  891. {
  892. $mapper = new FormMapper($this->getFormContractor(), $formBuilder, $this);
  893. $this->configureFormFields($mapper);
  894. foreach($this->extensions as $extension) {
  895. $extension->configureFormFields($mapper);
  896. }
  897. }
  898. /**
  899. * attach an admin instance to the given FieldDescription
  900. *
  901. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  902. */
  903. public function attachAdminClass(FieldDescriptionInterface $fieldDescription)
  904. {
  905. $pool = $this->getConfigurationPool();
  906. $admin = $pool->getAdminByClass($fieldDescription->getTargetEntity());
  907. if (!$admin) {
  908. return;
  909. }
  910. $fieldDescription->setAssociationAdmin($admin);
  911. }
  912. /**
  913. * Returns the target object
  914. *
  915. * @param integer $id
  916. * @return object
  917. */
  918. public function getObject($id)
  919. {
  920. return $this->getModelManager()->find($this->getClass(), $id);
  921. }
  922. /**
  923. * Returns a form depend on the given $object
  924. *
  925. * @return \Symfony\Component\Form\Form
  926. */
  927. public function getForm()
  928. {
  929. $this->buildForm();
  930. return $this->form;
  931. }
  932. /**
  933. * Returns a list depend on the given $object
  934. *
  935. * @return \Sonata\AdminBundle\Admin\FieldDescriptionCollection
  936. */
  937. public function getList()
  938. {
  939. $this->buildList();
  940. return $this->list;
  941. }
  942. /**
  943. * @return \Sonata\AdminBundle\Datagrid\ProxyQueryInterface
  944. */
  945. public function createQuery($context = 'list')
  946. {
  947. return $this->getModelManager()->createQuery($this->class);
  948. }
  949. /**
  950. * Returns a list depend on the given $object
  951. *
  952. * @return \Sonata\AdminBundle\Datagrid\DatagridInterface
  953. */
  954. public function getDatagrid()
  955. {
  956. $this->buildDatagrid();
  957. return $this->datagrid;
  958. }
  959. /**
  960. * Build the side menu related to the current action
  961. *
  962. * @param string $action
  963. * @param \Sonata\AdminBundle\Admin\AdminInterface $childAdmin
  964. * @return MenuItem|false
  965. */
  966. public function buildSideMenu($action, AdminInterface $childAdmin = null)
  967. {
  968. if ($this->loaded['side_menu']) {
  969. return;
  970. }
  971. $this->loaded['side_menu'] = true;
  972. $menu = $this->menuFactory->createItem('root');
  973. $this->configureSideMenu($menu, $action, $childAdmin);
  974. foreach ($this->extensions as $extension) {
  975. $extension->configureSideMenu($this, $menu, $action, $childAdmin);
  976. }
  977. $this->menu = $menu;
  978. }
  979. /**
  980. * @param string $action
  981. * @param \Sonata\AdminBundle\Admin\AdminInterface $childAdmin
  982. * @return \Knp\MenuBundle\Menu
  983. */
  984. public function getSideMenu($action, AdminInterface $childAdmin = null)
  985. {
  986. if ($this->isChild()) {
  987. return $this->getParent()->getSideMenu($action, $this);
  988. }
  989. $this->buildSideMenu($action, $childAdmin);
  990. return $this->menu;
  991. }
  992. /**
  993. * Returns the root code
  994. *
  995. * @return string the root code
  996. */
  997. public function getRootCode()
  998. {
  999. return $this->getRoot()->getCode();
  1000. }
  1001. /**
  1002. * Returns the master admin
  1003. *
  1004. * @return \Sonata\AdminBundle\Admin\Admin the root admin class
  1005. */
  1006. public function getRoot()
  1007. {
  1008. $parentFieldDescription = $this->getParentFieldDescription();
  1009. if (!$parentFieldDescription) {
  1010. return $this;
  1011. }
  1012. return $parentFieldDescription->getAdmin()->getRoot();
  1013. }
  1014. public function setBaseControllerName($baseControllerName)
  1015. {
  1016. $this->baseControllerName = $baseControllerName;
  1017. }
  1018. public function getBaseControllerName()
  1019. {
  1020. return $this->baseControllerName;
  1021. }
  1022. public function setLabel($label)
  1023. {
  1024. $this->label = $label;
  1025. }
  1026. public function getLabel()
  1027. {
  1028. return $this->label;
  1029. }
  1030. public function setMaxPerPage($maxPerPage)
  1031. {
  1032. $this->maxPerPage = $maxPerPage;
  1033. }
  1034. public function getMaxPerPage()
  1035. {
  1036. return $this->maxPerPage;
  1037. }
  1038. public function getFormGroups()
  1039. {
  1040. return $this->formGroups;
  1041. }
  1042. public function setFormGroups(array $formGroups)
  1043. {
  1044. $this->formGroups = $formGroups;
  1045. }
  1046. public function getShowGroups()
  1047. {
  1048. return $this->showGroups;
  1049. }
  1050. public function setShowGroups(array $showGroups)
  1051. {
  1052. $this->showGroups = $showGroups;
  1053. }
  1054. /**
  1055. * set the parent FieldDescription
  1056. *
  1057. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $parentFieldDescription
  1058. * @return void
  1059. */
  1060. public function setParentFieldDescription(FieldDescriptionInterface $parentFieldDescription)
  1061. {
  1062. $this->parentFieldDescription = $parentFieldDescription;
  1063. }
  1064. /**
  1065. *
  1066. * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface the parent field description
  1067. */
  1068. public function getParentFieldDescription()
  1069. {
  1070. return $this->parentFieldDescription;
  1071. }
  1072. /**
  1073. * Returns true if the Admin is linked to a parent FieldDescription
  1074. *
  1075. * @return bool
  1076. */
  1077. public function hasParentFieldDescription()
  1078. {
  1079. return $this->parentFieldDescription instanceof FieldDescriptionInterface;
  1080. }
  1081. /**
  1082. * set the subject linked to the admin, the subject is the related model
  1083. *
  1084. * @param object $subject
  1085. * @return void
  1086. */
  1087. public function setSubject($subject)
  1088. {
  1089. $this->subject = $subject;
  1090. }
  1091. /**
  1092. * Returns the subject, if none is set try to load one from the request
  1093. *
  1094. * @return object $object the subject
  1095. */
  1096. public function getSubject()
  1097. {
  1098. if ($this->subject === null && $this->request) {
  1099. $id = $this->request->get($this->getIdParameter());
  1100. if (!is_numeric($id)) {
  1101. $this->subject = false;
  1102. } else {
  1103. $this->subject = $this->getModelManager()->find($this->getClass(), $id);
  1104. }
  1105. }
  1106. return $this->subject;
  1107. }
  1108. /**
  1109. * @return bool
  1110. */
  1111. public function hasSubject()
  1112. {
  1113. return $this->subject != null;
  1114. }
  1115. /**
  1116. * build and return the collection of form FieldDescription
  1117. *
  1118. * @return array collection of form FieldDescription
  1119. */
  1120. public function getFormFieldDescriptions()
  1121. {
  1122. $this->buildForm();
  1123. return $this->formFieldDescriptions;
  1124. }
  1125. /**
  1126. * Returns the form FieldDescription with the given $name
  1127. *
  1128. * @param string $name
  1129. * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface
  1130. */
  1131. public function getFormFieldDescription($name)
  1132. {
  1133. return $this->hasFormFieldDescription($name) ? $this->formFieldDescriptions[$name] : null;
  1134. }
  1135. /**
  1136. * Returns true if the admin has a FieldDescription with the given $name
  1137. *
  1138. * @param string $name
  1139. * @return bool
  1140. */
  1141. public function hasFormFieldDescription($name)
  1142. {
  1143. return array_key_exists($name, $this->formFieldDescriptions) ? true : false;
  1144. }
  1145. /**
  1146. * add a FieldDescription
  1147. *
  1148. * @param string $name
  1149. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  1150. * @return void
  1151. */
  1152. public function addFormFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1153. {
  1154. $this->formFieldDescriptions[$name] = $fieldDescription;
  1155. }
  1156. /**
  1157. * remove a FieldDescription
  1158. *
  1159. * @param string $name
  1160. * @return void
  1161. */
  1162. public function removeFormFieldDescription($name)
  1163. {
  1164. unset($this->formFieldDescriptions[$name]);
  1165. }
  1166. /**
  1167. * build and return the collection of form FieldDescription
  1168. *
  1169. * @return array collection of form FieldDescription
  1170. */
  1171. public function getShowFieldDescriptions()
  1172. {
  1173. $this->buildShow();
  1174. return $this->showFieldDescriptions;
  1175. }
  1176. /**
  1177. * Returns the form FieldDescription with the given $name
  1178. *
  1179. * @param string $name
  1180. * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface
  1181. */
  1182. public function getShowFieldDescription($name)
  1183. {
  1184. $this->buildShow();
  1185. return $this->hasShowFieldDescription($name) ? $this->showFieldDescriptions[$name] : null;
  1186. }
  1187. /**
  1188. * Returns true if the admin has a FieldDescription with the given $name
  1189. *
  1190. * @param string $name
  1191. * @return bool
  1192. */
  1193. public function hasShowFieldDescription($name)
  1194. {
  1195. return array_key_exists($name, $this->showFieldDescriptions);
  1196. }
  1197. /**
  1198. * add a FieldDescription
  1199. *
  1200. * @param string $name
  1201. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  1202. * @return void
  1203. */
  1204. public function addShowFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1205. {
  1206. $this->showFieldDescriptions[$name] = $fieldDescription;
  1207. }
  1208. /**
  1209. * remove a FieldDescription
  1210. *
  1211. * @param string $name
  1212. * @return void
  1213. */
  1214. public function removeShowFieldDescription($name)
  1215. {
  1216. unset($this->showFieldDescriptions[$name]);
  1217. }
  1218. /**
  1219. * Returns the collection of list FieldDescriptions
  1220. *
  1221. * @return array
  1222. */
  1223. public function getListFieldDescriptions()
  1224. {
  1225. $this->buildList();
  1226. return $this->listFieldDescriptions;
  1227. }
  1228. /**
  1229. * Returns a list FieldDescription
  1230. *
  1231. * @param string $name
  1232. * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface
  1233. */
  1234. public function getListFieldDescription($name)
  1235. {
  1236. return $this->hasListFieldDescription($name) ? $this->listFieldDescriptions[$name] : null;
  1237. }
  1238. /**
  1239. * Returns true if the list FieldDescription exists
  1240. *
  1241. * @param string $name
  1242. * @return bool
  1243. */
  1244. public function hasListFieldDescription($name)
  1245. {
  1246. $this->buildList();
  1247. return array_key_exists($name, $this->listFieldDescriptions) ? true : false;
  1248. }
  1249. /**
  1250. * add a list FieldDescription
  1251. *
  1252. * @param string $name
  1253. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  1254. * @return void
  1255. */
  1256. public function addListFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1257. {
  1258. $this->listFieldDescriptions[$name] = $fieldDescription;
  1259. }
  1260. /**
  1261. * remove a list FieldDescription
  1262. *
  1263. * @param string $name
  1264. * @return void
  1265. */
  1266. public function removeListFieldDescription($name)
  1267. {
  1268. unset($this->listFieldDescriptions[$name]);
  1269. }
  1270. /**
  1271. * Returns a filter FieldDescription
  1272. *
  1273. * @param string $name
  1274. * @return array|null
  1275. */
  1276. public function getFilterFieldDescription($name)
  1277. {
  1278. return $this->hasFilterFieldDescription($name) ? $this->filterFieldDescriptions[$name] : null;
  1279. }
  1280. /**
  1281. * Returns true if the filter FieldDescription exists
  1282. *
  1283. * @param string $name
  1284. * @return bool
  1285. */
  1286. public function hasFilterFieldDescription($name)
  1287. {
  1288. return array_key_exists($name, $this->filterFieldDescriptions) ? true : false;
  1289. }
  1290. /**
  1291. * add a filter FieldDescription
  1292. *
  1293. * @param string $name
  1294. * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
  1295. * @return void
  1296. */
  1297. public function addFilterFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1298. {
  1299. $this->filterFieldDescriptions[$name] = $fieldDescription;
  1300. }
  1301. /**
  1302. * remove a filter FieldDescription
  1303. *
  1304. * @param string $name
  1305. */
  1306. public function removeFilterFieldDescription($name)
  1307. {
  1308. unset($this->filterFieldDescriptions[$name]);
  1309. }
  1310. /**
  1311. * Returns the filter FieldDescription collection
  1312. *
  1313. * @param array filter FieldDescription collection
  1314. */
  1315. public function getFilterFieldDescriptions()
  1316. {
  1317. $this->buildDatagrid();
  1318. return $this->filterFieldDescriptions;
  1319. }
  1320. /**
  1321. * add an Admin child to the current one
  1322. *
  1323. * @param \Sonata\AdminBundle\Admin\AdminInterface $child
  1324. * @return void
  1325. */
  1326. public function addChild(AdminInterface $child)
  1327. {
  1328. $this->children[$child->getCode()] = $child;
  1329. $child->setBaseCodeRoute($this->getCode().'|'.$child->getCode());
  1330. $child->setParent($this);
  1331. }
  1332. /**
  1333. * Returns true or false if an Admin child exists for the given $code
  1334. *
  1335. * @param string $code Admin code
  1336. * @return bool True if child exist, false otherwise
  1337. */
  1338. public function hasChild($code)
  1339. {
  1340. return isset($this->children[$code]);
  1341. }
  1342. /**
  1343. * Returns an collection of admin children
  1344. *
  1345. * @return array list of Admin children
  1346. */
  1347. public function getChildren()
  1348. {
  1349. return $this->children;
  1350. }
  1351. /**
  1352. * Returns an admin child with the given $code
  1353. *
  1354. * @param string $code
  1355. * @return array|null
  1356. */
  1357. public function getChild($code)
  1358. {
  1359. return $this->hasChild($code) ? $this->children[$code] : null;
  1360. }
  1361. /**
  1362. * set the Parent Admin
  1363. *
  1364. * @param \Sonata\AdminBundle\Admin\AdminInterface $parent
  1365. * @return void
  1366. */
  1367. public function setParent(AdminInterface $parent)
  1368. {
  1369. $this->parent = $parent;
  1370. }
  1371. /**
  1372. * get the Parent Admin
  1373. *
  1374. * @return \Sonata\AdminBundle\Admin\AdminInterface|null
  1375. */
  1376. public function getParent()
  1377. {
  1378. return $this->parent;
  1379. }
  1380. /**
  1381. * Returns true if the Admin class has an Parent Admin defined
  1382. *
  1383. * @return boolean
  1384. */
  1385. public function isChild()
  1386. {
  1387. return $this->parent instanceof AdminInterface;
  1388. }
  1389. /**
  1390. * Returns true if the admin has children, false otherwise
  1391. *
  1392. * @return bool if the admin has children
  1393. */
  1394. public function hasChildren()
  1395. {
  1396. return count($this->children) > 0;
  1397. }
  1398. /**
  1399. * set the uniqid
  1400. *
  1401. * @param $uniqid
  1402. * @return void
  1403. */
  1404. public function setUniqid($uniqid)
  1405. {
  1406. $this->uniqid = $uniqid;
  1407. }
  1408. /**
  1409. * Returns the uniqid
  1410. *
  1411. * @return integer
  1412. */
  1413. public function getUniqid()
  1414. {
  1415. return $this->uniqid;
  1416. }
  1417. /**
  1418. * Returns the classname label
  1419. *
  1420. * @return string the classname label
  1421. */
  1422. public function getClassnameLabel()
  1423. {
  1424. return $this->classnameLabel;
  1425. }
  1426. /**
  1427. * Returns an array of persistent parameters
  1428. *
  1429. * @return array
  1430. */
  1431. public function getPersistentParameters()
  1432. {
  1433. return array();
  1434. }
  1435. /**
  1436. * @param $name
  1437. * @return null|mixed
  1438. */
  1439. public function getPersistentParameter($name)
  1440. {
  1441. $parameters = $this->getPersistentParameters();
  1442. return isset($parameters[$name]) ? $parameters[$name] : null;
  1443. }
  1444. /**
  1445. * @param string $action
  1446. * @return array
  1447. */
  1448. public function getBreadcrumbs($action)
  1449. {
  1450. if ($this->isChild()) {
  1451. return $this->getParent()->getBreadcrumbs($action);
  1452. }
  1453. return $this->buildBreadcrumbs($action);
  1454. }
  1455. /**
  1456. * Generates the breadcrumbs array
  1457. *
  1458. * @param string $action
  1459. * @param \Knp\Menu\ItemInterface|null $menu
  1460. * @return array
  1461. */
  1462. public function buildBreadcrumbs($action, MenuItemInterface $menu = null)
  1463. {
  1464. if (isset($this->breadcrumbs[$action])) {
  1465. return $this->breadcrumbs[$action];
  1466. }
  1467. if (!$menu) {
  1468. $menu = $this->menuFactory->createItem('root');
  1469. }
  1470. $child = $menu->addChild(
  1471. $this->trans($this->getLabelTranslatorStrategy()->getLabel('dashboard', 'breadcrumb', 'link'), array(), 'SonataAdminBundle'),
  1472. array('uri' => $this->router->generate('sonata_admin_dashboard'))
  1473. );
  1474. $child = $child->addChild(
  1475. $this->trans($this->getLabelTranslatorStrategy()->getLabel(sprintf('%s_list', $this->getClassnameLabel()), 'breadcrumb', 'link')),
  1476. array('uri' => $this->generateUrl('list'))
  1477. );
  1478. $childAdmin = $this->getCurrentChildAdmin();
  1479. if ($childAdmin) {
  1480. $id = $this->request->get($this->getIdParameter());
  1481. $child = $child->addChild(
  1482. (string) $this->getSubject(),
  1483. array('uri' => $this->generateUrl('edit', array('id' => $id)))
  1484. );
  1485. return $childAdmin->buildBreadcrumbs($action, $child);
  1486. } elseif ($this->isChild()) {
  1487. if ($action != 'list') {
  1488. $menu = $menu->addChild(
  1489. $this->trans($this->getLabelTranslatorStrategy()->getLabel(sprintf('%s_list', $this->getClassnameLabel()), 'breadcrumb', 'link')),
  1490. array('uri' => $this->generateUrl('list'))
  1491. );
  1492. }
  1493. if ($this->hasSubject()) {
  1494. $breadcrumbs = $menu->getBreadcrumbsArray( (string) $this->getSubject());
  1495. } else {
  1496. $breadcrumbs = $menu->getBreadcrumbsArray(
  1497. $this->trans($this->getLabelTranslatorStrategy()->getLabel(sprintf('%s_%s', $this->getClassnameLabel(), $action), 'breadcrumb', 'link'))
  1498. );
  1499. }
  1500. } else if ($action != 'list') {
  1501. $breadcrumbs = $child->getBreadcrumbsArray(
  1502. $this->trans($this->getLabelTranslatorStrategy()->getLabel(sprintf('%s_%s', $this->getClassnameLabel(), $action), 'breadcrumb', 'link'))
  1503. );
  1504. } else {
  1505. $breadcrumbs = $child->getBreadcrumbsArray();
  1506. }
  1507. // the generated $breadcrumbs contains an empty element
  1508. array_shift($breadcrumbs);
  1509. return $this->breadcrumbs[$action] = $breadcrumbs;
  1510. }
  1511. /**
  1512. * set the current child status
  1513. *
  1514. * @param boolean $currentChild
  1515. * @return void
  1516. */
  1517. public function setCurrentChild($currentChild)
  1518. {
  1519. $this->currentChild = $currentChild;
  1520. }
  1521. /**
  1522. * Returns the current child status
  1523. *
  1524. * @return bool
  1525. */
  1526. public function getCurrentChild()
  1527. {
  1528. return $this->currentChild;
  1529. }
  1530. /**
  1531. * Returns the current child admin instance
  1532. *
  1533. * @return \Sonata\AdminBundle\Admin\AdminInterface|null the current child admin instance
  1534. */
  1535. public function getCurrentChildAdmin()
  1536. {
  1537. foreach ($this->children as $children) {
  1538. if ($children->getCurrentChild()) {
  1539. return $children;
  1540. }
  1541. }
  1542. return null;
  1543. }
  1544. /**
  1545. * translate a message id
  1546. *
  1547. * @param string $id
  1548. * @param array $parameters
  1549. * @param null $domain
  1550. * @param null $locale
  1551. * @return string the translated string
  1552. */
  1553. public function trans($id, array $parameters = array(), $domain = null, $locale = null)
  1554. {
  1555. $domain = $domain ?: $this->translationDomain;
  1556. if (!$this->translator) {
  1557. return $id;
  1558. }
  1559. return $this->translator->trans($id, $parameters, $domain, $locale);
  1560. }
  1561. /**
  1562. * set the translation domain
  1563. *
  1564. * @param string $translationDomain the translation domain
  1565. * @return void
  1566. */
  1567. public function setTranslationDomain($translationDomain)
  1568. {
  1569. $this->translationDomain = $translationDomain;
  1570. }
  1571. /**
  1572. * Returns the translation domain
  1573. *
  1574. * @return string the translation domain
  1575. */
  1576. public function getTranslationDomain()
  1577. {
  1578. return $this->translationDomain;
  1579. }
  1580. /**
  1581. * @param \Symfony\Component\Translation\TranslatorInterface $translator
  1582. * @return void
  1583. */
  1584. public function setTranslator(TranslatorInterface $translator)
  1585. {
  1586. $this->translator = $translator;
  1587. }
  1588. /**
  1589. * @return \Symfony\Component\Translation\TranslatorInterface
  1590. */
  1591. public function getTranslator()
  1592. {
  1593. return $this->translator;
  1594. }
  1595. /**
  1596. * @param \Symfony\Component\HttpFoundation\Request $request
  1597. * @return void
  1598. */
  1599. public function setRequest(Request $request)
  1600. {
  1601. $this->request = $request;
  1602. if ($request->get('uniqid')) {
  1603. $this->setUniqid($request->get('uniqid'));
  1604. }
  1605. foreach ($this->getChildren() as $children) {
  1606. $children->setRequest($request);
  1607. }
  1608. }
  1609. /**
  1610. * @return \Symfony\Component\HttpFoundation\Request
  1611. */
  1612. public function getRequest()
  1613. {
  1614. if (!$this->request) {
  1615. throw new \RuntimeException('The Request object has not been set');
  1616. }
  1617. return $this->request;
  1618. }
  1619. /**
  1620. *
  1621. * @return true if the request object is linked to the Admin
  1622. */
  1623. public function hasRequest()
  1624. {
  1625. return $this->request !== null;
  1626. }
  1627. /**
  1628. * @param \Sonata\AdminBundle\Builder\FormContractorInterface $formBuilder
  1629. * @return void
  1630. */
  1631. public function setFormContractor(FormContractorInterface $formBuilder)
  1632. {
  1633. $this->formContractor = $formBuilder;
  1634. }
  1635. /**
  1636. * @return \Sonata\AdminBundle\Builder\FormContractorInterface
  1637. */
  1638. public function getFormContractor()
  1639. {
  1640. return $this->formContractor;
  1641. }
  1642. /**
  1643. * @param \Sonata\AdminBundle\Builder\DatagridBuilderInterface $datagridBuilder
  1644. * @return void
  1645. */
  1646. public function setDatagridBuilder(DatagridBuilderInterface $datagridBuilder)
  1647. {
  1648. $this->datagridBuilder = $datagridBuilder;
  1649. }
  1650. /**
  1651. * @return \Sonata\AdminBundle\Builder\DatagridBuilderInterface
  1652. */
  1653. public function getDatagridBuilder()
  1654. {
  1655. return $this->datagridBuilder;
  1656. }
  1657. /**
  1658. * @param \Sonata\AdminBundle\Builder\ListBuilderInterface $listBuilder
  1659. * @return void
  1660. */
  1661. public function setListBuilder(ListBuilderInterface $listBuilder)
  1662. {
  1663. $this->listBuilder = $listBuilder;
  1664. }
  1665. /**
  1666. * @return \Sonata\AdminBundle\Builder\ListBuilderInterface
  1667. */
  1668. public function getListBuilder()
  1669. {
  1670. return $this->listBuilder;
  1671. }
  1672. /**
  1673. * @param \Sonata\AdminBundle\Builder\ShowBuilderInterface $showBuilder
  1674. * @return void
  1675. */
  1676. public function setShowBuilder(ShowBuilderInterface $showBuilder)
  1677. {
  1678. $this->showBuilder = $showBuilder;
  1679. }
  1680. /**
  1681. * @return \Sonata\AdminBundle\Builder\ShowBuilderInterface
  1682. */
  1683. public function getShowBuilder()
  1684. {
  1685. return $this->showBuilder;
  1686. }
  1687. /**
  1688. * @param Pool $configurationPool
  1689. * @return void
  1690. */
  1691. public function setConfigurationPool(Pool $configurationPool)
  1692. {
  1693. $this->configurationPool = $configurationPool;
  1694. }
  1695. /**
  1696. * @return Pool
  1697. */
  1698. public function getConfigurationPool()
  1699. {
  1700. return $this->configurationPool;
  1701. }
  1702. /**
  1703. * @param \Symfony\Component\Routing\RouterInterface $router
  1704. * @return void
  1705. */
  1706. public function setRouter(RouterInterface $router)
  1707. {
  1708. $this->router = $router;
  1709. }
  1710. /**
  1711. * @return \Symfony\Component\Routing\RouterInterface
  1712. */
  1713. public function getRouter()
  1714. {
  1715. return $this->router;
  1716. }
  1717. public function getCode()
  1718. {
  1719. return $this->code;
  1720. }
  1721. public function setBaseCodeRoute($baseCodeRoute)
  1722. {
  1723. $this->baseCodeRoute = $baseCodeRoute;
  1724. }
  1725. public function getBaseCodeRoute()
  1726. {
  1727. return $this->baseCodeRoute;
  1728. }
  1729. /**
  1730. * @return \Sonata\AdminBundle\Model\ModelManagerInterface
  1731. */
  1732. public function getModelManager()
  1733. {
  1734. return $this->modelManager;
  1735. }
  1736. /**
  1737. * @param \Sonata\AdminBundle\Model\ModelManagerInterface $modelManager
  1738. */
  1739. public function setModelManager(ModelManagerInterface $modelManager)
  1740. {
  1741. $this->modelManager = $modelManager;
  1742. }
  1743. /**
  1744. * Returns a unique identifier for this domain object.
  1745. *
  1746. * @return string
  1747. */
  1748. public function getObjectIdentifier()
  1749. {
  1750. return $this->getCode();
  1751. }
  1752. /**
  1753. * Return the list of security name available for the current admin
  1754. * This should be used by experimented users
  1755. *
  1756. * @return array
  1757. */
  1758. public function getSecurityInformation()
  1759. {
  1760. return array(
  1761. 'EDIT' => array('EDIT'),
  1762. 'LIST' => array('LIST'),
  1763. 'CREATE' => array('CREATE'),
  1764. 'VIEW' => array('VIEW'),
  1765. 'DELETE' => array('DELETE'),
  1766. 'OPERATOR' => array('OPERATOR')
  1767. );
  1768. }
  1769. /**
  1770. * @param \Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface $securityHandler
  1771. * @return void
  1772. */
  1773. public function setSecurityHandler(SecurityHandlerInterface $securityHandler)
  1774. {
  1775. $this->securityHandler = $securityHandler;
  1776. }
  1777. /**
  1778. * @return \Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface|null
  1779. */
  1780. public function getSecurityHandler()
  1781. {
  1782. return $this->securityHandler;
  1783. }
  1784. /**
  1785. * @param string $name
  1786. * @param object|null $object
  1787. * @return boolean
  1788. */
  1789. public function isGranted($name, $object = null)
  1790. {
  1791. return $this->securityHandler->isGranted($this, $name, $object ?: $this);
  1792. }
  1793. /**
  1794. * @param $entity
  1795. * @return mixed
  1796. */
  1797. public function getNormalizedIdentifier($entity)
  1798. {
  1799. return $this->getModelManager()->getNormalizedIdentifier($entity);
  1800. }
  1801. /**
  1802. * Shorthand method for templating
  1803. *
  1804. * @param object $entity
  1805. * @return mixed
  1806. */
  1807. public function id($entity)
  1808. {
  1809. return $this->getNormalizedIdentifier($entity);
  1810. }
  1811. /**
  1812. * @param \Symfony\Component\Validator\ValidatorInterface $validator
  1813. * @return void
  1814. */
  1815. public function setValidator(ValidatorInterface $validator)
  1816. {
  1817. $this->validator = $validator;
  1818. }
  1819. /**
  1820. * @return \Symfony\Component\Validator\ValidatorInterface
  1821. */
  1822. public function getValidator()
  1823. {
  1824. return $this->validator;
  1825. }
  1826. /**
  1827. * @return array
  1828. */
  1829. public function getShow()
  1830. {
  1831. $this->buildShow();
  1832. return $this->show;
  1833. }
  1834. /**
  1835. * @param array $formTheme
  1836. * @return void
  1837. */
  1838. public function setFormTheme(array $formTheme)
  1839. {
  1840. $this->formTheme = $formTheme;
  1841. }
  1842. /**
  1843. * @return array
  1844. */
  1845. public function getFormTheme()
  1846. {
  1847. return $this->formTheme;
  1848. }
  1849. /**
  1850. * @param array $filterTheme
  1851. * @return void
  1852. */
  1853. public function setFilterTheme(array $filterTheme)
  1854. {
  1855. $this->filterTheme = $filterTheme;
  1856. }
  1857. /**
  1858. * @return array
  1859. */
  1860. public function getFilterTheme()
  1861. {
  1862. return $this->filterTheme;
  1863. }
  1864. /**
  1865. * @param AdminExtensionInterface $extension
  1866. * @return void
  1867. */
  1868. public function addExtension(AdminExtensionInterface $extension)
  1869. {
  1870. $this->extensions[] = $extension;
  1871. }
  1872. /**
  1873. * @param \Knp\Menu\FactoryInterface $menuFactory
  1874. * @return void
  1875. */
  1876. public function setMenuFactory(MenuFactoryInterface $menuFactory)
  1877. {
  1878. $this->menuFactory = $menuFactory;
  1879. }
  1880. /**
  1881. * @return \Knp\Menu\FactoryInterface
  1882. */
  1883. public function getMenuFactory()
  1884. {
  1885. return $this->menuFactory;
  1886. }
  1887. /**
  1888. * @param \Sonata\AdminBundle\Builder\RouteBuilderInterface $routeBuilder
  1889. */
  1890. public function setRouteBuilder(RouteBuilderInterface $routeBuilder)
  1891. {
  1892. $this->routeBuilder = $routeBuilder;
  1893. }
  1894. /**
  1895. * @return \Sonata\AdminBundle\Builder\RouteBuilderInterface
  1896. */
  1897. public function getRouteBuilder()
  1898. {
  1899. return $this->routeBuilder;
  1900. }
  1901. /**
  1902. * @param $object
  1903. * @return string
  1904. */
  1905. public function toString($object)
  1906. {
  1907. if (method_exists($object, '__toString')) {
  1908. return (string) $object;
  1909. }
  1910. return '';
  1911. }
  1912. /**
  1913. * @param \Sonata\Adminbundle\Translator\LabelTranslatorStrategyInterface $labelTranslatorStrategy
  1914. */
  1915. public function setLabelTranslatorStrategy(LabelTranslatorStrategyInterface $labelTranslatorStrategy)
  1916. {
  1917. $this->labelTranslatorStrategy = $labelTranslatorStrategy;
  1918. }
  1919. /**
  1920. * @return \Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface
  1921. */
  1922. public function getLabelTranslatorStrategy()
  1923. {
  1924. return $this->labelTranslatorStrategy;
  1925. }
  1926. }