3 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
6 * Licensed under The MIT License
7 * For full copyright and license information, please see the LICENSE.txt
8 * Redistributions of files must retain the above copyright notice.
10 * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11 * @link http://cakephp.org CakePHP(tm) Project
13 * @license http://www.opensource.org/licenses/mit-license.php MIT License
15 namespace App\Console;
17 use Cake\Utility\Security;
18 use Composer\Script\Event;
22 * Provides installation hooks for when this application is installed via
23 * composer. Customize this class to suit your needs.
29 * Does some routine installation tasks so people don't have to.
31 * @param \Composer\Script\Event $event The composer event object.
32 * @throws \Exception Exception raised by validator.
35 public static function postInstall(Event $event)
37 $io = $event->getIO();
39 $rootDir = dirname(dirname(__DIR__));
41 static::createAppConfig($rootDir, $io);
42 static::createWritableDirectories($rootDir, $io);
44 // ask if the permissions should be changed
45 if ($io->isInteractive()) {
46 $validator = function ($arg) {
47 if (in_array($arg, ['Y', 'y', 'N', 'n'])) {
50 throw new Exception('This is not a valid answer. Please choose Y or n.');
52 $setFolderPermissions = $io->askAndValidate(
53 '<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ',
59 if (in_array($setFolderPermissions, ['Y', 'y'])) {
60 static::setFolderPermissions($rootDir, $io);
63 static::setFolderPermissions($rootDir, $io);
66 static::setSecuritySalt($rootDir, $io);
68 if (class_exists('\Cake\Codeception\Console\Installer')) {
69 \Cake\Codeception\Console\Installer::customizeCodeceptionBinary($event);
74 * Create the config/app.php file if it does not exist.
76 * @param string $dir The application's root directory.
77 * @param \Composer\IO\IOInterface $io IO interface to write to console.
80 public static function createAppConfig($dir, $io)
82 $appConfig = $dir . '/config/app.php';
83 $defaultConfig = $dir . '/config/app.default.php';
84 if (!file_exists($appConfig)) {
85 copy($defaultConfig, $appConfig);
86 $io->write('Created `config/app.php` file');
91 * Create the `logs` and `tmp` directories.
93 * @param string $dir The application's root directory.
94 * @param \Composer\IO\IOInterface $io IO interface to write to console.
97 public static function createWritableDirectories($dir, $io)
104 'tmp/cache/persistent',
110 foreach ($paths as $path) {
111 $path = $dir . '/' . $path;
112 if (!file_exists($path)) {
114 $io->write('Created `' . $path . '` directory');
120 * Set globally writable permissions on the "tmp" and "logs" directory.
122 * This is not the most secure default, but it gets people up and running quickly.
124 * @param string $dir The application's root directory.
125 * @param \Composer\IO\IOInterface $io IO interface to write to console.
128 public static function setFolderPermissions($dir, $io)
130 // Change the permissions on a path and output the results.
131 $changePerms = function ($path, $perms, $io) {
132 // Get permission bits from stat(2) result.
133 $currentPerms = fileperms($path) & 0777;
134 if (($currentPerms & $perms) == $perms) {
138 $res = chmod($path, $currentPerms | $perms);
140 $io->write('Permissions set on ' . $path);
142 $io->write('Failed to set permissions on ' . $path);
146 $walker = function ($dir, $perms, $io) use (&$walker, $changePerms) {
147 $files = array_diff(scandir($dir), ['.', '..']);
148 foreach ($files as $file) {
149 $path = $dir . '/' . $file;
151 if (!is_dir($path)) {
155 $changePerms($path, $perms, $io);
156 $walker($path, $perms, $io);
160 $worldWritable = bindec('0000000111');
161 $walker($dir . '/tmp', $worldWritable, $io);
162 $changePerms($dir . '/tmp', $worldWritable, $io);
163 $changePerms($dir . '/logs', $worldWritable, $io);
167 * Set the security.salt value in the application's config file.
169 * @param string $dir The application's root directory.
170 * @param \Composer\IO\IOInterface $io IO interface to write to console.
173 public static function setSecuritySalt($dir, $io)
175 $config = $dir . '/config/app.php';
176 $content = file_get_contents($config);
178 $newKey = hash('sha256', Security::randomBytes(64));
179 $content = str_replace('__SALT__', $newKey, $content, $count);
182 $io->write('No Security.salt placeholder to replace.');
187 $result = file_put_contents($config, $content);
189 $io->write('Updated Security.salt value in config/app.php');
193 $io->write('Unable to update Security.salt value.');