Completed
Pull Request — master (#1569)
by
unknown
03:52
created

transformObjectToDocument()   C

Complexity

Conditions 15
Paths 52

Size

Total Lines 61

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 15.8574

Importance

Changes 0
Metric Value
dl 0
loc 61
ccs 27
cts 32
cp 0.8438
rs 5.9166
c 0
b 0
f 0
cc 15
nc 52
nop 3
crap 15.8574

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\ElasticaBundle\Transformer;
13
14
use Elastica\Document;
15
use FOS\ElasticaBundle\Event\PostTransformEvent;
16
use FOS\ElasticaBundle\Event\PreTransformEvent;
17
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
18
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
19
20
/**
21
 * Maps Elastica documents with Doctrine objects
22
 * This mapper assumes an exact match between
23
 * elastica documents ids and doctrine object ids.
24
 */
25
class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterface
26
{
27
    /**
28
     * @var EventDispatcherInterface
29
     */
30
    protected $dispatcher;
31
32
    /**
33
     * Optional parameters.
34
     *
35
     * @var array
36
     */
37
    protected $options = [
38
        'identifier' => 'id',
39
        'index' => '',
40
    ];
41
42
    /**
43
     * PropertyAccessor instance.
44
     *
45
     * @var PropertyAccessorInterface
46
     */
47
    protected $propertyAccessor;
48
49
    /**
50
     * Instanciates a new Mapper.
51
     */
52 37
    public function __construct(array $options = [], ?EventDispatcherInterface $dispatcher = null)
53
    {
54 37
        $this->options = array_merge($this->options, $options);
55 37
        $this->dispatcher = $dispatcher;
56 37
    }
57
58
    /**
59
     * Set the PropertyAccessor.
60
     */
61 37
    public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
62
    {
63 37
        $this->propertyAccessor = $propertyAccessor;
64 37
    }
65
66
    /**
67
     * Transforms an object into an elastica object having the required keys.
68
     *
69
     * @param object $object the object to convert
70
     * @param array  $fields the keys we want to have in the returned array
71
     *
72
     * @return Document
73
     **/
74 27
    public function transform($object, array $fields)
75
    {
76 27
        $identifier = $this->propertyAccessor->getValue($object, $this->options['identifier']);
77
78 27
        return $this->transformObjectToDocument($object, $fields, (string) $identifier);
79
    }
80
81
    /**
82
     * transform a nested document or an object property into an array of ElasticaDocument.
83
     *
84
     * @param array|\Traversable|\ArrayAccess $objects the object to convert
85
     * @param array                           $fields  the keys we want to have in the returned array
86
     *
87
     * @return array
88
     */
89 6
    protected function transformNested($objects, array $fields)
90
    {
91 6
        if (is_array($objects) || $objects instanceof \Traversable || $objects instanceof \ArrayAccess) {
92 3
            $documents = [];
93 3
            foreach ($objects as $object) {
94 3
                $document = $this->transformObjectToDocument($object, $fields);
95 3
                $documents[] = $document->getData();
96
            }
97
98 3
            return $documents;
99 3
        } elseif (null !== $objects) {
100 2
            $document = $this->transformObjectToDocument($objects, $fields);
101
102 2
            return $document->getData();
103
        }
104
105 1
        return [];
106
    }
107
108
    /**
109
     * Attempts to convert any type to a string or an array of strings.
110
     *
111
     * @param mixed $value
112
     *
113
     * @return string|array
114
     */
115
    protected function normalizeValue($value)
116
    {
117 18
        $normalizeValue = function (&$v) {
118 18
            if ($v instanceof \DateTimeInterface) {
119 2
                $v = $v->format('c');
120 18
            } elseif (!is_scalar($v) && !is_null($v)) {
121 1
                $v = (string) $v;
122
            }
123 18
        };
124
125 18
        if (is_array($value) || $value instanceof \Traversable || $value instanceof \ArrayAccess) {
126 5
            $value = is_array($value) ? $value : iterator_to_array($value, false);
127 5
            array_walk_recursive($value, $normalizeValue);
128
        } else {
129 14
            $normalizeValue($value);
130
        }
131
132 18
        return $value;
133
    }
134
135
    /**
136
     * Transforms the given object to an elastica document.
137
     */
138 27
    protected function transformObjectToDocument(object $object, array $fields, string $identifier = ''): Document
139
    {
140 27
        $document = new Document($identifier, [], $this->options['index']);
141
142 27
        if ($this->dispatcher) {
143
            $this->dispatcher->dispatch($event = new PreTransformEvent($document, $fields, $object));
144
145
            $document = $event->getDocument();
146
        }
147
148 27
        foreach ($fields as $key => $mapping) {
149 26
            if ('_parent' == $key) {
150 4
                $property = (null !== $mapping['property']) ? $mapping['property'] : $mapping['type'];
151 4
                $value = $this->propertyAccessor->getValue($object, $property);
152 4
                $document->setParent($this->propertyAccessor->getValue($value, $mapping['identifier']));
0 ignored issues
show
Bug introduced by
The method setParent() does not seem to exist on object<Elastica\Document>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
153
154
                continue;
155
            }
156
157 22
            $path = isset($mapping['property_path']) ?
158 1
                $mapping['property_path'] :
159 22
                $key;
160 22
            if (false === $path) {
161 1
                continue;
162
            }
163 22
            $value = $this->propertyAccessor->getValue($object, $path);
164
165 21
            if (isset($mapping['type']) && in_array(
166 21
                    $mapping['type'], ['nested', 'object']
167 21
                ) && isset($mapping['properties']) && !empty($mapping['properties'])
168
            ) {
169
                /* $value is a nested document or object. Transform $value into
170
                 * an array of documents, respective the mapped properties.
171
                 */
172 6
                $document->set($key, $this->transformNested($value, $mapping['properties']));
173
174 6
                continue;
175
            }
176
177 20
            if (isset($mapping['type']) && 'attachment' == $mapping['type']) {
178
                // $value is an attachment. Add it to the document.
179 2
                if ($value instanceof \SplFileInfo) {
180 1
                    $document->addFile($key, $value->getPathName());
181
                } else {
182 1
                    $document->addFileContent($key, $value);
183
                }
184
185 2
                continue;
186
            }
187
188 18
            $document->set($key, $this->normalizeValue($value));
189
        }
190
191 22
        if ($this->dispatcher) {
192
            $this->dispatcher->dispatch($event = new PostTransformEvent($document, $fields, $object));
193
194
            $document = $event->getDocument();
195
        }
196
197 22
        return $document;
198
    }
199
}
200