Completed
Push — master ( 31c1f9...0bd8b0 )
by Karel
10s
created

hybridTransform()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 4
nop 1
crap 3
1
<?php
2
3
namespace FOS\ElasticaBundle\Doctrine;
4
5
use Doctrine\Common\Persistence\ManagerRegistry;
6
use FOS\ElasticaBundle\HybridResult;
7
use FOS\ElasticaBundle\Transformer\AbstractElasticaToModelTransformer as BaseTransformer;
8
use FOS\ElasticaBundle\Transformer\HighlightableModelInterface;
9
10
/**
11
 * Maps Elastica documents with Doctrine objects
12
 * This mapper assumes an exact match between
13
 * elastica documents ids and doctrine object ids.
14
 */
15
abstract class AbstractElasticaToModelTransformer extends BaseTransformer
16
{
17
    /**
18
     * Manager registry.
19
     *
20
     * @var ManagerRegistry
21
     */
22
    protected $registry = null;
23
24
    /**
25
     * Class of the model to map to the elastica documents.
26
     *
27
     * @var string
28
     */
29
    protected $objectClass = null;
30
31
    /**
32
     * Optional parameters.
33
     *
34
     * @var array
35
     */
36
    protected $options = array(
37
        'hints'        => array(),
38
        'hydrate'        => true,
39
        'identifier'     => 'id',
40
        'ignore_missing' => false,
41
        'query_builder_method' => 'createQueryBuilder',
42
    );
43
44
    /**
45
     * Instantiates a new Mapper.
46
     *
47
     * @param ManagerRegistry $registry
48
     * @param string          $objectClass
49
     * @param array           $options
50
     */
51 12
    public function __construct(ManagerRegistry $registry, $objectClass, array $options = array())
52
    {
53 12
        $this->registry    = $registry;
54 12
        $this->objectClass = $objectClass;
55 12
        $this->options     = array_merge($this->options, $options);
56 12
    }
57
58
    /**
59
     * Returns the object class that is used for conversion.
60
     *
61
     * @return string
62
     */
63 1
    public function getObjectClass()
64
    {
65 1
        return $this->objectClass;
66
    }
67
68
    /**
69
     * Transforms an array of elastica objects into an array of
70
     * model objects fetched from the doctrine repository.
71
     *
72
     * @param array $elasticaObjects of elastica objects
73
     *
74
     * @throws \RuntimeException
75
     *
76
     * @return array
77
     **/
78 7
    public function transform(array $elasticaObjects)
79
    {
80 7
        $ids = $highlights = array();
81 7
        foreach ($elasticaObjects as $elasticaObject) {
82 7
            $ids[] = $elasticaObject->getId();
83 7
            $highlights[$elasticaObject->getId()] = $elasticaObject->getHighlights();
84
        }
85
86 7
        $objects = $this->findByIdentifiers($ids, $this->options['hydrate']);
87 7
        $objectsCnt = count($objects);
88 7
        $elasticaObjectsCnt = count($elasticaObjects);
89 7
        if (!$this->options['ignore_missing'] && $objectsCnt < $elasticaObjectsCnt) {
90 1
            throw new \RuntimeException(sprintf('Cannot find corresponding Doctrine objects (%d) for all Elastica results (%d). IDs: %s', $objectsCnt, $elasticaObjectsCnt, join(', ', $ids)));
91
        };
92
93 6
        $propertyAccessor = $this->propertyAccessor;
94 6
        $identifier = $this->options['identifier'];
95 6
        foreach ($objects as $object) {
96 5
            if ($object instanceof HighlightableModelInterface) {
97 4
                $id = $propertyAccessor->getValue($object, $identifier);
98 5
                $object->setElasticHighlights($highlights[$id]);
99
            }
100
        }
101
102
        // sort objects in the order of ids
103 6
        $idPos = array_flip($ids);
104 6 View Code Duplication
        usort($objects, function($a, $b) use ($idPos, $identifier, $propertyAccessor)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105
        {
106 5
            return $idPos[$propertyAccessor->getValue($a, $identifier)] > $idPos[$propertyAccessor->getValue($b, $identifier)];
107 6
        });
108
109 6
        return $objects;
110
    }
111
112 2
    public function hybridTransform(array $elasticaObjects)
113
    {
114 2
        $indexedElasticaResults = array();
115 2
        foreach ($elasticaObjects as $elasticaObject) {
116 2
            $indexedElasticaResults[$elasticaObject->getId()] = $elasticaObject;
117
        }
118
119 2
        $objects = $this->transform($elasticaObjects);
120
121 2
        $result = array();
122 2
        foreach ($objects as $object) {
123 2
            $id = $this->propertyAccessor->getValue($object, $this->options['identifier']);
124 2
            $result[] = new HybridResult($indexedElasticaResults[$id], $object);
125
        }
126
127 2
        return $result;
128
    }
129
130
    /**
131
     * {@inheritDoc}
132
     */
133 1
    public function getIdentifierField()
134
    {
135 1
        return $this->options['identifier'];
136
    }
137
138
    /**
139
     * Fetches objects by theses identifier values.
140
     *
141
     * @param array   $identifierValues ids values
142
     * @param Boolean $hydrate          whether or not to hydrate the objects, false returns arrays
143
     *
144
     * @return array of objects or arrays
145
     */
146
    abstract protected function findByIdentifiers(array $identifierValues, $hydrate);
147
}
148