DatagridBuilder.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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\Builder;
  11. use Sonata\AdminBundle\Admin\FieldDescription;
  12. use Sonata\AdminBundle\Admin\Admin;
  13. use Sonata\AdminBundle\Datagrid\Datagrid;
  14. use Doctrine\ORM\Mapping\ClassMetadataInfo;
  15. class DatagridBuilder implements DatagridBuilderInterface
  16. {
  17. /**
  18. * todo: put this in the DIC
  19. *
  20. * built-in definition
  21. *
  22. * @var array
  23. */
  24. protected $filterClasses = array(
  25. 'string' => 'Sonata\\AdminBundle\\Filter\\StringFilter',
  26. 'text' => 'Sonata\\AdminBundle\\Filter\\StringFilter',
  27. 'boolean' => 'Sonata\\AdminBundle\\Filter\\BooleanFilter',
  28. 'integer' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  29. 'tinyint' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  30. 'smallint' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  31. 'mediumint' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  32. 'bigint' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  33. 'decimal' => 'Sonata\\AdminBundle\\Filter\\IntegerFilter',
  34. 'callback' => 'Sonata\\AdminBundle\\Filter\\CallbackFilter',
  35. );
  36. public function fixFieldDescription(Admin $admin, FieldDescription $fieldDescription)
  37. {
  38. // set default values
  39. $fieldDescription->setAdmin($admin);
  40. // set the default field mapping
  41. if (isset($admin->getClassMetaData()->fieldMappings[$fieldDescription->getName()])) {
  42. $fieldDescription->setFieldMapping($admin->getClassMetaData()->fieldMappings[$fieldDescription->getName()]);
  43. }
  44. // set the default association mapping
  45. if (isset($admin->getClassMetaData()->associationMappings[$fieldDescription->getName()])) {
  46. $fieldDescription->setAssociationMapping($admin->getClassMetaData()->associationMappings[$fieldDescription->getName()]);
  47. }
  48. if (!$fieldDescription->getType()) {
  49. throw new \RuntimeException(sprintf('Please define a type for field `%s` in `%s`', $fieldDescription->getName(), get_class($admin)));
  50. }
  51. $fieldDescription->setOption('code', $fieldDescription->getOption('code', $fieldDescription->getName()));
  52. $fieldDescription->setOption('label', $fieldDescription->getOption('label', $fieldDescription->getName()));
  53. $fieldDescription->setOption('filter_value', $fieldDescription->getOption('filter_value', null));
  54. $fieldDescription->setOption('filter_options', $fieldDescription->getOption('filter_options', null));
  55. $fieldDescription->setOption('filter_field_options', $fieldDescription->getOption('filter_field_options', null));
  56. $fieldDescription->setOption('name', $fieldDescription->getOption('name', $fieldDescription->getName()));
  57. // set the default type if none is set
  58. if (!$fieldDescription->getType()) {
  59. $fieldDescription->setType('string');
  60. }
  61. if (!$fieldDescription->getTemplate()) {
  62. $fieldDescription->setTemplate(sprintf('SonataAdminBundle:CRUD:filter_%s.html.twig', $fieldDescription->getType()));
  63. if ($fieldDescription->getType() == ClassMetadataInfo::MANY_TO_ONE) {
  64. $fieldDescription->setTemplate('SonataAdminBundle:CRUD:filter_many_to_one.html.twig');
  65. }
  66. if ($fieldDescription->getType() == ClassMetadataInfo::MANY_TO_MANY) {
  67. $fieldDescription->setTemplate('SonataAdminBundle:CRUD:filter_many_to_many.html.twig');
  68. }
  69. }
  70. }
  71. /**
  72. * return the class associated to a FieldDescription if any defined
  73. *
  74. * @throws RuntimeException
  75. * @param FieldDescription $fieldDescription
  76. * @return bool|string
  77. */
  78. public function getFilterFieldClass(FieldDescription $fieldDescription)
  79. {
  80. if ($fieldDescription->getOption('filter_field_widget', false)) {
  81. $class = $fieldDescription->getOption('filter_field_widget', false);
  82. } else {
  83. $class = array_key_exists($fieldDescription->getType(), $this->filterClasses) ? $this->filterClasses[$fieldDescription->getType()] : false;
  84. }
  85. if (!class_exists($class)) {
  86. throw new \RuntimeException(sprintf('The class `%s` does not exist for field `%s`', $class, $fieldDescription->getType()));
  87. }
  88. return $class;
  89. }
  90. public function getChoices(FieldDescription $fieldDescription)
  91. {
  92. $targets = $fieldDescription->getAdmin()->getModelManager()
  93. ->createQueryBuilder()
  94. ->select('t')
  95. ->from($fieldDescription->getTargetEntity(), 't')
  96. ->getQuery()
  97. ->execute();
  98. $choices = array();
  99. foreach ($targets as $target) {
  100. // todo : puts this into a configuration option and use reflection
  101. foreach (array('getTitle', 'getName', '__toString') as $getter) {
  102. if (method_exists($target, $getter)) {
  103. $choices[$target->getId()] = $target->$getter();
  104. break;
  105. }
  106. }
  107. }
  108. return $choices;
  109. }
  110. public function addFilter(Datagrid $datagrid, FieldDescription $fieldDescription)
  111. {
  112. if (!$fieldDescription->getType()) {
  113. return false;
  114. }
  115. switch($fieldDescription->getType()) {
  116. case ClassMetadataInfo::MANY_TO_ONE:
  117. $options = $fieldDescription->getOption('filter_field_options');
  118. $filter = new \Sonata\AdminBundle\Filter\IntegerFilter($fieldDescription);
  119. break;
  120. case ClassMetadataInfo::MANY_TO_MANY:
  121. $options = $fieldDescription->getOption('filter_field_options');
  122. $options['choices'] = $this->getChoices($fieldDescription);
  123. $fieldDescription->setOption('filter_field_options', $options);
  124. $filter = new \Sonata\AdminBundle\Filter\ChoiceFilter($fieldDescription);
  125. break;
  126. default:
  127. $class = $this->getFilterFieldClass($fieldDescription);
  128. $filter = new $class($fieldDescription);
  129. }
  130. $datagrid->addFilter($filter);
  131. }
  132. }