1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* WebHemi. |
4
|
|
|
* |
5
|
|
|
* PHP version 5.6 |
6
|
|
|
* |
7
|
|
|
* @copyright 2012 - 2016 Gixx-web (http://www.gixx-web.com) |
8
|
|
|
* @license https://opensource.org/licenses/MIT The MIT License (MIT) |
9
|
|
|
* |
10
|
|
|
* @link http://www.gixx-web.com |
11
|
|
|
*/ |
12
|
|
|
namespace WebHemi\Application; |
13
|
|
|
|
14
|
|
|
use InvalidArgumentException; |
15
|
|
|
use WebHemi\Config\ConfigInterface; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class EnvironmentManager. |
19
|
|
|
*/ |
20
|
|
|
class EnvironmentManager |
21
|
|
|
{ |
22
|
|
|
const APPLICATION_TYPE_DIRECTORY = 'directory'; |
23
|
|
|
const APPLICATION_TYPE_DOMAIN = 'domain'; |
24
|
|
|
|
25
|
|
|
const COOKIE_AUTO_LOGIN_PREFIX = 'atln'; |
26
|
|
|
const COOKIE_SESSION_PREFIX = 'atsn'; |
27
|
|
|
|
28
|
|
|
const DEFAULT_APPLICATION = 'website'; |
29
|
|
|
const DEFAULT_APPLICATION_URI = '/'; |
30
|
|
|
const DEFAULT_MODULE = 'Website'; |
31
|
|
|
const DEFAULT_THEME = 'default'; |
32
|
|
|
const DEFAULT_THEME_RESOURCE_PATH = '/resources/default_theme'; |
33
|
|
|
|
34
|
|
|
const SESSION_SALT = 'WebHemi'; |
35
|
|
|
|
36
|
|
|
/** @var ConfigInterface */ |
37
|
|
|
private $config; |
38
|
|
|
/** @var string */ |
39
|
|
|
private $url; |
40
|
|
|
/** @var string */ |
41
|
|
|
private $subDomain; |
42
|
|
|
/** @var string */ |
43
|
|
|
private $mainDomain; |
44
|
|
|
/** @var string */ |
45
|
|
|
private $applicationDomain; |
46
|
|
|
/** @var string */ |
47
|
|
|
private $documentRoot; |
48
|
|
|
/** @var string */ |
49
|
|
|
private $selectedModule; |
50
|
|
|
/** @var string */ |
51
|
|
|
private $selectedApplication; |
52
|
|
|
/** @var string */ |
53
|
|
|
private $selectedApplicationUri; |
54
|
|
|
/** @var string */ |
55
|
|
|
private $selectedTheme; |
56
|
|
|
/** @var string */ |
57
|
|
|
private $selectedThemeResourcePath; |
58
|
|
|
/** @var array */ |
59
|
|
|
private $environmentData; |
60
|
|
|
/** @var bool */ |
61
|
|
|
private $isHttps; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* ModuleManager constructor. |
65
|
|
|
* |
66
|
|
|
* @param ConfigInterface $config |
67
|
|
|
* @param array $getData |
68
|
|
|
* @param array $postData |
69
|
|
|
* @param array $serverData |
70
|
|
|
* @param array $cookieData |
71
|
|
|
* @param array $filesData |
72
|
|
|
*/ |
73
|
9 |
|
public function __construct( |
74
|
|
|
ConfigInterface $config, |
75
|
|
|
array $getData, |
76
|
|
|
array $postData, |
77
|
|
|
array $serverData, |
78
|
|
|
array $cookieData, |
79
|
|
|
array $filesData |
80
|
|
|
) { |
81
|
9 |
|
$this->config = $config; |
82
|
9 |
|
$this->documentRoot = realpath(__DIR__.'/../../../'); |
83
|
|
|
|
84
|
9 |
|
$this->environmentData = [ |
85
|
9 |
|
'GET' => $getData, |
86
|
9 |
|
'POST' => $postData, |
87
|
9 |
|
'SERVER' => $serverData, |
88
|
9 |
|
'COOKIE' => $cookieData, |
89
|
9 |
|
'FILES' => $filesData, |
90
|
|
|
]; |
91
|
|
|
|
92
|
9 |
|
$this->isHttps = isset($this->environmentData['SERVER']['HTTPS']) && $this->environmentData['SERVER']['HTTPS']; |
93
|
9 |
|
$this->url = 'http'.($this->isHttps ? 's' : '').'://' |
94
|
9 |
|
.$this->environmentData['SERVER']['HTTP_HOST'] |
95
|
9 |
|
.$this->environmentData['SERVER']['REQUEST_URI']; // contains also the query string |
96
|
|
|
|
97
|
9 |
|
$this->selectedModule = self::DEFAULT_MODULE; |
98
|
9 |
|
$this->selectedApplication = self::DEFAULT_APPLICATION; |
99
|
9 |
|
$this->selectedTheme = self::DEFAULT_THEME; |
100
|
9 |
|
$this->selectedThemeResourcePath = self::DEFAULT_THEME_RESOURCE_PATH; |
101
|
9 |
|
$this->selectedApplicationUri = self::DEFAULT_APPLICATION_URI; |
102
|
|
|
|
103
|
9 |
|
$this->setDomain() |
104
|
9 |
|
->selectModuleApplicationAndTheme(); |
105
|
9 |
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Gets the application domain. |
109
|
|
|
* |
110
|
|
|
* @return string |
111
|
|
|
*/ |
112
|
|
|
public function getApplicationDomain() |
113
|
|
|
{ |
114
|
|
|
return $this->applicationDomain; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Gets the application SSL status. |
119
|
|
|
* |
120
|
|
|
* @return bool |
121
|
|
|
*/ |
122
|
|
|
public function isSecuredApplication() |
123
|
|
|
{ |
124
|
|
|
return $this->isHttps; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Gets the selected application. |
129
|
|
|
* |
130
|
|
|
* @return string |
131
|
|
|
*/ |
132
|
4 |
|
public function getSelectedApplication() |
133
|
|
|
{ |
134
|
4 |
|
return $this->selectedApplication; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Get the URI path for the selected application. Required for the RouterAdapter to work with directory-based |
139
|
|
|
* applications correctly. |
140
|
|
|
* |
141
|
|
|
* @return string |
142
|
|
|
*/ |
143
|
8 |
|
public function getSelectedApplicationUri() |
144
|
|
|
{ |
145
|
8 |
|
return $this->selectedApplicationUri; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Gets the selected module. |
150
|
|
|
* |
151
|
|
|
* @return string |
152
|
|
|
*/ |
153
|
6 |
|
public function getSelectedModule() |
154
|
|
|
{ |
155
|
6 |
|
return $this->selectedModule; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Gets the selected theme. |
160
|
|
|
* |
161
|
|
|
* @return string |
162
|
|
|
*/ |
163
|
5 |
|
public function getSelectedTheme() |
164
|
|
|
{ |
165
|
5 |
|
return $this->selectedTheme; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Gets the resource path for the selected theme. |
170
|
|
|
* |
171
|
|
|
* @return string |
172
|
|
|
*/ |
173
|
6 |
|
public function getResourcePath() |
174
|
|
|
{ |
175
|
6 |
|
return $this->selectedThemeResourcePath; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Gets environment data. |
180
|
|
|
* |
181
|
|
|
* @param string $key |
182
|
|
|
* |
183
|
|
|
* @return array |
184
|
|
|
*/ |
185
|
5 |
|
public function getEnvironmentData($key) |
186
|
|
|
{ |
187
|
5 |
|
if (!isset($this->environmentData[$key])) { |
188
|
1 |
|
throw new InvalidArgumentException(sprintf('The "%s" is not a valid environment key.', $key)); |
189
|
|
|
} |
190
|
|
|
|
191
|
5 |
|
return $this->environmentData[$key]; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Gets the template settings for a specific theme. |
196
|
|
|
* |
197
|
|
|
* @param string $theme |
198
|
|
|
* |
199
|
|
|
* @codeCoverageIgnore - @see \WebHemiTest\Config\ConfigTest |
200
|
|
|
* |
201
|
|
|
* @return ConfigInterface |
202
|
|
|
*/ |
203
|
|
|
public function getApplicationTemplateSettings($theme = self::DEFAULT_THEME) |
204
|
|
|
{ |
205
|
|
|
return $this->config->getConfig('themes/'.$theme); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Gets the routing settings for the selected module. |
210
|
|
|
* |
211
|
|
|
* @codeCoverageIgnore - @see \WebHemiTest\Config\ConfigTest |
212
|
|
|
* |
213
|
|
|
* @return ConfigInterface |
214
|
|
|
*/ |
215
|
|
|
public function getModuleRouteSettings() |
216
|
|
|
{ |
217
|
|
|
return $this->config->getConfig('modules/'.$this->getSelectedModule().'/routing'); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Parses server data and tries to set domain information. |
222
|
|
|
* |
223
|
|
|
* @return $this |
224
|
|
|
*/ |
225
|
9 |
|
private function setDomain() |
226
|
|
|
{ |
227
|
9 |
|
$domain = $this->environmentData['SERVER']['SERVER_NAME']; |
228
|
9 |
|
$subDomain = ''; |
229
|
9 |
|
$urlParts = parse_url($this->url); |
230
|
|
|
|
231
|
|
|
// If the host is not an IP address, then check the sub-domain-based module names too |
232
|
9 |
|
if (!preg_match( |
233
|
9 |
|
'/^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/', |
234
|
9 |
|
$urlParts['host'] |
235
|
9 |
|
)) { |
236
|
9 |
|
$domainParts = explode('.', $urlParts['host']); |
237
|
|
|
// @todo find out how to support complex TLDs like `.co.uk` or `.com.br` |
238
|
9 |
|
$tld = array_pop($domainParts); |
239
|
9 |
|
$domain = array_pop($domainParts).'.'.$tld; |
240
|
|
|
// the rest is the sub-domain |
241
|
9 |
|
$subDomain = implode('.', $domainParts); |
242
|
9 |
|
} |
243
|
|
|
|
244
|
|
|
// If no sub-domain presents, then it should be handled as 'www' |
245
|
9 |
|
if (empty($subDomain)) { |
246
|
7 |
|
$subDomain = 'www'; |
247
|
7 |
|
} |
248
|
|
|
|
249
|
9 |
|
$this->subDomain = $subDomain; |
250
|
9 |
|
$this->mainDomain = $domain; |
251
|
9 |
|
$this->applicationDomain = $this->subDomain.'.'. $this->mainDomain; |
252
|
|
|
|
253
|
|
|
// Redirecting when the app domain is not equal to the server data |
254
|
9 |
|
if (!defined('PHPUNIT_WEBHEMI_TESTSUITE') |
255
|
9 |
|
&& $this->environmentData['SERVER']['SERVER_NAME'] != $this->applicationDomain |
256
|
9 |
|
) { |
257
|
|
|
$schema = 'http'.($this->isHttps ? 's' : '').'://'; |
258
|
|
|
$uri = $this->environmentData['SERVER']['REQUEST_URI']; |
259
|
|
|
header('Location: '.$schema.$this->applicationDomain.$uri); |
260
|
|
|
exit; |
|
|
|
|
261
|
|
|
} |
262
|
|
|
|
263
|
9 |
|
return $this; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* From the parsed domain data, selects the application, module and theme. |
268
|
|
|
* |
269
|
|
|
* @return $this |
270
|
|
|
*/ |
271
|
9 |
|
private function selectModuleApplicationAndTheme() |
272
|
|
|
{ |
273
|
9 |
|
$urlParts = parse_url($this->url); |
274
|
9 |
|
$applications = $this->config->getData('applications'); |
275
|
|
|
|
276
|
|
|
// Only the first segment is important (if exists). |
277
|
9 |
|
list($subDirectory) = explode('/', ltrim($urlParts['path'], '/'), 2); |
278
|
|
|
|
279
|
|
|
$applicationDataFixture = [ |
280
|
9 |
|
'type' => self::APPLICATION_TYPE_DIRECTORY, |
281
|
9 |
|
'module' => self::DEFAULT_MODULE, |
282
|
9 |
|
'theme' => self::DEFAULT_THEME, |
283
|
9 |
|
]; |
284
|
|
|
|
285
|
|
|
// Run through the available application-modules to validate and find active module |
286
|
9 |
|
foreach ($applications as $applicationName => $applicationData) { |
287
|
|
|
// Don't risk, fix. |
288
|
9 |
|
$applicationData = array_merge($applicationDataFixture, $applicationData); |
289
|
|
|
|
290
|
9 |
|
if ($this->checkDirectoryIsValid($applicationName, $applicationData, $subDirectory) |
291
|
9 |
|
|| $this->checkDomainIsValid($applicationName, $applicationData, $subDirectory) |
292
|
9 |
|
) { |
293
|
3 |
|
$this->selectedModule = $applicationData['module']; |
294
|
3 |
|
$this->selectedApplication = (string)$applicationName; |
295
|
3 |
|
$this->selectedTheme = $applicationData['theme']; |
296
|
|
|
|
297
|
3 |
|
$this->selectedApplicationUri = '/'.$subDirectory; |
298
|
3 |
|
break; |
299
|
|
|
} |
300
|
9 |
|
} |
301
|
|
|
|
302
|
9 |
|
if ($this->selectedTheme !== self::DEFAULT_THEME) { |
303
|
1 |
|
$this->selectedThemeResourcePath = '/resources/vendor_themes/'.$this->selectedTheme; |
304
|
1 |
|
} |
305
|
|
|
|
306
|
9 |
|
return $this; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Checks from type, path it the current URI segment is valid. |
311
|
|
|
* |
312
|
|
|
* @param string $applicationName |
313
|
|
|
* @param array $applicationData |
314
|
|
|
* @param string $subDirectory |
315
|
|
|
* |
316
|
|
|
* @return bool |
317
|
|
|
*/ |
318
|
9 |
|
private function checkDirectoryIsValid($applicationName, $applicationData, $subDirectory) |
319
|
|
|
{ |
320
|
9 |
|
return $this->subDomain == 'www' |
321
|
9 |
|
&& $applicationName != 'website' |
322
|
9 |
|
&& !empty($subDirectory) |
323
|
9 |
|
&& $applicationData['type'] == self::APPLICATION_TYPE_DIRECTORY |
324
|
9 |
|
&& $applicationData['path'] == $subDirectory; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Checks from type and path if the domain is valid. If so, it sets the $subDirectory to the default. |
329
|
|
|
* |
330
|
|
|
* @param string $applicationName |
331
|
|
|
* @param array $applicationData |
332
|
|
|
* @param string $subDirectory |
333
|
|
|
* |
334
|
|
|
* @return bool |
335
|
|
|
*/ |
336
|
9 |
|
private function checkDomainIsValid($applicationName, $applicationData, &$subDirectory) |
337
|
|
|
{ |
338
|
|
|
$isSubdomain = $applicationName == 'website' |
339
|
9 |
|
|| ( |
340
|
9 |
|
$this->subDomain != 'www' |
341
|
9 |
|
&& $applicationData['type'] == self::APPLICATION_TYPE_DOMAIN |
342
|
9 |
|
&& $applicationData['path'] == $this->subDomain |
343
|
9 |
|
); |
344
|
|
|
|
345
|
|
|
// If this method get called and will return TRUE, it means the $subDirectory paramtere will be used only for |
346
|
|
|
// setting the right selectedApplicationUri. To avoid complexity, we change it here. Doesn't matter. |
347
|
9 |
|
if ($isSubdomain) { |
348
|
2 |
|
$subDirectory = ''; |
349
|
2 |
|
} |
350
|
|
|
|
351
|
9 |
|
return $isSubdomain; |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.