Admin.php 55 KB

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