Completed
Push — master ( 3840d4...4b3c44 )
by ARCANEDEV
14s
created

Url::checkParsedUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 1
dl 0
loc 16
ccs 12
cts 12
cp 1
crap 1
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 Methods
19
     | -----------------------------------------------------------------
20
     */
21
22
    /**
23
     * Extract attributes for current url.
24
     *
25
     * @param  bool|false|string  $url
26
     *
27
     * @return array
28
     */
29 159
    public static function extractAttributes($url = false)
30
    {
31 159
        $parse = parse_url($url);
32 159
        $path  = isset($parse['path']) ? explode('/', $parse['path']) : [];
33 159
        $url   = [];
34
35 159
        foreach ($path as $segment) {
36 159
            if ( ! empty($segment)) $url[] = $segment;
37
        }
38
39
        /** @var \Illuminate\Routing\Router $router */
40 159
        $router = app('router');
41
42 159
        return self::extractAttributesFromRoutes($url, $router->getRoutes());
43
    }
44
45
    /**
46
     * Change uri attributes (wildcards) for the ones in the $attributes array.
47
     *
48
     * @param  array   $attributes
49
     * @param  string  $uri
50
     *
51
     * @return string
52
     */
53 165
    public static function substituteAttributes(array $attributes, $uri)
54
    {
55 165
        foreach ($attributes as $key => $value) {
56 57
            if ($value instanceof RouteBindable)
57 3
                $value = $value->getWildcardValue();
58
59 57
            $uri = str_replace(['{'.$key.'?}', '{'.$key.'}'], $value, $uri);
60
        }
61
62
        // delete empty optional arguments that are not in the $attributes array
63 165
        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 138
    public static function unparse($parsed)
74
    {
75 138
        if (empty($parsed)) return '';
76
77 138
        $parsed = self::checkParsedUrl($parsed);
78
79 138
        $url  = self::getUrl($parsed);
80 138
        $url .= self::getQuery($parsed);
81 138
        $url .= self::getFragment($parsed);
82
83 138
        return $url;
84
    }
85
86
    /* -----------------------------------------------------------------
87
     |  Extract Methods
88
     | -----------------------------------------------------------------
89
     */
90
91
    /**
92
     * Extract attributes from routes.
93
     *
94
     * @param  array                                $url
95
     * @param  \Illuminate\Routing\RouteCollection  $routes
96
     *
97
     * @return array
98
     */
99 159
    private static function extractAttributesFromRoutes($url, $routes)
100
    {
101 159
        $attributes = [];
102
103 159
        foreach ($routes as $route) {
104
            /**
105
             * @var  \Illuminate\Routing\Route  $route
106
             * @var  \Illuminate\Http\Request   $request
107
             */
108 159
            $request = Request::create(implode('/', $url));
109
110 159
            if ( ! $route->matches($request))
111 159
                continue;
112
113 126
            $match = self::hasAttributesFromUriPath($url, $route->uri(), $attributes);
114
115 126
            if ($match)
116 118
                break;
117
        }
118
119 159
        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 126
    private static function hasAttributesFromUriPath($url, $path, &$attributes)
132
    {
133 126
        $i     = 0;
134 126
        $match = true;
135 126
        $path  = explode('/', $path);
136
137 126
        foreach ($path as $j => $segment) {
138 126
            if (isset($url[$i])) {
139 102
                if ($segment !== $url[$i]) {
140 48
                    self::extractAttributesFromSegment($url, $path, $i, $j, $segment, $attributes);
141
                }
142
143 102
                $i++;
144 102
                continue;
145
            }
146 60
            elseif ( ! preg_match('/{[\w]+\?}/', $segment)) {
147
                // No optional parameters but no more $url given this route does not match the url
148 36
                $match = false;
149 52
                break;
150
            }
151
        }
152
153 126
        if (isset($url[$i + 1]))
154
            $match = false;
155
156 126
        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 48
    private static function extractAttributesFromSegment($url, $path, $i, $j, $segment, &$attributes)
170
    {
171
        // Required parameters
172 48
        if (preg_match('/{[\w]+}/', $segment)) {
173 48
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
174 48
            $attributes[$attributeName] = $url[$i];
175
        }
176
177
        // Optional parameter
178
        if (
179 48
            preg_match('/{[\w]+\?}/', $segment) &&
180 40
            ( ! isset($path[$j + 1]) || $path[$j + 1] !== $url[$i])
181
        ) {
182 24
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
183 24
            $attributes[$attributeName] = $url[$i];
184
        }
185 48
    }
186
187
    /* -----------------------------------------------------------------
188
     |  Other Methods
189
     | -----------------------------------------------------------------
190
     */
191
192
    /**
193
     * Check parsed URL.
194
     *
195
     * @param  array  $parsed
196
     *
197
     * @return array
198
     */
199 138
    private static function checkParsedUrl(array $parsed)
200
    {
201 138
        $scheme   =& $parsed['scheme'];
202 138
        $user     =& $parsed['user'];
203 138
        $pass     =& $parsed['pass'];
204 138
        $host     =& $parsed['host'];
205 138
        $port     =& $parsed['port'];
206 138
        $path     =& $parsed['path'];
207 138
        $path     = '/'.ltrim($path, '/'); // If / is missing for path.
208 138
        $query    =& $parsed['query'];
209 138
        $fragment =& $parsed['fragment'];
210
211 138
        return compact(
212 138
            'scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'
213
        );
214
    }
215
216
    /**
217
     * Get URL.
218
     *
219
     * @param  array  $parsed
220
     *
221
     * @return string
222
     */
223 138
    private static function getUrl(array $parsed)
224
    {
225 138
        return strlen($parsed['scheme']) ? $parsed['scheme'].':'.self::getHierPart($parsed) : '';
226
    }
227
228
    /**
229
     * Get hier part.
230
     *
231
     * @param  array  $parsed
232
     *
233
     * @return string
234
     */
235 138
    private static function getHierPart(array $parsed)
236
    {
237 138
        return strlen($authority = self::getAuthority($parsed))
238 138
            ? '//'.$authority.$parsed['path']
239 138
            : $parsed['path'];
240
    }
241
242
    /**
243
     * Get authority.
244
     *
245
     * @param  array  $parsed
246
     *
247
     * @return string
248
     */
249 138
    private static function getAuthority(array $parsed)
250
    {
251 138
        $host = self::getHost($parsed);
252
253 138
        return strlen($userInfo = self::getUserInfo($parsed)) ? $userInfo.'@'.$host : $host;
254
    }
255
256
    /**
257
     * Get user info.
258
     *
259
     * @param  array  $parsed
260
     *
261
     * @return string
262
     */
263 138
    private static function getUserInfo(array $parsed)
264
    {
265 138
        return strlen($parsed['pass']) ? $parsed['user'].':'.$parsed['pass'] : '';
266
    }
267
268
    /**
269
     * Get host.
270
     *
271
     * @param  array  $parsed
272
     *
273
     * @return string
274
     */
275 138
    private static function getHost(array $parsed)
276
    {
277 138
        return empty((string) $parsed['port'])
278 138
            ? $parsed['host']
279 138
            : $parsed['host'].':'.$parsed['port'];
280
    }
281
282
    /**
283
     * Get Query.
284
     *
285
     * @param  array  $parsed
286
     *
287
     * @return string
288
     */
289 138
    private static function getQuery(array $parsed)
290
    {
291 138
        return strlen($parsed['query']) ? '?'.$parsed['query'] : '';
292
    }
293
294
    /**
295
     * Get fragment.
296
     *
297
     * @param  array  $parsed
298
     *
299
     * @return string
300
     */
301 138
    private static function getFragment(array $parsed)
302
    {
303 138
        return strlen($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
304
    }
305
}
306