Completed
Push — master ( 6db6da...5370d9 )
by Angel
03:42
created

EmbeddableTrait::toArray()   B

Complexity

Conditions 10
Paths 72

Size

Total Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 7.2242
c 0
b 0
f 0
cc 10
nc 72
nop 3

How to fix   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
namespace roaresearch\yii2\roa\hal;
4
5
use yii\base\Arrayable;
6
use yii\base\ArrayableTrait;
7
use yii\helpers\ArrayHelper;
8
use yii\web\Link;
9
use yii\web\Linkable;
10
11
/**
12
 * Interface to get a the information of a file associated to a model.
13
 *
14
 * @author Angel (Faryshta) Guevara <[email protected]>
15
 */
16
trait EmbeddableTrait
17
{
18
    use ArrayableTrait;
19
20
    /**
21
     * @inheritdoc
22
     */
23
    public abstract function fields();
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
24
25
    /**
26
     * @inheritdoc
27
     */
28
    public abstract function extraFields();
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
29
30
    /**
31
     * @inheritdoc
32
     */
33
    public function toArray(
34
        array $fields = [],
35
        array $expand = [],
36
        $recursive = true
37
    ) {
38
        $data = [];
39
        foreach ($this->resolveFieldList($fields) as $field => $definition) {
40
            $data[$field] = $this->processField($field, $definition);
41
        }
42
43
        foreach ($this->resolveExpandList($expand) as $field => $definition) {
44
            $attribute = $this->processField($field, $definition);
45
46
            if ($recursive) {
47
                $nestedFields = $this->extractFieldsFor($fields, $field);
48
                $nestedExpand = $this->extractFieldsFor($expand, $field);
49
                if ($attribute instanceof Arrayable) {
50
                    $attribute = $attribute->toArray(
51
                        $nestedFields,
52
                        $nestedExpand
53
                    );
54
                } elseif (is_array($attribute)) {
55
                    $attribute = array_map(
56
                        function ($item) use ($nestedFields, $nestedExpand) {
57
                            if ($item instanceof Arrayable) {
58
                                return $item->toArray(
59
                                    $nestedFields,
60
                                    $nestedExpand
61
                                );
62
                            }
63
                            return $item;
64
                        },
65
                        $attribute
66
                    );
67
                }
68
            }
69
70
            if ($envelope = $this->getExpandEnvelope()) {
71
                $data[$envelope][$field] = $attribute;
72
            } else {
73
                $data[$field] = $attribute;
74
            }
75
        }
76
77
        if ($this instanceof Linkable) {
78
            $data['_links'] = Link::serialize($this->getLinks());
79
        }
80
81
        return $recursive ? ArrayHelper::toArray($data) : $data;
82
    }
83
84
    /**
85
     * @return string property which will contain all the expanded parameters.
86
     */
87
    public function getExpandEnvelope(): string
88
    {
89
        return Embeddable::EMBEDDED_PROPERTY;
90
    }
91
92
    /**
93
     * Determines which fields can be returned by [[toArray()]].
94
     * This method will first extract the root fields from the given fields.
95
     * Then it will check the requested root fields against those declared in
96
     * [[fields()]] to determine which fields can be returned.
97
     *
98
     * @param array $fields the fields being requested for exporting
99
     * @return array the list of fields to be exported. The array keys are the
100
     * field names, and the array values are the corresponding object property
101
     * names or PHP callables returning the field values.
102
     */
103 View Code Duplication
    protected function resolveFieldList($fields): array
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...
104
    {
105
        $fields = $this->extractRootFields($fields);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $fields. This often makes code more readable.
Loading history...
106
        $result = [];
107
108
        foreach ($this->fields() as $field => $definition) {
109
                if (is_int($field)) {
110
                    $field = $definition;
111
                }
112
113
                if (empty($fields) || in_array($field, $fields, true)) {
114
                    $result[$field] = $definition;
115
                }
116
        }
117
118
        return $result;
119
    }
120
121
    /**
122
     * Determines which expand fields can be returned by [[toArray()]].
123
     * This method will first extract the root fields from the given expand.
124
     * Then it will check the requested root fields against those declared in
125
     * [[extraFields()]] to determine which fields can be returned.
126
     *
127
     * @param array $expand the expand fields being requested for exporting
128
     * @return array the list of fields to be exported. The array keys are the
129
     * field names, and the array values are the corresponding object property
130
     * names or PHP callables returning the field values.
131
     */
132 View Code Duplication
    protected function resolveExpandList($expand): array
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...
133
    {
134
        if (empty($expand)) {
135
            return [];
136
        }
137
138
        $fields = $this->extractRootFields($expand);
139
        $result = [];
140
141
        foreach ($this->extraFields() as $field => $definition) {
142
                if (is_int($field)) {
143
                    $field = $definition;
144
                }
145
146
                if (in_array($field, $fields, true)) {
147
                    $result[$field] = $definition;
148
                }
149
        }
150
151
        return $result;
152
    }
153
154
    /**
155
     * @param string $field name of the field to be resolved.
156
     * @param string|callable $definition the field definition, it its an string
157
     * it will be used as a property name, or a callable with signature.
158
     *
159
     * ```php
160
     * function ($model, string $field)
161
     * ```
162
     * @return mixed data obtained from the model.
163
     */
164
    protected function processField($field, $definition)
165
    {
166
        return is_string($definition)
167
            ? $this->$definition
168
            : $definition($this, $field);
169
    }
170
}
171