Admin.php 55 KB

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