SelectQueryHydrator   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
dl 0
loc 110
c 0
b 0
f 0
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B hydrate() 0 74 7
1
<?php
2
3
namespace Mdiyakov\DoctrineSolrBundle\Query\Hydrator;
4
5
use Doctrine\ORM\EntityRepository;
6
use Mdiyakov\DoctrineSolrBundle\Exception\DiscriminatorFieldException;
7
use Mdiyakov\DoctrineSolrBundle\Exception\EntityNotExistInDatabaseException;
8
use Mdiyakov\DoctrineSolrBundle\Exception\HydratorException;
9
use Mdiyakov\DoctrineSolrBundle\Schema\Schema;
10
11
class SelectQueryHydrator
12
{
13
    /**
14
     * @var Schema
15
     */
16
    private $schema;
17
18
    /**
19
     * @var \Doctrine\ORM\EntityRepository
20
     */
21
    private $entityRepository;
22
23
    /**
24
     * @var array
25
     */
26
    private $entityConfig;
27
28
    /**
29
     * @param EntityRepository $repository
30
     * @param Schema $schema
31
     * @param array $entityConfig
32
     */
33
    public function __construct(EntityRepository $repository, Schema $schema, $entityConfig)
34
    {
35
        $this->schema = $schema;
36
        $this->entityRepository = $repository;
37
        $this->entityConfig = $entityConfig;
38
    }
39
40
    /**
41
     * @param array $documentsArray
42
     * @return object[]
43
     * @throws DiscriminatorFieldException
44
     * @throws EntityNotExistInDatabaseException
45
     * @thorws HydratorException
46
     */
47
    public function hydrate($documentsArray)
48
    {
49
        if (!is_array($documentsArray)) {
0 ignored issues
show
introduced by
The condition is_array($documentsArray) is always true.
Loading history...
50
            throw new HydratorException('Result dataset must be an array');
51
        }
52
53
        if (empty($documentsArray)) {
54
            throw new HydratorException('Result dataset is empty');
55
        }
56
57
        $scoreStatements = [];
58
        $discriminatorField = $this->schema->getDiscriminatorConfigField();
59
        $entityPrimaryKeyField = $this->schema->getEntityPrimaryKeyField();
60
        $primaryKeyValues = [];
61
        $orderValue = count($documentsArray);
62
        foreach($documentsArray as $documentRow) {
63
            if (!array_key_exists($discriminatorField->getDocumentFieldName(), $documentRow)) {
64
                throw new DiscriminatorFieldException(
65
                    sprintf('Discriminator field "%s" must be presented in dataset', $discriminatorField->getDocumentFieldName())
66
                );
67
            }
68
69
            if ($discriminatorField->getValue($this->entityConfig) !== $documentRow[$discriminatorField->getDocumentFieldName()]) {
70
                throw new DiscriminatorFieldException(
71
                    sprintf(
72
                        'Discriminator field value "%s" must be "%s" but "%s" is provided',
73
                        $discriminatorField->getConfigFieldName(),
74
                        $discriminatorField->getValue($this->entityConfig),
75
                        $documentRow[$discriminatorField->getDocumentFieldName()]
76
                    )
77
                );
78
            }
79
80
            $primaryKeyValues[] = $documentRow[$entityPrimaryKeyField->getDocumentFieldName()];
81
            $scoreStatements[] = sprintf(
82
                'WHEN entity.%s = %s THEN %s',
83
                $entityPrimaryKeyField->getEntityFieldName(),
84
                $documentRow[$entityPrimaryKeyField->getDocumentFieldName()],
85
                $orderValue
86
            );
87
            $orderValue = --$orderValue;
88
        }
89
90
        $entities = $this->entityRepository
91
            ->createQueryBuilder('entity')
92
            ->addSelect(sprintf('(CASE %s ELSE 0 END) AS HIDDEN score', join(' ' ,$scoreStatements)))
93
            ->where(
94
                sprintf('entity.%s in (:ids)', $entityPrimaryKeyField->getEntityFieldName())
95
            )
96
            ->setParameter(':ids', $primaryKeyValues)
97
            ->addOrderBy('score', 'desc')
98
            ->getQuery()->getResult()
99
        ;
100
101
        if (count($entities) != count($documentsArray)) {
102
            $entityIds = array_map(
103
                function($entity) use ($entityPrimaryKeyField)
104
                {
105
                    return  $entityPrimaryKeyField->getEntityFieldValue($entity);
106
                },
107
                $entities
108
            );
109
110
            $notFoundEntityIds = array_diff($primaryKeyValues, $entityIds);
111
            throw new HydratorException(
112
                sprintf(
113
                    'Entities of "%s" with "%s" primary keys are not found in database',
114
                    $this->entityConfig['class'],
115
                    join(', ', $notFoundEntityIds)
116
                )
117
            );
118
        }
119
120
        return $entities;
121
    }
122
}