DatagridBuilder.php 7.2 KB

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