Completed
Pull Request — master (#1043)
by Sebastian
07:23 queued 11s
created

ElasticaToModelTransformer::transform()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 33
Code Lines 14

Duplication

Lines 3
Ratio 9.09 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 3
loc 33
ccs 0
cts 20
cp 0
rs 8.439
cc 6
eloc 14
nc 8
nop 1
crap 42
1
<?php
2
3
namespace FOS\ElasticaBundle\Propel;
4
5
use FOS\ElasticaBundle\HybridResult;
6
use FOS\ElasticaBundle\Transformer\AbstractElasticaToModelTransformer;
7
use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
8
use FOS\ElasticaBundle\Transformer\HighlightableModelInterface;
9
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
10
11
/**
12
 * Maps Elastica documents with Propel objects.
13
 *
14
 * This mapper assumes an exact match between Elastica document IDs and Propel
15
 * entity IDs.
16
 *
17
 * @author William Durand <[email protected]>
18
 */
19
class ElasticaToModelTransformer extends AbstractElasticaToModelTransformer
20
{
21
    /**
22
     * Propel model class to map to Elastica documents.
23
     *
24
     * @var string
25
     */
26
    protected $objectClass = null;
27
28
    /**
29
     * Transformer options.
30
     *
31
     * @var array
32
     */
33
    protected $options = array(
34
        'hydrate'    => true,
35
        'identifier' => 'id',
36
    );
37
38
    /**
39
     * Constructor.
40
     *
41
     * @param string $objectClass
42
     * @param array  $options
43
     */
44
    public function __construct($objectClass, array $options = array())
45
    {
46
        $this->objectClass = $objectClass;
47
        $this->options = array_merge($this->options, $options);
48
    }
49
50
    /**
51
     * Transforms an array of Elastica document into an array of Propel entities
52
     * fetched from the database.
53
     *
54
     * @param array $elasticaObjects
55
     *
56
     * @return array|\ArrayObject
57
     */
58
    public function transform(array $elasticaObjects)
59
    {
60
        $ids = $highlights = array();
61
        foreach ($elasticaObjects as $elasticaObject) {
62
            $ids[] = $elasticaObject->getId();
63
            $highlights[$elasticaObject->getId()] = $elasticaObject->getHighlights();
64
        }
65
66
        $objects = $this->findByIdentifiers($ids, $this->options['hydrate']);
67
68 View Code Duplication
        if (!$this->options['ignore_missing'] && count($objects) < count($elasticaObjects)) {
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...
69
            throw new \RuntimeException('Cannot find corresponding Propel objects for all Elastica results.');
70
        }
71
72
        $_objects = [];
73
        foreach ($objects as $object) {
74
            if ($objects instanceof HighlightableModelInterface) {
75
                $object->setElasticHighlights($highlights[$object->getId()]);
76
            }
77
78
            $_objects[] = $object;
79
        }
80
81
82
//        $objects = $objects->toArray();
83
//
84
//        // Sort objects in the order of their IDs
85
//        $idPos = array_flip($ids);
86
//        $identifier = $this->options['identifier'];
87
//        usort($objects, $this->getSortingClosure($idPos, $identifier));
88
89
        return $_objects;
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95 View Code Duplication
    public function hybridTransform(array $elasticaObjects)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
96
    {
97
        $objects = $this->transform($elasticaObjects);
98
99
        $result = array();
100
        for ($i = 0, $j = count($elasticaObjects); $i < $j; $i++) {
101
            $result[] = new HybridResult($elasticaObjects[$i], $objects[$i]);
102
        }
103
104
        return $result;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function getObjectClass()
111
    {
112
        return $this->objectClass;
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function getIdentifierField()
119
    {
120
        return $this->options['identifier'];
121
    }
122
123
    /**
124
     * Fetch Propel entities for the given identifier values.
125
     *
126
     * If $hydrate is false, the returned array elements will be arrays.
127
     * Otherwise, the results will be hydrated to instances of the model class.
128
     *
129
     * @param array   $identifierValues Identifier values
130
     * @param boolean $hydrate          Whether or not to hydrate the results
131
     *
132
     * @return array
133
     */
134
    protected function findByIdentifiers(array $identifierValues, $hydrate)
135
    {
136
        if (empty($identifierValues)) {
137
            return array();
138
        }
139
140
        $query = $this->createQuery($this->objectClass, $this->options['identifier'], $identifierValues);
141
142
        if (! $hydrate) {
143
            return $query->toArray();
144
        }
145
146
        return $query->find()->getArrayCopy();
147
    }
148
149
    /**
150
     * Create a query to use in the findByIdentifiers() method.
151
     *
152
     * @param string $class            Propel model class
153
     * @param string $identifierField  Identifier field name (e.g. "id")
154
     * @param array  $identifierValues Identifier values
155
     *
156
     * @return \ModelCriteria
157
     */
158
    protected function createQuery($class, $identifierField, array $identifierValues)
159
    {
160
        $queryClass   = $class.'Query';
161
        $filterMethod = 'filterBy'.$this->camelize($identifierField);
162
163
        return $queryClass::create()->$filterMethod($identifierValues);
164
    }
165
166
    /**
167
     * @see https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Util/Inflector.php
168
     *
169
     * @param string $str
170
     */
171
    private function camelize($str)
172
    {
173
        return ucfirst(str_replace(" ", "", ucwords(strtr($str, "_-", "  "))));
174
    }
175
}
176