1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Ffcms\Core\Helper; |
4
|
|
|
|
5
|
|
|
use Ffcms\Core\App; |
6
|
|
|
use Ffcms\Core\Helper\HTML\System\NativeGenerator; |
7
|
|
|
use Ffcms\Core\Helper\Type\Arr; |
8
|
|
|
use Ffcms\Core\Helper\Type\Obj; |
9
|
|
|
use Ffcms\Core\Helper\Type\Str; |
10
|
|
|
|
11
|
|
|
class Url extends NativeGenerator |
12
|
|
|
{ |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Build link via controller/action and other params |
16
|
|
|
* @param string $controller_action |
17
|
|
|
* @param string|null $id |
18
|
|
|
* @param string|null $add |
19
|
|
|
* @param array $params |
20
|
|
|
* @param bool $encode |
21
|
|
|
* @return null|string |
22
|
|
|
*/ |
23
|
|
|
public static function to($controller_action, $id = null, $add = null, array $params = null, $encode = true) |
24
|
|
|
{ |
25
|
|
|
$pathway = self::buildPathway([$controller_action, $id, $add, $params], $encode); |
26
|
|
|
return App::$Alias->baseUrl . '/' . $pathway; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Build pathway from array $to. Example: ['controller/action', 'id', 'add', ['get' => 'value'], '#anchor'] |
31
|
|
|
* @param array $to |
32
|
|
|
* @param bool $encode |
33
|
|
|
* @return string|null |
34
|
|
|
*/ |
35
|
|
|
public static function buildPathway(array $to = null, $encode = true) |
36
|
|
|
{ |
37
|
|
|
|
38
|
|
|
// if empty passed - let show main page |
39
|
|
|
if ($to === null) { |
40
|
|
|
return null; |
41
|
|
|
} |
42
|
|
|
$response = Str::lowerCase(trim($to[0], '/')); // controller/action |
43
|
|
|
list($controller, $action) = explode('/', $response); |
44
|
|
|
|
45
|
|
|
$routing = App::$Properties->getAll('Routing'); |
46
|
|
|
// sounds like dynamic callback |
47
|
|
|
if (Str::startsWith('@', $controller)) { |
48
|
|
|
$controller = trim($controller, '@'); |
49
|
|
|
// search callback in properties |
50
|
|
|
if (isset($routing['Callback'][env_name]) && Arr::in($controller, $routing['Callback'][env_name])) { |
51
|
|
|
$pathInject = array_search($controller, $routing['Callback'][env_name]); |
52
|
|
|
// if path is founded - lets set source |
53
|
|
|
if ($pathInject !== false) { |
54
|
|
|
$controller = Str::lowerCase($pathInject); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
// if controller still looks like path injection - define last entity like controller name |
59
|
|
|
if (Str::contains('\\', $controller)) { |
60
|
|
|
$controller = Str::lastIn($controller, '\\', true); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
$response = $controller . '/' . $action; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
// check if controller and action is defined |
67
|
|
|
if (Str::likeEmpty($controller) || Str::likeEmpty($action)) { |
68
|
|
|
return null; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
// id is defined? |
72
|
|
View Code Duplication |
if (isset($to[1]) && !Str::likeEmpty($to[1])) { |
|
|
|
|
73
|
|
|
$response .= '/' . self::safeUri($to[1], $encode); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
// add param is defined? |
77
|
|
View Code Duplication |
if (isset($to[2]) && !Str::likeEmpty($to[2])) { |
|
|
|
|
78
|
|
|
$response .= '/' . self::safeUri($to[2], $encode); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
// try to find static alias |
82
|
|
|
if (isset($routing['Alias'][env_name]) && Arr::in('/' . $response, $routing['Alias'][env_name])) { |
83
|
|
|
$pathAlias = array_search('/' . $response, $routing['Alias'][env_name]); |
84
|
|
|
if ($pathAlias !== false) { |
85
|
|
|
$response = Str::lowerCase(trim($pathAlias, '/')); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
// parse get attributes |
90
|
|
|
if (isset($to[3]) && Obj::isArray($to[3]) && count($to[3]) > 0) { |
91
|
|
|
// check if anchor bindig is exist |
92
|
|
|
$anchor = false; |
93
|
|
|
if (isset($to[3]['#']) && Obj::isString($to[3]['#']) && Str::startsWith('#', $to[3]['#'])) { |
94
|
|
|
$anchor = $to[3]['#']; |
95
|
|
|
unset($to[3]['#']); |
96
|
|
|
} |
97
|
|
|
$queryString = http_build_query($to[3]); |
98
|
|
|
if (Str::length($queryString) > 0) { |
99
|
|
|
$response .= '?' . http_build_query($to[3]); |
100
|
|
|
} |
101
|
|
|
if ($anchor !== false) { |
102
|
|
|
$response .= $anchor; |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
// parse anchor link part #item-related-id-1 |
107
|
|
|
if (isset($to[4]) && Obj::isString($to[4]) && Str::startsWith('#', $to[4])) { |
108
|
|
|
$response .= $to[4]; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return $response; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Build current pathway with get data to compare in some methods |
116
|
|
|
* @return null|string |
117
|
|
|
*/ |
118
|
|
|
public static function buildPathwayFromRequest() |
119
|
|
|
{ |
120
|
|
|
return self::buildPathway([ |
121
|
|
|
Str::lowerCase(App::$Request->getController()) . '/' . Str::lowerCase(App::$Request->getAction()), |
122
|
|
|
App::$Request->getID(), |
123
|
|
|
App::$Request->getAdd(), |
124
|
|
|
App::$Request->query->all() |
125
|
|
|
]); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Create <a></a> block link |
130
|
|
|
* @param string|array $to |
131
|
|
|
* @param string $name |
132
|
|
|
* @param array|null $property |
133
|
|
|
* @return string |
134
|
|
|
*/ |
135
|
|
|
public static function link($to, $name, array $property = null) |
136
|
|
|
{ |
137
|
|
|
$compile_property = self::applyProperty($property); |
138
|
|
|
|
139
|
|
|
if (!Obj::isArray($to)) { // callback magic (: |
140
|
|
|
$to = [$to]; |
141
|
|
|
} |
142
|
|
|
// call Url::to(args) |
143
|
|
|
$callbackTo = call_user_func_array([__NAMESPACE__ . '\Url', 'to'], $to); |
144
|
|
|
|
145
|
|
|
return '<a href="' . $callbackTo . '"' . $compile_property . '>' . $name . '</a>'; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Build full URL link from URI string, if REQUEST data is not available (console, cron, etc) |
150
|
|
|
* @param string $uri |
151
|
|
|
* @param string|null $lang |
152
|
|
|
* @return string |
153
|
|
|
*/ |
154
|
|
|
public static function standaloneUrl($uri, $lang = null) |
155
|
|
|
{ |
156
|
|
|
/** @var array $configs */ |
157
|
|
|
$configs = \App::$Properties->getAll('default'); |
158
|
|
|
$httpHost = $configs['baseProto'] . '://' . $configs['baseDomain']; |
159
|
|
|
if ($configs['basePath'] !== '/') { |
160
|
|
|
$httpHost .= $configs['basePath'] . '/'; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
// check if is this is URI not URL |
164
|
|
|
if (!Str::startsWith($httpHost, $uri)) { |
165
|
|
|
// check if lang is defined in URI or define it |
166
|
|
|
if ($lang !== null && $configs['multiLanguage'] && !Str::startsWith($lang, $uri)) { |
167
|
|
|
$uri = $lang . '/' . ltrim($uri, '/'); |
168
|
|
|
} |
169
|
|
|
// add basic httpHost data |
170
|
|
|
$uri = rtrim($httpHost, '/') . '/' . ltrim($uri, '/'); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $uri; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Download remote content in binary string |
178
|
|
|
* @param string $url |
179
|
|
|
* @return null|string |
180
|
|
|
*/ |
181
|
|
|
public static function download($url) |
182
|
|
|
{ |
183
|
|
|
// check is valid url |
184
|
|
|
if (!filter_var($url, FILTER_VALIDATE_URL)) { |
185
|
|
|
return null; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
$content = null; |
|
|
|
|
189
|
|
|
if (function_exists('curl_version')) { |
190
|
|
|
$curl = \curl_init(); |
191
|
|
|
$userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)'; |
192
|
|
|
\curl_setopt($curl, CURLOPT_URL, $url); |
193
|
|
|
\curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); |
194
|
|
|
\curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); |
195
|
|
|
\curl_setopt($curl, CURLOPT_HEADER, 0); |
196
|
|
|
\curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); |
197
|
|
|
\curl_setopt($curl, CURLOPT_FAILONERROR, TRUE); |
198
|
|
|
\curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); |
199
|
|
|
\curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE); |
200
|
|
|
\curl_setopt($curl, CURLOPT_TIMEOUT, 10); |
201
|
|
|
$content = \curl_exec($curl); |
202
|
|
|
\curl_close($curl); |
203
|
|
|
} else { |
204
|
|
|
$content = @file_get_contents($url); |
205
|
|
|
} |
206
|
|
|
return $content; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.