diff options
Diffstat (limited to 'src/Wallabag/CoreBundle/Command/InstallCommand.php')
-rw-r--r-- | src/Wallabag/CoreBundle/Command/InstallCommand.php | 296 |
1 files changed, 221 insertions, 75 deletions
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php index feaaebf6..ac7583ea 100644 --- a/src/Wallabag/CoreBundle/Command/InstallCommand.php +++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php | |||
@@ -4,162 +4,308 @@ namespace Wallabag\CoreBundle\Command; | |||
4 | 4 | ||
5 | use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | 5 | use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
6 | use Symfony\Component\Console\Input\InputInterface; | 6 | use Symfony\Component\Console\Input\InputInterface; |
7 | use Symfony\Component\Console\Input\InputOption; | ||
8 | use Symfony\Component\Console\Input\ArrayInput; | ||
7 | use Symfony\Component\Console\Output\OutputInterface; | 9 | use Symfony\Component\Console\Output\OutputInterface; |
10 | use Symfony\Component\Console\Output\NullOutput; | ||
8 | use Wallabag\CoreBundle\Entity\User; | 11 | use Wallabag\CoreBundle\Entity\User; |
9 | use Wallabag\CoreBundle\Entity\UsersConfig; | 12 | use Wallabag\CoreBundle\Entity\Config; |
10 | 13 | ||
11 | class InstallCommand extends ContainerAwareCommand | 14 | class InstallCommand extends ContainerAwareCommand |
12 | { | 15 | { |
16 | /** | ||
17 | * @var InputInterface | ||
18 | */ | ||
19 | protected $defaultInput; | ||
20 | |||
21 | /** | ||
22 | * @var OutputInterface | ||
23 | */ | ||
24 | protected $defaultOutput; | ||
25 | |||
13 | protected function configure() | 26 | protected function configure() |
14 | { | 27 | { |
15 | $this | 28 | $this |
16 | ->setName('wallabag:install') | 29 | ->setName('wallabag:install') |
17 | ->setDescription('Wallabag installer.') | 30 | ->setDescription('Wallabag installer.') |
31 | ->addOption( | ||
32 | 'reset', | ||
33 | null, | ||
34 | InputOption::VALUE_NONE, | ||
35 | 'Reset current database' | ||
36 | ) | ||
18 | ; | 37 | ; |
19 | } | 38 | } |
20 | 39 | ||
21 | protected function execute(InputInterface $input, OutputInterface $output) | 40 | protected function execute(InputInterface $input, OutputInterface $output) |
22 | { | 41 | { |
23 | $output->writeln('<info>Installing Wallabag.</info>'); | 42 | $this->defaultInput = $input; |
43 | $this->defaultOutput = $output; | ||
44 | |||
45 | $output->writeln('<info>Installing Wallabag...</info>'); | ||
24 | $output->writeln(''); | 46 | $output->writeln(''); |
25 | 47 | ||
26 | $this | 48 | $this |
27 | ->checkStep($output) | 49 | ->checkRequirements() |
28 | ->setupStep($input, $output) | 50 | ->setupDatabase() |
51 | ->setupAdmin() | ||
52 | ->setupAsset() | ||
29 | ; | 53 | ; |
30 | 54 | ||
31 | $output->writeln('<info>Wallabag has been successfully installed.</info>'); | 55 | $output->writeln('<info>Wallabag has been successfully installed.</info>'); |
32 | $output->writeln('<comment>Just execute `php app/console server:run` for using wallabag: http://localhost:8000</comment>'); | 56 | $output->writeln('<comment>Just execute `php app/console server:run` for using wallabag: http://localhost:8000</comment>'); |
33 | } | 57 | } |
34 | 58 | ||
35 | protected function checkStep(OutputInterface $output) | 59 | protected function checkRequirements() |
36 | { | 60 | { |
37 | $output->writeln('<info>Checking system requirements.</info>'); | 61 | $this->defaultOutput->writeln('<info><comment>Step 1 of 4.</comment> Checking system requirements.</info>'); |
38 | 62 | ||
39 | $fulfilled = true; | 63 | $fulfilled = true; |
40 | 64 | ||
41 | // @TODO: find a better way to check requirements | 65 | // @TODO: find a better way to check requirements |
42 | $output->writeln('<comment>Check PCRE</comment>'); | 66 | $label = '<comment>PCRE</comment>'; |
43 | if (extension_loaded('pcre')) { | 67 | if (extension_loaded('pcre')) { |
44 | $output->writeln(' <info>OK</info>'); | 68 | $status = '<info>OK!</info>'; |
69 | $help = ''; | ||
45 | } else { | 70 | } else { |
46 | $fulfilled = false; | 71 | $fulfilled = false; |
47 | $output->writeln(' <error>ERROR</error>'); | 72 | $status = '<error>ERROR!</error>'; |
48 | $output->writeln('<comment>You should enabled PCRE extension</comment>'); | 73 | $help = 'You should enabled PCRE extension'; |
49 | } | 74 | } |
75 | $rows[] = array($label, $status, $help); | ||
50 | 76 | ||
51 | $output->writeln('<comment>Check DOM</comment>'); | 77 | $label = '<comment>DOM</comment>'; |
52 | if (extension_loaded('DOM')) { | 78 | if (extension_loaded('DOM')) { |
53 | $output->writeln(' <info>OK</info>'); | 79 | $status = '<info>OK!</info>'; |
80 | $help = ''; | ||
54 | } else { | 81 | } else { |
55 | $fulfilled = false; | 82 | $fulfilled = false; |
56 | $output->writeln(' <error>ERROR</error>'); | 83 | $status = '<error>ERROR!</error>'; |
57 | $output->writeln('<comment>You should enabled DOM extension</comment>'); | 84 | $help = 'You should enabled DOM extension'; |
58 | } | 85 | } |
86 | $rows[] = array($label, $status, $help); | ||
87 | |||
88 | $this->getHelper('table') | ||
89 | ->setHeaders(array('Checked', 'Status', 'Recommendation')) | ||
90 | ->setRows($rows) | ||
91 | ->render($this->defaultOutput); | ||
59 | 92 | ||
60 | if (!$fulfilled) { | 93 | if (!$fulfilled) { |
61 | throw new RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.'); | 94 | throw new \RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.'); |
95 | } else { | ||
96 | $this->defaultOutput->writeln('<info>Success! Your system can run Wallabag properly.</info>'); | ||
62 | } | 97 | } |
63 | 98 | ||
64 | $output->writeln(''); | 99 | $this->defaultOutput->writeln(''); |
65 | 100 | ||
66 | return $this; | 101 | return $this; |
67 | } | 102 | } |
68 | 103 | ||
69 | protected function setupStep(InputInterface $input, OutputInterface $output) | 104 | protected function setupDatabase() |
70 | { | 105 | { |
71 | $output->writeln('<info>Setting up database.</info>'); | 106 | $this->defaultOutput->writeln('<info><comment>Step 2 of 4.</comment> Setting up database.</info>'); |
72 | 107 | ||
73 | $this->setupDatabase($input, $output); | 108 | // user want to reset everything? Don't care about what is already here |
109 | if (true === $this->defaultInput->getOption('reset')) { | ||
110 | $this->defaultOutput->writeln('Droping database, creating database and schema'); | ||
74 | 111 | ||
75 | // if ($this->getHelperSet()->get('dialog')->askConfirmation($output, '<question>Load fixtures (Y/N)?</question>', false)) { | 112 | $this |
76 | // $this->setupFixtures($input, $output); | 113 | ->runCommand('doctrine:database:drop', array('--force' => true)) |
77 | // } | 114 | ->runCommand('doctrine:database:create') |
115 | ->runCommand('doctrine:schema:create') | ||
116 | ; | ||
78 | 117 | ||
79 | $output->writeln(''); | 118 | return $this; |
80 | $output->writeln('<info>Administration setup.</info>'); | 119 | } |
81 | 120 | ||
82 | $this->setupAdmin($output); | 121 | if (!$this->isDatabasePresent()) { |
122 | $this->defaultOutput->writeln('Creating database and schema, clearing the cache'); | ||
83 | 123 | ||
84 | $output->writeln(''); | 124 | $this |
125 | ->runCommand('doctrine:database:create') | ||
126 | ->runCommand('doctrine:schema:create') | ||
127 | ->runCommand('cache:clear') | ||
128 | ; | ||
85 | 129 | ||
86 | return $this; | 130 | return $this; |
87 | } | 131 | } |
88 | 132 | ||
89 | protected function setupDatabase(InputInterface $input, OutputInterface $output) | 133 | $dialog = $this->getHelper('dialog'); |
90 | { | ||
91 | if ($this->getHelperSet()->get('dialog')->askConfirmation($output, '<question>Drop current database (Y/N)?</question>', true)) { | ||
92 | $connection = $this->getContainer()->get('doctrine')->getConnection(); | ||
93 | $params = $connection->getParams(); | ||
94 | 134 | ||
95 | $name = isset($params['path']) ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false); | 135 | if ($dialog->askConfirmation($this->defaultOutput, '<question>It appears that your database already exists. Would you like to reset it? (y/N)</question> ', false)) { |
96 | unset($params['dbname']); | 136 | $this->defaultOutput->writeln('Droping database, creating database and schema'); |
97 | 137 | ||
98 | if (!isset($params['path'])) { | 138 | $this |
99 | $name = $connection->getDatabasePlatform()->quoteSingleIdentifier($name); | 139 | ->runCommand('doctrine:database:drop', array('--force' => true)) |
100 | } | 140 | ->runCommand('doctrine:database:create') |
141 | ->runCommand('doctrine:schema:create') | ||
142 | ; | ||
143 | } elseif ($this->isSchemaPresent()) { | ||
144 | if ($dialog->askConfirmation($this->defaultOutput, '<question>Seems like your database contains schema. Do you want to reset it? (y/N)</question> ', false)) { | ||
145 | $this->defaultOutput->writeln('Droping schema and creating schema'); | ||
101 | 146 | ||
102 | $connection->getSchemaManager()->dropDatabase($name); | 147 | $this |
148 | ->runCommand('doctrine:schema:drop', array('--force' => true)) | ||
149 | ->runCommand('doctrine:schema:create') | ||
150 | ; | ||
151 | } | ||
103 | } else { | 152 | } else { |
104 | throw new \Exception("Install setup stopped, database need to be dropped. Please backup your current one and re-launch the install command."); | 153 | $this->defaultOutput->writeln('Creating schema'); |
154 | |||
155 | $this | ||
156 | ->runCommand('doctrine:schema:create') | ||
157 | ; | ||
105 | } | 158 | } |
106 | 159 | ||
107 | $this | 160 | $this->defaultOutput->writeln('Clearing the cache'); |
108 | ->runCommand('doctrine:database:create', $input, $output) | 161 | $this->runCommand('cache:clear'); |
109 | ->runCommand('doctrine:schema:create', $input, $output) | 162 | |
110 | ->runCommand('cache:clear', $input, $output) | 163 | /* |
111 | ->runCommand('assets:install', $input, $output) | 164 | if ($this->getHelperSet()->get('dialog')->askConfirmation($this->defaultOutput, '<question>Load fixtures (Y/N)?</question>', false)) { |
112 | ->runCommand('assetic:dump', $input, $output) | 165 | $doctrineConfig = $this->getContainer()->get('doctrine.orm.entity_manager')->getConnection()->getConfiguration(); |
113 | ; | 166 | $logger = $doctrineConfig->getSQLLogger(); |
114 | } | 167 | // speed up fixture load |
168 | $doctrineConfig->setSQLLogger(null); | ||
169 | $this->runCommand('doctrine:fixtures:load'); | ||
170 | $doctrineConfig->setSQLLogger($logger); | ||
171 | } | ||
172 | */ | ||
115 | 173 | ||
116 | protected function setupFixtures(InputInterface $input, OutputInterface $output) | 174 | $this->defaultOutput->writeln(''); |
117 | { | 175 | |
118 | $doctrineConfig = $this->getContainer()->get('doctrine.orm.entity_manager')->getConnection()->getConfiguration(); | 176 | return $this; |
119 | $logger = $doctrineConfig->getSQLLogger(); | ||
120 | // speed up fixture load | ||
121 | $doctrineConfig->setSQLLogger(null); | ||
122 | $this->runCommand('doctrine:fixtures:load', $input, $output); | ||
123 | $doctrineConfig->setSQLLogger($logger); | ||
124 | } | 177 | } |
125 | 178 | ||
126 | protected function setupAdmin(OutputInterface $output) | 179 | protected function setupAdmin() |
127 | { | 180 | { |
181 | $this->defaultOutput->writeln('<info><comment>Step 3 of 4.</comment> Administration setup.</info>'); | ||
182 | |||
128 | $dialog = $this->getHelperSet()->get('dialog'); | 183 | $dialog = $this->getHelperSet()->get('dialog'); |
184 | |||
185 | if (false === $dialog->askConfirmation($this->defaultOutput, '<question>Would you like to create a new user ? (y/N)</question>', true)) { | ||
186 | return $this; | ||
187 | } | ||
188 | |||
129 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); | 189 | $em = $this->getContainer()->get('doctrine.orm.entity_manager'); |
130 | 190 | ||
131 | $user = new User(); | 191 | $user = new User(); |
132 | $user->setUsername($dialog->ask($output, '<question>Username</question> <comment>(default: wallabag)</comment> :', 'wallabag')); | 192 | $user->setUsername($dialog->ask($this->defaultOutput, '<question>Username</question> <comment>(default: wallabag)</comment> :', 'wallabag')); |
133 | $user->setPassword($dialog->ask($output, '<question>Password</question> <comment>(default: wallabag)</comment> :', 'wallabag')); | 193 | $user->setPassword($dialog->ask($this->defaultOutput, '<question>Password</question> <comment>(default: wallabag)</comment> :', 'wallabag')); |
134 | $user->setEmail($dialog->ask($output, '<question>Email:</question>', '')); | 194 | $user->setEmail($dialog->ask($this->defaultOutput, '<question>Email:</question>', '')); |
135 | 195 | ||
136 | $em->persist($user); | 196 | $em->persist($user); |
137 | 197 | ||
138 | $pagerConfig = new UsersConfig(); | 198 | $config = new Config($user); |
139 | $pagerConfig->setUserId($user->getId()); | 199 | $config->setTheme($this->getContainer()->getParameter('theme')); |
140 | $pagerConfig->setName('pager'); | 200 | $config->setItemsPerPage($this->getContainer()->getParameter('items_on_page')); |
141 | $pagerConfig->setValue(10); | 201 | $config->setLanguage($this->getContainer()->getParameter('language')); |
142 | 202 | ||
143 | $em->persist($pagerConfig); | 203 | $em->persist($config); |
144 | 204 | ||
145 | // $languageConfig = new LanguageConfig(); | 205 | $em->flush(); |
146 | // $languageConfig->setUserId($user->getId()); | ||
147 | // $languageConfig->setName('language'); | ||
148 | // $languageConfig->setValue('en_EN.UTF8'); | ||
149 | 206 | ||
150 | // $em->persist($languageConfig); | 207 | $this->defaultOutput->writeln(''); |
151 | 208 | ||
152 | $em->flush(); | 209 | return $this; |
153 | } | 210 | } |
154 | 211 | ||
155 | protected function runCommand($command, InputInterface $input, OutputInterface $output) | 212 | protected function setupAsset() |
156 | { | 213 | { |
214 | $this->defaultOutput->writeln('<info><comment>Step 4 of 4.</comment> Installing assets.</info>'); | ||
215 | |||
157 | $this | 216 | $this |
158 | ->getApplication() | 217 | ->runCommand('assets:install') |
159 | ->find($command) | 218 | ->runCommand('assetic:dump') |
160 | ->run($input, $output) | ||
161 | ; | 219 | ; |
162 | 220 | ||
221 | $this->defaultOutput->writeln(''); | ||
222 | |||
163 | return $this; | 223 | return $this; |
164 | } | 224 | } |
225 | |||
226 | /** | ||
227 | * Run a command | ||
228 | * | ||
229 | * @param string $command | ||
230 | * @param array $parameters Parameters to this command (usually 'force' => true) | ||
231 | */ | ||
232 | protected function runCommand($command, $parameters = array()) | ||
233 | { | ||
234 | $parameters = array_merge( | ||
235 | array('command' => $command), | ||
236 | $parameters, | ||
237 | array( | ||
238 | '--no-debug' => true, | ||
239 | '--env' => $this->defaultInput->getOption('env') ?: 'dev', | ||
240 | ) | ||
241 | ); | ||
242 | |||
243 | if ($this->defaultInput->getOption('no-interaction')) { | ||
244 | $parameters = array_merge($parameters, array('--no-interaction' => true)); | ||
245 | } | ||
246 | |||
247 | $this->getApplication()->setAutoExit(false); | ||
248 | $exitCode = $this->getApplication()->run(new ArrayInput($parameters), new NullOutput()); | ||
249 | |||
250 | if (0 !== $exitCode) { | ||
251 | $this->getApplication()->setAutoExit(true); | ||
252 | |||
253 | $errorMessage = sprintf('The command "%s" terminated with an error code: %u.', $command, $exitCode); | ||
254 | $this->defaultOutput->writeln("<error>$errorMessage</error>"); | ||
255 | $exception = new \Exception($errorMessage, $exitCode); | ||
256 | |||
257 | throw $exception; | ||
258 | } | ||
259 | |||
260 | // PDO does not always close the connection after Doctrine commands. | ||
261 | // See https://github.com/symfony/symfony/issues/11750. | ||
262 | $this->getContainer()->get('doctrine')->getManager()->getConnection()->close(); | ||
263 | |||
264 | return $this; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * Check if the database already exists | ||
269 | * | ||
270 | * @return boolean | ||
271 | */ | ||
272 | private function isDatabasePresent() | ||
273 | { | ||
274 | $databaseName = $this->getContainer()->getParameter('database_name'); | ||
275 | |||
276 | try { | ||
277 | $schemaManager = $this->getContainer()->get('doctrine')->getManager()->getConnection()->getSchemaManager(); | ||
278 | } catch (\Exception $exception) { | ||
279 | if (false !== strpos($exception->getMessage(), sprintf("Unknown database '%s'", $databaseName))) { | ||
280 | return false; | ||
281 | } | ||
282 | |||
283 | throw $exception; | ||
284 | } | ||
285 | |||
286 | // custom verification for sqlite, since `getListDatabasesSQL` doesn't work for sqlite | ||
287 | if ('sqlite' == $schemaManager->getDatabasePlatform()->getName()) { | ||
288 | $params = $this->getContainer()->get('doctrine.dbal.default_connection')->getParams(); | ||
289 | |||
290 | if (isset($params['path']) && file_exists($params['path'])) { | ||
291 | return true; | ||
292 | } | ||
293 | |||
294 | return false; | ||
295 | } | ||
296 | |||
297 | return in_array($databaseName, $schemaManager->listDatabases()); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * Check if the schema is already created | ||
302 | * | ||
303 | * @return boolean | ||
304 | */ | ||
305 | private function isSchemaPresent() | ||
306 | { | ||
307 | $schemaManager = $this->getContainer()->get('doctrine')->getManager()->getConnection()->getSchemaManager(); | ||
308 | |||
309 | return $schemaManager->tablesExist(array('entry')); | ||
310 | } | ||
165 | } | 311 | } |