Test Failed
Pull Request — master (#101)
by Alex
03:43
created

MetadataControllerTrait::getMethodName()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 42
Code Lines 23

Duplication

Lines 8
Ratio 19.05 %

Code Coverage

Tests 23
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 8
loc 42
ccs 23
cts 23
cp 1
rs 6.7272
cc 7
eloc 23
nc 7
nop 2
crap 7
1
<?php
2
3
namespace AlgoWeb\PODataLaravel\Controllers;
4
5
use Illuminate\Routing\Controller as BaseController;
6
7
trait MetadataControllerTrait
8
{
9
    /*
10
     * Allowed crud verbs
11
     */
12
    protected $crudVerbs = ['create', 'read', 'update', 'delete'];
13
14
    /*
15
     * Optional crud verbs - if these are unset in mapping array, LaravelQuery drops through to default handler
16
     */
17
    protected $optionalVerbs = ['bulkCreate', 'bulkUpdate'];
18
19
    /*
20
     * Array to record mapping betweeen model-verb combos and names
21
     * First-level key is fully-qualified model name
22
     * (eg Alt\Swedish\Chef\Bork\Bork\Bork)
23
     * Second-level key is CRUD verb
24
     */
25
    protected $mapping;
26
27
    /*
28
     * Given model and verb, get method name and parameter list
29
     *
30 9
     * @param $modelName
31
     * @param $crudVerb
32
     * @return null|array
33 9
     * @throws \Exception
34
     */
35 9
    public function getMethodName($modelName, $crudVerb)
36
    {
37 8
        // enforce we're actually hooked up to a controller
38 1
        assert($this instanceof BaseController, get_class($this));
39
        // enforce that mapping is actually not empty
40
        assert(0 < count($this->mapping), 'Mapping array must not be empty');
41 7
42 1
        if (!array_key_exists($modelName, $this->mapping)) {
43
            throw new \Exception('Metadata mapping for model '.$modelName.' not defined');
44
        }
45 6
46 6
        $this->checkCrudVerbDefined($crudVerb);
47 1
        $isOptional = in_array($crudVerb, $this->optionalVerbs);
48
49
        $lookup = $this->mapping[$modelName];
50 5
        if (!is_array($lookup)) {
51 1
            throw new \Exception('Metadata mapping for model '.$modelName.' not an array');
52
        }
53 4
54 4
        if (!array_key_exists($crudVerb, $lookup)) {
55 1
            if ($isOptional) {
56
                // optional crud verbs don't have to be defined - so we can return null
57
                return null;
58 3
            }
59 1
            throw new \Exception('Metadata mapping for CRUD verb '.$crudVerb.' on model '.$modelName.' not defined');
60 1
        }
61 1
        $result = $lookup[$crudVerb];
62 View Code Duplication
        if (!isset($result)) {
63
            throw new \Exception('Metadata mapping for CRUD verb '.$crudVerb.' on model '.$modelName.' null');
64 2
        }
65 2
66 View Code Duplication
        if (!method_exists($this, $result)) {
67 2
            throw new \Exception(
68
                'Metadata target for CRUD verb '.$crudVerb.' on model '.$modelName.' does not exist'
69
            );
70 68
        }
71
72
        $class = get_class($this);
73 68
        $parmArray = $this->getParameterNames($result);
74
75 68
        return ['method' => $result, 'controller' => $class, 'parameters' => $parmArray];
76
    }
77 68
78
    public function getMappings()
79
    {
80 68
        // enforce we're actually hooked up to a controller
81 68
        assert($this instanceof BaseController, get_class($this));
82 1
        // enforce that mapping is actually not empty
83
        assert(!empty($this->mapping), 'Mapping array must not be empty');
84 68
85 68
        $allMappings = [];
86 1
87
        // check that mapping array is well formed and sane, rather than waiting to stab us with a spatula
88 68
        foreach ($this->mapping as $key => $map) {
89 1
            if (!is_array($map)) {
90
                throw new \Exception('Metadata mapping for model '.$key.' not an array');
91
            }
92 68
            foreach ($map as $verb => $method) {
93 1
                $this->checkCrudVerbDefined($verb);
94 1
                if (!isset($method)) {
95 1
                    throw new \Exception('Metadata mapping for CRUD verb '.$verb.' on model '.$key.' null');
96
                }
97 68
98 68
                if (!method_exists($this, $method)) {
99 68
                    throw new \Exception(
100 68
                        'Metadata target for CRUD verb '.$verb.' on model '.$key.' does not exist'
101
                    );
102 68
                }
103 68
                $parmArray = $this->getParameterNames($method);
104 68
                if (!array_key_exists($key, $allMappings)) {
105 68
                    $allMappings[$key] = [];
106 68
                }
107
108
                $class = get_class($this);
109
                $allMappings[$key][$verb] = ['method' => $method, 'controller' => $class, 'parameters' => $parmArray];
110
            }
111
        }
112
        // bolt on optional, undefined mappings - empty mappings will need to be deduplicated in metadata controller
113 68
        // provider
114
        $mapKeys = array_keys($this->mapping);
115 68
        foreach ($mapKeys as $map) {
116 68
            $undefined = array_diff($this->optionalVerbs, array_keys($this->mapping[$map]));
117 68
            foreach ($undefined as $undef) {
118 68
                $allMappings[$map][$undef] = null;
119 68
            }
120 68
        }
121 68
122 68
        return $allMappings;
123 68
    }
124
125 68
    /**
126 68
     * @param $result
127 68
     * @return array
128 68
     */
129 68
    protected function getParameterNames($result)
130
    {
131 68
        $parmArray = [];
132 68
        $reflec = new \ReflectionMethod($this, $result);
133
        $params = $reflec->getParameters();
134 68
        foreach ($params as $parm) {
135 68
            $detail = [];
136
            $detail['name'] = $parm->name;
137
            $classHint = $parm->getClass();
138
            $isRequest = false;
139
            if (null != $classHint) {
140
                // check to see if this is a request
141
                $className = $classHint->name;
142
                $class = new $className();
143
                $isRequest = $class instanceof \Illuminate\Http\Request;
144
                $detail['type'] = $className;
145
            }
146
147
            $detail['isRequest'] = $isRequest;
148
            $parmArray[$parm->name] = $detail;
149
        }
150
        return $parmArray;
151
    }
152
153
    /**
154
     * @param string $crudVerb
155
     * @throws \Exception
156
     */
157
    private function checkCrudVerbDefined($crudVerb)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
158
    {
159
        assert(is_string($crudVerb));
160
        $lowVerb = strtolower($crudVerb);
161
        if (!in_array($lowVerb, $this->crudVerbs) && !in_array($crudVerb, $this->optionalVerbs)) {
162
            throw new \Exception('CRUD verb ' . $crudVerb . ' not defined');
163
        }
164
    }
165
}
166