PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Admin/AbstractAdmin.php

http://github.com/sonata-project/SonataAdminBundle
PHP | 3234 lines | 2798 code | 88 blank | 348 comment | 10 complexity | efa0736c1dec5e7723a89caddf908a18 MD5 | raw file
Possible License(s): JSON, Apache-2.0, MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * This file is part of the Sonata Project 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 Doctrine\Common\Util\ClassUtils;
  12. use Knp\Menu\FactoryInterface as MenuFactoryInterface;
  13. use Knp\Menu\ItemInterface;
  14. use Knp\Menu\ItemInterface as MenuItemInterface;
  15. use Sonata\AdminBundle\Builder\DatagridBuilderInterface;
  16. use Sonata\AdminBundle\Builder\FormContractorInterface;
  17. use Sonata\AdminBundle\Builder\ListBuilderInterface;
  18. use Sonata\AdminBundle\Builder\RouteBuilderInterface;
  19. use Sonata\AdminBundle\Builder\ShowBuilderInterface;
  20. use Sonata\AdminBundle\Datagrid\DatagridInterface;
  21. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  22. use Sonata\AdminBundle\Datagrid\ListMapper;
  23. use Sonata\AdminBundle\Datagrid\Pager;
  24. use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
  25. use Sonata\AdminBundle\Form\FormMapper;
  26. use Sonata\AdminBundle\Model\ModelManagerInterface;
  27. use Sonata\AdminBundle\Route\RouteCollection;
  28. use Sonata\AdminBundle\Route\RouteGeneratorInterface;
  29. use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
  30. use Sonata\AdminBundle\Security\Handler\SecurityHandlerInterface;
  31. use Sonata\AdminBundle\Show\ShowMapper;
  32. use Sonata\AdminBundle\Translator\LabelTranslatorStrategyInterface;
  33. use Sonata\CoreBundle\Model\Metadata;
  34. use Sonata\CoreBundle\Validator\Constraints\InlineConstraint;
  35. use Sonata\CoreBundle\Validator\ErrorElement;
  36. use Symfony\Component\Form\Form;
  37. use Symfony\Component\Form\FormBuilderInterface;
  38. use Symfony\Component\HttpFoundation\Request;
  39. use Symfony\Component\PropertyAccess\PropertyPath;
  40. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  41. use Symfony\Component\Security\Acl\Model\DomainObjectInterface;
  42. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  43. use Symfony\Component\Translation\TranslatorInterface;
  44. use Symfony\Component\Validator\Validator\ValidatorInterface;
  45. use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface;
  46. /**
  47. * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  48. */
  49. abstract class AbstractAdmin implements AdminInterface, DomainObjectInterface
  50. {
  51. const CONTEXT_MENU = 'menu';
  52. const CONTEXT_DASHBOARD = 'dashboard';
  53. const CLASS_REGEX =
  54. '@
  55. (?:([A-Za-z0-9]*)\\\)? # vendor name / app name
  56. (Bundle\\\)? # optional bundle directory
  57. ([A-Za-z0-9]+?)(?:Bundle)?\\\ # bundle name, with optional suffix
  58. (
  59. Entity|Document|Model|PHPCR|CouchDocument|Phpcr|
  60. Doctrine\\\Orm|Doctrine\\\Phpcr|Doctrine\\\MongoDB|Doctrine\\\CouchDB
  61. )\\\(.*)@x';
  62. const MOSAIC_ICON_CLASS = 'fa fa-th-large fa-fw';
  63. /**
  64. * The list FieldDescription constructed from the configureListField method.
  65. *
  66. * @var array
  67. */
  68. protected $listFieldDescriptions = array();
  69. /**
  70. * The show FieldDescription constructed from the configureShowFields method.
  71. *
  72. * @var array
  73. */
  74. protected $showFieldDescriptions = array();
  75. /**
  76. * The list FieldDescription constructed from the configureFormField method.
  77. *
  78. * @var array
  79. */
  80. protected $formFieldDescriptions = array();
  81. /**
  82. * The filter FieldDescription constructed from the configureFilterField method.
  83. *
  84. * @var array
  85. */
  86. protected $filterFieldDescriptions = array();
  87. /**
  88. * The number of result to display in the list.
  89. *
  90. * @var int
  91. */
  92. protected $maxPerPage = 32;
  93. /**
  94. * The maximum number of page numbers to display in the list.
  95. *
  96. * @var int
  97. */
  98. protected $maxPageLinks = 25;
  99. /**
  100. * The base route name used to generate the routing information.
  101. *
  102. * @var string
  103. */
  104. protected $baseRouteName;
  105. /**
  106. * The base route pattern used to generate the routing information.
  107. *
  108. * @var string
  109. */
  110. protected $baseRoutePattern;
  111. /**
  112. * The base name controller used to generate the routing information.
  113. *
  114. * @var string
  115. */
  116. protected $baseControllerName;
  117. /**
  118. * The label class name (used in the title/breadcrumb ...).
  119. *
  120. * @var string
  121. */
  122. protected $classnameLabel;
  123. /**
  124. * The translation domain to be used to translate messages.
  125. *
  126. * @var string
  127. */
  128. protected $translationDomain = 'messages';
  129. /**
  130. * Options to set to the form (ie, validation_groups).
  131. *
  132. * @var array
  133. */
  134. protected $formOptions = array();
  135. /**
  136. * Default values to the datagrid.
  137. *
  138. * @var array
  139. */
  140. protected $datagridValues = array(
  141. '_page' => 1,
  142. '_per_page' => 32,
  143. );
  144. /**
  145. * Predefined per page options.
  146. *
  147. * @var array
  148. */
  149. protected $perPageOptions = array(16, 32, 64, 128, 192);
  150. /**
  151. * Pager type.
  152. *
  153. * @var string
  154. */
  155. protected $pagerType = Pager::TYPE_DEFAULT;
  156. /**
  157. * The code related to the admin.
  158. *
  159. * @var string
  160. */
  161. protected $code;
  162. /**
  163. * The label.
  164. *
  165. * @var string
  166. */
  167. protected $label;
  168. /**
  169. * Whether or not to persist the filters in the session.
  170. *
  171. * @var bool
  172. */
  173. protected $persistFilters = false;
  174. /**
  175. * Array of routes related to this admin.
  176. *
  177. * @var RouteCollection
  178. */
  179. protected $routes;
  180. /**
  181. * The subject only set in edit/update/create mode.
  182. *
  183. * @var object
  184. */
  185. protected $subject;
  186. /**
  187. * Define a Collection of child admin, ie /admin/order/{id}/order-element/{childId}.
  188. *
  189. * @var array
  190. */
  191. protected $children = array();
  192. /**
  193. * Reference the parent collection.
  194. *
  195. * @var AdminInterface|null
  196. */
  197. protected $parent = null;
  198. /**
  199. * The base code route refer to the prefix used to generate the route name.
  200. *
  201. * @var string
  202. */
  203. protected $baseCodeRoute = '';
  204. /**
  205. * The related field reflection, ie if OrderElement is linked to Order,
  206. * then the $parentReflectionProperty must be the ReflectionProperty of
  207. * the order (OrderElement::$order).
  208. *
  209. * @var \ReflectionProperty
  210. */
  211. protected $parentAssociationMapping = null;
  212. /**
  213. * Reference the parent FieldDescription related to this admin
  214. * only set for FieldDescription which is associated to an Sub Admin instance.
  215. *
  216. * @var FieldDescriptionInterface
  217. */
  218. protected $parentFieldDescription;
  219. /**
  220. * If true then the current admin is part of the nested admin set (from the url).
  221. *
  222. * @var bool
  223. */
  224. protected $currentChild = false;
  225. /**
  226. * The uniqid is used to avoid clashing with 2 admin related to the code
  227. * ie: a Block linked to a Block.
  228. *
  229. * @var string
  230. */
  231. protected $uniqid;
  232. /**
  233. * The Entity or Document manager.
  234. *
  235. * @var ModelManagerInterface
  236. */
  237. protected $modelManager;
  238. /**
  239. * The current request object.
  240. *
  241. * @var \Symfony\Component\HttpFoundation\Request
  242. */
  243. protected $request;
  244. /**
  245. * The translator component.
  246. *
  247. * @var \Symfony\Component\Translation\TranslatorInterface
  248. */
  249. protected $translator;
  250. /**
  251. * The related form contractor.
  252. *
  253. * @var FormContractorInterface
  254. */
  255. protected $formContractor;
  256. /**
  257. * The related list builder.
  258. *
  259. * @var ListBuilderInterface
  260. */
  261. protected $listBuilder;
  262. /**
  263. * The related view builder.
  264. *
  265. * @var ShowBuilderInterface
  266. */
  267. protected $showBuilder;
  268. /**
  269. * The related datagrid builder.
  270. *
  271. * @var DatagridBuilderInterface
  272. */
  273. protected $datagridBuilder;
  274. /**
  275. * @var RouteBuilderInterface
  276. */
  277. protected $routeBuilder;
  278. /**
  279. * The datagrid instance.
  280. *
  281. * @var \Sonata\AdminBundle\Datagrid\DatagridInterface
  282. */
  283. protected $datagrid;
  284. /**
  285. * The router instance.
  286. *
  287. * @var RouteGeneratorInterface
  288. */
  289. protected $routeGenerator;
  290. /**
  291. * The generated breadcrumbs.
  292. *
  293. * NEXT_MAJOR : remove this property
  294. *
  295. * @var array
  296. */
  297. protected $breadcrumbs = array();
  298. /**
  299. * @var SecurityHandlerInterface
  300. */
  301. protected $securityHandler = null;
  302. /**
  303. * @var ValidatorInterface|LegacyValidatorInterface
  304. */
  305. protected $validator = null;
  306. /**
  307. * The configuration pool.
  308. *
  309. * @var Pool
  310. */
  311. protected $configurationPool;
  312. /**
  313. * @var MenuItemInterface
  314. */
  315. protected $menu;
  316. /**
  317. * @var MenuFactoryInterface
  318. */
  319. protected $menuFactory;
  320. /**
  321. * @var array
  322. */
  323. protected $loaded = array(
  324. 'view_fields' => false,
  325. 'view_groups' => false,
  326. 'routes' => false,
  327. 'tab_menu' => false,
  328. );
  329. /**
  330. * @var array
  331. */
  332. protected $formTheme = array();
  333. /**
  334. * @var array
  335. */
  336. protected $filterTheme = array();
  337. /**
  338. * @var array
  339. */
  340. protected $templates = array();
  341. /**
  342. * @var AdminExtensionInterface[]
  343. */
  344. protected $extensions = array();
  345. /**
  346. * @var LabelTranslatorStrategyInterface
  347. */
  348. protected $labelTranslatorStrategy;
  349. /**
  350. * Setting to true will enable preview mode for
  351. * the entity and show a preview button in the
  352. * edit/create forms.
  353. *
  354. * @var bool
  355. */
  356. protected $supportsPreviewMode = false;
  357. /**
  358. * Roles and permissions per role.
  359. *
  360. * @var array [role] => array([permission], [permission])
  361. */
  362. protected $securityInformation = array();
  363. protected $cacheIsGranted = array();
  364. /**
  365. * Action list for the search result.
  366. *
  367. * @var string[]
  368. */
  369. protected $searchResultActions = array('edit', 'show');
  370. protected $listModes = array(
  371. 'list' => array(
  372. 'class' => 'fa fa-list fa-fw',
  373. ),
  374. 'mosaic' => array(
  375. 'class' => self::MOSAIC_ICON_CLASS,
  376. ),
  377. );
  378. /**
  379. * The Access mapping.
  380. *
  381. * @var array
  382. */
  383. protected $accessMapping = array();
  384. /**
  385. * The class name managed by the admin class.
  386. *
  387. * @var string
  388. */
  389. private $class;
  390. /**
  391. * The subclasses supported by the admin class.
  392. *
  393. * @var array
  394. */
  395. private $subClasses = array();
  396. /**
  397. * The list collection.
  398. *
  399. * @var array
  400. */
  401. private $list;
  402. /**
  403. * @var FieldDescriptionCollection
  404. */
  405. private $show;
  406. /**
  407. * @var Form
  408. */
  409. private $form;
  410. /**
  411. * @var DatagridInterface
  412. */
  413. private $filter;
  414. /**
  415. * The cached base route name.
  416. *
  417. * @var string
  418. */
  419. private $cachedBaseRouteName;
  420. /**
  421. * The cached base route pattern.
  422. *
  423. * @var string
  424. */
  425. private $cachedBaseRoutePattern;
  426. /**
  427. * The form group disposition.
  428. *
  429. * @var array|bool
  430. */
  431. private $formGroups = false;
  432. /**
  433. * The form tabs disposition.
  434. *
  435. * @var array|bool
  436. */
  437. private $formTabs = false;
  438. /**
  439. * The view group disposition.
  440. *
  441. * @var array|bool
  442. */
  443. private $showGroups = false;
  444. /**
  445. * The view tab disposition.
  446. *
  447. * @var array|bool
  448. */
  449. private $showTabs = false;
  450. /**
  451. * The manager type to use for the admin.
  452. *
  453. * @var string
  454. */
  455. private $managerType;
  456. /**
  457. * The breadcrumbsBuilder component.
  458. *
  459. * @var BreadcrumbsBuilderInterface
  460. */
  461. private $breadcrumbsBuilder;
  462. /**
  463. * @param string $code
  464. * @param string $class
  465. * @param string $baseControllerName
  466. */
  467. public function __construct($code, $class, $baseControllerName)
  468. {
  469. $this->code = $code;
  470. $this->class = $class;
  471. $this->baseControllerName = $baseControllerName;
  472. $this->predefinePerPageOptions();
  473. $this->datagridValues['_per_page'] = $this->maxPerPage;
  474. }
  475. /**
  476. * {@inheritdoc}
  477. */
  478. public function getExportFormats()
  479. {
  480. return array(
  481. 'json', 'xml', 'csv', 'xls',
  482. );
  483. }
  484. /**
  485. * @return array
  486. */
  487. public function getExportFields()
  488. {
  489. $fields = $this->getModelManager()->getExportFields($this->getClass());
  490. foreach ($this->getExtensions() as $extension) {
  491. if (method_exists($extension, 'configureExportFields')) {
  492. $fields = $extension->configureExportFields($this, $fields);
  493. }
  494. }
  495. return $fields;
  496. }
  497. /**
  498. * {@inheritdoc}
  499. */
  500. public function getDataSourceIterator()
  501. {
  502. $datagrid = $this->getDatagrid();
  503. $datagrid->buildPager();
  504. $fields = array();
  505. foreach ($this->getExportFields() as $key => $field) {
  506. $label = $this->getTranslationLabel($field, 'export', 'label');
  507. $transLabel = $this->trans($label);
  508. // NEXT_MAJOR: Remove this hack, because all field labels will be translated with the major release
  509. // No translation key exists
  510. if ($transLabel == $label) {
  511. $fields[$key] = $field;
  512. } else {
  513. $fields[$transLabel] = $field;
  514. }
  515. }
  516. return $this->getModelManager()->getDataSourceIterator($datagrid, $fields);
  517. }
  518. /**
  519. * {@inheritdoc}
  520. */
  521. public function validate(ErrorElement $errorElement, $object)
  522. {
  523. }
  524. /**
  525. * define custom variable.
  526. */
  527. public function initialize()
  528. {
  529. if (!$this->classnameLabel) {
  530. $this->classnameLabel = substr($this->getClass(), strrpos($this->getClass(), '\\') + 1);
  531. }
  532. $this->baseCodeRoute = $this->getCode();
  533. $this->configure();
  534. }
  535. /**
  536. * {@inheritdoc}
  537. */
  538. public function configure()
  539. {
  540. }
  541. /**
  542. * {@inheritdoc}
  543. */
  544. public function update($object)
  545. {
  546. $this->preUpdate($object);
  547. foreach ($this->extensions as $extension) {
  548. $extension->preUpdate($this, $object);
  549. }
  550. $result = $this->getModelManager()->update($object);
  551. // BC compatibility
  552. if (null !== $result) {
  553. $object = $result;
  554. }
  555. $this->postUpdate($object);
  556. foreach ($this->extensions as $extension) {
  557. $extension->postUpdate($this, $object);
  558. }
  559. return $object;
  560. }
  561. /**
  562. * {@inheritdoc}
  563. */
  564. public function create($object)
  565. {
  566. $this->prePersist($object);
  567. foreach ($this->extensions as $extension) {
  568. $extension->prePersist($this, $object);
  569. }
  570. $result = $this->getModelManager()->create($object);
  571. // BC compatibility
  572. if (null !== $result) {
  573. $object = $result;
  574. }
  575. $this->postPersist($object);
  576. foreach ($this->extensions as $extension) {
  577. $extension->postPersist($this, $object);
  578. }
  579. $this->createObjectSecurity($object);
  580. return $object;
  581. }
  582. /**
  583. * {@inheritdoc}
  584. */
  585. public function delete($object)
  586. {
  587. $this->preRemove($object);
  588. foreach ($this->extensions as $extension) {
  589. $extension->preRemove($this, $object);
  590. }
  591. $this->getSecurityHandler()->deleteObjectSecurity($this, $object);
  592. $this->getModelManager()->delete($object);
  593. $this->postRemove($object);
  594. foreach ($this->extensions as $extension) {
  595. $extension->postRemove($this, $object);
  596. }
  597. }
  598. /**
  599. * {@inheritdoc}
  600. */
  601. public function preValidate($object)
  602. {
  603. }
  604. /**
  605. * {@inheritdoc}
  606. */
  607. public function preUpdate($object)
  608. {
  609. }
  610. /**
  611. * {@inheritdoc}
  612. */
  613. public function postUpdate($object)
  614. {
  615. }
  616. /**
  617. * {@inheritdoc}
  618. */
  619. public function prePersist($object)
  620. {
  621. }
  622. /**
  623. * {@inheritdoc}
  624. */
  625. public function postPersist($object)
  626. {
  627. }
  628. /**
  629. * {@inheritdoc}
  630. */
  631. public function preRemove($object)
  632. {
  633. }
  634. /**
  635. * {@inheritdoc}
  636. */
  637. public function postRemove($object)
  638. {
  639. }
  640. /**
  641. * {@inheritdoc}
  642. */
  643. public function preBatchAction($actionName, ProxyQueryInterface $query, array &$idx, $allElements)
  644. {
  645. }
  646. /**
  647. * {@inheritdoc}
  648. */
  649. public function getFilterParameters()
  650. {
  651. $parameters = array();
  652. // build the values array
  653. if ($this->hasRequest()) {
  654. $filters = $this->request->query->get('filter', array());
  655. // if persisting filters, save filters to session, or pull them out of session if no new filters set
  656. if ($this->persistFilters) {
  657. if ($filters == array() && $this->request->query->get('filters') != 'reset') {
  658. $filters = $this->request->getSession()->get($this->getCode().'.filter.parameters', array());
  659. } else {
  660. $this->request->getSession()->set($this->getCode().'.filter.parameters', $filters);
  661. }
  662. }
  663. $parameters = array_merge(
  664. $this->getModelManager()->getDefaultSortValues($this->getClass()),
  665. $this->datagridValues,
  666. $filters
  667. );
  668. if (!$this->determinedPerPageValue($parameters['_per_page'])) {
  669. $parameters['_per_page'] = $this->maxPerPage;
  670. }
  671. // always force the parent value
  672. if ($this->isChild() && $this->getParentAssociationMapping()) {
  673. $name = str_replace('.', '__', $this->getParentAssociationMapping());
  674. $parameters[$name] = array('value' => $this->request->get($this->getParent()->getIdParameter()));
  675. }
  676. }
  677. return $parameters;
  678. }
  679. /**
  680. * {@inheritdoc}
  681. */
  682. public function buildDatagrid()
  683. {
  684. if ($this->datagrid) {
  685. return;
  686. }
  687. $filterParameters = $this->getFilterParameters();
  688. // transform _sort_by from a string to a FieldDescriptionInterface for the datagrid.
  689. if (isset($filterParameters['_sort_by']) && is_string($filterParameters['_sort_by'])) {
  690. if ($this->hasListFieldDescription($filterParameters['_sort_by'])) {
  691. $filterParameters['_sort_by'] = $this->getListFieldDescription($filterParameters['_sort_by']);
  692. } else {
  693. $filterParameters['_sort_by'] = $this->getModelManager()->getNewFieldDescriptionInstance(
  694. $this->getClass(),
  695. $filterParameters['_sort_by'],
  696. array()
  697. );
  698. $this->getListBuilder()->buildField(null, $filterParameters['_sort_by'], $this);
  699. }
  700. }
  701. // initialize the datagrid
  702. $this->datagrid = $this->getDatagridBuilder()->getBaseDatagrid($this, $filterParameters);
  703. $this->datagrid->getPager()->setMaxPageLinks($this->maxPageLinks);
  704. $mapper = new DatagridMapper($this->getDatagridBuilder(), $this->datagrid, $this);
  705. // build the datagrid filter
  706. $this->configureDatagridFilters($mapper);
  707. // ok, try to limit to add parent filter
  708. if ($this->isChild() && $this->getParentAssociationMapping() && !$mapper->has($this->getParentAssociationMapping())) {
  709. $mapper->add($this->getParentAssociationMapping(), null, array(
  710. 'show_filter' => false,
  711. 'label' => false,
  712. 'field_type' => 'sonata_type_model_hidden',
  713. 'field_options' => array(
  714. 'model_manager' => $this->getModelManager(),
  715. ),
  716. 'operator_type' => 'hidden',
  717. ), null, null, array(
  718. 'admin_code' => $this->getParent()->getCode(),
  719. ));
  720. }
  721. foreach ($this->getExtensions() as $extension) {
  722. $extension->configureDatagridFilters($mapper);
  723. }
  724. }
  725. /**
  726. * Returns the name of the parent related field, so the field can be use to set the default
  727. * value (ie the parent object) or to filter the object.
  728. *
  729. * @return string the name of the parent related field
  730. */
  731. public function getParentAssociationMapping()
  732. {
  733. return $this->parentAssociationMapping;
  734. }
  735. /**
  736. * Returns the baseRoutePattern used to generate the routing information.
  737. *
  738. * @throws \RuntimeException
  739. *
  740. * @return string the baseRoutePattern used to generate the routing information
  741. */
  742. public function getBaseRoutePattern()
  743. {
  744. if (null !== $this->cachedBaseRoutePattern) {
  745. return $this->cachedBaseRoutePattern;
  746. }
  747. if ($this->isChild()) { // the admin class is a child, prefix it with the parent route pattern
  748. if (!$this->baseRoutePattern) {
  749. preg_match(self::CLASS_REGEX, $this->class, $matches);
  750. if (!$matches) {
  751. throw new \RuntimeException(sprintf('Please define a default `baseRoutePattern` value for the admin class `%s`', get_class($this)));
  752. }
  753. }
  754. $this->cachedBaseRoutePattern = sprintf('%s/{id}/%s',
  755. $this->getParent()->getBaseRoutePattern(),
  756. $this->baseRoutePattern ?: $this->urlize($matches[5], '-')
  757. );
  758. } elseif ($this->baseRoutePattern) {
  759. $this->cachedBaseRoutePattern = $this->baseRoutePattern;
  760. } else {
  761. preg_match(self::CLASS_REGEX, $this->class, $matches);
  762. if (!$matches) {
  763. throw new \RuntimeException(sprintf('Please define a default `baseRoutePattern` value for the admin class `%s`', get_class($this)));
  764. }
  765. $this->cachedBaseRoutePattern = sprintf('/%s%s/%s',
  766. empty($matches[1]) ? '' : $this->urlize($matches[1], '-').'/',
  767. $this->urlize($matches[3], '-'),
  768. $this->urlize($matches[5], '-')
  769. );
  770. }
  771. return $this->cachedBaseRoutePattern;
  772. }
  773. /**
  774. * Returns the baseRouteName used to generate the routing information.
  775. *
  776. * @throws \RuntimeException
  777. *
  778. * @return string the baseRouteName used to generate the routing information
  779. */
  780. public function getBaseRouteName()
  781. {
  782. if (null !== $this->cachedBaseRouteName) {
  783. return $this->cachedBaseRouteName;
  784. }
  785. if ($this->isChild()) { // the admin class is a child, prefix it with the parent route name
  786. if (!$this->baseRouteName) {
  787. preg_match(self::CLASS_REGEX, $this->class, $matches);
  788. if (!$matches) {
  789. throw new \RuntimeException(sprintf('Cannot automatically determine base route name, please define a default `baseRouteName` value for the admin class `%s`', get_class($this)));
  790. }
  791. }
  792. $this->cachedBaseRouteName = sprintf('%s_%s',
  793. $this->getParent()->getBaseRouteName(),
  794. $this->baseRouteName ?: $this->urlize($matches[5])
  795. );
  796. } elseif ($this->baseRouteName) {
  797. $this->cachedBaseRouteName = $this->baseRouteName;
  798. } else {
  799. preg_match(self::CLASS_REGEX, $this->class, $matches);
  800. if (!$matches) {
  801. throw new \RuntimeException(sprintf('Cannot automatically determine base route name, please define a default `baseRouteName` value for the admin class `%s`', get_class($this)));
  802. }
  803. $this->cachedBaseRouteName = sprintf('admin_%s%s_%s',
  804. empty($matches[1]) ? '' : $this->urlize($matches[1]).'_',
  805. $this->urlize($matches[3]),
  806. $this->urlize($matches[5])
  807. );
  808. }
  809. return $this->cachedBaseRouteName;
  810. }
  811. /**
  812. * urlize the given word.
  813. *
  814. * @param string $word
  815. * @param string $sep the separator
  816. *
  817. * @return string
  818. */
  819. public function urlize($word, $sep = '_')
  820. {
  821. return strtolower(preg_replace('/[^a-z0-9_]/i', $sep.'$1', $word));
  822. }
  823. /**
  824. * {@inheritdoc}
  825. */
  826. public function getClass()
  827. {
  828. // see https://github.com/sonata-project/SonataCoreBundle/commit/247eeb0a7ca7211142e101754769d70bc402a5b4
  829. if ($this->hasSubject() && is_object($this->getSubject())) {
  830. return ClassUtils::getClass($this->getSubject());
  831. }
  832. if (!$this->hasActiveSubClass()) {
  833. if (count($this->getSubClasses()) > 0) {
  834. $subject = $this->getSubject();
  835. if ($subject && is_object($subject)) {
  836. return ClassUtils::getClass($subject);
  837. }
  838. }
  839. return $this->class;
  840. }
  841. if ($this->getParentFieldDescription() && $this->hasActiveSubClass()) {
  842. throw new \RuntimeException('Feature not implemented: an embedded admin cannot have subclass');
  843. }
  844. $subClass = $this->getRequest()->query->get('subclass');
  845. return $this->getSubClass($subClass);
  846. }
  847. /**
  848. * {@inheritdoc}
  849. */
  850. public function getSubClasses()
  851. {
  852. return $this->subClasses;
  853. }
  854. /**
  855. * {@inheritdoc}
  856. */
  857. public function addSubClass($subClass)
  858. {
  859. if (!in_array($subClass, $this->subClasses)) {
  860. $this->subClasses[] = $subClass;
  861. }
  862. }
  863. /**
  864. * {@inheritdoc}
  865. */
  866. public function setSubClasses(array $subClasses)
  867. {
  868. $this->subClasses = $subClasses;
  869. }
  870. /**
  871. * {@inheritdoc}
  872. */
  873. public function hasSubClass($name)
  874. {
  875. return isset($this->subClasses[$name]);
  876. }
  877. /**
  878. * {@inheritdoc}
  879. */
  880. public function hasActiveSubClass()
  881. {
  882. if (count($this->subClasses) > 0 && $this->request) {
  883. return null !== $this->getRequest()->query->get('subclass');
  884. }
  885. return false;
  886. }
  887. /**
  888. * {@inheritdoc}
  889. */
  890. public function getActiveSubClass()
  891. {
  892. if (!$this->hasActiveSubClass()) {
  893. return;
  894. }
  895. return $this->getClass();
  896. }
  897. /**
  898. * {@inheritdoc}
  899. */
  900. public function getActiveSubclassCode()
  901. {
  902. if (!$this->hasActiveSubClass()) {
  903. return;
  904. }
  905. $subClass = $this->getRequest()->query->get('subclass');
  906. if (!$this->hasSubClass($subClass)) {
  907. return;
  908. }
  909. return $subClass;
  910. }
  911. /**
  912. * {@inheritdoc}
  913. */
  914. public function getBatchActions()
  915. {
  916. $actions = array();
  917. if ($this->hasRoute('delete') && $this->isGranted('DELETE')) {
  918. $actions['delete'] = array(
  919. 'label' => 'action_delete',
  920. 'translation_domain' => 'SonataAdminBundle',
  921. 'ask_confirmation' => true, // by default always true
  922. );
  923. }
  924. $actions = $this->configureBatchActions($actions);
  925. foreach ($this->getExtensions() as $extension) {
  926. // TODO: remove method check in next major release
  927. if (method_exists($extension, 'configureBatchActions')) {
  928. $actions = $extension->configureBatchActions($this, $actions);
  929. }
  930. }
  931. return $actions;
  932. }
  933. /**
  934. * {@inheritdoc}
  935. */
  936. public function getRoutes()
  937. {
  938. $this->buildRoutes();
  939. return $this->routes;
  940. }
  941. /**
  942. * {@inheritdoc}
  943. */
  944. public function getRouterIdParameter()
  945. {
  946. return $this->isChild() ? '{childId}' : '{id}';
  947. }
  948. /**
  949. * {@inheritdoc}
  950. */
  951. public function getIdParameter()
  952. {
  953. return $this->isChild() ? 'childId' : 'id';
  954. }
  955. /**
  956. * {@inheritdoc}
  957. */
  958. public function hasRoute($name)
  959. {
  960. if (!$this->routeGenerator) {
  961. throw new \RuntimeException('RouteGenerator cannot be null');
  962. }
  963. return $this->routeGenerator->hasAdminRoute($this, $name);
  964. }
  965. /**
  966. * {@inheritdoc}
  967. */
  968. public function isCurrentRoute($name, $adminCode = null)
  969. {
  970. if (!$this->hasRequest()) {
  971. return false;
  972. }
  973. $request = $this->getRequest();
  974. $route = $request->get('_route');
  975. if ($adminCode) {
  976. $admin = $this->getConfigurationPool()->getAdminByAdminCode($adminCode);
  977. } else {
  978. $admin = $this;
  979. }
  980. if (!$admin) {
  981. return false;
  982. }
  983. return ($admin->getBaseRouteName().'_'.$name) == $route;
  984. }
  985. /**
  986. * {@inheritdoc}
  987. */
  988. public function generateObjectUrl($name, $object, array $parameters = array(), $absolute = UrlGeneratorInterface::ABSOLUTE_PATH)
  989. {
  990. $parameters['id'] = $this->getUrlsafeIdentifier($object);
  991. return $this->generateUrl($name, $parameters, $absolute);
  992. }
  993. /**
  994. * {@inheritdoc}
  995. */
  996. public function generateUrl($name, array $parameters = array(), $absolute = UrlGeneratorInterface::ABSOLUTE_PATH)
  997. {
  998. return $this->routeGenerator->generateUrl($this, $name, $parameters, $absolute);
  999. }
  1000. /**
  1001. * {@inheritdoc}
  1002. */
  1003. public function generateMenuUrl($name, array $parameters = array(), $absolute = UrlGeneratorInterface::ABSOLUTE_PATH)
  1004. {
  1005. return $this->routeGenerator->generateMenuUrl($this, $name, $parameters, $absolute);
  1006. }
  1007. /**
  1008. * @param array $templates
  1009. */
  1010. public function setTemplates(array $templates)
  1011. {
  1012. $this->templates = $templates;
  1013. }
  1014. /**
  1015. * @param string $name
  1016. * @param string $template
  1017. */
  1018. public function setTemplate($name, $template)
  1019. {
  1020. $this->templates[$name] = $template;
  1021. }
  1022. /**
  1023. * @return array
  1024. */
  1025. public function getTemplates()
  1026. {
  1027. return $this->templates;
  1028. }
  1029. /**
  1030. * {@inheritdoc}
  1031. */
  1032. public function getTemplate($name)
  1033. {
  1034. if (isset($this->templates[$name])) {
  1035. return $this->templates[$name];
  1036. }
  1037. }
  1038. /**
  1039. * {@inheritdoc}
  1040. */
  1041. public function getNewInstance()
  1042. {
  1043. $object = $this->getModelManager()->getModelInstance($this->getClass());
  1044. foreach ($this->getExtensions() as $extension) {
  1045. $extension->alterNewInstance($this, $object);
  1046. }
  1047. return $object;
  1048. }
  1049. /**
  1050. * {@inheritdoc}
  1051. */
  1052. public function getFormBuilder()
  1053. {
  1054. $this->formOptions['data_class'] = $this->getClass();
  1055. $formBuilder = $this->getFormContractor()->getFormBuilder(
  1056. $this->getUniqid(),
  1057. $this->formOptions
  1058. );
  1059. $this->defineFormBuilder($formBuilder);
  1060. return $formBuilder;
  1061. }
  1062. /**
  1063. * This method is being called by the main admin class and the child class,
  1064. * the getFormBuilder is only call by the main admin class.
  1065. *
  1066. * @param FormBuilderInterface $formBuilder
  1067. */
  1068. public function defineFormBuilder(FormBuilderInterface $formBuilder)
  1069. {
  1070. $mapper = new FormMapper($this->getFormContractor(), $formBuilder, $this);
  1071. $this->configureFormFields($mapper);
  1072. foreach ($this->getExtensions() as $extension) {
  1073. $extension->configureFormFields($mapper);
  1074. }
  1075. $this->attachInlineValidator();
  1076. }
  1077. /**
  1078. * {@inheritdoc}
  1079. */
  1080. public function attachAdminClass(FieldDescriptionInterface $fieldDescription)
  1081. {
  1082. $pool = $this->getConfigurationPool();
  1083. $adminCode = $fieldDescription->getOption('admin_code');
  1084. if ($adminCode !== null) {
  1085. $admin = $pool->getAdminByAdminCode($adminCode);
  1086. } else {
  1087. $admin = $pool->getAdminByClass($fieldDescription->getTargetEntity());
  1088. }
  1089. if (!$admin) {
  1090. return;
  1091. }
  1092. if ($this->hasRequest()) {
  1093. $admin->setRequest($this->getRequest());
  1094. }
  1095. $fieldDescription->setAssociationAdmin($admin);
  1096. }
  1097. /**
  1098. * {@inheritdoc}
  1099. */
  1100. public function getObject($id)
  1101. {
  1102. $object = $this->getModelManager()->find($this->getClass(), $id);
  1103. foreach ($this->getExtensions() as $extension) {
  1104. $extension->alterObject($this, $object);
  1105. }
  1106. return $object;
  1107. }
  1108. /**
  1109. * {@inheritdoc}
  1110. */
  1111. public function getForm()
  1112. {
  1113. $this->buildForm();
  1114. return $this->form;
  1115. }
  1116. /**
  1117. * {@inheritdoc}
  1118. */
  1119. public function getList()
  1120. {
  1121. $this->buildList();
  1122. return $this->list;
  1123. }
  1124. /**
  1125. * {@inheritdoc}
  1126. */
  1127. public function createQuery($context = 'list')
  1128. {
  1129. if (func_num_args() > 0) {
  1130. @trigger_error(
  1131. 'The $context argument of '.__METHOD__.' is deprecated since 3.3, to be removed in 4.0.',
  1132. E_USER_DEPRECATED
  1133. );
  1134. }
  1135. $query = $this->getModelManager()->createQuery($this->class);
  1136. foreach ($this->extensions as $extension) {
  1137. $extension->configureQuery($this, $query, $context);
  1138. }
  1139. return $query;
  1140. }
  1141. /**
  1142. * {@inheritdoc}
  1143. */
  1144. public function getDatagrid()
  1145. {
  1146. $this->buildDatagrid();
  1147. return $this->datagrid;
  1148. }
  1149. /**
  1150. * {@inheritdoc}
  1151. */
  1152. public function buildTabMenu($action, AdminInterface $childAdmin = null)
  1153. {
  1154. if ($this->loaded['tab_menu']) {
  1155. return;
  1156. }
  1157. $this->loaded['tab_menu'] = true;
  1158. $menu = $this->menuFactory->createItem('root');
  1159. $menu->setChildrenAttribute('class', 'nav navbar-nav');
  1160. $menu->setExtra('translation_domain', $this->translationDomain);
  1161. // Prevents BC break with KnpMenuBundle v1.x
  1162. if (method_exists($menu, 'setCurrentUri')) {
  1163. $menu->setCurrentUri($this->getRequest()->getBaseUrl().$this->getRequest()->getPathInfo());
  1164. }
  1165. $this->configureTabMenu($menu, $action, $childAdmin);
  1166. foreach ($this->getExtensions() as $extension) {
  1167. $extension->configureTabMenu($this, $menu, $action, $childAdmin);
  1168. }
  1169. $this->menu = $menu;
  1170. }
  1171. /**
  1172. * {@inheritdoc}
  1173. */
  1174. public function buildSideMenu($action, AdminInterface $childAdmin = null)
  1175. {
  1176. return $this->buildTabMenu($action, $childAdmin);
  1177. }
  1178. /**
  1179. * @param string $action
  1180. * @param AdminInterface $childAdmin
  1181. *
  1182. * @return ItemInterface
  1183. */
  1184. public function getSideMenu($action, AdminInterface $childAdmin = null)
  1185. {
  1186. if ($this->isChild()) {
  1187. return $this->getParent()->getSideMenu($action, $this);
  1188. }
  1189. $this->buildSideMenu($action, $childAdmin);
  1190. return $this->menu;
  1191. }
  1192. /**
  1193. * Returns the root code.
  1194. *
  1195. * @return string the root code
  1196. */
  1197. public function getRootCode()
  1198. {
  1199. return $this->getRoot()->getCode();
  1200. }
  1201. /**
  1202. * Returns the master admin.
  1203. *
  1204. * @return Admin the root admin class
  1205. */
  1206. public function getRoot()
  1207. {
  1208. $parentFieldDescription = $this->getParentFieldDescription();
  1209. if (!$parentFieldDescription) {
  1210. return $this;
  1211. }
  1212. return $parentFieldDescription->getAdmin()->getRoot();
  1213. }
  1214. /**
  1215. * {@inheritdoc}
  1216. */
  1217. public function setBaseControllerName($baseControllerName)
  1218. {
  1219. $this->baseControllerName = $baseControllerName;
  1220. }
  1221. /**
  1222. * {@inheritdoc}
  1223. */
  1224. public function getBaseControllerName()
  1225. {
  1226. return $this->baseControllerName;
  1227. }
  1228. /**
  1229. * @param string $label
  1230. */
  1231. public function setLabel($label)
  1232. {
  1233. $this->label = $label;
  1234. }
  1235. /**
  1236. * {@inheritdoc}
  1237. */
  1238. public function getLabel()
  1239. {
  1240. return $this->label;
  1241. }
  1242. /**
  1243. * @param bool $persist
  1244. */
  1245. public function setPersistFilters($persist)
  1246. {
  1247. $this->persistFilters = $persist;
  1248. }
  1249. /**
  1250. * @param int $maxPerPage
  1251. */
  1252. public function setMaxPerPage($maxPerPage)
  1253. {
  1254. $this->maxPerPage = $maxPerPage;
  1255. }
  1256. /**
  1257. * @return int
  1258. */
  1259. public function getMaxPerPage()
  1260. {
  1261. return $this->maxPerPage;
  1262. }
  1263. /**
  1264. * @param int $maxPageLinks
  1265. */
  1266. public function setMaxPageLinks($maxPageLinks)
  1267. {
  1268. $this->maxPageLinks = $maxPageLinks;
  1269. }
  1270. /**
  1271. * @return int
  1272. */
  1273. public function getMaxPageLinks()
  1274. {
  1275. return $this->maxPageLinks;
  1276. }
  1277. /**
  1278. * {@inheritdoc}
  1279. */
  1280. public function getFormGroups()
  1281. {
  1282. return $this->formGroups;
  1283. }
  1284. /**
  1285. * {@inheritdoc}
  1286. */
  1287. public function setFormGroups(array $formGroups)
  1288. {
  1289. $this->formGroups = $formGroups;
  1290. }
  1291. /**
  1292. * {@inheritdoc}
  1293. */
  1294. public function removeFieldFromFormGroup($key)
  1295. {
  1296. foreach ($this->formGroups as $name => $formGroup) {
  1297. unset($this->formGroups[$name]['fields'][$key]);
  1298. if (empty($this->formGroups[$name]['fields'])) {
  1299. unset($this->formGroups[$name]);
  1300. }
  1301. }
  1302. }
  1303. /**
  1304. * @param array $group
  1305. * @param array $keys
  1306. */
  1307. public function reorderFormGroup($group, array $keys)
  1308. {
  1309. $formGroups = $this->getFormGroups();
  1310. $formGroups[$group]['fields'] = array_merge(array_flip($keys), $formGroups[$group]['fields']);
  1311. $this->setFormGroups($formGroups);
  1312. }
  1313. /**
  1314. * {@inheritdoc}
  1315. */
  1316. public function getFormTabs()
  1317. {
  1318. return $this->formTabs;
  1319. }
  1320. /**
  1321. * {@inheritdoc}
  1322. */
  1323. public function setFormTabs(array $formTabs)
  1324. {
  1325. $this->formTabs = $formTabs;
  1326. }
  1327. /**
  1328. * {@inheritdoc}
  1329. */
  1330. public function getShowTabs()
  1331. {
  1332. return $this->showTabs;
  1333. }
  1334. /**
  1335. * {@inheritdoc}
  1336. */
  1337. public function setShowTabs(array $showTabs)
  1338. {
  1339. $this->showTabs = $showTabs;
  1340. }
  1341. /**
  1342. * {@inheritdoc}
  1343. */
  1344. public function getShowGroups()
  1345. {
  1346. return $this->showGroups;
  1347. }
  1348. /**
  1349. * {@inheritdoc}
  1350. */
  1351. public function setShowGroups(array $showGroups)
  1352. {
  1353. $this->showGroups = $showGroups;
  1354. }
  1355. /**
  1356. * {@inheritdoc}
  1357. */
  1358. public function reorderShowGroup($group, array $keys)
  1359. {
  1360. $showGroups = $this->getShowGroups();
  1361. $showGroups[$group]['fields'] = array_merge(array_flip($keys), $showGroups[$group]['fields']);
  1362. $this->setShowGroups($showGroups);
  1363. }
  1364. /**
  1365. * {@inheritdoc}
  1366. */
  1367. public function setParentFieldDescription(FieldDescriptionInterface $parentFieldDescription)
  1368. {
  1369. $this->parentFieldDescription = $parentFieldDescription;
  1370. }
  1371. /**
  1372. * {@inheritdoc}
  1373. */
  1374. public function getParentFieldDescription()
  1375. {
  1376. return $this->parentFieldDescription;
  1377. }
  1378. /**
  1379. * {@inheritdoc}
  1380. */
  1381. public function hasParentFieldDescription()
  1382. {
  1383. return $this->parentFieldDescription instanceof FieldDescriptionInterface;
  1384. }
  1385. /**
  1386. * {@inheritdoc}
  1387. */
  1388. public function setSubject($subject)
  1389. {
  1390. if (is_object($subject) && !is_a($subject, $this->class, true)) {
  1391. $message = <<<'EOT'
  1392. You are trying to set entity an instance of "%s",
  1393. which is not the one registered with this admin class ("%s").
  1394. This is deprecated since 3.x and will no longer be supported in 4.0.
  1395. EOT;
  1396. trigger_error(
  1397. sprintf($message, get_class($subject), $this->class),
  1398. E_USER_DEPRECATED
  1399. ); // NEXT_MAJOR : throw an exception instead
  1400. }
  1401. $this->subject = $subject;
  1402. }
  1403. /**
  1404. * {@inheritdoc}
  1405. */
  1406. public function getSubject()
  1407. {
  1408. if ($this->subject === null && $this->request) {
  1409. $id = $this->request->get($this->getIdParameter());
  1410. $this->subject = $this->getModelManager()->find($this->class, $id);
  1411. }
  1412. return $this->subject;
  1413. }
  1414. /**
  1415. * {@inheritdoc}
  1416. */
  1417. public function hasSubject()
  1418. {
  1419. return $this->subject != null;
  1420. }
  1421. /**
  1422. * {@inheritdoc}
  1423. */
  1424. public function getFormFieldDescriptions()
  1425. {
  1426. $this->buildForm();
  1427. return $this->formFieldDescriptions;
  1428. }
  1429. /**
  1430. * {@inheritdoc}
  1431. */
  1432. public function getFormFieldDescription($name)
  1433. {
  1434. return $this->hasFormFieldDescription($name) ? $this->formFieldDescriptions[$name] : null;
  1435. }
  1436. /**
  1437. * Returns true if the admin has a FieldDescription with the given $name.
  1438. *
  1439. * @param string $name
  1440. *
  1441. * @return bool
  1442. */
  1443. public function hasFormFieldDescription($name)
  1444. {
  1445. return array_key_exists($name, $this->formFieldDescriptions) ? true : false;
  1446. }
  1447. /**
  1448. * {@inheritdoc}
  1449. */
  1450. public function addFormFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1451. {
  1452. $this->formFieldDescriptions[$name] = $fieldDescription;
  1453. }
  1454. /**
  1455. * remove a FieldDescription.
  1456. *
  1457. * @param string $name
  1458. */
  1459. public function removeFormFieldDescription($name)
  1460. {
  1461. unset($this->formFieldDescriptions[$name]);
  1462. }
  1463. /**
  1464. * build and return the collection of form FieldDescription.
  1465. *
  1466. * @return array collection of form FieldDescription
  1467. */
  1468. public function getShowFieldDescriptions()
  1469. {
  1470. $this->buildShow();
  1471. return $this->showFieldDescriptions;
  1472. }
  1473. /**
  1474. * Returns the form FieldDescription with the given $name.
  1475. *
  1476. * @param string $name
  1477. *
  1478. * @return FieldDescriptionInterface
  1479. */
  1480. public function getShowFieldDescription($name)
  1481. {
  1482. $this->buildShow();
  1483. return $this->hasShowFieldDescription($name) ? $this->showFieldDescriptions[$name] : null;
  1484. }
  1485. /**
  1486. * {@inheritdoc}
  1487. */
  1488. public function hasShowFieldDescription($name)
  1489. {
  1490. return array_key_exists($name, $this->showFieldDescriptions);
  1491. }
  1492. /**
  1493. * {@inheritdoc}
  1494. */
  1495. public function addShowFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1496. {
  1497. $this->showFieldDescriptions[$name] = $fieldDescription;
  1498. }
  1499. /**
  1500. * {@inheritdoc}
  1501. */
  1502. public function removeShowFieldDescription($name)
  1503. {
  1504. unset($this->showFieldDescriptions[$name]);
  1505. }
  1506. /**
  1507. * {@inheritdoc}
  1508. */
  1509. public function getListFieldDescriptions()
  1510. {
  1511. $this->buildList();
  1512. return $this->listFieldDescriptions;
  1513. }
  1514. /**
  1515. * {@inheritdoc}
  1516. */
  1517. public function getListFieldDescription($name)
  1518. {
  1519. return $this->hasListFieldDescription($name) ? $this->listFieldDescriptions[$name] : null;
  1520. }
  1521. /**
  1522. * {@inheritdoc}
  1523. */
  1524. public function hasListFieldDescription($name)
  1525. {
  1526. $this->buildList();
  1527. return array_key_exists($name, $this->listFieldDescriptions) ? true : false;
  1528. }
  1529. /**
  1530. * {@inheritdoc}
  1531. */
  1532. public function addListFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1533. {
  1534. $this->listFieldDescriptions[$name] = $fieldDescription;
  1535. }
  1536. /**
  1537. * {@inheritdoc}
  1538. */
  1539. public function removeListFieldDescription($name)
  1540. {
  1541. unset($this->listFieldDescriptions[$name]);
  1542. }
  1543. /**
  1544. * {@inheritdoc}
  1545. */
  1546. public function getFilterFieldDescription($name)
  1547. {
  1548. return $this->hasFilterFieldDescription($name) ? $this->filterFieldDescriptions[$name] : null;
  1549. }
  1550. /**
  1551. * {@inheritdoc}
  1552. */
  1553. public function hasFilterFieldDescription($name)
  1554. {
  1555. return array_key_exists($name, $this->filterFieldDescriptions) ? true : false;
  1556. }
  1557. /**
  1558. * {@inheritdoc}
  1559. */
  1560. public function addFilterFieldDescription($name, FieldDescriptionInterface $fieldDescription)
  1561. {
  1562. $this->filterFieldDescriptions[$name] = $fieldDescription;
  1563. }
  1564. /**
  1565. * {@inheritdoc}
  1566. */
  1567. public function removeFilterFieldDescription($name)
  1568. {
  1569. unset($this->filterFieldDescriptions[$name]);
  1570. }
  1571. /**
  1572. * {@inheritdoc}
  1573. */
  1574. public function getFilterFieldDescriptions()
  1575. {
  1576. $this->buildDatagrid();
  1577. return $this->filterFieldDescriptions;
  1578. }
  1579. /**
  1580. * {@inheritdoc}
  1581. */
  1582. public function addChild(AdminInterface $child)
  1583. {
  1584. $this->children[$child->getCode()] = $child;
  1585. $child->setBaseCodeRoute($this->getCode().'|'.$child->getCode());
  1586. $child->setParent($this);
  1587. }
  1588. /**
  1589. * {@inheritdoc}
  1590. */
  1591. public function hasChild($code)
  1592. {
  1593. return isset($this->children[$code]);
  1594. }
  1595. /**
  1596. * {@inheritdoc}
  1597. */
  1598. public function getChildren()
  1599. {
  1600. return $this->children;
  1601. }
  1602. /**
  1603. * {@inheritdoc}
  1604. */
  1605. public function getChild($code)
  1606. {
  1607. return $this->hasChild($code) ? $this->children[$code] : null;
  1608. }
  1609. /**
  1610. * {@inheritdoc}
  1611. */
  1612. public function setParent(AdminInterface $parent)
  1613. {
  1614. $this->parent = $parent;
  1615. }
  1616. /**
  1617. * {@inheritdoc}
  1618. */
  1619. public function getParent()
  1620. {
  1621. return $this->parent;
  1622. }
  1623. /**
  1624. * {@inheritdoc}
  1625. */
  1626. public function isChild()
  1627. {
  1628. return $this->parent instanceof AdminInterface;
  1629. }
  1630. /**
  1631. * Returns true if the admin has children, false otherwise.
  1632. *
  1633. * @return bool if the admin has children
  1634. */
  1635. public function hasChildren()
  1636. {
  1637. return count($this->children) > 0;
  1638. }
  1639. /**
  1640. * {@inheritdoc}
  1641. */
  1642. public function setUniqid($uniqid)
  1643. {
  1644. $this->uniqid = $uniqid;
  1645. }
  1646. /**
  1647. * {@inheritdoc}
  1648. */
  1649. public function getUniqid()
  1650. {
  1651. if (!$this->uniqid) {
  1652. $this->uniqid = 's'.uniqid();
  1653. }
  1654. return $this->uniqid;
  1655. }
  1656. /**
  1657. * Returns the classname label.
  1658. *
  1659. * @return string the classname label
  1660. */
  1661. public function getClassnameLabel()
  1662. {
  1663. return $this->classnameLabel;
  1664. }
  1665. /**
  1666. * {@inheritdoc}
  1667. */
  1668. public function getPersistentParameters()
  1669. {
  1670. $parameters = array();
  1671. foreach ($this->getExtensions() as $extension) {
  1672. $params = $extension->getPersistentParameters($this);
  1673. if (!is_array($params)) {
  1674. throw new \RuntimeException(sprintf('The %s::getPersistentParameters must return an array', get_class($extension)));
  1675. }
  1676. $parameters = array_merge($parameters, $params);
  1677. }
  1678. return $parameters;
  1679. }
  1680. /**
  1681. * @param string $name
  1682. *
  1683. * @return null|mixed
  1684. */
  1685. public function getPersistentParameter($name)
  1686. {
  1687. $parameters = $this->getPersistentParameters();
  1688. return isset($parameters[$name]) ? $parameters[$name] : null;
  1689. }
  1690. /**
  1691. * {@inheritdoc}
  1692. */
  1693. public function getBreadcrumbs($action)
  1694. {
  1695. @trigger_error(
  1696. 'The '.__METHOD__.' method is deprecated since version 3.2 and will be removed in 4.0.'.
  1697. ' Use Sonata\AdminBundle\Admin\BreadcrumbsBuilder::getBreadcrumbs instead.',
  1698. E_USER_DEPRECATED
  1699. );
  1700. return $this->getBreadcrumbsBuilder()->getBreadcrumbs($this, $action);
  1701. }
  1702. /**
  1703. * Generates the breadcrumbs array.
  1704. *
  1705. * Note: the method will be called by the top admin instance (parent => child)
  1706. *
  1707. * @param string $action
  1708. * @param ItemInterface|null $menu
  1709. *
  1710. * @return array
  1711. */
  1712. public function buildBreadcrumbs($action, MenuItemInterface $menu = null)
  1713. {
  1714. @trigger_error(
  1715. 'The '.__METHOD__.' method is deprecated since version 3.2 and will be removed in 4.0.',
  1716. E_USER_DEPRECATED
  1717. );
  1718. if (isset($this->breadcrumbs[$action])) {
  1719. return $this->breadcrumbs[$action];
  1720. }
  1721. return $this->breadcrumbs[$action] = $this->getBreadcrumbsBuilder()
  1722. ->buildBreadcrumbs($this, $action, $menu);
  1723. }
  1724. /**
  1725. * NEXT_MAJOR : remove this method.
  1726. *
  1727. * @return BreadcrumbsBuilderInterface
  1728. */
  1729. final public function getBreadcrumbsBuilder()
  1730. {
  1731. @trigger_error(
  1732. 'The '.__METHOD__.' method is deprecated since version 3.2 and will be removed in 4.0.'.
  1733. ' Use the sonata.admin.breadcrumbs_builder service instead.',
  1734. E_USER_DEPRECATED
  1735. );
  1736. if ($this->breadcrumbsBuilder === null) {
  1737. $this->breadcrumbsBuilder = new BreadcrumbsBuilder();
  1738. }
  1739. return $this->breadcrumbsBuilder;
  1740. }
  1741. /**
  1742. * NEXT_MAJOR : remove this method.
  1743. *
  1744. * @param BreadcrumbsBuilderInterface
  1745. *
  1746. * @return AbstractAdmin
  1747. */
  1748. final public function setBreadcrumbsBuilder(BreadcrumbsBuilderInterface $value)
  1749. {
  1750. @trigger_error(
  1751. 'The '.__METHOD__.' method is deprecated since version 3.2 and will be removed in 4.0.'.
  1752. ' Use the sonata.admin.breadcrumbs_builder service instead.',
  1753. E_USER_DEPRECATED
  1754. );
  1755. $this->breadcrumbsBuilder = $value;
  1756. return $this;
  1757. }
  1758. /**
  1759. * {@inheritdoc}
  1760. */
  1761. public function setCurrentChild($currentChild)
  1762. {
  1763. $this->currentChild = $currentChild;
  1764. }
  1765. /**
  1766. * {@inheritdoc}
  1767. */
  1768. public function getCurrentChild()
  1769. {
  1770. return $this->currentChild;
  1771. }
  1772. /**
  1773. * Returns the current child admin instance.
  1774. *
  1775. * @return AdminInterface|null the current child admin instance
  1776. */
  1777. public function getCurrentChild

Large files files are truncated, but you can click here to view the full file