Vhost::disableProtocol()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
/**
4
 * admin
5
 *
6
 * @category    Tollwerk
7
 * @package     Tollwerk\Admin
8
 * @subpackage  Tollwerk\Admin\Domain\Vhost
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2018 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2018 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Tollwerk\Admin\Domain\Vhost;
38
39
use Tollwerk\Admin\Domain\Domain\DomainInterface;
40
41
/**
42
 * Virtual host
43
 *
44
 * @package Tollwerk\Admin
45
 * @subpackage Tollwerk\Admin\Domain
46
 */
47
class Vhost implements VhostInterface
48
{
49
    /**
50
     * Active account
51
     *
52
     * @var boolean
53
     */
54
    protected $active = false;
55
    /**
56
     * Primary domain
57
     *
58
     * @var DomainInterface
59
     */
60
    protected $primaryDomain;
61
    /**
62
     * Secondary domains
63
     *
64
     * @var DomainInterface[]
65
     */
66
    protected $secondaryDomains = [];
67
    /**
68
     * Document root
69
     *
70
     * @var string
71
     */
72
    protected $docroot;
73
    /**
74
     * Virtual host type
75
     *
76
     * @var string
77
     */
78
    protected $type = self::TYPE_APACHE;
79
    /**
80
     * Ports
81
     *
82
     * @var array
83
     */
84
    protected $ports = [];
85
    /**
86
     * Active PHP version
87
     *
88
     * @var null|string
89
     */
90
    protected $php = null;
91
    /**
92
     * Absolute URL to redirect to
93
     *
94
     * @var null|string
95
     */
96
    protected $redirectUrl = null;
97
    /**
98
     * Redirect status code
99
     *
100
     * @var int
101
     */
102
    protected $redirectStatus = self::REDIRECT_DEFAULT_STATUS;
103
    /**
104
     * Default port for HTTP virtual hosts
105
     *
106
     * @var int
107
     */
108
    const PORT_HTTP_DEFAULT = 80;
109
    /**
110
     * Default port for HTTPS virtual hosts
111
     *
112
     * @var int
113
     */
114
    const PORT_HTTPS_DEFAULT = 443;
115
    /**
116
     * Default redirect status
117
     *
118
     * @var int
119
     */
120
    const REDIRECT_DEFAULT_STATUS = 301;
121
    /**
122
     * HTTP protocol
123
     *
124
     * @var int
125
     */
126
    const PROTOCOL_HTTP = 1;
127
    /**
128
     * HTTPS protocol
129
     *
130
     * @var int
131
     */
132
    const PROTOCOL_HTTPS = 2;
133
    /**
134
     * Apache virtual host
135
     *
136
     * @var string
137
     */
138
    const TYPE_APACHE = 'apache';
139
    /**
140
     * Supported protocols
141
     *
142
     * @var array
143
     */
144
    public static $supportedProtocols = [
145
        self::PROTOCOL_HTTP => 'http',
146
        self::PROTOCOL_HTTPS => 'https',
147
    ];
148
    /**
149
     * Default protocol ports
150
     *
151
     * @var array
152
     */
153
    public static $defaultProtocolPorts = [
154
        self::PROTOCOL_HTTP => self::PORT_HTTP_DEFAULT,
155
        self::PROTOCOL_HTTPS => self::PORT_HTTPS_DEFAULT,
156
    ];
157
158
    /**
159
     * Virtual host constructor
160
     *
161
     * @param DomainInterface $primaryDomain Primary domain
162
     * @param string $docroot Document root
163
     * @param string $type Virtual host type
164
     * @internal param int $port Port
165
     */
166 10
    public function __construct(DomainInterface $primaryDomain, $docroot, $type = self::TYPE_APACHE)
167
    {
168 10
        $this->primaryDomain = $primaryDomain;
169 10
        $this->docroot = $docroot;
170 10
        $this->type = $type;
171 10
    }
172
173
    /**
174
     * Return whether the account is active
175
     *
176
     * @return boolean Active
177
     */
178
    public function isActive()
179
    {
180
        return $this->active;
181
    }
182
183
    /**
184
     * Set whether the account is active
185
     *
186
     * @param boolean $active Active
187
     * @return VhostInterface Self reference
188
     */
189
    public function setActive($active)
190
    {
191
        $this->active = $active;
192
        return $this;
193
    }
194
195
    /**
196
     * Return the primary domain
197
     *
198
     * @return DomainInterface Primary domain
199
     */
200 2
    public function getPrimaryDomain()
201
    {
202 2
        return $this->primaryDomain;
203
    }
204
205
    /**
206
     * Return the document root
207
     *
208
     * @return string Document root
209
     */
210 1
    public function getDocroot()
211
    {
212 1
        return $this->docroot;
213
    }
214
215
    /**
216
     * Return the virtual host type
217
     *
218
     * @return string Virtual host type
219
     */
220
    public function getType()
221
    {
222
        return $this->type;
223
    }
224
225
    /**
226
     * Return a ports list
227
     *
228
     * @param int|null $protocol Optional Protocol
229
     * @return array|null Ports list
230
     * @throws \RuntimeException If the requested protocol is unsupported
231
     */
232 3
    public function getPorts($protocol = null)
233
    {
234 3
        if ($protocol !== null) {
235 3
            $protocol = intval($protocol);
236
237
            // If the protocol is unsupported
238 3
            if (empty(self::$supportedProtocols[$protocol])) {
239 1
                throw new \RuntimeException(sprintf('Invalid protocol "%s"', $protocol), 1475484081);
240
            }
241
242 2
            return empty($this->ports[$protocol]) ? null : $this->ports[$protocol];
243
        }
244
245 1
        return $this->ports;
246
    }
247
248
    /**
249
     * Return the secondary domains
250
     *
251
     * @param bool $excludeWildcards Exclude wildcard domains
252
     * @return DomainInterface[] Secondary domains
253
     */
254 1
    public function getSecondaryDomains($excludeWildcards = false)
255
    {
256 1
        $secondaryDomains = array_values($this->secondaryDomains);
257
        return $excludeWildcards ?
258
            array_filter($secondaryDomains, function (DomainInterface $domain) {
259
                return !$domain->isWildcard();
260
            }) :
261 1
            $secondaryDomains;
262
    }
263
264
    /**
265
     * Set the secondary domains
266
     *
267
     * @param DomainInterface[] $secondaryDomains
268
     * @return Vhost Self reference
269
     * @throws \RuntimeException If the domain is invalid
270
     */
271 1
    public function setSecondaryDomains(array $secondaryDomains)
272
    {
273 1
        $this->secondaryDomains = [];
274
        /** @var DomainInterface $secondaryDomain */
275 1
        foreach ($secondaryDomains as $secondaryDomain) {
276
            // If the domain is invalid
277 1
            if (!is_object($secondaryDomain)
278 1
                || !(new \ReflectionClass($secondaryDomain))->implementsInterface(DomainInterface::class)
279 1
            ) {
280 1
                throw new \RuntimeException(sprintf('Invalid secondary domain "%s"', $secondaryDomain), 1475484852);
281
            }
282 1
            $this->secondaryDomains[strval($secondaryDomain)] = $secondaryDomain;
283 1
        }
284
285 1
        return $this;
286
    }
287
288
    /**
289
     * Add a secondary domain
290
     *
291
     * @param DomainInterface $secondaryDomain Secondary domain
292
     * @return Vhost Self reference
293
     */
294 1
    public function addSecondaryDomain(DomainInterface $secondaryDomain)
295
    {
296 1
        if (!array_key_exists(strval($secondaryDomain), $this->secondaryDomains)) {
297 1
            $this->secondaryDomains[strval($secondaryDomain)] = $secondaryDomain;
298 1
        }
299 1
        return $this;
300
    }
301
302
    /**
303
     * Remove a secondary domain
304
     *
305
     * @param DomainInterface $secondaryDomain Secondary domain
306
     * @return Vhost Self reference
307
     */
308 1
    public function removeSecondaryDomain(DomainInterface $secondaryDomain)
309
    {
310 1
        unset($this->secondaryDomains[strval($secondaryDomain)]);
311 1
        return $this;
312
    }
313
314
    /**
315
     * Return the active PHP version
316
     *
317
     * @return null|string Active PHP version
318
     */
319 1
    public function getPhp()
320
    {
321 1
        return $this->php;
322
    }
323
324
    /**
325
     * Set the active PHP version
326
     *
327
     * @param null|string $php Active PHP version
328
     * @return Vhost Self reference
329
     * @throws \RuntimeException If the PHP version is invalid
330
     */
331 1
    public function setPhp($php)
332
    {
333
        // If the PHP version is invalid
334 1
        if (($php !== null) && !preg_match('%^\d\.\d$%', $php)) {
335 1
            throw new \RuntimeException(sprintf('Invalid PHP version "%s"', $php), 1475485163);
336
        }
337
338 1
        $this->php = $php;
339 1
        return $this;
340
    }
341
342
    /**
343
     * Enable a port
344
     *
345
     * @param int $protocol Protocol
346
     * @param int $port Optional: Port (defaults to protocol specific port)
347
     * @return Vhost Self reference
348
     * @throws \RuntimeException If the protocol is unsupported
349
     * @throws \RuntimeException If the port is invalid
350
     */
351 2
    public function enablePort($protocol, $port = null)
352
    {
353 2
        $protocol = intval($protocol);
354
355
        // If the protocol is unsupported
356 2
        if (empty(self::$supportedProtocols[$protocol])) {
357
            throw new \RuntimeException(sprintf('Invalid protocol "%s"', $protocol), 1475484081);
358
        }
359
360
        // If the port is invalid
361 2
        $port = ($port === null) ? self::$defaultProtocolPorts[$protocol] : intval($port);
362 2
        if ($port <= 0) {
363 1
            throw new \RuntimeException(sprintf('Invalid port "%s"', $port), 1475502412);
364
        }
365
366
        // Create the protocol specific port list if necessary
367 1
        if (empty($this->ports[$protocol])) {
368 1
            $this->ports[$protocol] = [];
369 1
        }
370
371
        // Register the port
372 1
        $this->ports[$protocol] = array_unique(array_merge($this->ports[$protocol], [$port]));
373 1
        return $this;
374
    }
375
376
    /**
377
     * Disable a port
378
     *
379
     * @param int $port Port
380
     * @return Vhost Self reference
381
     * @throws \RuntimeException If the port is invalid
382
     */
383 1
    public function disablePort($port)
384
    {
385 1
        $port = intval($port);
386
387
        // If the port is invalid
388 1
        if ($port <= 0) {
389
            throw new \RuntimeException(sprintf('Invalid port "%s"', $port), 1475502412);
390
        }
391
392
        // Run through all protocols and delete the port
393 1
        foreach ($this->ports as $protocol => $ports) {
394 1
            $this->ports[$protocol] = array_values(array_diff($ports, [$port]));
395 1
        }
396 1
        return $this;
397
    }
398
399
    /**
400
     * Disable a supported protocol
401
     *
402
     * @param int $protocol Protocol
403
     * @return Vhost Self reference
404
     * @throws \RuntimeException If the protocol is unsupported
405
     */
406 2
    public function disableProtocol($protocol)
407
    {
408 2
        $protocol = intval($protocol);
409
410
        // If the protocol is unsupported
411 2
        if (empty(self::$supportedProtocols[$protocol])) {
412 1
            throw new \RuntimeException(sprintf('Invalid protocol "%s"', $protocol), 1475484081);
413
        }
414
415 1
        unset($this->ports[$protocol]);
416 1
        return $this;
417
    }
418
419
    /**
420
     * Return the redirect URL
421
     *
422
     * @return null|string Redirect URL
423
     */
424 1
    public function getRedirectUrl()
425
    {
426 1
        return $this->redirectUrl;
427
    }
428
429
    /**
430
     * Set the redirect URL
431
     *
432
     * @param null|string $redirectUrl Redirect URL
433
     * @return Vhost Self reference
434
     * @throws \RuntimeException If the redirect URL is invalid
435
     */
436 1
    public function setRedirectUrl($redirectUrl)
437
    {
438 1
        $redirectUrl = trim($redirectUrl) ?: null;
439
440
        // If the redirect URL is invalid
441 1
        if (($redirectUrl !== null) &&
442 1
            (!filter_var($redirectUrl, FILTER_VALIDATE_URL)
443 1
                || !in_array(strtolower(parse_url($redirectUrl, PHP_URL_SCHEME)), self::$supportedProtocols))
444 1
        ) {
445 1
            throw new \RuntimeException(sprintf('Invalid redirect URL "%s"', $redirectUrl), 1475486589);
446
        }
447
448 1
        $this->redirectUrl = $redirectUrl;
449 1
        return $this;
450
    }
451
452
    /**
453
     * Return the redirect HTTP status code
454
     *
455
     * @return int Redirect HTTP status code
456
     */
457 1
    public function getRedirectStatus()
458
    {
459 1
        return $this->redirectStatus;
460
    }
461
462
    /**
463
     * Set the redirect HTTP status code
464
     *
465
     * @param int $redirectStatus Redirect HTTP status code
466
     * @return Vhost Self reference
467
     * @throw \RuntimeException If the redirect HTTP status code is invalid
468
     */
469 1
    public function setRedirectStatus($redirectStatus)
470
    {
471
        // If the redirect HTTP status code is invalid
472 1
        if (!is_int($redirectStatus) || (($redirectStatus < 300) || ($redirectStatus > 308))) {
473 1
            throw new \RuntimeException(sprintf('Invalid redirect HTTP status code "%s"', $redirectStatus), 1475486679);
474
        }
475 1
        $this->redirectStatus = $redirectStatus;
476 1
        return $this;
477
    }
478
}
479