Passed
Pull Request — master (#748)
by Stefano
02:38
created

Installer::setFolderPermissions()   B

Complexity

Conditions 8
Paths 3

Size

Total Lines 55
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 33
c 1
b 0
f 0
dl 0
loc 55
rs 8.1475
cc 8
nc 3
nop 2

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
declare(strict_types=1);
3
4
/**
5
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
13
 * @link      https://cakephp.org CakePHP(tm) Project
14
 * @since     3.0.0
15
 * @license   https://opensource.org/licenses/mit-license.php MIT License
16
 */
17
namespace App\Console;
18
19
if (!defined('STDIN')) {
20
    define('STDIN', fopen('php://stdin', 'r'));
21
}
22
23
use Cake\Codeception\Console\Installer as CodeceptionInstaller;
0 ignored issues
show
Bug introduced by
The type Cake\Codeception\Console\Installer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use Cake\Utility\Security;
25
use Composer\Script\Event;
26
use Exception;
27
28
/**
29
 * Provides installation hooks for when this application is installed through
30
 * composer. Customize this class to suit your needs.
31
 */
32
class Installer
33
{
34
    /**
35
     * An array of directories to be made writable
36
     */
37
    public const WRITABLE_DIRS = [
38
        'logs',
39
        'tmp',
40
        'tmp/cache',
41
        'tmp/cache/models',
42
        'tmp/cache/persistent',
43
        'tmp/cache/views',
44
        'tmp/sessions',
45
        'tmp/tests',
46
    ];
47
48
    /**
49
     * Does some routine installation tasks so people don't have to.
50
     *
51
     * @param \Composer\Script\Event $event The composer event object.
52
     * @throws \Exception Exception raised by validator.
53
     * @return void
54
     */
55
    public static function postInstall(Event $event)
56
    {
57
        $io = $event->getIO();
58
59
        $rootDir = dirname(dirname(__DIR__));
60
61
        static::createAppLocalConfig($rootDir, $io);
62
        static::createWritableDirectories($rootDir, $io);
63
64
        static::setFolderPermissions($rootDir, $io);
65
        static::setSecuritySalt($rootDir, $io);
66
67
        if (class_exists(CodeceptionInstaller::class)) {
68
            CodeceptionInstaller::customizeCodeceptionBinary($event);
69
        }
70
    }
71
72
    /**
73
     * Create config/app_local.php file if it does not exist.
74
     *
75
     * @param string $dir The application's root directory.
76
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
77
     * @return void
78
     */
79
    public static function createAppLocalConfig($dir, $io)
80
    {
81
        $appLocalConfig = $dir . '/config/app_local.php';
82
        $appLocalConfigTemplate = $dir . '/config/app_local.example.php';
83
        if (!file_exists($appLocalConfig)) {
84
            copy($appLocalConfigTemplate, $appLocalConfig);
85
            $io->write('Created `config/app_local.php` file');
86
        }
87
    }
88
89
    /**
90
     * Create the config/.env file if it does not exist.
91
     *
92
     * @param string $dir The application's root directory.
93
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
94
     * @return void
95
     */
96
    public static function createDotEnvConfig($dir, $io): void
97
    {
98
        $appConfig = $dir . '/config/.env';
99
        $defaultConfig = $dir . '/config/.env.default';
100
        if (!file_exists($appConfig)) {
101
            copy($defaultConfig, $appConfig);
102
            $io->write('Created `config/.env` file');
103
        }
104
    }
105
106
    /**
107
     * Create the `logs` and `tmp` directories.
108
     *
109
     * @param string $dir The application's root directory.
110
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
111
     * @return void
112
     */
113
    public static function createWritableDirectories($dir, $io)
114
    {
115
        foreach (static::WRITABLE_DIRS as $path) {
116
            $path = $dir . '/' . $path;
117
            if (!file_exists($path)) {
118
                mkdir($path);
119
                $io->write('Created `' . $path . '` directory');
120
            }
121
        }
122
    }
123
124
    /**
125
     * Set globally writable permissions on the "tmp" and "logs" directory.
126
     *
127
     * This is not the most secure default, but it gets people up and running quickly.
128
     *
129
     * @param string $dir The application's root directory.
130
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
131
     * @return void
132
     */
133
    public static function setFolderPermissions($dir, $io)
134
    {
135
        // ask if the permissions should be changed
136
        if ($io->isInteractive()) {
137
            $validator = function ($arg) {
138
                if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
139
                    return $arg;
140
                }
141
                throw new Exception('This is not a valid answer. Please choose Y or n.');
142
            };
143
            $setFolderPermissions = $io->askAndValidate(
144
                '<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
145
                $validator,
146
                10,
147
                'Y'
148
            );
149
150
            if (in_array($setFolderPermissions, ['n', 'N'])) {
151
                return;
152
            }
153
        }
154
155
        // Change the permissions on a path and output the results.
156
        $changePerms = function ($path) use ($io) {
157
            $currentPerms = fileperms($path) & 0777;
158
            $worldWritable = $currentPerms | 0007;
159
            if ($worldWritable == $currentPerms) {
160
                return;
161
            }
162
163
            $res = chmod($path, $worldWritable);
164
            if ($res) {
165
                $io->write('Permissions set on ' . $path);
166
            } else {
167
                $io->write('Failed to set permissions on ' . $path);
168
            }
169
        };
170
171
        $walker = function ($dir) use (&$walker, $changePerms) {
172
            $files = array_diff(scandir($dir), ['.', '..']);
173
            foreach ($files as $file) {
174
                $path = $dir . '/' . $file;
175
176
                if (!is_dir($path)) {
177
                    continue;
178
                }
179
180
                $changePerms($path);
181
                $walker($path);
182
            }
183
        };
184
185
        $walker($dir . '/tmp');
186
        $changePerms($dir . '/tmp');
187
        $changePerms($dir . '/logs');
188
    }
189
190
    /**
191
     * Set the security.salt value in the application's config file.
192
     *
193
     * @param string $dir The application's root directory.
194
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
195
     * @return void
196
     */
197
    public static function setSecuritySalt($dir, $io)
198
    {
199
        $newKey = hash('sha256', Security::randomBytes(64));
200
        static::setSecuritySaltInFile($dir, $io, $newKey, 'app_local.php');
201
    }
202
203
    /**
204
     * Set the security.salt value in a given file
205
     *
206
     * @param string $dir The application's root directory.
207
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
208
     * @param string $newKey key to set in the file
209
     * @param string $file A path to a file relative to the application's root
210
     * @return void
211
     */
212
    public static function setSecuritySaltInFile($dir, $io, $newKey, $file)
213
    {
214
        $config = $dir . '/config/' . $file;
215
        $content = file_get_contents($config);
216
217
        $content = str_replace('__SALT__', $newKey, $content, $count);
218
219
        if ($count == 0) {
220
            $io->write('No Security.salt placeholder to replace.');
221
222
            return;
223
        }
224
225
        $result = file_put_contents($config, $content);
226
        if ($result) {
227
            $io->write('Updated Security.salt value in config/' . $file);
228
229
            return;
230
        }
231
        $io->write('Unable to update Security.salt value.');
232
    }
233
234
    /**
235
     * Set the APP_NAME value in a given file
236
     *
237
     * @param string $dir The application's root directory.
238
     * @param \Composer\IO\IOInterface $io IO interface to write to console.
239
     * @param string $appName app name to set in the file
240
     * @param string $file A path to a file relative to the application's root
241
     * @return void
242
     */
243
    public static function setAppNameInFile($dir, $io, $appName, $file)
244
    {
245
        $config = $dir . '/config/' . $file;
246
        $content = file_get_contents($config);
247
        $content = str_replace('__APP_NAME__', $appName, $content, $count);
248
249
        if ($count == 0) {
250
            $io->write('No __APP_NAME__ placeholder to replace.');
251
252
            return;
253
        }
254
255
        $result = file_put_contents($config, $content);
256
        if ($result) {
257
            $io->write('Updated __APP_NAME__ value in config/' . $file);
258
259
            return;
260
        }
261
        $io->write('Unable to update __APP_NAME__ value.');
262
    }
263
}
264