AbstractDateFilter.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace Sonata\DoctrineORMAdminBundle\Filter;
  3. use Sonata\AdminBundle\Form\Type\Filter\DateType;
  4. use Sonata\AdminBundle\Form\Type\Filter\DateRangeType;
  5. use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
  6. use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
  7. use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
  8. abstract class AbstractDateFilter extends Filter
  9. {
  10. /**
  11. * Flag indicating that filter will have range
  12. * @var boolean
  13. */
  14. protected $range = false;
  15. /**
  16. * Flag indicating that filter will filter by datetime instead by date
  17. * @var boolean
  18. */
  19. protected $time = false;
  20. /**
  21. * {@inheritdoc}
  22. */
  23. public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data)
  24. {
  25. //check data sanity
  26. if (!$data || !is_array($data) || !array_key_exists('value', $data)) {
  27. return;
  28. }
  29. if ($this->range) {
  30. //additional data check for ranged items
  31. if (!array_key_exists('start', $data['value']) || !array_key_exists('end', $data['value'])) {
  32. return;
  33. }
  34. if (!$data['value']['start'] || !$data['value']['end']) {
  35. return;
  36. }
  37. //transform types
  38. if ($this->getOption('input_type') == 'timestamp') {
  39. $data['value']['start'] = $data['value']['start'] instanceof \DateTime ? $data['value']['start']->getTimestamp() : 0;
  40. $data['value']['end'] = $data['value']['end'] instanceof \DateTime ? $data['value']['end']->getTimestamp() : 0;
  41. }
  42. //default type for range filter
  43. $data['type'] = !isset($data['type']) || !is_numeric($data['type']) ? DateRangeType::TYPE_BETWEEN : $data['type'];
  44. $startDateParameterName = $this->getNewParameterName($queryBuilder);
  45. $endDateParameterName = $this->getNewParameterName($queryBuilder);
  46. if ($data['type'] == DateRangeType::TYPE_NOT_BETWEEN) {
  47. $this->applyWhere($queryBuilder, sprintf('%s.%s < :%s OR %s.%s > :%s', $alias, $field, $startDateParameterName, $alias, $field, $endDateParameterName));
  48. } else {
  49. $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '>=', $startDateParameterName));
  50. $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '<=', $endDateParameterName));
  51. }
  52. $queryBuilder->setParameter($startDateParameterName, $data['value']['start']);
  53. $queryBuilder->setParameter($endDateParameterName, $data['value']['end']);
  54. } else {
  55. if (!$data['value']) {
  56. return;
  57. }
  58. //default type for simple filter
  59. $data['type'] = !isset($data['type']) || !is_numeric($data['type']) ? DateType::TYPE_EQUAL : $data['type'];
  60. //just find an operator and apply query
  61. $operator = $this->getOperator($data['type']);
  62. //transform types
  63. if ($this->getOption('input_type') == 'timestamp') {
  64. $data['value'] = $data['value'] instanceof \DateTime ? $data['value']->getTimestamp() : 0;
  65. }
  66. //null / not null only check for col
  67. if (in_array($operator, array('NULL', 'NOT NULL'))) {
  68. $this->applyWhere($queryBuilder, sprintf('%s.%s IS %s ', $alias, $field, $operator));
  69. } else {
  70. $parameterName = $this->getNewParameterName($queryBuilder);
  71. $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $parameterName));
  72. $queryBuilder->setParameter($parameterName, $data['value']);
  73. }
  74. }
  75. }
  76. /**
  77. * Resolves DataType:: constants to SQL operators
  78. *
  79. * @param integer $type
  80. *
  81. * @return string
  82. */
  83. protected function getOperator($type)
  84. {
  85. $type = intval($type);
  86. $choices = array(
  87. DateType::TYPE_EQUAL => '=',
  88. DateType::TYPE_GREATER_EQUAL => '>=',
  89. DateType::TYPE_GREATER_THAN => '>',
  90. DateType::TYPE_LESS_EQUAL => '<=',
  91. DateType::TYPE_LESS_THAN => '<',
  92. DateType::TYPE_NULL => 'NULL',
  93. DateType::TYPE_NOT_NULL => 'NOT NULL',
  94. );
  95. return isset($choices[$type]) ? $choices[$type] : '=';
  96. }
  97. /**
  98. * {@inheritdoc}
  99. */
  100. public function getDefaultOptions()
  101. {
  102. return array();
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. public function getRenderSettings()
  108. {
  109. $name = 'sonata_type_filter_date';
  110. if ($this->time) {
  111. $name .= 'time';
  112. }
  113. if ($this->range) {
  114. $name .= '_range';
  115. }
  116. return array($name, array(
  117. 'field_type' => $this->getFieldType(),
  118. 'field_options' => $this->getFieldOptions(),
  119. 'label' => $this->getLabel(),
  120. 'input_type' => 'datetime'
  121. ));
  122. }
  123. }