Completed
Push — master ( 7502f4...6a4100 )
by Craig
05:41
created

ZikulaRequirements::addZikulaSystemRequirements()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 19
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 25
rs 9.6333
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\Bundle\CoreInstallerBundle\Util;
15
16
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
17
use Symfony\Component\Filesystem\Filesystem;
18
use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException;
19
use Symfony\Requirements\Requirement;
20
use Symfony\Requirements\SymfonyRequirements;
21
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
22
23
/**
24
 * Portions of this class copied from or inspired by the Symfony Installer (@see https://github.com/symfony/symfony-installer)
25
 * Class ZikulaRequirements
26
 */
27
class ZikulaRequirements
28
{
29
    /**
30
     * @var array
31
     */
32
    public $requirementsErrors = [];
33
34
    public function runSymfonyChecks(array $parameters = []): void
35
    {
36
        try {
37
            $symfonyRequirements = new SymfonyRequirements($parameters['kernel.project_dir'], '5.0.0');
38
            $this->addZikulaSystemRequirements($symfonyRequirements);
39
            $this->addZikulaPathRequirements($symfonyRequirements, $parameters);
40
41
            foreach ($symfonyRequirements->getRequirements() as $req) {
42
                if ($helpText = $this->getErrorMessage($req)) {
43
                    $this->requirementsErrors[] = $helpText;
44
                }
45
            }
46
        } catch (MethodArgumentValueNotImplementedException $e) {
47
            // workaround https://github.com/symfony/symfony-installer/issues/163
48
        }
49
    }
50
51
    protected function getErrorMessage(Requirement $requirement, $lineSize = 70): string
52
    {
53
        if ($requirement->isFulfilled()) {
54
            return '';
55
        }
56
        $errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL . '   ') . PHP_EOL;
57
        $errorMessage .= '   > ' . wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL . '   > ') . PHP_EOL;
58
59
        return $errorMessage;
60
    }
61
62
    private function addZikulaSystemRequirements(SymfonyRequirements $symfonyRequirements)
63
    {
64
        $installedPhpVersion = phpversion();
65
        $symfonyRequirements->addRequirement(
66
            version_compare($installedPhpVersion, ZikulaKernel::PHP_MINIMUM_VERSION, '>='),
67
            sprintf('PHP version must be at least %s (%s installed)', ZikulaKernel::PHP_MINIMUM_VERSION, $installedPhpVersion),
68
            sprintf(
69
                'You are running PHP version "<strong>%s</strong>", but Zikula needs at least PHP "<strong>%s</strong>" to run.
70
            Before using Zikula, upgrade your PHP installation, preferably to the latest version.',
71
                $installedPhpVersion,
72
                ZikulaKernel::PHP_MINIMUM_VERSION
73
            ),
74
            sprintf('Install PHP %s or newer (installed version is %s)', ZikulaKernel::PHP_MINIMUM_VERSION, $installedPhpVersion)
75
        );
76
        $symfonyRequirements->addRequirement(
77
            // pdo has been included with php since 5.1
78
            extension_loaded('pdo'),
79
            'The pdo extension must be loaded.',
80
            'Please install the pdo extension and enable it in the php config.'
81
        );
82
        $supportsUnicode = preg_match('/^\p{L}+$/u', 'TheseAreLetters');
83
        $symfonyRequirements->addRequirement(
84
            (isset($supportsUnicode) && false !== $supportsUnicode),
85
            'PHP\'s PCRE library does not have Unicode property support enabled.',
86
            'The PCRE library used with PHP must be compiled with the \'--enable-unicode-properties\' option.'
87
        );
88
    }
89
90
    private function addZikulaPathRequirements(SymfonyRequirements $symfonyRequirements, array $parameters = []): void
91
    {
92
        $fileSystem = new Filesystem();
93
        $projectDir = $parameters['kernel.project_dir'];
94
        $symfonyRequirements->addRequirement(
95
            is_writable($projectDir . '/config'),
96
            'config/ directory must be writable',
97
            'Change the permissions of "<strong>config/</strong>" directory so that the web server can write into it.'
98
        );
99
        $symfonyRequirements->addRequirement(
100
            is_writable($projectDir . '/config/dynamic'),
101
            'config/dynamic/ directory must be writable',
102
            'Change the permissions of "<strong>config/dynamic/</strong>" directory so that the web server can write into it.'
103
        );
104
        $dataDir = $projectDir . '/' . $parameters['datadir'];
105
        if (!is_dir($dataDir)) {
106
            $fileSystem->mkdir($dataDir);
107
        }
108
        $symfonyRequirements->addRequirement(
109
            is_writable($dataDir),
110
            $parameters['datadir'] . '/ directory must be writable',
111
            'Change the permissions of "<strong>' . $parameters['datadir'] . '</strong>" directory so that the web server can write into it.'
112
        );
113
        $customParametersPath = $projectDir . '/config/services_custom.yaml';
114
        if (file_exists($customParametersPath)) {
115
            $symfonyRequirements->addRequirement(
116
                is_writable($customParametersPath),
117
                'config/services_custom.yaml file must be writable',
118
                'Change the permissions of "<strong>config/services_custom.yaml</strong>" so that the web server can write into it.'
119
            );
120
        }
121
        $customEnvVarsPath = $projectDir . '/.env.local';
122
        if (!file_exists($customEnvVarsPath)) {
123
            // try to create the file
124
            try {
125
                $fileSystem->touch($customEnvVarsPath);
126
            } catch (IOExceptionInterface $exception) {
127
                $symfonyRequirements->addRequirement(
128
                    false,
129
                    '.env.local file must exists',
130
                    'Create an empty file "<strong>.env.local</strong>" in the root folder.'
131
                );
132
            }
133
        }
134
        if (file_exists($customEnvVarsPath)) {
135
            $content = file_get_contents($customEnvVarsPath);
136
            if (false === mb_strpos($content, 'DATABASE_URL')) {
137
                // no database credentials are set yet
138
                try {
139
                    $fileSystem->dumpFile($customEnvVarsPath, 'Test');
140
                    $fileSystem->dumpFile($customEnvVarsPath, '');
141
                } catch (IOExceptionInterface $exception) {
142
                    $symfonyRequirements->addRequirement(
143
                        false,
144
                        '.env.local file must be writable',
145
                        'Change the permissions of "<strong>.env.local</strong>" so that the web server can write into it.'
146
                    );
147
                }
148
            }
149
        }
150
    }
151
}
152