Completed
Push — master ( 56c231...fd9f50 )
by
unknown
03:15
created

getRelationshipAsPropertyName()   C

Complexity

Conditions 11
Paths 28

Size

Total Lines 46
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 46
rs 5.2653
cc 11
eloc 26
nc 28
nop 4

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 NilPortugues\Serializer\Drivers\Eloquent\Helper;
4
5
use ErrorException;
6
use Illuminate\Database\Eloquent\Model;
7
use NilPortugues\Serializer\Drivers\Eloquent\Driver;
8
use NilPortugues\Serializer\Serializer;
9
use ReflectionClass;
10
use ReflectionMethod;
11
12
class RelationshipPropertyExtractor
13
{
14
    /**
15
     * @var array
16
     */
17
    private static $forbiddenFunction = [
18
        'forceDelete',
19
        'forceFill',
20
        'delete',
21
        'newQueryWithoutScopes',
22
        'newQuery',
23
        'bootIfNotBooted',
24
        'boot',
25
        'bootTraits',
26
        'clearBootedModels',
27
        'query',
28
        'onWriteConnection',
29
        'delete',
30
        'forceDelete',
31
        'performDeleteOnModel',
32
        'flushEventListeners',
33
        'push',
34
        'touchOwners',
35
        'touch',
36
        'updateTimestamps',
37
        'freshTimestamp',
38
        'freshTimestampString',
39
        'newQuery',
40
        'newQueryWithoutScopes',
41
        'newBaseQueryBuilder',
42
        'usesTimestamps',
43
        'reguard',
44
        'isUnguarded',
45
        'totallyGuarded',
46
        'syncOriginal',
47
        'getConnectionResolver',
48
        'unsetConnectionResolver',
49
        'getEventDispatcher',
50
        'unsetEventDispatcher',
51
        '__toString',
52
        '__wakeup',
53
    ];
54
55
    /**
56
     * @param $value
57
     * @param $className
58
     * @param ReflectionClass $reflection
59
     * @param Driver          $serializer
60
     *
61
     * @return array
62
     */
63
    public static function getRelationshipAsPropertyName(
64
        $value,
65
        $className,
66
        ReflectionClass $reflection,
67
        Driver $serializer
68
    ) {
69
        $methods = [];
70
        foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
71
            if (\ltrim($method->class, '\\') === \ltrim($className, '\\')) {
72
                $name = $method->name;
73
                $reflectionMethod = $reflection->getMethod($name);
74
75
                // Eloquent relations do not include parameters, so we'll be filtering based on this criteria.
76
                if (0 == $reflectionMethod->getNumberOfParameters()) {
77
                    try {
78
                        if (self::isAllowedEloquentModelFunction($name)) {
79
                            $returned = $reflectionMethod->invoke($value);
80
                            //All operations (eg: boolean operations) are now filtered out.
81
                            if (\is_object($returned)) {
82
83
                                // Only keep those methods as properties if these are returning Eloquent relations.
84
                                // But do not run the operation as it is an expensive operation.
85
                                if (self::isAnEloquentRelation($returned)) {
86
                                    $items = [];
87
                                    foreach ($returned->getResults() as $model) {
88
                                        if (\is_object($model)) {
89
                                            $items[] = self::getModelData($serializer, $model);
90
                                        }
91
                                    }
92
                                    if (!empty($items)) {
93
                                        $methods[$name] = [
94
                                            Serializer::MAP_TYPE => 'array',
95
                                            Serializer::SCALAR_VALUE => $items,
96
                                        ];
97
                                    }
98
                                }
99
                            }
100
                        }
101
                    } catch (ErrorException $e) {
102
                    }
103
                }
104
            }
105
        }
106
107
        return $methods;
108
    }
109
110
    /**
111
     * @param $name
112
     *
113
     * @return bool
114
     */
115
    protected static function isAllowedEloquentModelFunction($name)
116
    {
117
        return false === in_array($name, self::$forbiddenFunction, true);
118
    }
119
120
    /**
121
     * @param $returned
122
     *
123
     * @return bool
124
     */
125
    protected static function isAnEloquentRelation($returned)
126
    {
127
        return false !== strpos(get_class($returned), 'Illuminate\Database\Eloquent\Relations');
128
    }
129
130
    /**
131
     * @param Driver $serializer
132
     * @param Model  $model
133
     *
134
     * @return array
135
     */
136
    protected static function getModelData(Driver $serializer, Model $model)
137
    {
138
        $stdClass = (object) $model->getAttributes();
139
        $data = $serializer->serialize($stdClass);
140
        $data[Serializer::CLASS_IDENTIFIER_KEY] = get_class($model);
141
142
        return $data;
143
    }
144
}
145