ResourceRegistrar::getResourceWildcard()   B
last analyzed

Complexity

Conditions 7
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 10
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 7
rs 8.8333
1
<?php
2
3
namespace ShiftOneLabs\SingularResourceRoutes;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Routing\ResourceRegistrar as BaseResourceRegistrar;
7
8
class ResourceRegistrar extends BaseResourceRegistrar
9
{
10
    /**
11
     * The default actions for a singular resourceful controller.
12
     *
13
     * @var array
14
     */
15
    protected $singularResourceDefaults = ['create', 'store', 'show', 'edit', 'update', 'destroy'];
16
17
    /**
18
     * The resources to treat as singular.
19
     *
20
     * @var array
21
     */
22
    protected $singularResources = [];
23
24
    /**
25
     * Route a resource to a controller.
26
     *
27
     * @param  string  $name
28
     * @param  string  $controller
29
     * @param  array  $options
30
     *
31
     * @return void
32
     */
33 160
    public function register($name, $controller, array $options = [])
34
    {
35 160
        if (isset($options['parameters']) && !isset($this->parameters)) {
36 44
            $this->parameters = $options['parameters'];
37 4
        }
38
39
        // If the resource name contains a slash, we will assume the developer wishes to
40
        // register these resource routes with a prefix so we will set that up out of
41
        // the box so they don't have to mess with it. Otherwise, we will continue.
42 160
        if (Str::contains($name, '/')) {
43 58
            $this->prefixedResource($name, $controller, $options);
44
45 58
            return;
46
        }
47
48 160
        $resources = explode('.', $name);
49
50
        // If the singular option is set, we need to determine which resources are meant
51
        // to be singular resources. If set to true, then only the last resource will
52
        // be singular, otherwise intersect all resources with the given resources.
53 160
        if (!empty($options['singular'])) {
54 58
            $singular = $options['singular'];
55 58
            $this->singularResources = array_intersect(
56 58
                $resources,
57 58
                $singular === true ? [last($resources)] : (!is_array($singular) ? [$singular] : $singular)
58 8
            );
59 8
        }
60
61
        // We need to extract the base resource from the resource name. Nested resources
62
        // are supported in the framework, but we need to know what name to use for a
63
        // place-holder on the route parameters, which should be the base resources.
64 160
        $base = $this->getResourceWildcard(last($resources));
65
66 160
        $defaults = $this->getResourceDefaults(last($resources));
67
68 160
        foreach ($this->getResourceMethods($defaults, $options) as $m) {
69 160
            $this->{'addResource'.ucfirst($m)}($name, $base, $controller, $options);
70 20
        }
71 160
    }
72
73
    /**
74
     * Get the default resource methods defaults for the given resource.
75
     *
76
     * @param  string  $resource
77
     *
78
     * @return array
79
     */
80 160
    protected function getResourceDefaults($resource)
81
    {
82 160
        if (in_array($resource, $this->singularResources)) {
83 58
            return $this->singularResourceDefaults;
84
        }
85
86 160
        return $this->resourceDefaults;
87
    }
88
89
    /**
90
     * Add the show method for a resourceful route.
91
     *
92
     * @param  string  $name
93
     * @param  string  $base
94
     * @param  string  $controller
95
     * @param  array  $options
96
     *
97
     * @return \Illuminate\Routing\Route
98
     */
99 160
    protected function addResourceShow($name, $base, $controller, $options)
100
    {
101 160
        $uri = $this->getResourceUri($name).$this->getResourceUriParameter($base);
102
103 160
        $action = $this->getResourceAction($name, $controller, 'show', $options);
104
105 160
        return $this->router->get($uri, $action);
106
    }
107
108
    /**
109
     * Add the edit method for a resourceful route.
110
     *
111
     * @param  string  $name
112
     * @param  string  $base
113
     * @param  string  $controller
114
     * @param  array  $options
115
     *
116
     * @return \Illuminate\Routing\Route
117
     */
118 160
    protected function addResourceEdit($name, $base, $controller, $options)
119
    {
120 160
        $uri = $this->getResourceUri($name).$this->getResourceUriParameter($base).'/'.$this->getVerb('edit');
121
122 160
        $action = $this->getResourceAction($name, $controller, 'edit', $options);
123
124 160
        return $this->router->get($uri, $action);
125
    }
126
127
    /**
128
     * Add the update method for a resourceful route.
129
     *
130
     * @param  string  $name
131
     * @param  string  $base
132
     * @param  string  $controller
133
     * @param  array  $options
134
     *
135
     * @return \Illuminate\Routing\Route
136
     */
137 160
    protected function addResourceUpdate($name, $base, $controller, $options)
138
    {
139 160
        $uri = $this->getResourceUri($name).$this->getResourceUriParameter($base);
140
141 160
        $action = $this->getResourceAction($name, $controller, 'update', $options);
142
143 160
        return $this->router->match(['PUT', 'PATCH'], $uri, $action);
144
    }
145
146
    /**
147
     * Add the destroy method for a resourceful route.
148
     *
149
     * @param  string  $name
150
     * @param  string  $base
151
     * @param  string  $controller
152
     * @param  array  $options
153
     *
154
     * @return \Illuminate\Routing\Route
155
     */
156 160
    protected function addResourceDestroy($name, $base, $controller, $options)
157
    {
158 160
        $uri = $this->getResourceUri($name).$this->getResourceUriParameter($base);
159
160 160
        $action = $this->getResourceAction($name, $controller, 'destroy', $options);
161
162 160
        return $this->router->delete($uri, $action);
163
    }
164
165
    /**
166
     * Get the URI for a nested resource segment array.
167
     *
168
     * @param  array  $segments
169
     *
170
     * @return string
171
     */
172
    protected function getNestedResourceUri(array $segments)
173
    {
174
        // We will spin through the segments and create a place-holder for each of the
175
        // resource segments, as well as the resource itself. Then we should get an
176
        // entire string for the resource URI that contains all nested resources.
177 160
        return implode('/', array_map(function ($s) {
178 160
            return $s.$this->getResourceUriParameter($this->getResourceWildcard($s));
179 160
        }, $segments));
180
    }
181
182
    /**
183
     * Format a resource parameter for usage.
184
     *
185
     * @param  string  $value
186
     *
187
     * @return string|null
188
     */
189 160
    public function getResourceWildcard($value)
190
    {
191 160
        if (in_array($value, $this->singularResources)) {
192 58
            return;
193
        }
194
195
        // parameters/parameterMap properties do not exist until 5.2.20
196 160
        if (property_exists($this, 'parameters')) {
197 132
            if (isset($this->parameters[$value])) {
198 44
                $value = $this->parameters[$value];
199 132
            } elseif (isset(static::$parameterMap[$value])) {
200 44
                $value = static::$parameterMap[$value];
201 132
            } elseif ($this->parameters === 'singular' || static::$singularParameters) {
202 132
                $value = Str::singular($value);
203 12
            }
204 12
        }
205
206 160
        return str_replace('-', '_', $value);
207
    }
208
209
    /**
210
     * Get the parameter name as a resource URI parameter segment.
211
     *
212
     * @param  string  $value
213
     *
214
     * @return string
215
     */
216 160
    protected function getResourceUriParameter($value)
217
    {
218 160
        if (empty($value)) {
219 58
            return '';
220
        }
221
222 160
        return '/{'.$value.'}';
223
    }
224
225
    /**
226
     * Get the url verb for the specified verb.
227
     *
228
     * @return string
229
     */
230 160
    protected function getVerb($verb)
231
    {
232
        // verbs property does not exist until 5.3.27
233 160
        if (property_exists(get_class(), 'verbs') && !empty(static::$verbs[$verb])) {
234 111
            return static::$verbs[$verb];
235
        }
236
237 49
        return $verb;
238
    }
239
}
240