Completed
Push — master ( 04a8d9...c00a50 )
by ARCANEDEV
11s
created

Url::hasAttributesFromUriPath()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 16
nc 10
nop 3
dl 0
loc 27
ccs 18
cts 18
cp 1
crap 6
rs 8.439
c 0
b 0
f 0
1
<?php namespace Arcanedev\Localization\Utilities;
2
3
use Arcanedev\Localization\Contracts\RouteBindable;
4
use Arcanedev\Localization\Contracts\Url as UrlContract;
5
use Illuminate\Http\Request;
6
7
/**
8
 * Class     Url
9
 *
10
 * @package  Arcanedev\Localization\Utilities
11
 * @author   ARCANEDEV <[email protected]>
12
 *
13
 * @todo:    Refactoring
14
 */
15
class Url implements UrlContract
16
{
17
    /* ------------------------------------------------------------------------------------------------
18
     |  Main Functions
19
     | ------------------------------------------------------------------------------------------------
20
     */
21
    /**
22
     * Extract attributes for current url.
23
     *
24
     * @param  bool|false|string  $url
25
     *
26
     * @return array
27
     */
28 27
    public static function extractAttributes($url = false)
29
    {
30 27
        $parse  = parse_url($url);
31 27
        $path   = isset($parse['path']) ? explode('/', $parse['path']) : [];
32 27
        $url    = [];
33
34 27
        foreach ($path as $segment) {
35 27
            if ( ! empty($segment)) $url[] = $segment;
36 9
        }
37
38
        /** @var \Illuminate\Routing\Router $router */
39 27
        $router = app('router');
40
41 27
        return self::extractAttributesFromRoutes($url, $router->getRoutes());
42
    }
43
44
    /**
45
     * Change uri attributes (wildcards) for the ones in the $attributes array.
46
     *
47
     * @param  array   $attributes
48
     * @param  string  $uri
49
     *
50
     * @return string
51
     */
52 30
    public static function substituteAttributes(array $attributes, $uri)
53
    {
54 30
        foreach ($attributes as $key => $value) {
55 9
            if ($value instanceof RouteBindable) {
56 3
                $value = $value->getWildcardValue();
57 1
            }
58
59 9
            $uri = str_replace(['{' . $key . '?}', '{' . $key . '}'], $value, $uri);
60 10
        }
61
62
        // delete empty optional arguments that are not in the $attributes array
63 30
        return preg_replace('/\/{[^)]+\?}/', '', $uri);
64
    }
65
66
    /**
67
     * Build URL using array data from parse_url.
68
     *
69
     * @param  array|false  $parsed
70
     *
71
     * @return string
72
     */
73 30
    public static function unparse($parsed)
74
    {
75 30
        if (empty($parsed)) return '';
76
77 30
        self::checkParsedUrl($parsed);
78
79 30
        $url  = self::getUrl($parsed);
80 30
        $url .= self::getQuery($parsed);
81 30
        $url .= self::getFragment($parsed);
82
83 30
        return $url;
84
    }
85
86
    /* ------------------------------------------------------------------------------------------------
87
     |  Extract Functions
88
     | ------------------------------------------------------------------------------------------------
89
     */
90
    /**
91
     * Extract attributes from routes.
92
     *
93
     * @param  array                                $url
94
     * @param  \Illuminate\Routing\RouteCollection  $routes
95
     *
96
     * @return array
97
     */
98 27
    private static function extractAttributesFromRoutes($url, $routes)
99
    {
100 27
        $attributes = [];
101
102 27
        foreach ($routes as $route) {
103
            /**
104
             * @var  \Illuminate\Routing\Route  $route
105
             * @var  \Illuminate\Http\Request   $request
106
             */
107 27
            $request = Request::create(implode('/', $url));
108
109 27
            if ( ! $route->matches($request)) {
110 27
                continue;
111
            }
112
113 24
            $match = self::hasAttributesFromUriPath($url, $route->uri(), $attributes);
114
115 16
            if ($match)
116 18
                break;
117 9
        }
118
119 27
        return $attributes;
120
    }
121
122
    /**
123
     * Check if has attributes from a route.
124
     *
125
     * @param  array   $url
126
     * @param  string  $path
127
     * @param  array   $attributes
128
     *
129
     * @return bool
130
     */
131 24
    private static function hasAttributesFromUriPath($url, $path, &$attributes)
132
    {
133 24
        $i     = 0;
134 24
        $match = true;
135 24
        $path  = explode('/', $path);
136
137 24
        foreach ($path as $j => $segment) {
138 24
            if (isset($url[$i])) {
139 6
                if ($segment !== $url[$i]) {
140 3
                    self::extractAttributesFromSegment($url, $path, $i, $j, $segment, $attributes);
141 1
                }
142
143 6
                $i++;
144 6
                continue;
145
            }
146 24
            elseif ( ! preg_match('/{[\w]+\?}/', $segment)) {
147
                // No optional parameters but no more $url given this route does not match the url
148 24
                $match = false;
149 24
                break;
150
            }
151 8
        }
152
153 24
        if (isset($url[$i + 1]))
154 8
            $match = false;
155
156 24
        return $match;
157
    }
158
159
    /**
160
     * Extract attribute from a segment.
161
     *
162
     * @param  array   $url
163
     * @param  array   $path
164
     * @param  int     $i
165
     * @param  int     $j
166
     * @param  string  $segment
167
     * @param  array   $attributes
168
     */
169 3
    private static function extractAttributesFromSegment($url, $path, $i, $j, $segment, &$attributes)
170
    {
171
        // Required parameters
172 3
        if (preg_match('/{[\w]+}/', $segment)) {
173 3
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
174 3
            $attributes[$attributeName] = $url[$i];
175 1
        }
176
177
        // Optional parameter
178
        if (
179 3
            preg_match('/{[\w]+\?}/', $segment) &&
180 3
            ( ! isset($path[$j + 1]) || $path[$j + 1] !== $url[$i])
181 1
        ) {
182 3
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
183 3
            $attributes[$attributeName] = $url[$i];
184 1
        }
185 3
    }
186
187
    /* ------------------------------------------------------------------------------------------------
188
     |  Unparse Functions
189
     | ------------------------------------------------------------------------------------------------
190
     */
191
    /**
192
     * Check parsed URL.
193
     *
194
     * @param  array  $parsed
195
     */
196 30
    private static function checkParsedUrl(array &$parsed)
197
    {
198 30
        $scheme    =& $parsed['scheme'];
199 30
        $user      =& $parsed['user'];
200 30
        $pass      =& $parsed['pass'];
201 30
        $host      =& $parsed['host'];
202 30
        $port      =& $parsed['port'];
203 30
        $path      =& $parsed['path'];
204 30
        $path      = '/' . ltrim($path, '/'); // If / is missing for path.
205 30
        $query     =& $parsed['query'];
206 30
        $fragment  =& $parsed['fragment'];
207
208 30
        $parsed    = compact(
209 30
            'scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'
210 10
        );
211 30
    }
212
213
    /**
214
     * Get URL.
215
     *
216
     * @param  array  $parsed
217
     *
218
     * @return string
219
     */
220 30
    private static function getUrl(array $parsed)
221
    {
222 30
        $url       = '';
223
224 30
        if (strlen($parsed['scheme'])) {
225 30
            $url = $parsed['scheme'] . ':' . self::getHierPart($parsed);
226 10
        }
227
228 30
        return $url;
229
    }
230
231
    /**
232
     * Get hier part.
233
     *
234
     * @param  array  $parsed
235
     *
236
     * @return string
237
     */
238 30
    private static function getHierPart(array $parsed)
239
    {
240 30
        $path      = $parsed['path'];
241 30
        $authority = self::getAuthority($parsed);
242
243 30
        if (strlen($authority)) {
244 30
            $path = '//' . $authority . $path;
245 10
        }
246
247 30
        return $path;
248
    }
249
250
    /**
251
     * Get authority.
252
     *
253
     * @param  array  $parsed
254
     *
255
     * @return string
256
     */
257 30
    private static function getAuthority(array $parsed)
258
    {
259 30
        $userInfo  = self::getUserInfo($parsed);
260 30
        $host      = self::getHost($parsed);
261
262 30
        if (strlen($userInfo)) {
263 3
            return $userInfo . '@' . $host;
264
        }
265
266 30
        return $host;
267
    }
268
269
    /**
270
     * Get user info.
271
     *
272
     * @param  array  $parsed
273
     *
274
     * @return string
275
     */
276 30
    private static function getUserInfo(array $parsed)
277
    {
278 30
        $userInfo = '';
279
280 30
        if (strlen($parsed['pass'])) {
281 3
            $userInfo = $parsed['user'] . ':' . $parsed['pass'];
282 1
        }
283
284 30
        return $userInfo;
285
    }
286
287
    /**
288
     * Get host.
289
     *
290
     * @param  array  $parsed
291
     *
292
     * @return string
293
     */
294 30
    private static function getHost(array $parsed)
295
    {
296 30
        $host = $parsed['host'];
297
298 30
        if ( ! empty((string) $parsed['port'])) {
299 3
            $host = $host . ':' . $parsed['port'];
300 1
        }
301
302 30
        return $host;
303
    }
304
305
    /**
306
     * Get Query.
307
     *
308
     * @param  array  $parsed
309
     *
310
     * @return string
311
     */
312 30
    private static function getQuery(array $parsed)
313
    {
314 30
        $query = '';
315
316 30
        if (strlen($parsed['query'])) {
317 3
            $query = '?' . $parsed['query'];
318 1
        }
319
320 30
        return $query;
321
    }
322
323
    /**
324
     * Get fragment.
325
     *
326
     * @param  array  $parsed
327
     *
328
     * @return string
329
     */
330 30
    private static function getFragment(array $parsed)
331
    {
332 30
        $fragment = '';
333
334 30
        if (strlen($parsed['fragment'])) {
335 3
            $fragment = '#' . $parsed['fragment'];
336 1
        }
337
338 30
        return $fragment;
339
    }
340
}
341