Apache::__invoke()   C
last analyzed

Complexity

Conditions 8
Paths 25

Size

Total Lines 111

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 111
ccs 0
cts 78
cp 0
rs 6.7555
c 0
b 0
f 0
cc 8
nc 25
nop 1
crap 72

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * admin
5
 *
6
 * @category    Tollwerk
7
 * @package     Tollwerk\Admin
8
 * @subpackage  Tollwerk\Admin\Infrastructure\Persistence
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\Infrastructure\Persistence;
38
39
use Psr\Log\LogLevel;
40
use Tollwerk\Admin\Domain\Account\AccountInterface;
41
use Tollwerk\Admin\Domain\Vhost\Vhost;
42
use Tollwerk\Admin\Domain\Vhost\VhostInterface;
43
use Tollwerk\Admin\Infrastructure\App;
44
use Tollwerk\Admin\Infrastructure\Factory\CertbotServiceFactory;
45
use Tollwerk\Admin\Infrastructure\Service\TemplateService;
46
47
/**
48
 * Apache persister
49
 *
50
 * @package Tollwerk\Admin
51
 * @subpackage Tollwerk\Admin\Infrastructure
52
 */
53
class Apache
54
{
55
    /**
56
     * Account
57
     *
58
     * @var AccountInterface
59
     */
60
    protected $account;
61
    /**
62
     * Configuration
63
     *
64
     * @var array
65
     */
66
    protected $config;
67
    /**
68
     * Account helper
69
     *
70
     * @var AccountHelper
71
     */
72
    protected $helper;
73
74
    /**
75
     * Constructor
76
     *
77
     * @param AccountInterface $account Account
78
     * @param array $config Configuration
79
     */
80
    public function __construct(AccountInterface $account, array $config)
81
    {
82
        $this->account = $account;
83
        $this->config = $config;
84
        $this->helper = new AccountHelper($this->account);
85
86
        // Add some directory names
87
        $this->config['dataroot'] = $this->helper->directory('data');
88
        $this->config['vhostroot'] = $this->helper->directory('config'.DIRECTORY_SEPARATOR.'vhosts-available');
89
        $this->config['logdir'] = $this->helper->directory('log');
90
        $this->config['account'] = $this->account->getName();
91
    }
92
93
    /**
94
     * Persist a virtual host
95
     *
96
     * @param VhostInterface $vhost Virtual host
97
     * @return array Files
98
     */
99
    public function __invoke(VhostInterface $vhost)
100
    {
101
        $files = [];
102
103
        $variables = $this->config;
104
        $variables['primary_domain'] = strval($vhost->getPrimaryDomain());
105
        $variables['primary_domain_pcre'] = preg_quote($variables['primary_domain']);
106
        $variables['secondary_domains'] = implode(' ', array_map('strval', $vhost->getSecondaryDomains()));
107
        $variables['secondary_domains_without_wildcards'] =
108
            implode(', ', array_map('strval', $vhost->getSecondaryDomains(true)));
109
        $variables['docroot'] =
110
            rtrim($this->config['dataroot'].DIRECTORY_SEPARATOR.$vhost->getDocroot(), DIRECTORY_SEPARATOR);
111
        $variables['configroot'] = $this->config['vhostroot'].DIRECTORY_SEPARATOR.$variables['primary_domain'];
112
        $variables['php_version'] = $vhost->getPhp();
113
114
        // If the virtual host should redirect
115
        if ($vhost->getRedirectUrl() !== null) {
116
            // TODO: Redirect
117
118
            return $files;
119
        }
120
121
        // If the virtual host should support PHP
122
        if ($vhost->getPhp() !== null) {
123
            $this->createPhpConfig($vhost, $files, $variables);
124
        }
125
126
        // Add the virtual host include
127
        $this->addEntry($files, 'apache_vhost.include', TemplateService::render('apache_vhost.include', $variables));
128
        $this->addEntry(
129
            $files,
130
            'apache_vhost_custom_directory.include?',
131
            TemplateService::render('apache_vhost_custom_directory.include', $variables)
132
        );
133
        $this->addEntry(
134
            $files,
135
            'apache_vhost_custom_all.include?',
136
            TemplateService::render('apache_vhost_all.include', $variables)
137
        );
138
139
        // If the HTTPS protocol is supported
140
        $httpsPorts = $vhost->getPorts(Vhost::PROTOCOL_HTTPS);
141
        if (!empty($httpsPorts)) {
142
            $certbotConfig = $this->helper->vhostDirectory($vhost).DIRECTORY_SEPARATOR.'certbot.ini';
143
            $certbotService = CertbotServiceFactory::create($certbotConfig);
144
            $primaryDomainIsCertified = $certbotService->isCertified($variables['primary_domain']);
145
146
            // Add the SSL configuration include
147
            $this->addEntry(
148
                $files,
149
                'apache_ssl.include',
150
                TemplateService::render('apache_ssl.include', $variables, !$primaryDomainIsCertified)
151
            );
152
153
            // Run through all SSL ports
154
            foreach ($httpsPorts as $httpsPort) {
155
156
                // Add the HTTPS vhost declaration
157
                $variables['port'] = $httpsPort;
158
                $variables['ssl'] = true;
159
                $this->addEntry(
160
                    $files, 'apache_vhost.conf',
161
                    TemplateService::render('apache_vhost.conf', $variables)
162
                );
163
                $this->addEntry($files, 'apache_vhost_custom_'.$httpsPort.'.include?', '');
164
            }
165
166
            // Add the Certbot configuration
167
            $this->addEntry(
168
                $files, 'certbot.ini',
169
                TemplateService::render('certbot.ini', $variables)
170
            );
171
172
            // Create the well-known symlink
173
            $certbotService->prepare($vhost, $this->helper);
174
175
            // Output a hint if the primary domain isn't certified
176
            if (!$primaryDomainIsCertified) {
177
                App::addMessage(
178
                    sprintf(
179
                        'The virtual host primary domain "%s" should be properly certified!',
180
                        $variables['primary_domain']
181
                    ),
182
                    LogLevel::NOTICE
183
                );
184
            }
185
        }
186
187
        // Run through all non-SSL ports
188
        foreach ((array)$vhost->getPorts(Vhost::PROTOCOL_HTTP) as $httpPort) {
189
190
            // Add the HTTP vhost declaration
191
            $variables['port'] = $httpPort;
192
            $variables['ssl'] = false;
193
            $this->addEntry(
194
                $files, 'apache_vhost.conf',
195
                TemplateService::render('apache_vhost.conf', $variables)
196
            );
197
            $this->addEntry(
198
                $files, 'apache_vhost_custom_'.$httpPort.'.include?',
199
                TemplateService::render('apache_vhost_http.include', $variables)
200
            );
201
        }
202
203
        $absoluteFiles = [];
204
        foreach ($files as $relativeFile => $fileContent) {
205
            $absoluteFiles[$this->helper->vhostDirectory($vhost).DIRECTORY_SEPARATOR.$relativeFile] =
206
                implode(PHP_EOL, (array)$fileContent);
207
        }
208
        return $absoluteFiles;
209
    }
210
211
    /**
212
     * Create a PHP configuration include
213
     *
214
     * @param VhostInterface $vhost Virtual host
215
     * @param array $files Configuration files
216
     * @param array $variables Templating variables
217
     */
218
    protected function createPhpConfig(VhostInterface $vhost, array &$files, array $variables)
219
    {
220
        $variables['pool'] = $variables['account'];
221
        if (strlen(trim($vhost->getDocroot()))) {
222
            $variables['pool'] .= '/'.$vhost->getDocroot();
223
        }
224
225
        // Add the FPM configuration
226
        $this->addEntry($files, 'fpm-'.$vhost->getPhp().'.conf', TemplateService::render('fpm.conf', $variables));
227
228
        // Add the FPM custom configuration
229
        $this->addEntry($files, 'fpm.include?', TemplateService::render('fpm.include', $variables));
230
231
        // Add the FPM include
232
        $this->addEntry(
233
            $files, 'apache_fmp.include',
234
            TemplateService::render('apache_fpm.include', $variables)
235
        );
236
    }
237
238
    /**
239
     * Add a file entry
240
     *
241
     * @param array $files Files
242
     * @param string $name File name
243
     * @param string $entry entry
244
     */
245
    protected function addEntry(&$files, $name, $entry)
246
    {
247
        if (empty($files[$name])) {
248
            $files[$name] = [];
249
        }
250
        $files[$name][] = $entry;
251
    }
252
}
253