RelationshipPropertyExtractor::getModelData()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 2
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
use Traversable;
12
13
class RelationshipPropertyExtractor
14
{
15
    /**
16
     * @var array
17
     */
18
    private static $forbiddenFunction = [
19
        'forceDelete',
20
        'forceFill',
21
        'delete',
22
        'newQueryWithoutScopes',
23
        'newQuery',
24
        'bootIfNotBooted',
25
        'boot',
26
        'bootTraits',
27
        'clearBootedModels',
28
        'query',
29
        'onWriteConnection',
30
        'delete',
31
        'forceDelete',
32
        'performDeleteOnModel',
33
        'flushEventListeners',
34
        'push',
35
        'touchOwners',
36
        'touch',
37
        'updateTimestamps',
38
        'freshTimestamp',
39
        'freshTimestampString',
40
        'newQuery',
41
        'newQueryWithoutScopes',
42
        'newBaseQueryBuilder',
43
        'usesTimestamps',
44
        'reguard',
45
        'isUnguarded',
46
        'totallyGuarded',
47
        'syncOriginal',
48
        'getConnectionResolver',
49
        'unsetConnectionResolver',
50
        'getEventDispatcher',
51
        'unsetEventDispatcher',
52
        '__toString',
53
        '__wakeup',
54
    ];
55
56
    /**
57
     * @param $value
58
     * @param $className
59
     * @param ReflectionClass $reflection
60
     * @param Driver          $serializer
61
     *
62
     * @return array
63
     */
64
    public static function getRelationshipAsPropertyName(
65
        $value,
66
        $className,
67
        ReflectionClass $reflection,
68
        Driver $serializer
69
    ) {
70
        $methods = [];
71
        foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
72
            if (ltrim($method->class, '\\') !== ltrim($className, '\\')) {
73
                continue;
74
            }
75
76
            $name = $method->name;
77
            $reflectionMethod = $reflection->getMethod($name);
78
79
            if (!self::isAllowedEloquentModelFunction($name) || $reflectionMethod->getNumberOfParameters() > 0) {
80
                continue;
81
            }
82
83
            if (in_array($name, $value->getHidden(), true)) {
84
                continue;
85
            }
86
87
            try {
88
                $returned = $reflectionMethod->invoke($value);
89
90
                if (!(\is_object($returned) && self::isAnEloquentRelation($returned))) {
91
                    continue;
92
                }
93
94
                $relationData = $returned->getResults();
95
96
                if ($relationData instanceof Traversable) {
97
                    //Something traversable with Models
98
                    $items = [];
99
100
                    foreach ($relationData as $model) {
101
                        if ($model instanceof Model) {
102
                            $items[] = self::getModelData($serializer, $model);
103
                        }
104
                    }
105
106
                    $methods[$name] = [
107
                        Serializer::MAP_TYPE => 'array',
108
                        Serializer::SCALAR_VALUE => $items,
109
                    ];
110
                } elseif ($relationData instanceof Model) {
111
                    //Single element returned.
112
                    $methods[$name] = self::getModelData($serializer, $relationData);
113
                }
114
115
            } catch (ErrorException $e) {
116
            }
117
        }
118
119
        return $methods;
120
    }
121
122
    /**
123
     * @param $name
124
     *
125
     * @return bool
126
     */
127
    protected static function isAllowedEloquentModelFunction($name)
128
    {
129
        return false === in_array($name, self::$forbiddenFunction, true);
130
    }
131
132
    /**
133
     * @param $returned
134
     *
135
     * @return bool
136
     */
137
    protected static function isAnEloquentRelation($returned)
138
    {
139
        return false !== strpos(get_class($returned), 'Illuminate\Database\Eloquent\Relations');
140
    }
141
142
    /**
143
     * @param Driver $serializer
144
     * @param Model  $model
145
     *
146
     * @return array
147
     */
148
    protected static function getModelData(Driver $serializer, Model $model)
149
    {
150
        $stdClass = (object) $model->attributesToArray();
151
        $data = $serializer->serialize($stdClass);
152
        $data[Serializer::CLASS_IDENTIFIER_KEY] = get_class($model);
153
154
        return $data;
155
    }
156
}
157