getIO(); $rootDir = dirname(dirname(__DIR__)); static::createAppConfig($rootDir, $io); static::createWritableDirectories($rootDir, $io); // ask if the permissions should be changed if ($io->isInteractive()) { $validator = function ($arg) { if (in_array($arg, ['Y', 'y', 'N', 'n'])) { return $arg; } throw new Exception('This is not a valid answer. Please choose Y or n.'); }; $setFolderPermissions = $io->askAndValidate( 'Set Folder Permissions ? (Default to Y) [Y,n]? ', $validator, 10, 'Y' ); if (in_array($setFolderPermissions, ['Y', 'y'])) { static::setFolderPermissions($rootDir, $io); } } else { static::setFolderPermissions($rootDir, $io); } static::setSecuritySalt($rootDir, $io); if (class_exists('\Cake\Codeception\Console\Installer')) { \Cake\Codeception\Console\Installer::customizeCodeceptionBinary($event); } } /** * Create the config/app.php file if it does not exist. * * @param string $dir The application's root directory. * @param \Composer\IO\IOInterface $io IO interface to write to console. * @return void */ public static function createAppConfig($dir, $io) { $appConfig = $dir . '/config/app.php'; $defaultConfig = $dir . '/config/app.default.php'; if (!file_exists($appConfig)) { copy($defaultConfig, $appConfig); $io->write('Created `config/app.php` file'); } } /** * Create the `logs` and `tmp` directories. * * @param string $dir The application's root directory. * @param \Composer\IO\IOInterface $io IO interface to write to console. * @return void */ public static function createWritableDirectories($dir, $io) { $paths = [ 'logs', 'tmp', 'tmp/cache', 'tmp/cache/models', 'tmp/cache/persistent', 'tmp/cache/views', 'tmp/sessions', 'tmp/tests' ]; foreach ($paths as $path) { $path = $dir . '/' . $path; if (!file_exists($path)) { mkdir($path); $io->write('Created `' . $path . '` directory'); } } } /** * Set globally writable permissions on the "tmp" and "logs" directory. * * This is not the most secure default, but it gets people up and running quickly. * * @param string $dir The application's root directory. * @param \Composer\IO\IOInterface $io IO interface to write to console. * @return void */ public static function setFolderPermissions($dir, $io) { // Change the permissions on a path and output the results. $changePerms = function ($path, $perms, $io) { // Get permission bits from stat(2) result. $currentPerms = fileperms($path) & 0777; if (($currentPerms & $perms) == $perms) { return; } $res = chmod($path, $currentPerms | $perms); if ($res) { $io->write('Permissions set on ' . $path); } else { $io->write('Failed to set permissions on ' . $path); } }; $walker = function ($dir, $perms, $io) use (&$walker, $changePerms) { $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { $path = $dir . '/' . $file; if (!is_dir($path)) { continue; } $changePerms($path, $perms, $io); $walker($path, $perms, $io); } }; $worldWritable = bindec('0000000111'); $walker($dir . '/tmp', $worldWritable, $io); $changePerms($dir . '/tmp', $worldWritable, $io); $changePerms($dir . '/logs', $worldWritable, $io); } /** * Set the security.salt value in the application's config file. * * @param string $dir The application's root directory. * @param \Composer\IO\IOInterface $io IO interface to write to console. * @return void */ public static function setSecuritySalt($dir, $io) { $config = $dir . '/config/app.php'; $content = file_get_contents($config); $newKey = hash('sha256', Security::randomBytes(64)); $content = str_replace('__SALT__', $newKey, $content, $count); if ($count == 0) { $io->write('No Security.salt placeholder to replace.'); return; } $result = file_put_contents($config, $content); if ($result) { $io->write('Updated Security.salt value in config/app.php'); return; } $io->write('Unable to update Security.salt value.'); } }