Passed
Pull Request — master (#221)
by Christopher
11:00 queued 03:55
created

MetadataRelationsTrait::addRelationsHook()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 10
c 2
b 0
f 0
dl 0
loc 22
rs 9.9332
cc 3
nc 4
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: alex
5
 * Date: 13/02/20
6
 * Time: 1:08 PM.
7
 */
8
namespace AlgoWeb\PODataLaravel\Models;
9
10
use Illuminate\Database\Eloquent\Model;
11
use Illuminate\Database\Eloquent\Relations\BelongsTo;
12
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
13
use Illuminate\Database\Eloquent\Relations\MorphMany;
14
use Illuminate\Database\Eloquent\Relations\MorphOne;
15
use Illuminate\Database\Eloquent\Relations\MorphToMany;
16
use Illuminate\Database\Eloquent\Relations\Relation;
17
use Mockery\Mock;
18
use POData\Common\InvalidOperationException;
19
20
trait MetadataRelationsTrait
21
{
22
23
    /**
24
     * Get model's relationships.
25
     *
26
     * @throws InvalidOperationException
27
     * @throws \ReflectionException
28
     * @return array
29
     */
30
    public function getRelationships()
31
    {
32
        return  $this->getRelationshipsFromMethods();
33
    }
34
35
    /**
36
     * @param  \ReflectionMethod         $method
37
     * @throws InvalidOperationException
38
     * @return string
39
     */
40
    protected function getCodeForMethod(\ReflectionMethod $method) : string
41
    {
42
        $fileName = $method->getFileName();
43
44
        $file = new \SplFileObject($fileName);
45
        $file->seek($method->getStartLine() - 1);
46
        $code = '';
47
        while ($file->key() < $method->getEndLine()) {
48
            $code .= $file->current();
49
            $file->next();
50
        }
51
52
        $code = trim(preg_replace('/\s\s+/', '', $code));
53
        if (false === stripos($code, 'function')) {
54
            $msg = 'Function definition must have keyword \'function\'';
55
            throw new InvalidOperationException($msg);
56
        }
57
        $begin = strpos($code, 'function(');
58
        $code = substr($code, $begin, strrpos($code, '}') - $begin + 1);
59
        $lastCode = $code[strlen($code) - 1];
60
        if ('}' != $lastCode) {
61
            $msg = 'Final character of function definition must be closing brace';
62
            throw new InvalidOperationException($msg);
63
        }
64
        return $code;
65
    }
66
    /**
67
     * @param  Model $model
68
     * @return array
69
     */
70
    protected function getModelClassMethods(Model $model)
71
    {
72
        // TODO: Handle case when Mock::class not present
73
        return array_diff(
74
            get_class_methods($model),
75
            get_class_methods(\Illuminate\Database\Eloquent\Model::class),
76
            get_class_methods(Mock::class),
77
            get_class_methods(MetadataTrait::class)
78
        );
79
    }
80
    /**
81
     * @param bool $biDir
82
     *
83
     * @throws InvalidOperationException
84
     * @throws \ReflectionException
85
     * @return array
86
     */
87
    protected function getRelationshipsFromMethods()
88
    {
89
        /*$biDirVal = true;
90
        $isCached = isset(static::$relationCategories[$biDirVal]) && !empty(static::$relationCategories[$biDirVal]);
91
        if ($isCached) {
92
            return static::$relationCategories[$biDirVal];
93
        }*/
94
        $relationships = [];
95
        /** @var Model $model */
96
        $model = $this;
97
        $methods = $this->getModelClassMethods($model);
98
        foreach ($methods as $method) {
99
            //Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php
100
            $reflection = new \ReflectionMethod($model, $method);
101
            $code = $this->getCodeForMethod($reflection);
102
            foreach (static::$relTypes as $relation) {
103
                //Resolve the relation's model to a Relation object.
104
                if (
105
                    !stripos($code, sprintf('$this->%s(', $relation)) ||
106
                    !(($relationObj = $model->$method()) instanceof Relation) ||
107
                    !in_array(MetadataTrait::class, class_uses($relationObj->getRelated()))
108
                ) {
109
                    continue;
110
                }
111
                $relationships[]= $method;
112
            }
113
        }
114
        return $relationships;
115
    }
116
}
117