Passed
Branch master (30ae21)
by Gabor
03:15
created

EnvironmentManager::getSelectedApplicationUri()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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;
0 ignored issues
show
Coding Style Compatibility introduced by
The method setDomain() contains an exit expression.

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.

Loading history...
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