Completed
Pull Request — master (#4265)
by Craig
05:53
created

ZikulaRequirements::runSymfonyChecks()   A

Complexity

Conditions 4
Paths 13

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
c 3
b 0
f 0
nc 13
nop 1
dl 0
loc 13
rs 10
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('You are running PHP version "<strong>%s</strong>", but Zikula needs at least PHP "<strong>%s</strong>" to run.
69
            Before using Zikula, upgrade your PHP installation, preferably to the latest version.',
70
                $installedPhpVersion, ZikulaKernel::PHP_MINIMUM_VERSION),
71
            sprintf('Install PHP %s or newer (installed version is %s)', ZikulaKernel::PHP_MINIMUM_VERSION, $installedPhpVersion)
72
        );
73
        $symfonyRequirements->addRequirement(
74
            // pdo has been included with php since 5.1
75
            extension_loaded('pdo'),
76
            'The pdo extension must be loaded.',
77
            'Please install the pdo extension and enable it in the php config.'
78
        );
79
        $supportsUnicode = preg_match('/^\p{L}+$/u', 'TheseAreLetters');
80
        $symfonyRequirements->addRequirement(
81
            (isset($supportsUnicode) && false !== $supportsUnicode),
82
            'PHP\'s PCRE library does not have Unicode property support enabled.',
83
            'The PCRE library used with PHP must be compiled with the \'--enable-unicode-properties\' option.'
84
        );
85
    }
86
87
    private function addZikulaPathRequirements(SymfonyRequirements $symfonyRequirements, array $parameters = []): void
88
    {
89
        $fileSystem = new Filesystem();
90
        $projectDir = $parameters['kernel.project_dir'];
91
        $symfonyRequirements->addRequirement(
92
            is_writable($projectDir . '/config'),
93
            'config/ directory must be writable',
94
            'Change the permissions of "<strong>config/</strong>" directory so that the web server can write into it.'
95
        );
96
        $symfonyRequirements->addRequirement(
97
            is_writable($projectDir . '/config/dynamic'),
98
            'config/dynamic/ directory must be writable',
99
            'Change the permissions of "<strong>config/dynamic/</strong>" directory so that the web server can write into it.'
100
        );
101
        $dataDir = $projectDir . '/' . $parameters['datadir'];
102
        if (!is_dir($dataDir)) {
103
            $fileSystem->mkdir($dataDir);
104
        }
105
        $symfonyRequirements->addRequirement(
106
            is_writable($dataDir),
107
            $parameters['datadir'] . '/ directory must be writable',
108
            'Change the permissions of "<strong>' . $parameters['datadir'] . '</strong>" directory so that the web server can write into it.'
109
        );
110
        $customParametersPath = $projectDir . '/config/services_custom.yaml';
111
        if (file_exists($customParametersPath)) {
112
            $symfonyRequirements->addRequirement(
113
                is_writable($customParametersPath),
114
                'config/services_custom.yaml file must be writable',
115
                'Change the permissions of "<strong>config/services_custom.yaml</strong>" so that the web server can write into it.'
116
            );
117
        }
118
        $customEnvVarsPath = $projectDir . '/.env.local';
119
        if (!file_exists($customEnvVarsPath)) {
120
            // try to create the file
121
            try {
122
                $fileSystem->touch($customEnvVarsPath);
123
            } catch (IOExceptionInterface $exception) {
124
                $symfonyRequirements->addRequirement(
125
                    false,
126
                    '.env.local file must exists',
127
                    'Create an empty file "<strong>.env.local</strong>" in the root folder.'
128
                );
129
            }
130
        }
131
        if (file_exists($customEnvVarsPath)) {
132
            $content = file_get_contents($customEnvVarsPath);
133
            if (false === mb_strpos($content, 'DATABASE_URL')) {
134
                // no database credentials are set yet
135
                try {
136
                    $fileSystem->dumpFile($customEnvVarsPath, 'Test');
137
                    $fileSystem->dumpFile($customEnvVarsPath, '');
138
                } catch (IOExceptionInterface $exception) {
139
                    $symfonyRequirements->addRequirement(
140
                        false,
141
                        '.env.local file must be writable',
142
                        'Change the permissions of "<strong>.env.local</strong>" so that the web server can write into it.'
143
                    );
144
                }
145
            }
146
        }
147
    }
148
}
149