11<?php
2+ declare (strict_types=1 );
3+
24/**
35 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
46 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
1416 */
1517namespace App \Console ;
1618
17- if (! defined ('STDIN ' )) {
19+ if (!defined ('STDIN ' )) {
1820 define ('STDIN ' , fopen ('php://stdin ' , 'r ' ));
1921}
2022
23+ use Cake \Codeception \Console \Installer as CodeceptionInstaller ;
2124use Cake \Utility \Security ;
25+ use Composer \IO \IOInterface ;
2226use Composer \Script \Event ;
2327use Exception ;
2428
2529/**
26- * Provides installation hooks for when this application is installed via
30+ * Provides installation hooks for when this application is installed through
2731 * composer. Customize this class to suit your needs.
2832 */
2933class Installer
3034{
31-
3235 /**
3336 * An array of directories to be made writable
37+ *
38+ * @var list<string>
3439 */
35- const WRITABLE_DIRS = [
40+ public const WRITABLE_DIRS = [
3641 'logs ' ,
3742 'tmp ' ,
3843 'tmp/cache ' ,
@@ -50,74 +55,52 @@ class Installer
5055 * @throws \Exception Exception raised by validator.
5156 * @return void
5257 */
53- public static function postInstall (Event $ event )
58+ public static function postInstall (Event $ event ): void
5459 {
5560 $ io = $ event ->getIO ();
5661
57- $ rootDir = dirname (dirname ( __DIR__ ) );
62+ $ rootDir = dirname (__DIR__ , 2 );
5863
59- static ::createAppConfig ($ rootDir , $ io );
64+ static ::createAppLocalConfig ($ rootDir , $ io );
6065 static ::createWritableDirectories ($ rootDir , $ io );
6166
62- // ask if the permissions should be changed
63- if ($ io ->isInteractive ()) {
64- $ validator = function ($ arg ) {
65- if (in_array ($ arg , ['Y ' , 'y ' , 'N ' , 'n ' ])) {
66- return $ arg ;
67- }
68- throw new Exception ('This is not a valid answer. Please choose Y or n. ' );
69- };
70- $ setFolderPermissions = $ io ->askAndValidate (
71- '<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ' ,
72- $ validator ,
73- 10 ,
74- 'Y '
75- );
76-
77- if (in_array ($ setFolderPermissions , ['Y ' , 'y ' ])) {
78- static ::setFolderPermissions ($ rootDir , $ io );
79- }
80- } else {
81- static ::setFolderPermissions ($ rootDir , $ io );
82- }
83-
67+ static ::setFolderPermissions ($ rootDir , $ io );
8468 static ::setSecuritySalt ($ rootDir , $ io );
8569
86- $ class = 'Cake\Codeception\Console\Installer ' ;
87- if (class_exists ($ class )) {
88- $ class ::customizeCodeceptionBinary ($ event );
70+ if (class_exists (CodeceptionInstaller::class)) {
71+ CodeceptionInstaller::customizeCodeceptionBinary ($ event );
8972 }
9073 }
9174
9275 /**
93- * Create the config/app .php file if it does not exist.
76+ * Create config/app_local .php file if it does not exist.
9477 *
95- * @param string $dir The application's root directory.
96- * @param \Composer\IO\IOInterface $io IO interface to write to console.
78+ * @param string $dir The application's root directory.
79+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
9780 * @return void
9881 */
99- public static function createAppConfig ( $ dir , $ io )
82+ public static function createAppLocalConfig ( string $ dir , IOInterface $ io ): void
10083 {
101- $ appConfig = $ dir . '/config/app .php ' ;
102- $ defaultConfig = $ dir . '/config/app.default .php ' ;
103- if (! file_exists ($ appConfig )) {
104- copy ($ defaultConfig , $ appConfig );
105- $ io ->write ('Created `config/app .php` file ' );
84+ $ appLocalConfig = $ dir . '/config/app_local .php ' ;
85+ $ appLocalConfigTemplate = $ dir . '/config/app_local.example .php ' ;
86+ if (!file_exists ($ appLocalConfig )) {
87+ copy ($ appLocalConfigTemplate , $ appLocalConfig );
88+ $ io ->write ('Created `config/app_local .php` file ' );
10689 }
10790 }
10891
10992 /**
11093 * Create the `logs` and `tmp` directories.
11194 *
112- * @param string $dir The application's root directory.
113- * @param \Composer\IO\IOInterface $io IO interface to write to console.
95+ * @param string $dir The application's root directory.
96+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
11497 * @return void
11598 */
116- public static function createWritableDirectories ($ dir , $ io )
99+ public static function createWritableDirectories (string $ dir , IOInterface $ io ): void
117100 {
118101 foreach (static ::WRITABLE_DIRS as $ path ) {
119102 $ path = $ dir . '/ ' . $ path ;
120- if (! file_exists ($ path )) {
103+ if (!file_exists ($ path )) {
121104 mkdir ($ path );
122105 $ io ->write ('Created ` ' . $ path . '` directory ' );
123106 }
@@ -129,14 +112,34 @@ public static function createWritableDirectories($dir, $io)
129112 *
130113 * This is not the most secure default, but it gets people up and running quickly.
131114 *
132- * @param string $dir The application's root directory.
133- * @param \Composer\IO\IOInterface $io IO interface to write to console.
115+ * @param string $dir The application's root directory.
116+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
134117 * @return void
135118 */
136- public static function setFolderPermissions ($ dir , $ io )
119+ public static function setFolderPermissions (string $ dir , IOInterface $ io ): void
137120 {
121+ // ask if the permissions should be changed
122+ if ($ io ->isInteractive ()) {
123+ $ validator = function (string $ arg ): string {
124+ if (in_array ($ arg , ['Y ' , 'y ' , 'N ' , 'n ' ])) {
125+ return $ arg ;
126+ }
127+ throw new Exception ('This is not a valid answer. Please choose Y or n. ' );
128+ };
129+ $ setFolderPermissions = $ io ->askAndValidate (
130+ '<info>Set Folder Permissions ? (Default to Y)</info> [<comment>Y,n</comment>]? ' ,
131+ $ validator ,
132+ 10 ,
133+ 'Y ' ,
134+ );
135+
136+ if (in_array ($ setFolderPermissions , ['n ' , 'N ' ])) {
137+ return ;
138+ }
139+ }
140+
138141 // Change the permissions on a path and output the results.
139- $ changePerms = function ($ path ) use ($ io ) {
142+ $ changePerms = function (string $ path ) use ($ io ): void {
140143 $ currentPerms = fileperms ($ path ) & 0777 ;
141144 $ worldWritable = $ currentPerms | 0007 ;
142145 if ($ worldWritable == $ currentPerms ) {
@@ -151,12 +154,12 @@ public static function setFolderPermissions($dir, $io)
151154 }
152155 };
153156
154- $ walker = function ($ dir ) use (&$ walker , $ changePerms ) {
155- $ files = array_diff (scandir ($ dir ), ['. ' , '.. ' ]);
157+ $ walker = function (string $ dir ) use (&$ walker , $ changePerms ): void {
158+ $ files = array_diff (scandir ($ dir ) ?: [] , ['. ' , '.. ' ]);
156159 foreach ($ files as $ file ) {
157160 $ path = $ dir . '/ ' . $ file ;
158161
159- if (! is_dir ($ path )) {
162+ if (!is_dir ($ path )) {
160163 continue ;
161164 }
162165
@@ -173,29 +176,34 @@ public static function setFolderPermissions($dir, $io)
173176 /**
174177 * Set the security.salt value in the application's config file.
175178 *
176- * @param string $dir The application's root directory.
177- * @param \Composer\IO\IOInterface $io IO interface to write to console.
179+ * @param string $dir The application's root directory.
180+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
178181 * @return void
179182 */
180- public static function setSecuritySalt ($ dir , $ io )
183+ public static function setSecuritySalt (string $ dir , IOInterface $ io ): void
181184 {
182185 $ newKey = hash ('sha256 ' , Security::randomBytes (64 ));
183- static ::setSecuritySaltInFile ($ dir , $ io , $ newKey , 'app .php ' );
186+ static ::setSecuritySaltInFile ($ dir , $ io , $ newKey , 'app_local .php ' );
184187 }
185188
186189 /**
187190 * Set the security.salt value in a given file
188191 *
189- * @param string $dir The application's root directory.
190- * @param \Composer\IO\IOInterface $io IO interface to write to console.
191- * @param string $newKey key to set in the file
192- * @param string $file A path to a file relative to the application's root
192+ * @param string $dir The application's root directory.
193+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
194+ * @param string $newKey key to set in the file
195+ * @param string $file A path to a file relative to the application's root
193196 * @return void
194197 */
195- public static function setSecuritySaltInFile ($ dir , $ io , $ newKey , $ file )
198+ public static function setSecuritySaltInFile (string $ dir , IOInterface $ io , string $ newKey , string $ file ): void
196199 {
197200 $ config = $ dir . '/config/ ' . $ file ;
198201 $ content = file_get_contents ($ config );
202+ if ($ content === false ) {
203+ $ io ->write ('Config file not readable or not found: config/ ' . $ file );
204+
205+ return ;
206+ }
199207
200208 $ content = str_replace ('__SALT__ ' , $ newKey , $ content , $ count );
201209
@@ -217,16 +225,22 @@ public static function setSecuritySaltInFile($dir, $io, $newKey, $file)
217225 /**
218226 * Set the APP_NAME value in a given file
219227 *
220- * @param string $dir The application's root directory.
221- * @param \Composer\IO\IOInterface $io IO interface to write to console.
222- * @param string $appName app name to set in the file
223- * @param string $file A path to a file relative to the application's root
228+ * @param string $dir The application's root directory.
229+ * @param \Composer\IO\IOInterface $io IO interface to write to console.
230+ * @param string $appName app name to set in the file
231+ * @param string $file A path to a file relative to the application's root
224232 * @return void
225233 */
226- public static function setAppNameInFile ($ dir , $ io , $ appName , $ file )
234+ public static function setAppNameInFile (string $ dir , IOInterface $ io , string $ appName , string $ file ): void
227235 {
228236 $ config = $ dir . '/config/ ' . $ file ;
229237 $ content = file_get_contents ($ config );
238+ if ($ content === false ) {
239+ $ io ->write ('Config file not readable or not found: config/ ' . $ file );
240+
241+ return ;
242+ }
243+
230244 $ content = str_replace ('__APP_NAME__ ' , $ appName , $ content , $ count );
231245
232246 if ($ count == 0 ) {
0 commit comments