Completed
Push — master ( b47912...4eb3ae )
by ARCANEDEV
12s
created

Url::getAuthority()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
ccs 3
cts 3
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 Methods
19
     | -----------------------------------------------------------------
20
     */
21
22
    /**
23
     * Extract attributes for current url.
24
     *
25
     * @param  bool|false|string  $url
26
     *
27
     * @return array
28
     */
29 106
    public static function extractAttributes($url = false)
30
    {
31 106
        $parse = parse_url($url);
32 106
        $path  = isset($parse['path']) ? explode('/', $parse['path']) : [];
33 106
        $url   = [];
34
35 106
        foreach ($path as $segment) {
36 106
            if ( ! empty($segment)) $url[] = $segment;
37
        }
38
39
        /** @var \Illuminate\Routing\Router $router */
40 106
        $router = app('router');
41
42 106
        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 110
    public static function substituteAttributes(array $attributes, $uri)
54
    {
55 110
        foreach ($attributes as $key => $value) {
56 38
            if ($value instanceof RouteBindable)
57 2
                $value = $value->getWildcardValue();
58
59 38
            $uri = str_replace(['{'.$key.'?}', '{'.$key.'}'], $value, $uri);
60
        }
61
62
        // delete empty optional arguments that are not in the $attributes array
63 110
        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 92
    public static function unparse($parsed)
74
    {
75 92
        if (empty($parsed)) return '';
76
77 92
        $parsed = self::checkParsedUrl($parsed);
78
79 92
        $url  = self::getUrl($parsed);
80 92
        $url .= self::getQuery($parsed);
81 92
        $url .= self::getFragment($parsed);
82
83 92
        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 106
    private static function extractAttributesFromRoutes($url, $routes)
100
    {
101 106
        $attributes = [];
102
103 106
        foreach ($routes as $route) {
104
            /**
105
             * @var  \Illuminate\Routing\Route  $route
106
             * @var  \Illuminate\Http\Request   $request
107
             */
108 106
            $request = Request::create(implode('/', $url));
109
110 106
            if ( ! $route->matches($request))
111 106
                continue;
112
113 84
            $match = self::hasAttributesFromUriPath($url, $route->uri(), $attributes);
114
115 84
            if ($match)
116 84
                break;
117
        }
118
119 106
        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 84
    private static function hasAttributesFromUriPath($url, $path, &$attributes)
132
    {
133 84
        $i     = 0;
134 84
        $match = true;
135 84
        $path  = explode('/', $path);
136
137 84
        foreach ($path as $j => $segment) {
138 84
            if (isset($url[$i])) {
139 68
                if ($segment !== $url[$i]) {
140 32
                    self::extractAttributesFromSegment($url, $path, $i, $j, $segment, $attributes);
141
                }
142
143 68
                $i++;
144 68
                continue;
145
            }
146 40
            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 40
                break;
150
            }
151
        }
152
153 84
        if (isset($url[$i + 1]))
154
            $match = false;
155
156 84
        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 32
    private static function extractAttributesFromSegment($url, $path, $i, $j, $segment, &$attributes)
170
    {
171
        // Required parameters
172 32
        if (preg_match('/{[\w]+}/', $segment)) {
173 32
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
174 32
            $attributes[$attributeName] = $url[$i];
175
        }
176
177
        // Optional parameter
178
        if (
179 32
            preg_match('/{[\w]+\?}/', $segment) &&
180 32
            ( ! isset($path[$j + 1]) || $path[$j + 1] !== $url[$i])
181
        ) {
182 16
            $attributeName              = preg_replace(['/{/', '/\?/', '/}/'], '', $segment);
183 16
            $attributes[$attributeName] = $url[$i];
184
        }
185 32
    }
186
187
    /* -----------------------------------------------------------------
188
     |  Other Methods
189
     | -----------------------------------------------------------------
190
     */
191
192
    /**
193
     * Check parsed URL.
194
     *
195
     * @param  array  $parsed
196
     *
197
     * @return array
198
     */
199 92
    private static function checkParsedUrl(array $parsed)
200
    {
201 92
        $scheme   =& $parsed['scheme'];
202 92
        $user     =& $parsed['user'];
203 92
        $pass     =& $parsed['pass'];
204 92
        $host     =& $parsed['host'];
205 92
        $port     =& $parsed['port'];
206 92
        $path     =& $parsed['path'];
207 92
        $path     = '/'.ltrim($path, '/'); // If / is missing for path.
208 92
        $query    =& $parsed['query'];
209 92
        $fragment =& $parsed['fragment'];
210
211 92
        return compact(
212 92
            '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 92
    private static function getUrl(array $parsed)
224
    {
225 92
        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 92
    private static function getHierPart(array $parsed)
236
    {
237 92
        return strlen($authority = self::getAuthority($parsed))
238 92
            ? '//'.$authority.$parsed['path']
239 92
            : $parsed['path'];
240
    }
241
242
    /**
243
     * Get authority.
244
     *
245
     * @param  array  $parsed
246
     *
247
     * @return string
248
     */
249 92
    private static function getAuthority(array $parsed)
250
    {
251 92
        $host = self::getHost($parsed);
252
253 92
        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 92
    private static function getUserInfo(array $parsed)
264
    {
265 92
        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 92
    private static function getHost(array $parsed)
276
    {
277 92
        return empty((string) $parsed['port'])
278 92
            ? $parsed['host']
279 92
            : $parsed['host'].':'.$parsed['port'];
280
    }
281
282
    /**
283
     * Get Query.
284
     *
285
     * @param  array  $parsed
286
     *
287
     * @return string
288
     */
289 92
    private static function getQuery(array $parsed)
290
    {
291 92
        return strlen($parsed['query']) ? '?'.$parsed['query'] : '';
292
    }
293
294
    /**
295
     * Get fragment.
296
     *
297
     * @param  array  $parsed
298
     *
299
     * @return string
300
     */
301 92
    private static function getFragment(array $parsed)
302
    {
303 92
        return strlen($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
304
    }
305
}
306