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);
$class = 'Cake\Codeception\Console\Installer';
if (class_exists($class)) {
$class::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)
{
foreach (static::WRITABLE_DIRS 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) use ($io) {
$currentPerms = fileperms($path) & 0777;
$worldWritable = $currentPerms | 0007;
if ($worldWritable == $currentPerms) {
return;
}
$res = chmod($path, $worldWritable);
if ($res) {
$io->write('Permissions set on ' . $path);
} else {
$io->write('Failed to set permissions on ' . $path);
}
};
$walker = function ($dir) use (&$walker, $changePerms) {
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
$path = $dir . '/' . $file;
if (!is_dir($path)) {
continue;
}
$changePerms($path);
$walker($path);
}
};
$walker($dir . '/tmp');
$changePerms($dir . '/tmp');
$changePerms($dir . '/logs');
}
/**
* 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)
{
$newKey = hash('sha256', Security::randomBytes(64));
static::setSecuritySaltInFile($dir, $io, $newKey, 'app.php');
}
/**
* Set the security.salt value in a given file
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @param string $newKey key to set in the file
* @param string $file A path to a file relative to the application's root
* @return void
*/
public static function setSecuritySaltInFile($dir, $io, $newKey, $file)
{
$config = $dir . '/config/' . $file;
$content = file_get_contents($config);
$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/' . $file);
return;
}
$io->write('Unable to update Security.salt value.');
}
/**
* Set the APP_NAME value in a given file
*
* @param string $dir The application's root directory.
* @param \Composer\IO\IOInterface $io IO interface to write to console.
* @param string $appName app name to set in the file
* @param string $file A path to a file relative to the application's root
* @return void
*/
public static function setAppNameInFile($dir, $io, $appName, $file)
{
$config = $dir . '/config/' . $file;
$content = file_get_contents($config);
$content = str_replace('__APP_NAME__', $appName, $content, $count);
if ($count == 0) {
$io->write('No __APP_NAME__ placeholder to replace.');
return;
}
$result = file_put_contents($config, $content);
if ($result) {
$io->write('Updated __APP_NAME__ value in config/' . $file);
return;
}
$io->write('Unable to update __APP_NAME__ value.');
}
}