These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file contains scripts that are run on composer events and commands - for |
||
4 | * example, you might want to regenerate the cache after updating |
||
5 | * |
||
6 | * @license https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3 |
||
7 | */ |
||
8 | |||
9 | namespace BZIon\Composer; |
||
10 | |||
11 | use Composer\IO\ConsoleIO; |
||
12 | use Composer\IO\IOInterface; |
||
13 | use Composer\Script\Event; |
||
14 | use Phinx\Console\PhinxApplication; |
||
15 | use Symfony\Component\Console\Helper\HelperSet; |
||
16 | use Symfony\Component\Console\Helper\QuestionHelper; |
||
17 | use Symfony\Component\Console\Input\ArrayInput; |
||
18 | use Symfony\Component\Console\Output\ConsoleOutput; |
||
19 | use Symfony\Component\Filesystem\Filesystem; |
||
20 | use Symfony\Component\Finder\Finder; |
||
21 | use Symfony\Component\Process\Process; |
||
22 | use Symfony\Component\Yaml\Yaml; |
||
23 | |||
24 | /** |
||
25 | * A manager for composer events |
||
26 | */ |
||
27 | class ScriptHandler |
||
28 | { |
||
29 | /** |
||
30 | * Shows what changed since the last update |
||
31 | * |
||
32 | * @param $event Event Composer's event |
||
33 | */ |
||
34 | public static function showChangelog(Event $event) |
||
35 | { |
||
36 | static::executeCommand($event, 'bzion:changes'); |
||
37 | } |
||
38 | |||
39 | /** |
||
40 | * Clears the Symfony cache. |
||
41 | * |
||
42 | * This command won't fail if the current cache prevents the kernel from |
||
43 | * booting |
||
44 | * |
||
45 | * @param $event Event Composer's event |
||
46 | * @param $env string|null The environment to clear the cache for, 'all' |
||
47 | * to clear the cache for all environments, null |
||
48 | * to pick an environment based on command line |
||
49 | * arguments (defaults to 'all') |
||
50 | */ |
||
51 | public static function clearCache(Event $event, $env = null) |
||
52 | { |
||
53 | $io = $event->getIO(); |
||
54 | $args = $event->getArguments(); |
||
55 | |||
56 | if ($env === null) { |
||
57 | if (isset($args[0])) { |
||
58 | $env = $args[0]; |
||
59 | } elseif (getenv('SYMFONY_ENV')) { |
||
60 | $env = getenv('SYMFONY_ENV'); |
||
61 | } else { |
||
62 | $env = 'all'; |
||
63 | } |
||
64 | } |
||
65 | |||
66 | // Delete all cache files |
||
67 | $finder = new Finder(); |
||
68 | $cacheDirectory = __DIR__ . '/../../app/cache/'; |
||
69 | |||
70 | $fs = new Filesystem(); |
||
71 | |||
72 | $clear = true; |
||
73 | |||
74 | // We make sure that the root directories for each environment aren't |
||
75 | // removed, so that permission settings are kept |
||
76 | if ($env === 'all') { |
||
77 | $io->write("Clearing cache for <fg=green;bold>all</> environments"); |
||
78 | $finder->in($cacheDirectory)->depth('== 1'); |
||
79 | } else { |
||
80 | $directory = $cacheDirectory . str_replace('/', '', $env); |
||
81 | |||
82 | if ($fs->exists($directory)) { |
||
83 | $io->write("Clearing cache for the <fg=green>$env</> environment"); |
||
84 | $finder->in($directory)->depth('== 0'); |
||
85 | } else { |
||
86 | $io->write("Cache directory for the <fg=green>$env</> environment doesn't exist and won't be cleared"); |
||
87 | $clear = false; |
||
88 | } |
||
89 | } |
||
90 | |||
91 | if ($clear) { |
||
92 | // We use Symfony's Filesystem component to delete files recursively |
||
93 | $fs->remove($finder); |
||
0 ignored issues
–
show
|
|||
94 | } |
||
95 | |||
96 | if ($env === 'prod' || $env === 'all') { |
||
97 | static::executeCommand($event, 'cache:warmup'); |
||
98 | } |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Clear the cache for all environments |
||
103 | * |
||
104 | * @param $event Event Composer's event |
||
105 | */ |
||
106 | public static function clearAllCaches(Event $event) |
||
107 | { |
||
108 | return static::clearCache($event, 'all'); |
||
109 | } |
||
110 | |||
111 | /** |
||
112 | * Initialize the last update file so that when the user updates and asks |
||
113 | * for the changelog, the entries added before the installation are not shown |
||
114 | * |
||
115 | * @param $event Event Composer's event |
||
116 | */ |
||
117 | public static function initializeChangelog(Event $event) |
||
118 | { |
||
119 | static::executeCommand($event, 'bzion:changes --read'); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Migrate the config.yml file |
||
124 | * |
||
125 | * @param $event Event Composer's event |
||
126 | */ |
||
127 | public static function buildConfig(Event $event) |
||
128 | { |
||
129 | $configHandler = new ConfigHandler($event); |
||
130 | $configHandler->build(); |
||
131 | } |
||
132 | |||
133 | /* |
||
134 | * Create and update the database schema |
||
135 | * |
||
136 | * @param $event Event|null Composer's event |
||
137 | * @param $testing boolean Whether to migrate the testing database (only applicable when $event is null) |
||
138 | */ |
||
139 | 1 | public static function migrateDatabase(Event $event = null, $testing = false) |
|
140 | { |
||
141 | 1 | if ($event) { |
|
142 | // Use the event's IO |
||
143 | $io = $event->getIO(); |
||
144 | |||
145 | $arguments = $event->getArguments(); |
||
146 | |||
147 | $testingArguments = array('testing', '--testing', '-t'); |
||
148 | $testing = count(array_intersect($arguments, $testingArguments)) > 0; |
||
149 | } else { |
||
150 | // Create our own IO |
||
151 | 1 | $input = new ArrayInput(array()); |
|
152 | 1 | $output = new ConsoleOutput(); |
|
153 | 1 | $helperSet = new HelperSet(array(new QuestionHelper())); |
|
154 | |||
155 | 1 | $io = new ConsoleIO($input, $output, $helperSet); |
|
156 | } |
||
157 | |||
158 | try { |
||
159 | 1 | $config = self::getDatabaseConfig($testing); |
|
160 | } catch (\Exception $e) { |
||
161 | $io->write("<bg=red>\n\n [WARNING] " . $e->getMessage() . ", the database won't be updated\n</>"); |
||
162 | |||
163 | return; |
||
164 | } |
||
165 | |||
166 | // If the database doesn't exist, ask the user to create it and perform |
||
167 | // the necessary migrations (unless the user didn't agree to |
||
168 | // create the database) |
||
169 | 1 | if (self::createDatabase($io, $config['host'], $config['username'], $config['password'], $config['database'])) { |
|
170 | 1 | $io->write(''); // newline |
|
171 | |||
172 | 1 | $arguments = array('migrate', '-e' => ($testing) ? 'test' : 'main'); |
|
173 | 1 | $app = new PhinxApplication(); |
|
174 | 1 | $app->doRun(new ArrayInput($arguments), new ConsoleOutput()); |
|
175 | } |
||
176 | 1 | } |
|
177 | |||
178 | /** |
||
179 | * Shows an installation success message |
||
180 | * |
||
181 | * @param $event Event Composer's event |
||
182 | */ |
||
183 | public static function showSuccessMessage(Event $event) |
||
184 | { |
||
185 | static::executeCommand($event, 'bzion:success'); |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Create the database schema if needed |
||
190 | * |
||
191 | * @param IOInterface $io Composer's IO interface |
||
192 | * @param string $host The database host |
||
193 | * @param string $username The username for the MySQL user |
||
194 | * @param string $password The password for the MySQL user |
||
195 | * @param string $database The name of the database |
||
196 | * |
||
197 | * @return bool Whether the database was created |
||
198 | */ |
||
199 | 1 | private static function createDatabase(IOInterface $io, $host, $username, $password, $database) |
|
200 | { |
||
201 | 1 | $io->write(" Connecting to MySQL database $database@$host"); |
|
202 | |||
203 | 1 | $dsn = 'mysql:host=' . $host . ';charset=UTF8'; |
|
204 | 1 | $pdo = new \PDO($dsn, $username, $password); |
|
205 | |||
206 | 1 | $statement = $pdo->prepare("USE `$database`"); |
|
207 | 1 | $status = $statement->execute(); |
|
208 | 1 | $errors = $statement->errorInfo(); |
|
209 | |||
210 | // Throw an exception on error for any query that will be sent next |
||
211 | 1 | $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); |
|
212 | |||
213 | // 1049 is the error code thrown when the database doesn't exist, but |
||
214 | // the MySQL user has the privilege to see it |
||
215 | 1 | if ($errors[1] == 1049) { |
|
216 | $answer = $io->askConfirmation( |
||
217 | " <fg=green>The $database database doesn't exist. Would you like to have it created? (yes/no)</> [<comment>yes</comment>]\n > ", |
||
218 | true); |
||
219 | |||
220 | if ($answer) { |
||
221 | $pdo->query("CREATE DATABASE `$database` COLLATE utf8_unicode_ci"); |
||
222 | $pdo->query("USE `$database`"); |
||
223 | |||
224 | $io->write(" <fg=green>New database created</>"); |
||
225 | } else { |
||
226 | return false; |
||
227 | } |
||
228 | 1 | } elseif (!$status) { |
|
229 | throw new \Exception("Unable to connect to database: " . $errors[2]); |
||
230 | } |
||
231 | |||
232 | // If the database is empty, fill it |
||
233 | 1 | if ($pdo->query('SHOW TABLES')->rowCount() === 0) { |
|
234 | 1 | $io->write(" <fg=green>Creating database schema...</> ", false); |
|
235 | |||
236 | 1 | $sqlPath = realpath(__DIR__ . '/../../migrations/' . 'DATABASE.sql'); |
|
237 | 1 | $pdo->exec(file_get_contents($sqlPath)); |
|
238 | |||
239 | 1 | $io->write("<fg=green>done.</>"); |
|
240 | } |
||
241 | |||
242 | 1 | return true; |
|
243 | } |
||
244 | |||
245 | /** |
||
246 | * Execute a symfony console command |
||
247 | * |
||
248 | * @param Event $event Composer's event |
||
249 | * @param string $command The command to execute |
||
250 | * @param int $timeout The timeout of the command in seconds |
||
251 | * @return void |
||
252 | */ |
||
253 | protected static function executeCommand(Event $event, $command, $timeout = 300) |
||
254 | { |
||
255 | $console = escapeshellarg(__DIR__ . '/../../app/console') . ' --env=prod'; |
||
256 | |||
257 | if ($event->getIO()->isDecorated()) { |
||
258 | $console .= ' --ansi'; |
||
259 | } |
||
260 | |||
261 | $process = new Process("$console $command", null, null, null, $timeout); |
||
262 | $process->run(function ($type, $buffer) use ($event) { $event->getIO()->write($buffer, false); }); |
||
263 | |||
264 | if (!$process->isSuccessful()) { |
||
265 | throw new \RuntimeException(sprintf('An error occurred when executing the "%s" command.', escapeshellarg($command))); |
||
266 | } |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Get the database's configuration |
||
271 | * |
||
272 | * @param bool $testing Whether to retrieve the test database credentials |
||
273 | * @return array|null The configuration as defined in the config.yml file, null if no configuration was found |
||
274 | */ |
||
275 | 1 | public static function getDatabaseConfig($testing = false) |
|
276 | { |
||
277 | 1 | $configPath = ConfigHandler::getConfigurationPath(); |
|
278 | 1 | if (!is_file($configPath)) { |
|
279 | throw new \Exception("The configuration file could not be read"); |
||
280 | } |
||
281 | |||
282 | 1 | $path = $testing ? 'testing' : 'mysql'; |
|
283 | |||
284 | 1 | $config = Yaml::parse(file_get_contents($configPath)); |
|
285 | |||
286 | 1 | if (isset($config['bzion'][$path])) { |
|
287 | 1 | return $config['bzion'][$path]; |
|
288 | } |
||
289 | |||
290 | return null; |
||
291 | } |
||
292 | } |
||
293 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: