Completed
Pull Request — master (#1105)
by Tim
42:55
created

Setup   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 462
Duplicated Lines 9.52 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 44
loc 462
rs 9.52
c 0
b 0
f 0
wmc 36
lcom 1
cbo 0

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\Meta\Composer\Script\Setup
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/appserver
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Appserver\Meta\Composer\Script;
22
23
use Composer\Script\Event;
24
25
/**
26
 * Class that provides functionality that'll be executed by composer
27
 * after installation or update of the application server.
28
 *
29
 * @author    Tim Wagner <[email protected]>
30
 * @copyright 2015 TechDivision GmbH <[email protected]>
31
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
32
 * @link      https://github.com/appserver-io/appserver
33
 * @link      http://www.appserver.io
34
 */
35
class Setup
36
{
37
38
    /**
39
     * appserver.io written in ASCI art.
40
     *
41
     * @var string
42
     */
43
    protected static $logo = '                                                    _
44
  ____ _____  ____  ________  ______   _____  _____(_)___
45
 / __ `/ __ \/ __ \/ ___/ _ \/ ___/ | / / _ \/ ___/ / __ \
46
/ /_/ / /_/ / /_/ (__  )  __/ /   | |/ /  __/ /  / / /_/ /
47
\__,_/ .___/ .___/____/\___/_/    |___/\___/_(_)/_/\____/
48
    /_/   /_/
49
50
';
51
52
    /**
53
     * The array with the merged and os specific template variables.
54
     *
55
     * @var array
56
     */
57
    protected static $mergedProperties = array();
58
59
    /**
60
     * The available properties we used for parsing the template.
61
     *
62
     * @var array
63
     */
64
    protected static $defaultProperties = array(
65
        SetupKeys::PHP_VERSION                                   => PHP_VERSION,
66
        SetupKeys::ADMIN_EMAIL                                   => '[email protected]',
67
        SetupKeys::CONTAINER_SERVER_WORKER_ACCEPT_MIN            => 3,
68
        SetupKeys::CONTAINER_SERVER_WORKER_ACCEPT_MAX            => 8,
69
        SetupKeys::CONTAINER_HTTP_WORKER_NUMBER                  => 16,
70
        SetupKeys::CONTAINER_HTTP_HOST                           => SetupKeys::OPEN_HOST,
71
        SetupKeys::CONTAINER_HTTP_PORT                           => 9080,
72
        SetupKeys::CONTAINER_HTTPS_WORKER_NUMBER                 => 16,
73
        SetupKeys::CONTAINER_HTTPS_HOST                          => SetupKeys::OPEN_HOST,
74
        SetupKeys::CONTAINER_HTTPS_PORT                          => 9443,
75
        SetupKeys::CONTAINER_MESSAGE_QUEUE_WORKER_NUMBER         => 4,
76
        SetupKeys::CONTAINER_MESSAGE_QUEUE_HOST                  => SetupKeys::DEFAULT_HOST,
77
        SetupKeys::CONTAINER_MESSAGE_QUEUE_PORT                  => 8587,
78
        SetupKeys::PHP_FPM_PORT                                  => 9010,
79
        SetupKeys::PHP_FPM_HOST                                  => SetupKeys::DEFAULT_HOST,
80
        SetupKeys::UMASK                                         => '0002',
81
        SetupKeys::USER                                          => 'nobody',
82
        SetupKeys::GROUP                                         => 'nobody'
83
    );
84
85
    /**
86
     * The OS specific configuration properties.
87
     *
88
     * @var array
89
     */
90
    protected static $osProperties = array(
91
        SetupKeys::OS_DARWIN  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_DARWIN, SetupKeys::OS_ARCHITECTURE => 'x86_64', SetupKeys::GROUP => 'staff',    SetupKeys::USER => '_www'),
92
        SetupKeys::OS_DEBIAN  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', SetupKeys::GROUP => 'www-data', SetupKeys::USER => 'www-data'),
93
        SetupKeys::OS_UBUNTU  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', SetupKeys::GROUP => 'www-data', SetupKeys::USER => 'www-data'),
94
        SetupKeys::OS_ARCH    => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', ),
95
        SetupKeys::OS_FEDORA  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', ),
96
        SetupKeys::OS_REDHAT  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', ),
97
        SetupKeys::OS_CENTOS  => array(SetupKeys::OS_FAMILY => SetupKeys::OS_FAMILY_LINUX,  SetupKeys::OS_ARCHITECTURE => 'x86_64', ),
98
        SetupKeys::OS_WINDOWS => array(
99
            SetupKeys::OS_FAMILY                                     => SetupKeys::OS_FAMILY_WINDOWS,
100
            SetupKeys::OS_ARCHITECTURE                               => 'x86',
101
            SetupKeys::CONTAINER_HTTP_WORKER_NUMBER                  => 8,
102
            SetupKeys::CONTAINER_HTTPS_WORKER_NUMBER                 => 8
103
        )
104
    );
105
106
    /**
107
     * Returns the Linux distribution we're running on.
108
     *
109
     * @return string The Linux distribution we're running on
110
     */
111
    public static function getLinuxDistro()
112
    {
113
114
        // declare Linux distros (extensible list).
115
        $distros = array(
116
            SetupKeys::OS_ARCH   => 'arch-release',
117
            SetupKeys::OS_DEBIAN => 'debian_version',
118
            SetupKeys::OS_FEDORA => 'fedora-release',
119
            SetupKeys::OS_UBUNTU => 'lsb-release',
120
            SetupKeys::OS_REDHAT => 'redhat-release',
121
            SetupKeys::OS_CENTOS => 'centos-release'
122
        );
123
124
        // get everything from /etc directory.
125
        $etcList = scandir('/etc');
126
127
        // loop through /etc results...
128
        $distro = '';
129
130
        // iterate over all found files
131
        foreach ($etcList as $entry) {
132
            // loop through list of distros..
133
            foreach ($distros as $distroReleaseFile) {
134
                // match was found.
135
                if ($distroReleaseFile === $entry) {
136
                    // find distros array key (i.e. distro name) by value (i.e. distro release file)
137
                    $distro = array_search($distroReleaseFile, $distros);
138
                    break 2; // break inner and outer loop.
139
                }
140
            }
141
        }
142
143
        // return the found distro string
144
        return $distro;
145
    }
146
147
    /**
148
     * Merge the properties based on the passed OS.
149
     *
150
     * @param string $os                The OS we want to merge the properties for
151
     * @param array  $contextProperties The properties to merge
152
     *
153
     * @return void
154
     */
155
    public static function prepareProperties($os, array $contextProperties)
156
    {
157
158
        // merge all properties
159
        Setup::$mergedProperties = array_merge(
160
            $contextProperties,
161
            Setup::$defaultProperties,
162
            Setup::$osProperties[$os]
163
        );
164
165
        // prepare the properties for the OS identifier, e. g. iron-horse_debian_x86_64
166
        Setup::$mergedProperties[SetupKeys::OS_IDENTIFIER] = sprintf(
167
            '%s_%s_%s',
168
            str_replace(' ', '-', strtolower(Setup::$mergedProperties[SetupKeys::RELEASE_NAME])),
169
            $os,
170
            Setup::$mergedProperties[SetupKeys::OS_ARCHITECTURE]
171
        );
172
173
        // prepare the properties for the software identifier, e. g. appserver/1.0.0 (debian) PHP/5.5.21
174
        Setup::$mergedProperties[SetupKeys::SOFTWARE_IDENTIFIER] = sprintf(
175
            'appserver/%s (%s) PHP/%s',
176
            Setup::$mergedProperties[SetupKeys::VERSION],
177
            Setup::$mergedProperties[SetupKeys::OS_FAMILY],
178
            Setup::$mergedProperties[SetupKeys::PHP_VERSION]
179
        );
180
    }
181
182
    /**
183
     * Prepares the context by given event or without event for other usage
184
     *
185
     * @param null|string $installDir The install dir to check for info files
186
     * @param null|Event  $event      The event instance or null
187
     *
188
     * @return void
189
     */
190
    public static function prepareContext($installDir = null, $event = null)
191
    {
192
        // initialize the installation directory
193
        if (is_null($installDir)) {
194
            $installDir = getcwd();
195
        }
196
197
        // check if we've a file with the actual version number
198
        $version = '';
199
        if (file_exists($filename = $installDir .'/etc/appserver/.release-version')) {
200
            $version = file_get_contents($filename);
201
        } else {
202
            // load the version (GIT) of this package as fallback if called with event instance
203
            if (!is_null($event)) {
204
                $version = $event->getComposer()->getPackage()->getPrettyVersion();
205
            }
206
        }
207
208
        // check if we've a file with the actual release name
209
        if (file_exists($filename = $installDir .'/etc/appserver/.release-name')) {
210
            $releaseName = file_get_contents($filename);
211
        } else {
212
            // set the release name to 'Unknown' if not
213
            $releaseName = 'Unknown';
214
        }
215
216
        // prepare the context properties
217
        $contextProperties = array(
218
            SetupKeys::VERSION => $version,
219
            SetupKeys::INSTALL_DIR => $installDir,
220
            SetupKeys::RELEASE_NAME => $releaseName
221
        );
222
223
        // load the OS signature => sscanf is necessary to detect Windows, e. g. Windows NT for Windows 7
224
        list($os, ) = sscanf(strtolower(php_uname('s')), '%s %s');
225
226
        // check what OS we are running on
227
        switch ($os) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
228
229
            // installation running on Linux
230
            case SetupKeys::OS_FAMILY_LINUX:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
231
232
                // get the distribution
233
                $distribution = Setup::getLinuxDistro();
234
                // if we cant find one of the supported systems
235
                if ($distribution == null) {
236
                    // set debian as default
237
                    $distribution = SetupKeys::OS_DEBIAN;
238
239
                    // write a message to the console if called with event instance
240
                    if (!is_null($event)) {
241
                        $event->getIo()->write(
242
                            sprintf(
243
                                '<warning>Unknown Linux distribution found, use Debian default values: ' .
244
                                'Please check user/group configuration in etc/appserver/appserver.xml</warning>'
245
                            )
246
                        );
247
                    }
248
                }
249
250
                // merge the properties for the found Linux distribution
251
                Setup::prepareProperties($distribution, $contextProperties);
252
253
                break;
254
255
            // installation running on Mac OS X
256
            case SetupKeys::OS_FAMILY_DARWIN:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
257
258
                // merge the properties for Mac OS X
259
                Setup::prepareProperties($os, $contextProperties);
260
                break;
261
262
            // installation running on Windows
263
            case SetupKeys::OS_FAMILY_WINDOWS:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
264
265
                // merge the properties for Windows
266
                Setup::prepareProperties($os, $contextProperties);
267
                break;
268
269
            // all other OS are NOT supported actually
270
            default:
271
                break;
272
        }
273
    }
274
275
    /**
276
     * This method will be invoked by composer after a successful update and creates
277
     * the application server configuration file under etc/appserver/appserver.xml.
278
     *
279
     * @param \Composer\Script\Event $event The event that invokes this method
280
     *
281
     * @return void
282
     */
283
    public static function postUpdate(Event $event)
284
    {
285
        Setup::postInstall($event);
286
    }
287
288
    /**
289
     * This method will be invoked by composer after a successful installation and creates
290
     * the application server configuration file under etc/appserver/appserver.xml.
291
     *
292
     * @param \Composer\Script\Event $event The event that invokes this method
293
     *
294
     * @return void
295
     */
296
    public static function postInstall(Event $event)
297
    {
298
        // initialize the installation directory
299
        $override = false;
300
        $installDir = getcwd();
301
302
        // check the arguments for an installation directory
303
        foreach ($event->getArguments() as $arg) {
304
            // extract arguments
305
            list ($key, ) = explode('=', $arg);
306
            // query we want to override files
307
            if ($key === SetupKeys::ARG_OVERRIDE) {
308
                $override = true;
309
            }
310
            // query for a custom installation directory
311
            if ($key === SetupKeys::ARG_INSTALL_DIR) {
312
                $installDir = str_replace("$key=", '', $arg);
313
            }
314
        }
315
316
        Setup::prepareContext($installDir, $event);
317
318
        // process and move the configuration files their target directory
319
        Setup::processTemplate('etc/appserver/appserver.xml', $override);
320
        Setup::processTemplate('etc/appserver/appserver-runner.xml', $override);
321
322
        // write a message to the console
323
        $event->getIo()->write(
324
            sprintf(
325
                '%s<info>Successfully invoked appserver.io Composer post-install-cmd script ...</info>',
326
                Setup::$logo
327
            )
328
        );
329
    }
330
331
    /**
332
     * Returns the configuration value with the passed key.
333
     *
334
     * @param string $key The key to get value for
335
     *
336
     * @return mixed|null The configuration value
337
     */
338
    public static function getValue($key)
339
    {
340
        if (array_key_exists($key, Setup::$mergedProperties)) {
341
            return Setup::$mergedProperties[$key];
342
        }
343
    }
344
345
    /**
346
     * Copies the passed OS specific resource file to the target directory.
347
     *
348
     * @param string  $os       The OS we want to copy the files for
349
     * @param string  $resource The resource file we want to copy
350
     * @param boolean $override TRUE if the file should be overwritten if exists, else FALSE
351
     * @param integer $mode     The mode of the target file
352
     *
353
     * @return void
354
     */
355
    public static function copyOsSpecificResource($os, $resource, $override = false, $mode = 0644)
356
    {
357
358
        // we need the installation directory
359
        $installDir = Setup::getValue(SetupKeys::INSTALL_DIR);
360
361
        // prepare source and target directory
362
        $source = Setup::prepareOsSpecificPath(sprintf('%s/resources/os-specific/%s/%s', $installDir, $os, $resource));
363
        $target = Setup::prepareOsSpecificPath(sprintf('%s/%s', $installDir, $resource));
364
365
        // query whether we've to override the file
366
        if ($override === false && is_file($target) === true) {
367
            return;
368
        }
369
370
        // prepare the target directory
371
        Setup::prepareDirectory($target);
372
373
        // copy the file to the target directory
374
        copy($source, $target);
375
376
        // set the correct mode for the file
377
        Setup::changeFilePermissions($target, $mode);
378
    }
379
380
    /**
381
     * Processes the OS specific template and replace the properties with the OS specific values.
382
     *
383
     * @param string  $os       The OS we want to process the template for
384
     * @param string  $template The path to the template
385
     * @param boolean $override TRUE if the file should be overwritten if exists, else FALSE
386
     * @param integer $mode     The mode of the target file
387
     *
388
     * @return void
389
     */
390
    public static function processOsSpecificTemplate($os, $template, $override = false, $mode = 0644)
391
    {
392
393
        // prepare the target filename
394
        $targetFile = Setup::prepareOsSpecificPath($template);
395
396
        // query whether we've to override the file
397
        if ($override === false && is_file($targetFile) === true) {
398
            return;
399
        }
400
401
        // prepare the target directory
402
        Setup::prepareDirectory($template);
403
404
        // process the template and store the result in the passed file
405
        ob_start();
406
        include Setup::prepareOsSpecificPath(sprintf('resources/templates/os-specific/%s/%s.phtml', $os, $template));
407
        file_put_contents($targetFile, ob_get_clean());
408
409
        // set the correct mode for the file
410
        Setup::changeFilePermissions($template, $mode);
411
    }
412
413
    /**
414
     * Processes the template and replace the properties with the OS specific values.
415
     *
416
     * @param string  $template The path to the template
417
     * @param boolean $override TRUE if the file should be overwritten if exists, else FALSE
418
     * @param integer $mode     The mode of the target file
419
     *
420
     * @return void
421
     */
422
    public static function processTemplate($template, $override = false, $mode = 0644)
423
    {
424
425
        // prepare the target filename
426
        $targetFile = Setup::prepareOsSpecificPath($template);
427
428
        // query whether we've to override the file
429
        if ($override === false && is_file($targetFile) === true) {
430
            return;
431
        }
432
433
        // prepare the target directory
434
        Setup::prepareDirectory($template);
435
436
        // process the template and store the result in the passed file
437
        ob_start();
438
        include Setup::prepareOsSpecificPath(sprintf('resources/templates/%s.phtml', $template));
439
        file_put_contents($targetFile, ob_get_clean());
440
441
        // set the correct mode for the file
442
        Setup::changeFilePermissions($template, $mode);
443
    }
444
445
    /**
446
     * Sets the passed mode for the file if NOT on Windows.
447
     *
448
     * @param string  $filename The filename to set the mode for
449
     * @param integer $mode     The mode to set
450
     *
451
     * @return void
452
     */
453
    public static function changeFilePermissions($filename, $mode = 0644)
454
    {
455
456
        // make the passed filename OS compliant
457
        $toBeChanged = Setup::prepareOsSpecificPath($filename);
458
459
        // change the mode, if we're not on Windows
460
        if (SetupKeys::OS_FAMILY_WINDOWS !== strtolower(php_uname('s'))) {
461
            chmod($toBeChanged, $mode);
462
        }
463
    }
464
465
    /**
466
     * Prepares the passed directory if necessary.
467
     *
468
     * @param string  $directory The directory to prepare
469
     * @param integer $mode      The mode of the directory
470
     *
471
     * @return void
472
     */
473
    public static function prepareDirectory($directory, $mode = 0775)
474
    {
475
476
        // make the passed directory OS compliant
477
        $toBePreapared = Setup::prepareOsSpecificPath($directory);
478
479
        // make sure the directory exists
480
        if (is_dir(dirname($toBePreapared)) === false) {
481
            mkdir(dirname($toBePreapared), $mode, true);
482
        }
483
    }
484
485
    /**
486
     * Prepares the passed path to work on the actual OS.
487
     *
488
     * @param string $path The path we want to perpare
489
     *
490
     * @return string The prepared path
491
     */
492
    public static function prepareOsSpecificPath($path)
493
    {
494
        return str_replace('/', DIRECTORY_SEPARATOR, $path);
495
    }
496
}
497