aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Wallabag/CoreBundle/Command/InstallCommand.php270
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php45
-rw-r--r--src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php2
-rw-r--r--src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php61
4 files changed, 314 insertions, 64 deletions
diff --git a/src/Wallabag/CoreBundle/Command/InstallCommand.php b/src/Wallabag/CoreBundle/Command/InstallCommand.php
index c1b72604..a528c309 100644
--- a/src/Wallabag/CoreBundle/Command/InstallCommand.php
+++ b/src/Wallabag/CoreBundle/Command/InstallCommand.php
@@ -4,134 +4,194 @@ namespace Wallabag\CoreBundle\Command;
4 4
5use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 5use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6use Symfony\Component\Console\Input\InputInterface; 6use Symfony\Component\Console\Input\InputInterface;
7use Symfony\Component\Console\Input\InputOption;
8use Symfony\Component\Console\Input\ArrayInput;
7use Symfony\Component\Console\Output\OutputInterface; 9use Symfony\Component\Console\Output\OutputInterface;
10use Symfony\Component\Console\Output\NullOutput;
8use Wallabag\CoreBundle\Entity\User; 11use Wallabag\CoreBundle\Entity\User;
9use Wallabag\CoreBundle\Entity\Config; 12use Wallabag\CoreBundle\Entity\Config;
10 13
11class InstallCommand extends ContainerAwareCommand 14class 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
@@ -141,16 +201,100 @@ class InstallCommand extends ContainerAwareCommand
141 $config->setLanguage($this->getContainer()->getParameter('language')); 201 $config->setLanguage($this->getContainer()->getParameter('language'));
142 202
143 $em->persist($config); 203 $em->persist($config);
204
205 $em->flush();
206
207 $this->defaultOutput->writeln('');
208
209 return $this;
144 } 210 }
145 211
146 protected function runCommand($command, InputInterface $input, OutputInterface $output) 212 protected function setupAsset()
147 { 213 {
214 $this->defaultOutput->writeln('<info><comment>Step 4 of 4.</comment> Installing assets.</info>');
215
148 $this 216 $this
149 ->getApplication() 217 ->runCommand('assets:install')
150 ->find($command) 218 ->runCommand('assetic:dump')
151 ->run($input, $output)
152 ; 219 ;
153 220
221 $this->defaultOutput->writeln('');
222
223 return $this;
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
154 return $this; 264 return $this;
155 } 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 return in_array($databaseName, $schemaManager->listDatabases());
287 }
288
289 /**
290 * Check if the schema is already created
291 *
292 * @return boolean
293 */
294 private function isSchemaPresent()
295 {
296 $schemaManager = $this->getContainer()->get('doctrine')->getManager()->getConnection()->getSchemaManager();
297
298 return $schemaManager->tablesExist(array('entry'));
299 }
156} 300}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php
new file mode 100644
index 00000000..900e151d
--- /dev/null
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadConfigData.php
@@ -0,0 +1,45 @@
1<?php
2
3namespace Wallabag\CoreBundle\DataFixtures\ORM;
4
5use Doctrine\Common\DataFixtures\AbstractFixture;
6use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
7use Doctrine\Common\Persistence\ObjectManager;
8use Wallabag\CoreBundle\Entity\Config;
9
10class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
11{
12 /**
13 * {@inheritDoc}
14 */
15 public function load(ObjectManager $manager)
16 {
17 $adminConfig = new Config($this->getReference('admin-user'));
18 $adminConfig->setTheme('baggy');
19 $adminConfig->setItemsPerPage(30);
20 $adminConfig->setLanguage('en_US');
21
22 $manager->persist($adminConfig);
23
24 $this->addReference('admin-config', $adminConfig);
25
26 $bobConfig = new Config($this->getReference('bob-user'));
27 $bobConfig->setTheme('default');
28 $bobConfig->setItemsPerPage(10);
29 $bobConfig->setLanguage('fr_FR');
30
31 $manager->persist($bobConfig);
32
33 $this->addReference('bob-config', $bobConfig);
34
35 $manager->flush();
36 }
37
38 /**
39 * {@inheritDoc}
40 */
41 public function getOrder()
42 {
43 return 20;
44 }
45}
diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
index 520b44b8..3be323ed 100644
--- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
+++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php
@@ -49,6 +49,6 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface
49 */ 49 */
50 public function getOrder() 50 public function getOrder()
51 { 51 {
52 return 20; 52 return 30;
53 } 53 }
54} 54}
diff --git a/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php
new file mode 100644
index 00000000..6bcc9707
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php
@@ -0,0 +1,61 @@
1<?php
2
3namespace Wallabag\CoreBundle\Tests\Command;
4
5use Wallabag\CoreBundle\Tests\WallabagTestCase;
6use Wallabag\CoreBundle\Command\InstallCommand;
7use Symfony\Bundle\FrameworkBundle\Console\Application;
8use Symfony\Component\Console\Tester\CommandTester;
9use Symfony\Component\Console\Input\ArrayInput;
10use Symfony\Component\Console\Output\NullOutput;
11
12class InstallCommandTest extends WallabagTestCase
13{
14 public function tearDown()
15 {
16 parent::tearDown();
17
18 $application = new Application(static::$kernel);
19 $application->setAutoExit(false);
20
21 $code = $application->run(new ArrayInput(array(
22 'command' => 'doctrine:fixtures:load',
23 '--no-interaction' => true,
24 '--env' => 'test',
25 )), new NullOutput());
26 }
27
28 public function testRunInstallCommand()
29 {
30 $this->container = static::$kernel->getContainer();
31
32 $application = new Application(static::$kernel);
33 $application->add(new InstallCommand());
34
35 $command = $application->find('wallabag:install');
36
37 // We mock the DialogHelper
38 $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper')
39 ->disableOriginalConstructor()
40 ->getMock();
41 $dialog->expects($this->any())
42 ->method('ask')
43 ->will($this->returnValue('test'));
44 $dialog->expects($this->any())
45 ->method('askConfirmation')
46 ->will($this->returnValue(true));
47
48 // We override the standard helper with our mock
49 $command->getHelperSet()->set($dialog, 'dialog');
50
51 $tester = new CommandTester($command);
52 $tester->execute(array(
53 'command' => $command->getName()
54 ));
55
56 $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay());
57 $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay());
58 $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay());
59 $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay());
60 }
61}