Licitator 1.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.8 KiB

5 years ago
  1. <?php
  2. namespace Zitec\RuleEngineBundle\Autocomplete;
  3. use Doctrine\ORM\EntityManager;
  4. use Doctrine\ORM\QueryBuilder;
  5. /**
  6. * Abstract class that provides basic autocomplete functionality for doctrine entities.
  7. * Should be extended by autocomplete service implementations.
  8. */
  9. abstract class AbstractAutocompleteEntity implements AutocompleteInterface
  10. {
  11. /**
  12. * @var EntityManager
  13. */
  14. protected $entityManager;
  15. /**
  16. * Entity class name, to be used by the query builder.
  17. *
  18. * @var string
  19. */
  20. protected $entity;
  21. /**
  22. * Name of the entity field used for the id parameter of the autocomplete results array.
  23. *
  24. * @var string
  25. */
  26. protected $idField;
  27. /**
  28. * Name of the entity field used for the text parameter of the autocomplete results array.
  29. *
  30. * @var string
  31. */
  32. protected $textField;
  33. /**
  34. * Items per page for paginated results. Set to zero for unlimited.
  35. *
  36. * @var int
  37. */
  38. protected $ipp = 10;
  39. /**
  40. * If true, the text column will include the id column in parenthesis.
  41. *
  42. * @var bool
  43. */
  44. protected $concatenatedText = false;
  45. /**
  46. * EntityAutocomplete constructor.
  47. *
  48. * @param EntityManager $entityManager
  49. */
  50. public function __construct(EntityManager $entityManager)
  51. {
  52. $this->entityManager = $entityManager;
  53. $this->entity = $this->getEntityClass();
  54. $this->idField = $this->getIdField();
  55. $this->textField = $this->getTextField();
  56. }
  57. /**
  58. * @param string $queryString
  59. * @param int $page
  60. * @return array
  61. */
  62. public function getSuggestions(string $queryString, int $page = 1): array
  63. {
  64. $results = [
  65. 'items' => [],
  66. 'more' => false,
  67. ];
  68. $qb = $this->entityManager->createQueryBuilder();
  69. $qb->from($this->entity, 'e')
  70. ->where("e.$this->idField = :key")
  71. ->orWhere("e.$this->textField LIKE :keyLike")
  72. ->setParameters(['key' => $queryString, 'keyLike' => $queryString . '%']);
  73. $this->alterQuery($qb);
  74. if ($this->ipp) {
  75. $count = clone $qb;
  76. $count->select("count(e.$this->idField)");
  77. $countResult = $count->getQuery()->getSingleResult();
  78. $qb->setFirstResult($this->ipp * ($page - 1))->setMaxResults($this->ipp);
  79. }
  80. $text = $this->concatenatedText ?
  81. "CONCAT(e.$this->textField, ' (', e.$this->idField, ')')" : "e.$this->textField";
  82. $qb->select(["e.$this->idField as id", "$text as text"]);
  83. $results['items'] = $qb->getQuery()->getResult();
  84. if ($this->ipp) {
  85. $results['more'] = ($this->ipp * $page) < reset($countResult);
  86. }
  87. return $results;
  88. }
  89. /**
  90. * @param array $ids
  91. * @return array
  92. */
  93. public function getLabels(array $ids): array
  94. {
  95. $qb = $this->entityManager->createQueryBuilder();
  96. $text = $this->concatenatedText ?
  97. "CONCAT(e.$this->textField, ' (', e.$this->idField, ')')" : "e.$this->textField";
  98. $qb->select(
  99. ["e.$this->idField as id", "$text as text"]
  100. )->from($this->entity, 'e')
  101. ->where($qb->expr()->in("e.$this->idField", ':id'))->setParameter('id', $ids);
  102. $this->alterQuery($qb);
  103. return $qb->getQuery()->getResult();
  104. }
  105. /**
  106. * Allows extending classes alter the query and add extra joins or wheres.
  107. *
  108. * @param QueryBuilder $qb
  109. */
  110. protected function alterQuery(QueryBuilder &$qb)
  111. {
  112. }
  113. /**
  114. * @return string
  115. */
  116. abstract protected function getEntityClass(): string;
  117. /**
  118. * @return string
  119. */
  120. abstract protected function getIdField(): string;
  121. /**
  122. * @return string
  123. */
  124. abstract protected function getTextField(): string;
  125. }