Completed
Push — master ( bb58d0...11d1cc )
by ARCANEDEV
9s
created

Url::getUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 2
rs 9.4285
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 72
    public static function extractAttributes($url = false)
29
    {
30 72
        $parse  = parse_url($url);
31 72
        $path   = isset($parse['path']) ? explode('/', $parse['path']) : [];
32 72
        $url    = [];
33
34 72
        foreach ($path as $segment) {
35 72
            if ( ! empty($segment)) $url[] = $segment;
36 36
        }
37
38
        /** @var \Illuminate\Routing\Router $router */
39 72
        $router = app('router');
40
41 72
        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 80
    public static function substituteAttributes(array $attributes, $uri)
53
    {
54 80
        foreach ($attributes as $key => $value) {
55 24
            if ($value instanceof RouteBindable) {
56 8
                $value = $value->getWildcardValue();
57 4
            }
58
59 24
            $uri = str_replace(['{' . $key . '?}', '{' . $key . '}'], $value, $uri);
60 40
        }
61
62
        // delete empty optional arguments that are not in the $attributes array
63 80
        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 80
    public static function unparse($parsed)
74
    {
75 80
        if (empty($parsed)) return '';
76
77 80
        self::checkParsedUrl($parsed);
78
79 80
        $url  = self::getUrl($parsed);
80 80
        $url .= self::getQuery($parsed);
81 80
        $url .= self::getFragment($parsed);
82
83 80
        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 72
    private static function extractAttributesFromRoutes($url, $routes)
99
    {
100 72
        $attributes = [];
101
102 72
        foreach ($routes as $route) {
103
            /**
104
             * @var  \Illuminate\Routing\Route  $route
105
             * @var  \Illuminate\Http\Request   $request
106
             */
107 72
            $request = Request::create(implode('/', $url));
108
109 72
            if ( ! $route->matches($request)) {
110 72
                continue;
111
            }
112
113 64
            $match = self::hasAttributesFromUriPath($url, $route->getUri(), $attributes);
114
115 32
            if ($match)
116 64
                break;
117 36
        }
118
119 72
        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 64
    private static function hasAttributesFromUriPath($url, $path, &$attributes)
132
    {
133 64
        $i     = 0;
134 64
        $match = true;
135 64
        $path  = explode('/', $path);
136
137 64
        foreach ($path as $j => $segment) {
138 64
            if (isset($url[$i])) {
139 16
                if ($segment !== $url[$i]) {
140 8
                    self::extractAttributesFromSegment($url, $path, $i, $j, $segment, $attributes);
141 4
                }
142
143 16
                $i++;
144 16
                continue;
145
            }
146 64
            elseif ( ! preg_match('/{[\w]+\?}/', $segment)) {
147
                // No optional parameters but no more $url given this route does not match the url
148 64
                $match = false;
149 64
                break;
150
            }
151 32
        }
152
153 64
        if (isset($url[$i + 1]))
154 32
            $match = false;
155
156 64
        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 8
    private static function extractAttributesFromSegment($url, $path, $i, $j, $segment, &$attributes)
170
    {
171
        // Required parameters
172 8
        if (preg_match('/{[\w]+}/', $segment)) {
173 8
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
174 8
            $attributes[$attributeName] = $url[$i];
175 4
        }
176
177
        // Optional parameter
178
        if (
179 8
            preg_match('/{[\w]+\?}/', $segment) &&
180 8
            ( ! isset($path[$j + 1]) || $path[$j + 1] !== $url[$i])
181 4
        ) {
182 8
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
183 8
            $attributes[$attributeName] = $url[$i];
184 4
        }
185 8
    }
186
187
    /* ------------------------------------------------------------------------------------------------
188
     |  Unparse Functions
189
     | ------------------------------------------------------------------------------------------------
190
     */
191
    /**
192
     * Check parsed URL.
193
     *
194
     * @param  array  $parsed
195
     */
196 80
    private static function checkParsedUrl(array &$parsed)
197
    {
198 80
        $scheme    =& $parsed['scheme'];
199 80
        $user      =& $parsed['user'];
200 80
        $pass      =& $parsed['pass'];
201 80
        $host      =& $parsed['host'];
202 80
        $port      =& $parsed['port'];
203 80
        $path      =& $parsed['path'];
204 80
        $path      = '/' . ltrim($path, '/'); // If / is missing for path.
205 80
        $query     =& $parsed['query'];
206 80
        $fragment  =& $parsed['fragment'];
207
208 80
        $parsed    = compact(
209 80
            'scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'
210 40
        );
211 80
    }
212
213
    /**
214
     * Get URL.
215
     *
216
     * @param  array  $parsed
217
     *
218
     * @return string
219
     */
220 80
    private static function getUrl(array $parsed)
221
    {
222 80
        $url       = '';
223
224 80
        if (strlen($parsed['scheme'])) {
225 80
            $url = $parsed['scheme'] . ':' . self::getHierPart($parsed);
226 40
        }
227
228 80
        return $url;
229
    }
230
231
    /**
232
     * Get hier part.
233
     *
234
     * @param  array  $parsed
235
     *
236
     * @return string
237
     */
238 80
    private static function getHierPart(array $parsed)
239
    {
240 80
        $path      = $parsed['path'];
241 80
        $authority = self::getAuthority($parsed);
242
243 80
        if (strlen($authority)) {
244 80
            $path = '//' . $authority . $path;
245 40
        }
246
247 80
        return $path;
248
    }
249
250
    /**
251
     * Get authority.
252
     *
253
     * @param  array  $parsed
254
     *
255
     * @return string
256
     */
257 80
    private static function getAuthority(array $parsed)
258
    {
259 80
        $userInfo  = self::getUserInfo($parsed);
260 80
        $host      = self::getHost($parsed);
261
262 80
        if (strlen($userInfo)) {
263 8
            return $userInfo . '@' . $host;
264
        }
265
266 80
        return $host;
267
    }
268
269
    /**
270
     * Get user info.
271
     *
272
     * @param  array  $parsed
273
     *
274
     * @return string
275
     */
276 80
    private static function getUserInfo(array $parsed)
277
    {
278 80
        $userInfo = '';
279
280 80
        if (strlen($parsed['pass'])) {
281 8
            $userInfo = $parsed['user'] . ':' . $parsed['pass'];
282 4
        }
283
284 80
        return $userInfo;
285
    }
286
287
    /**
288
     * Get host.
289
     *
290
     * @param  array  $parsed
291
     *
292
     * @return string
293
     */
294 80
    private static function getHost(array $parsed)
295
    {
296 80
        $host = $parsed['host'];
297
298 80
        if ( ! empty((string) $parsed['port'])) {
299 8
            $host = $host . ':' . $parsed['port'];
300 4
        }
301
302 80
        return $host;
303
    }
304
305
    /**
306
     * Get Query.
307
     *
308
     * @param  array  $parsed
309
     *
310
     * @return string
311
     */
312 80
    private static function getQuery(array $parsed)
313
    {
314 80
        $query = '';
315
316 80
        if (strlen($parsed['query'])) {
317 8
            $query = '?' . $parsed['query'];
318 4
        }
319
320 80
        return $query;
321
    }
322
323
    /**
324
     * Get fragment.
325
     *
326
     * @param  array  $parsed
327
     *
328
     * @return string
329
     */
330 80
    private static function getFragment(array $parsed)
331
    {
332 80
        $fragment = '';
333
334 80
        if (strlen($parsed['fragment'])) {
335 8
            $fragment = '#' . $parsed['fragment'];
336 4
        }
337
338 80
        return $fragment;
339
    }
340
}
341