Completed
Pull Request — master (#1125)
by
unknown
05:37
created

ElasticaToModelTransformer::findByIdentifiers()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 26
ccs 0
cts 19
cp 0
rs 8.8571
cc 3
eloc 14
nc 3
nop 2
crap 12
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
        if (!$this->options['ignore_missing'] && count($objects) < count($elasticaObjects)) {
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
        return $_objects;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 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...
88
    {
89
        $objects = $this->transform($elasticaObjects);
90
91
        $result = array();
92
        for ($i = 0, $j = count($elasticaObjects); $i < $j; $i++) {
93
            $result[] = new HybridResult($elasticaObjects[$i], $objects[$i]);
94
        }
95
96
        return $result;
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function getObjectClass()
103
    {
104
        return $this->objectClass;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function getIdentifierField()
111
    {
112
        return $this->options['identifier'];
113
    }
114
115
    /**
116
     * Fetch Propel entities for the given identifier values.
117
     *
118
     * If $hydrate is false, the returned array elements will be arrays.
119
     * Otherwise, the results will be hydrated to instances of the model class.
120
     *
121
     * @param array   $identifierValues Identifier values
122
     * @param boolean $hydrate          Whether or not to hydrate the results
123
     *
124
     * @return array
125
     */
126
    protected function findByIdentifiers(array $identifierValues, $hydrate)
127
    {
128
        if (empty($identifierValues)) {
129
            return array();
130
        }
131
132
        $queryClass = $this->objectClass.'Query';
133
        $camelizedIdentifier = $this->camelize($this->options['identifier']);
134
        $filterMethod = 'filterBy'.$camelizedIdentifier;
135
136
        $query = $queryClass::create()->$filterMethod($identifierValues);
137
138
        if (! $hydrate) {
139
            $query->setFormatter($queryClass::FORMAT_ARRAY);
140
        }
141
142
        $data = $query->find()->getArrayCopy($camelizedIdentifier);
143
144
        // order results, since Propel Criteria::IN doesn't preserve it
145
        $idsOrder = array_flip($identifierValues);
146
        uksort($data, function($a, $b) use ($idsOrder) {
147
            return $idsOrder[$a] - $idsOrder[$b];
148
        });
149
150
        return $data;
151
    }
152
153
    /**
154
     * @see https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Util/Inflector.php
155
     *
156
     * @param string $str
157
     *
158
     * @return string
159
     */
160
    private function camelize($str)
161
    {
162
        return ucfirst(str_replace(" ", "", ucwords(strtr($str, "_-", "  "))));
163
    }
164
}
165