Completed
Push — master ( 3214c9...a8a248 )
by Quentin
10:44 queued 01:22
created

EntityCollection::chunk()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
cc 2
eloc 3
nc 1
nop 1
crap 6
1
<?php
2
3
namespace Majora\Framework\Model;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Majora\Framework\Normalizer\MajoraNormalizer;
7
use Majora\Framework\Normalizer\Model\NormalizableInterface;
8
use Symfony\Component\PropertyAccess\PropertyAccess;
9
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
10
11
/**
12
 * Base class for entity aggregation collection.
13
 */
14
class EntityCollection extends ArrayCollection implements NormalizableInterface
15
{
16
    /**
17
     * @var PropertyAccessorInterface
18
     */
19
    private static $propertyAccessor;
20
21
    /**
22
     * Create and returns local property accessor.
23
     *
24
     * @return PropertyAccessorInterface
25
     */
26
    private function getPropertyAccessor()
27
    {
28
        return self::$propertyAccessor = self::$propertyAccessor
29
            ?: PropertyAccess::createPropertyAccessor()
30
        ;
31
    }
32
33
    /**
34
     * return collectionned entity class.
35
     *
36
     * @return string
37
     */
38
    public function getEntityClass()
39
    {
40
        throw new \BadMethodCallException(sprintf('%s() method has to be defined in %s class.',
41
            __FUNCTION__, static::class
42
        ));
43
    }
44
45
    /**
46
     * @see NormalizableInterface::getScopes()
47
     */
48
    public static function getScopes()
49
    {
50
        return array();
51
    }
52
53
    /**
54
     * @see NormalizableInterface::normalize()
55
     */
56 6
    public function normalize($scope = 'default')
57
    {
58 3
        return $this
59
            ->map(function (NormalizableInterface $entity) use ($scope) {
60 6
                return $entity->normalize($scope);
61 6
            })
62 6
            ->toArray()
63 3
        ;
64
    }
65
66
    /**
67
     * @see NormalizableInterface::denormalize()
68
     */
69
    public function denormalize(array $data)
70
    {
71
        $this->clear();
72
73
        foreach ($data as $key => $majoraEntityData) {
74
            $this->set($key, MajoraNormalizer::createNormalizer()
75
                ->denormalize($majoraEntityData, $this->getEntityClass())
76
            );
77
        }
78
79
        return $this;
80
    }
81
82
    /**
83
     * @see SerializableInterface::serialize()
84
     */
85
    public function serialize($scope = 'default', PropertyAccessorInterface $propertyAccessor = null)
0 ignored issues
show
Unused Code introduced by
The parameter $propertyAccessor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
    {
87
        @trigger_error(sprintf('The method %s() is deprecated and will be removed in 2.0. Use normalize() instead.', __METHOD__), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
88
89
        return $this->normalize($scope);
90
    }
91
92
    /**
93
     * @see SerializableInterface::deserialize()
94
     */
95
    public function deserialize(array $data, PropertyAccessorInterface $propertyAccessor = null)
0 ignored issues
show
Unused Code introduced by
The parameter $propertyAccessor is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
96
    {
97
        @trigger_error(sprintf('The method %s() is deprecated and will be removed in 2.0. Use denormalize() instead.', __METHOD__), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
98
99
        return $this->denormalize($data);
100
    }
101
102
    /**
103
     * filter given collection on given fields.
104
     *
105
     * @param array $filters
106
     *
107
     * @return EntityCollection
108
     */
109
    public function search(array $filters)
110
    {
111
        return $this->filter(function (CollectionableInterface $entity) use ($filters) {
112
            $res = true;
113
            foreach ($filters as $key => $value) {
114
                $current = $this->getPropertyAccessor()->getValue($entity, $key);
115
                $res = $res && (is_array($value) ?
116
                    in_array($current, $value) :
117
                    $current == $value
118
                );
119
            }
120
121
            return $res;
122
        });
123
    }
124
125
    /**
126
     * extract the first $length elements from collection.
127
     *
128
     * @param int $length
129
     *
130
     * @return EntityCollection
131
     */
132
    public function chunk($length)
133
    {
134
        $chunkedData = array_chunk($this->toArray(), $length, true);
135
136
        return new static(empty($chunkedData) ? array() : $chunkedData[0]);
137
    }
138
139
    /**
140
     * @see ArrayCollection::slice()
141
     *
142
     * @return EntityCollection
143
     */
144
    public function cslice($offset, $length = null)
145
    {
146
        return new static($this->slice($offset, $length));
147
    }
148
149
    /**
150
     * Sort collection with given closure.
151
     *
152
     * @param \Closure $p
153
     *
154
     * @return EntityCollection
155
     */
156
    public function sort(\Closure $p)
157
    {
158
        $elements = $this->toArray();
159
160
        if (!uasort($elements, $p)) {
161
            throw new \InvalidArgumentException('Sort failed.');
162
        }
163
164
        return new static(array_values($elements));
165
    }
166
167
    /**
168
     * Reduce collection with given closure.
169
     *
170
     * @link http://php.net/manual/en/function.array-reduce.php
171
     *
172
     * @param \Closure $p
173
     * @param mixed    $initialValue
174
     *
175
     * @return mixed
176
     */
177
    public function reduce(\Closure $p, $initialValue = null)
178
    {
179
        return array_reduce($this->toArray(), $p, $initialValue);
180
    }
181
182
    /**
183
     * reads and returns value of given field into given element.
184
     *
185
     * @param CollectionableInterface $element
186
     * @param string                  $field
187
     *
188
     * @return mixed
189
     */
190
    private function getFieldValue(CollectionableInterface $element, $field)
191
    {
192
        return $this->getPropertyAccessor()->getValue($element, $field);
193
    }
194
195
    /**
196
     * index collection by given object field.
197
     *
198
     * @param string $field
199
     *
200
     * @return EntityCollection
201
     */
202
    public function indexBy($field)
203
    {
204
        $elements = $this->toArray();
205
        $this->clear();
206
207
        foreach ($elements as $element) {
208
            $this->set(
209
                $this->getFieldValue($element, $field),
210
                $element
211
            );
212
        }
213
214
        return $this;
215
    }
216
217
    /**
218
     * Return value of inner objects given property as an array.
219
     *
220
     * This is an object version of array_column() method.
221
     * @link http://php.net/manual/fr/function.array-column.php
222
     *
223
     * @param string $column
224
     *
225
     * @return array
226
     */
227
    public function column($column)
228
    {
229
        return $this
230
            ->map(function (CollectionableInterface $entity) use ($column) {
231
                return $this->getFieldValue($entity, $column);
232
            })
233
            ->toArray()
234
        ;
235
    }
236
237
    /**
238
     * Create a flattened view of collection as a key value array.
239
     *
240
     * @param string $indexColumn
241
     * @param string $valueColumn
242
     *
243
     * @return array
244
     */
245
    public function flatten($indexColumn, $valueColumn)
246
    {
247
        return $this->reduce(
248
            function ($carry, CollectionableInterface $entity) use ($indexColumn, $valueColumn) {
249
                $carry[$this->getFieldValue($entity, $indexColumn)] = $this->getFieldValue($entity, $valueColumn);
250
251
                return $carry;
252
            },
253
            array()
254
        );
255
    }
256
257
    /**
258
     * Returns a string representation of given column values.
259
     *
260
     * @param string $column
261
     * @param string $slug
262
     *
263
     * @return string
264
     */
265
    public function display($column, $slug = '", "', $format = '["%s"]')
266
    {
267
        return sprintf($format, implode($slug, $this
0 ignored issues
show
Bug introduced by
The method toArray cannot be called on $this->column($column) (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
268
            ->column($column)
269
            ->toArray()
270
        ));
271
    }
272
}
273