diff options
Diffstat (limited to 'src')
29 files changed, 1574 insertions, 299 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 | } |
diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php new file mode 100644 index 00000000..68e034fa --- /dev/null +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php | |||
@@ -0,0 +1,128 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Controller; | ||
4 | |||
5 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
6 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
7 | use Symfony\Component\HttpFoundation\Request; | ||
8 | use Wallabag\CoreBundle\Entity\Config; | ||
9 | use Wallabag\CoreBundle\Entity\User; | ||
10 | use Wallabag\CoreBundle\Form\Type\ConfigType; | ||
11 | use Wallabag\CoreBundle\Form\Type\ChangePasswordType; | ||
12 | use Wallabag\CoreBundle\Form\Type\UserType; | ||
13 | use Wallabag\CoreBundle\Form\Type\NewUserType; | ||
14 | |||
15 | class ConfigController extends Controller | ||
16 | { | ||
17 | /** | ||
18 | * @param Request $request | ||
19 | * | ||
20 | * @Route("/config", name="config") | ||
21 | */ | ||
22 | public function indexAction(Request $request) | ||
23 | { | ||
24 | $em = $this->getDoctrine()->getManager(); | ||
25 | $config = $this->getConfig(); | ||
26 | $user = $this->getUser(); | ||
27 | |||
28 | // handle basic config detail | ||
29 | $configForm = $this->createForm(new ConfigType(), $config); | ||
30 | $configForm->handleRequest($request); | ||
31 | |||
32 | if ($configForm->isValid()) { | ||
33 | $em->persist($config); | ||
34 | $em->flush(); | ||
35 | |||
36 | $this->get('session')->getFlashBag()->add( | ||
37 | 'notice', | ||
38 | 'Config saved' | ||
39 | ); | ||
40 | |||
41 | return $this->redirect($this->generateUrl('config')); | ||
42 | } | ||
43 | |||
44 | // handle changing password | ||
45 | $pwdForm = $this->createForm(new ChangePasswordType()); | ||
46 | $pwdForm->handleRequest($request); | ||
47 | |||
48 | if ($pwdForm->isValid()) { | ||
49 | $user->setPassword($pwdForm->get('new_password')->getData()); | ||
50 | $em->persist($user); | ||
51 | $em->flush(); | ||
52 | |||
53 | $this->get('session')->getFlashBag()->add( | ||
54 | 'notice', | ||
55 | 'Password updated' | ||
56 | ); | ||
57 | |||
58 | return $this->redirect($this->generateUrl('config')); | ||
59 | } | ||
60 | |||
61 | // handle changing user information | ||
62 | $userForm = $this->createForm(new UserType(), $user); | ||
63 | $userForm->handleRequest($request); | ||
64 | |||
65 | if ($userForm->isValid()) { | ||
66 | $em->persist($user); | ||
67 | $em->flush(); | ||
68 | |||
69 | $this->get('session')->getFlashBag()->add( | ||
70 | 'notice', | ||
71 | 'Information updated' | ||
72 | ); | ||
73 | |||
74 | return $this->redirect($this->generateUrl('config')); | ||
75 | } | ||
76 | |||
77 | // handle adding new user | ||
78 | $newUser = new User(); | ||
79 | $newUserForm = $this->createForm(new NewUserType(), $newUser); | ||
80 | $newUserForm->handleRequest($request); | ||
81 | |||
82 | if ($newUserForm->isValid()) { | ||
83 | $em->persist($newUser); | ||
84 | |||
85 | $config = new Config($newUser); | ||
86 | $config->setTheme($this->container->getParameter('theme')); | ||
87 | $config->setItemsPerPage($this->container->getParameter('items_on_page')); | ||
88 | $config->setLanguage($this->container->getParameter('language')); | ||
89 | |||
90 | $em->persist($config); | ||
91 | |||
92 | $em->flush(); | ||
93 | |||
94 | $this->get('session')->getFlashBag()->add( | ||
95 | 'notice', | ||
96 | sprintf('User "%s" added', $newUser->getUsername()) | ||
97 | ); | ||
98 | |||
99 | return $this->redirect($this->generateUrl('config')); | ||
100 | } | ||
101 | |||
102 | return $this->render('WallabagCoreBundle:Config:index.html.twig', array( | ||
103 | 'configForm' => $configForm->createView(), | ||
104 | 'pwdForm' => $pwdForm->createView(), | ||
105 | 'userForm' => $userForm->createView(), | ||
106 | 'newUserForm' => $newUserForm->createView(), | ||
107 | )); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Retrieve config for the current user. | ||
112 | * If no config were found, create a new one. | ||
113 | * | ||
114 | * @return Wallabag\CoreBundle\Entity\Config | ||
115 | */ | ||
116 | private function getConfig() | ||
117 | { | ||
118 | $config = $this->getDoctrine() | ||
119 | ->getRepository('WallabagCoreBundle:Config') | ||
120 | ->findOneByUser($this->getUser()); | ||
121 | |||
122 | if (!$config) { | ||
123 | $config = new Config($this->getUser()); | ||
124 | } | ||
125 | |||
126 | return $config; | ||
127 | } | ||
128 | } | ||
diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 89677bef..81ab7788 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php | |||
@@ -7,7 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |||
7 | use Symfony\Component\HttpFoundation\Request; | 7 | use Symfony\Component\HttpFoundation\Request; |
8 | use Wallabag\CoreBundle\Entity\Entry; | 8 | use Wallabag\CoreBundle\Entity\Entry; |
9 | use Wallabag\CoreBundle\Service\Extractor; | 9 | use Wallabag\CoreBundle\Service\Extractor; |
10 | use Wallabag\CoreBundle\Helper\Url; | 10 | use Wallabag\CoreBundle\Form\Type\EntryType; |
11 | 11 | ||
12 | class EntryController extends Controller | 12 | class EntryController extends Controller |
13 | { | 13 | { |
@@ -22,10 +22,7 @@ class EntryController extends Controller | |||
22 | { | 22 | { |
23 | $entry = new Entry($this->getUser()); | 23 | $entry = new Entry($this->getUser()); |
24 | 24 | ||
25 | $form = $this->createFormBuilder($entry) | 25 | $form = $this->createForm(new EntryType(), $entry); |
26 | ->add('url', 'url') | ||
27 | ->add('save', 'submit') | ||
28 | ->getForm(); | ||
29 | 26 | ||
30 | $form->handleRequest($request); | 27 | $form->handleRequest($request); |
31 | 28 | ||
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 | |||
3 | namespace Wallabag\CoreBundle\DataFixtures\ORM; | ||
4 | |||
5 | use Doctrine\Common\DataFixtures\AbstractFixture; | ||
6 | use Doctrine\Common\DataFixtures\OrderedFixtureInterface; | ||
7 | use Doctrine\Common\Persistence\ObjectManager; | ||
8 | use Wallabag\CoreBundle\Entity\Config; | ||
9 | |||
10 | class 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/DataFixtures/ORM/LoadUserData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php index e4751f20..d99412f4 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadUserData.php | |||
@@ -18,7 +18,7 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface | |||
18 | $userAdmin->setName('Big boss'); | 18 | $userAdmin->setName('Big boss'); |
19 | $userAdmin->setEmail('bigboss@wallabag.org'); | 19 | $userAdmin->setEmail('bigboss@wallabag.org'); |
20 | $userAdmin->setUsername('admin'); | 20 | $userAdmin->setUsername('admin'); |
21 | $userAdmin->setPassword('test'); | 21 | $userAdmin->setPassword('mypassword'); |
22 | 22 | ||
23 | $manager->persist($userAdmin); | 23 | $manager->persist($userAdmin); |
24 | 24 | ||
@@ -28,7 +28,7 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface | |||
28 | $bobUser->setName('Bobby'); | 28 | $bobUser->setName('Bobby'); |
29 | $bobUser->setEmail('bobby@wallabag.org'); | 29 | $bobUser->setEmail('bobby@wallabag.org'); |
30 | $bobUser->setUsername('bob'); | 30 | $bobUser->setUsername('bob'); |
31 | $bobUser->setPassword('test'); | 31 | $bobUser->setPassword('mypassword'); |
32 | 32 | ||
33 | $manager->persist($bobUser); | 33 | $manager->persist($bobUser); |
34 | 34 | ||
diff --git a/src/Wallabag/CoreBundle/Entity/Config.php b/src/Wallabag/CoreBundle/Entity/Config.php index 045ca308..7b4464a1 100644 --- a/src/Wallabag/CoreBundle/Entity/Config.php +++ b/src/Wallabag/CoreBundle/Entity/Config.php | |||
@@ -3,10 +3,12 @@ | |||
3 | namespace Wallabag\CoreBundle\Entity; | 3 | namespace Wallabag\CoreBundle\Entity; |
4 | 4 | ||
5 | use Doctrine\ORM\Mapping as ORM; | 5 | use Doctrine\ORM\Mapping as ORM; |
6 | use Symfony\Component\Validator\Constraints as Assert; | ||
6 | 7 | ||
7 | /** | 8 | /** |
8 | * Config | 9 | * Config |
9 | * | 10 | * |
11 | * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\ConfigRepository") | ||
10 | * @ORM\Table(name="config") | 12 | * @ORM\Table(name="config") |
11 | * @ORM\Entity | 13 | * @ORM\Entity |
12 | */ | 14 | */ |
@@ -15,25 +17,50 @@ class Config | |||
15 | /** | 17 | /** |
16 | * @var integer | 18 | * @var integer |
17 | * | 19 | * |
18 | * @ORM\Column(name="id", type="integer", nullable=false) | 20 | * @ORM\Column(name="id", type="integer") |
19 | * @ORM\Id | 21 | * @ORM\Id |
20 | * @ORM\GeneratedValue(strategy="IDENTITY") | 22 | * @ORM\GeneratedValue(strategy="AUTO") |
21 | */ | 23 | */ |
22 | private $id; | 24 | private $id; |
23 | 25 | ||
24 | /** | 26 | /** |
25 | * @var string | 27 | * @var string |
26 | * | 28 | * |
27 | * @ORM\Column(name="name", type="string", nullable=true) | 29 | * @Assert\NotBlank() |
30 | * @ORM\Column(name="theme", type="string", nullable=false) | ||
28 | */ | 31 | */ |
29 | private $name; | 32 | private $theme; |
30 | 33 | ||
31 | /** | 34 | /** |
32 | * @var string | 35 | * @var string |
33 | * | 36 | * |
34 | * @ORM\Column(name="value", type="blob", nullable=true) | 37 | * @Assert\NotBlank() |
38 | * @ORM\Column(name="items_per_page", type="integer", nullable=false) | ||
35 | */ | 39 | */ |
36 | private $value; | 40 | private $items_per_page; |
41 | |||
42 | /** | ||
43 | * @var string | ||
44 | * | ||
45 | * @Assert\NotBlank() | ||
46 | * @ORM\Column(name="language", type="string", nullable=false) | ||
47 | */ | ||
48 | private $language; | ||
49 | |||
50 | /** | ||
51 | * @ORM\ManyToOne(targetEntity="User", inversedBy="config") | ||
52 | */ | ||
53 | private $user; | ||
54 | |||
55 | /* | ||
56 | * @param User $user | ||
57 | */ | ||
58 | public function __construct(User $user) | ||
59 | { | ||
60 | $this->user = $user; | ||
61 | $this->items_per_page = 12; | ||
62 | $this->language = 'en_US'; | ||
63 | } | ||
37 | 64 | ||
38 | /** | 65 | /** |
39 | * Get id | 66 | * Get id |
@@ -46,48 +73,94 @@ class Config | |||
46 | } | 73 | } |
47 | 74 | ||
48 | /** | 75 | /** |
49 | * Set name | 76 | * Set theme |
50 | * | 77 | * |
51 | * @param string $name | 78 | * @param string $theme |
52 | * @return Config | 79 | * @return Config |
53 | */ | 80 | */ |
54 | public function setName($name) | 81 | public function setTheme($theme) |
55 | { | 82 | { |
56 | $this->name = $name; | 83 | $this->theme = $theme; |
57 | 84 | ||
58 | return $this; | 85 | return $this; |
59 | } | 86 | } |
60 | 87 | ||
61 | /** | 88 | /** |
62 | * Get name | 89 | * Get theme |
63 | * | 90 | * |
64 | * @return string | 91 | * @return string |
65 | */ | 92 | */ |
66 | public function getName() | 93 | public function getTheme() |
67 | { | 94 | { |
68 | return $this->name; | 95 | return $this->theme; |
69 | } | 96 | } |
70 | 97 | ||
71 | /** | 98 | /** |
72 | * Set value | 99 | * Set items_per_page |
73 | * | 100 | * |
74 | * @param string $value | 101 | * @param integer $itemsPerPage |
75 | * @return Config | 102 | * @return Config |
76 | */ | 103 | */ |
77 | public function setValue($value) | 104 | public function setItemsPerPage($itemsPerPage) |
78 | { | 105 | { |
79 | $this->value = $value; | 106 | $this->items_per_page = $itemsPerPage; |
80 | 107 | ||
81 | return $this; | 108 | return $this; |
82 | } | 109 | } |
83 | 110 | ||
84 | /** | 111 | /** |
85 | * Get value | 112 | * Get items_per_page |
113 | * | ||
114 | * @return integer | ||
115 | */ | ||
116 | public function getItemsPerPage() | ||
117 | { | ||
118 | return $this->items_per_page; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Set language | ||
123 | * | ||
124 | * @param string $language | ||
125 | * @return Config | ||
126 | */ | ||
127 | public function setLanguage($language) | ||
128 | { | ||
129 | $this->language = $language; | ||
130 | |||
131 | return $this; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Get language | ||
86 | * | 136 | * |
87 | * @return string | 137 | * @return string |
88 | */ | 138 | */ |
89 | public function getValue() | 139 | public function getLanguage() |
140 | { | ||
141 | return $this->language; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Set user | ||
146 | * | ||
147 | * @param \Wallabag\CoreBundle\Entity\User $user | ||
148 | * @return Config | ||
149 | */ | ||
150 | public function setUser(\Wallabag\CoreBundle\Entity\User $user = null) | ||
151 | { | ||
152 | $this->user = $user; | ||
153 | |||
154 | return $this; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Get user | ||
159 | * | ||
160 | * @return \Wallabag\CoreBundle\Entity\User | ||
161 | */ | ||
162 | public function getUser() | ||
90 | { | 163 | { |
91 | return $this->value; | 164 | return $this->user; |
92 | } | 165 | } |
93 | } | 166 | } |
diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php index c83250c3..193dfebc 100644 --- a/src/Wallabag/CoreBundle/Entity/User.php +++ b/src/Wallabag/CoreBundle/Entity/User.php | |||
@@ -6,6 +6,7 @@ use Doctrine\Common\Collections\ArrayCollection; | |||
6 | use Doctrine\ORM\Mapping as ORM; | 6 | use Doctrine\ORM\Mapping as ORM; |
7 | use Symfony\Component\Security\Core\User\UserInterface; | 7 | use Symfony\Component\Security\Core\User\UserInterface; |
8 | use Symfony\Component\Security\Core\User\AdvancedUserInterface; | 8 | use Symfony\Component\Security\Core\User\AdvancedUserInterface; |
9 | use Symfony\Component\Validator\Constraints as Assert; | ||
9 | 10 | ||
10 | /** | 11 | /** |
11 | * User | 12 | * User |
@@ -29,6 +30,11 @@ class User implements AdvancedUserInterface, \Serializable | |||
29 | * @var string | 30 | * @var string |
30 | * | 31 | * |
31 | * @ORM\Column(name="username", type="text") | 32 | * @ORM\Column(name="username", type="text") |
33 | * @Assert\NotBlank() | ||
34 | * @Assert\Length( | ||
35 | * min = "3", | ||
36 | * max = "255" | ||
37 | * ) | ||
32 | */ | 38 | */ |
33 | private $username; | 39 | private $username; |
34 | 40 | ||
@@ -56,14 +62,16 @@ class User implements AdvancedUserInterface, \Serializable | |||
56 | /** | 62 | /** |
57 | * @var string | 63 | * @var string |
58 | * | 64 | * |
59 | * @ORM\Column(name="email", type="text", nullable=true) | 65 | * @ORM\Column(name="email", type="text", nullable=false) |
66 | * @Assert\Email() | ||
67 | * @Assert\NotBlank() | ||
60 | */ | 68 | */ |
61 | private $email; | 69 | private $email; |
62 | 70 | ||
63 | /** | 71 | /** |
64 | * @ORM\Column(name="is_active", type="boolean") | 72 | * @ORM\Column(name="is_active", type="boolean", nullable=false) |
65 | */ | 73 | */ |
66 | private $isActive; | 74 | private $isActive = true; |
67 | 75 | ||
68 | /** | 76 | /** |
69 | * @var date | 77 | * @var date |
@@ -86,9 +94,8 @@ class User implements AdvancedUserInterface, \Serializable | |||
86 | 94 | ||
87 | public function __construct() | 95 | public function __construct() |
88 | { | 96 | { |
89 | $this->isActive = true; | 97 | $this->salt = md5(uniqid(null, true)); |
90 | $this->salt = md5(uniqid(null, true)); | 98 | $this->entries = new ArrayCollection(); |
91 | $this->entries = new ArrayCollection(); | ||
92 | } | 99 | } |
93 | 100 | ||
94 | /** | 101 | /** |
diff --git a/src/Wallabag/CoreBundle/Entity/UsersConfig.php b/src/Wallabag/CoreBundle/Entity/UsersConfig.php deleted file mode 100644 index 0742edbc..00000000 --- a/src/Wallabag/CoreBundle/Entity/UsersConfig.php +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Entity; | ||
4 | |||
5 | use Doctrine\ORM\Mapping as ORM; | ||
6 | |||
7 | /** | ||
8 | * UsersConfig | ||
9 | * | ||
10 | * @ORM\Table(name="users_config") | ||
11 | * @ORM\Entity | ||
12 | */ | ||
13 | class UsersConfig | ||
14 | { | ||
15 | /** | ||
16 | * @var integer | ||
17 | * | ||
18 | * @ORM\Column(name="id", type="integer", nullable=true) | ||
19 | * @ORM\Id | ||
20 | * @ORM\GeneratedValue(strategy="IDENTITY") | ||
21 | */ | ||
22 | private $id; | ||
23 | |||
24 | /** | ||
25 | * @var string | ||
26 | * | ||
27 | * @ORM\Column(name="user_id", type="decimal", precision=10, scale=0, nullable=true) | ||
28 | */ | ||
29 | private $userId; | ||
30 | |||
31 | /** | ||
32 | * @var string | ||
33 | * | ||
34 | * @ORM\Column(name="name", type="text", nullable=true) | ||
35 | */ | ||
36 | private $name; | ||
37 | |||
38 | /** | ||
39 | * @var string | ||
40 | * | ||
41 | * @ORM\Column(name="value", type="text", nullable=true) | ||
42 | */ | ||
43 | private $value; | ||
44 | |||
45 | /** | ||
46 | * Get id | ||
47 | * | ||
48 | * @return integer | ||
49 | */ | ||
50 | public function getId() | ||
51 | { | ||
52 | return $this->id; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Set userId | ||
57 | * | ||
58 | * @param string $userId | ||
59 | * @return UsersConfig | ||
60 | */ | ||
61 | public function setUserId($userId) | ||
62 | { | ||
63 | $this->userId = $userId; | ||
64 | |||
65 | return $this; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Get userId | ||
70 | * | ||
71 | * @return string | ||
72 | */ | ||
73 | public function getUserId() | ||
74 | { | ||
75 | return $this->userId; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Set name | ||
80 | * | ||
81 | * @param string $name | ||
82 | * @return UsersConfig | ||
83 | */ | ||
84 | public function setName($name) | ||
85 | { | ||
86 | $this->name = $name; | ||
87 | |||
88 | return $this; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Get name | ||
93 | * | ||
94 | * @return string | ||
95 | */ | ||
96 | public function getName() | ||
97 | { | ||
98 | return $this->name; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Set value | ||
103 | * | ||
104 | * @param string $value | ||
105 | * @return UsersConfig | ||
106 | */ | ||
107 | public function setValue($value) | ||
108 | { | ||
109 | $this->value = $value; | ||
110 | |||
111 | return $this; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Get value | ||
116 | * | ||
117 | * @return string | ||
118 | */ | ||
119 | public function getValue() | ||
120 | { | ||
121 | return $this->value; | ||
122 | } | ||
123 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/ChangePasswordType.php b/src/Wallabag/CoreBundle/Form/Type/ChangePasswordType.php new file mode 100644 index 00000000..e141789f --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/ChangePasswordType.php | |||
@@ -0,0 +1,39 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; | ||
7 | use Symfony\Component\Validator\Constraints; | ||
8 | |||
9 | class ChangePasswordType extends AbstractType | ||
10 | { | ||
11 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
12 | { | ||
13 | $builder | ||
14 | ->add('old_password', 'password', array( | ||
15 | 'constraints' => new UserPassword(array('message' => 'Wrong value for your current password')), | ||
16 | )) | ||
17 | ->add('new_password', 'repeated', array( | ||
18 | 'type' => 'password', | ||
19 | 'invalid_message' => 'The password fields must match.', | ||
20 | 'required' => true, | ||
21 | 'first_options' => array('label' => 'New password'), | ||
22 | 'second_options' => array('label' => 'Repeat new password'), | ||
23 | 'constraints' => array( | ||
24 | new Constraints\Length(array( | ||
25 | 'min' => 8, | ||
26 | 'minMessage' => 'Password should by at least 8 chars long', | ||
27 | )), | ||
28 | new Constraints\NotBlank(), | ||
29 | ), | ||
30 | )) | ||
31 | ->add('save', 'submit') | ||
32 | ; | ||
33 | } | ||
34 | |||
35 | public function getName() | ||
36 | { | ||
37 | return 'change_passwd'; | ||
38 | } | ||
39 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/ConfigType.php b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php new file mode 100644 index 00000000..a1e0ce47 --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/ConfigType.php | |||
@@ -0,0 +1,41 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
7 | |||
8 | class ConfigType extends AbstractType | ||
9 | { | ||
10 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
11 | { | ||
12 | $builder | ||
13 | ->add('theme', 'choice', array( | ||
14 | 'choices' => array( | ||
15 | 'baggy' => 'Baggy', | ||
16 | 'courgette' => 'Courgette', | ||
17 | 'dark' => 'Dark', | ||
18 | 'default' => 'Default', | ||
19 | 'dmagenta' => 'Dmagenta', | ||
20 | 'solarized' => 'Solarized', | ||
21 | 'solarized_dark' => 'Solarized Dark', | ||
22 | ), | ||
23 | )) | ||
24 | ->add('items_per_page', 'text') | ||
25 | ->add('language') | ||
26 | ->add('save', 'submit') | ||
27 | ; | ||
28 | } | ||
29 | |||
30 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
31 | { | ||
32 | $resolver->setDefaults(array( | ||
33 | 'data_class' => 'Wallabag\CoreBundle\Entity\Config', | ||
34 | )); | ||
35 | } | ||
36 | |||
37 | public function getName() | ||
38 | { | ||
39 | return 'config'; | ||
40 | } | ||
41 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/EntryType.php b/src/Wallabag/CoreBundle/Form/Type/EntryType.php new file mode 100644 index 00000000..cfd64473 --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/EntryType.php | |||
@@ -0,0 +1,29 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
7 | |||
8 | class EntryType extends AbstractType | ||
9 | { | ||
10 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
11 | { | ||
12 | $builder | ||
13 | ->add('url', 'url') | ||
14 | ->add('save', 'submit') | ||
15 | ; | ||
16 | } | ||
17 | |||
18 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
19 | { | ||
20 | $resolver->setDefaults(array( | ||
21 | 'data_class' => 'Wallabag\CoreBundle\Entity\Entry', | ||
22 | )); | ||
23 | } | ||
24 | |||
25 | public function getName() | ||
26 | { | ||
27 | return 'entry'; | ||
28 | } | ||
29 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/NewUserType.php b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php new file mode 100644 index 00000000..313a9aae --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/NewUserType.php | |||
@@ -0,0 +1,40 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
7 | use Symfony\Component\Validator\Constraints; | ||
8 | |||
9 | class NewUserType extends AbstractType | ||
10 | { | ||
11 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
12 | { | ||
13 | $builder | ||
14 | ->add('username', 'text') | ||
15 | ->add('password', 'password', array( | ||
16 | 'constraints' => array( | ||
17 | new Constraints\Length(array( | ||
18 | 'min' => 8, | ||
19 | 'minMessage' => 'Password should by at least 8 chars long', | ||
20 | )), | ||
21 | new Constraints\NotBlank(), | ||
22 | ), | ||
23 | )) | ||
24 | ->add('email', 'text') | ||
25 | ->add('save', 'submit') | ||
26 | ; | ||
27 | } | ||
28 | |||
29 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
30 | { | ||
31 | $resolver->setDefaults(array( | ||
32 | 'data_class' => 'Wallabag\CoreBundle\Entity\User', | ||
33 | )); | ||
34 | } | ||
35 | |||
36 | public function getName() | ||
37 | { | ||
38 | return 'new_user'; | ||
39 | } | ||
40 | } | ||
diff --git a/src/Wallabag/CoreBundle/Form/Type/UserType.php b/src/Wallabag/CoreBundle/Form/Type/UserType.php new file mode 100644 index 00000000..b479a0b5 --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/UserType.php | |||
@@ -0,0 +1,31 @@ | |||
1 | <?php | ||
2 | namespace Wallabag\CoreBundle\Form\Type; | ||
3 | |||
4 | use Symfony\Component\Form\AbstractType; | ||
5 | use Symfony\Component\Form\FormBuilderInterface; | ||
6 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
7 | |||
8 | class UserType extends AbstractType | ||
9 | { | ||
10 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
11 | { | ||
12 | $builder | ||
13 | ->add('username', 'text') | ||
14 | ->add('name', 'text') | ||
15 | ->add('email', 'text') | ||
16 | ->add('save', 'submit') | ||
17 | ; | ||
18 | } | ||
19 | |||
20 | public function setDefaultOptions(OptionsResolverInterface $resolver) | ||
21 | { | ||
22 | $resolver->setDefaults(array( | ||
23 | 'data_class' => 'Wallabag\CoreBundle\Entity\User', | ||
24 | )); | ||
25 | } | ||
26 | |||
27 | public function getName() | ||
28 | { | ||
29 | return 'user'; | ||
30 | } | ||
31 | } | ||
diff --git a/src/Wallabag/CoreBundle/Repository/ConfigRepository.php b/src/Wallabag/CoreBundle/Repository/ConfigRepository.php new file mode 100644 index 00000000..b2b1f627 --- /dev/null +++ b/src/Wallabag/CoreBundle/Repository/ConfigRepository.php | |||
@@ -0,0 +1,9 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Repository; | ||
4 | |||
5 | use Doctrine\ORM\EntityRepository; | ||
6 | |||
7 | class ConfigRepository extends EntityRepository | ||
8 | { | ||
9 | } | ||
diff --git a/src/Wallabag/CoreBundle/Resources/config/routing.yml b/src/Wallabag/CoreBundle/Resources/config/routing.yml index ec1d23cc..f3502e15 100644 --- a/src/Wallabag/CoreBundle/Resources/config/routing.yml +++ b/src/Wallabag/CoreBundle/Resources/config/routing.yml | |||
@@ -1,3 +1,7 @@ | |||
1 | _wllbg: | 1 | entry: |
2 | resource: "@WallabagCoreBundle/Controller/EntryController.php" | 2 | resource: "@WallabagCoreBundle/Controller/EntryController.php" |
3 | type: annotation | 3 | type: annotation |
4 | |||
5 | config: | ||
6 | resource: "@WallabagCoreBundle/Controller/ConfigController.php" | ||
7 | type: annotation | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig new file mode 100644 index 00000000..051dafd6 --- /dev/null +++ b/src/Wallabag/CoreBundle/Resources/views/Config/index.html.twig | |||
@@ -0,0 +1,137 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{% trans %}Config{% endtrans %}{% endblock %} | ||
4 | |||
5 | {% block menu %} | ||
6 | {% include "WallabagCoreBundle::_menu.html.twig" %} | ||
7 | {% endblock %} | ||
8 | |||
9 | {% block content %} | ||
10 | <h2>{% trans %}Wallabag configuration{% endtrans %}</h2> | ||
11 | |||
12 | <form action="{{ path('config') }}" method="post" {{ form_enctype(configForm) }}> | ||
13 | {{ form_errors(configForm) }} | ||
14 | |||
15 | <fieldset class="w500p inline"> | ||
16 | <div class="row"> | ||
17 | {{ form_label(configForm.theme) }} | ||
18 | {{ form_errors(configForm.theme) }} | ||
19 | {{ form_widget(configForm.theme) }} | ||
20 | </div> | ||
21 | </fieldset> | ||
22 | |||
23 | <fieldset class="w500p inline"> | ||
24 | <div class="row"> | ||
25 | {{ form_label(configForm.items_per_page) }} | ||
26 | {{ form_errors(configForm.items_per_page) }} | ||
27 | {{ form_widget(configForm.items_per_page) }} | ||
28 | </div> | ||
29 | </fieldset> | ||
30 | |||
31 | <fieldset class="w500p inline"> | ||
32 | <div class="row"> | ||
33 | {{ form_label(configForm.language) }} | ||
34 | {{ form_errors(configForm.language) }} | ||
35 | {{ form_widget(configForm.language) }} | ||
36 | </div> | ||
37 | </fieldset> | ||
38 | |||
39 | {{ form_rest(configForm) }} | ||
40 | </form> | ||
41 | |||
42 | <h2>{% trans %}User information{% endtrans %}</h2> | ||
43 | |||
44 | <form action="{{ path('config') }}" method="post" {{ form_enctype(userForm) }}> | ||
45 | {{ form_errors(userForm) }} | ||
46 | |||
47 | <fieldset class="w500p inline"> | ||
48 | <div class="row"> | ||
49 | {{ form_label(userForm.username) }} | ||
50 | {{ form_errors(userForm.username) }} | ||
51 | {{ form_widget(userForm.username) }} | ||
52 | </div> | ||
53 | </fieldset> | ||
54 | |||
55 | <fieldset class="w500p inline"> | ||
56 | <div class="row"> | ||
57 | {{ form_label(userForm.name) }} | ||
58 | {{ form_errors(userForm.name) }} | ||
59 | {{ form_widget(userForm.name) }} | ||
60 | </div> | ||
61 | </fieldset> | ||
62 | |||
63 | <fieldset class="w500p inline"> | ||
64 | <div class="row"> | ||
65 | {{ form_label(userForm.email) }} | ||
66 | {{ form_errors(userForm.email) }} | ||
67 | {{ form_widget(userForm.email) }} | ||
68 | </div> | ||
69 | </fieldset> | ||
70 | |||
71 | {{ form_rest(userForm) }} | ||
72 | </form> | ||
73 | |||
74 | <h2>{% trans %}Change your password{% endtrans %}</h2> | ||
75 | |||
76 | <form action="{{ path('config') }}" method="post" {{ form_enctype(pwdForm) }}> | ||
77 | {{ form_errors(pwdForm) }} | ||
78 | |||
79 | <fieldset class="w500p inline"> | ||
80 | <div class="row"> | ||
81 | {{ form_label(pwdForm.old_password) }} | ||
82 | {{ form_errors(pwdForm.old_password) }} | ||
83 | {{ form_widget(pwdForm.old_password) }} | ||
84 | </div> | ||
85 | </fieldset> | ||
86 | |||
87 | <fieldset class="w500p inline"> | ||
88 | <div class="row"> | ||
89 | {{ form_label(pwdForm.new_password.first) }} | ||
90 | {{ form_errors(pwdForm.new_password.first) }} | ||
91 | {{ form_widget(pwdForm.new_password.first) }} | ||
92 | </div> | ||
93 | </fieldset> | ||
94 | |||
95 | <fieldset class="w500p inline"> | ||
96 | <div class="row"> | ||
97 | {{ form_label(pwdForm.new_password.second) }} | ||
98 | {{ form_errors(pwdForm.new_password.second) }} | ||
99 | {{ form_widget(pwdForm.new_password.second) }} | ||
100 | </div> | ||
101 | </fieldset> | ||
102 | |||
103 | {{ form_rest(pwdForm) }} | ||
104 | </form> | ||
105 | |||
106 | <h2>{% trans %}Add a user{% endtrans %}</h2> | ||
107 | |||
108 | <form action="{{ path('config') }}" method="post" {{ form_enctype(newUserForm) }}> | ||
109 | {{ form_errors(newUserForm) }} | ||
110 | |||
111 | <fieldset class="w500p inline"> | ||
112 | <div class="row"> | ||
113 | {{ form_label(newUserForm.username) }} | ||
114 | {{ form_errors(newUserForm.username) }} | ||
115 | {{ form_widget(newUserForm.username) }} | ||
116 | </div> | ||
117 | </fieldset> | ||
118 | |||
119 | <fieldset class="w500p inline"> | ||
120 | <div class="row"> | ||
121 | {{ form_label(newUserForm.password) }} | ||
122 | {{ form_errors(newUserForm.password) }} | ||
123 | {{ form_widget(newUserForm.password) }} | ||
124 | </div> | ||
125 | </fieldset> | ||
126 | |||
127 | <fieldset class="w500p inline"> | ||
128 | <div class="row"> | ||
129 | {{ form_label(newUserForm.email) }} | ||
130 | {{ form_errors(newUserForm.email) }} | ||
131 | {{ form_widget(newUserForm.email) }} | ||
132 | </div> | ||
133 | </fieldset> | ||
134 | |||
135 | {{ form_rest(newUserForm) }} | ||
136 | </form> | ||
137 | {% endblock %} | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/_footer.html.twig b/src/Wallabag/CoreBundle/Resources/views/_footer.html.twig index 26411da9..1b5f9a0f 100644 --- a/src/Wallabag/CoreBundle/Resources/views/_footer.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/_footer.html.twig | |||
@@ -1,3 +1,3 @@ | |||
1 | <footer class="w600p center mt3 mb3 smaller txtright"> | 1 | <footer class="w600p center mt3 mb3 smaller txtright"> |
2 | <p>{% trans %}powered by{% endtrans %} <a href="http://wallabag.org">wallabag</a></p> | 2 | <p>{% trans %}powered by{% endtrans %} <a href="http://wallabag.org">wallabag</a></p> |
3 | </footer> | 3 | </footer> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/_head.html.twig b/src/Wallabag/CoreBundle/Resources/views/_head.html.twig index 726b4163..3bdbe812 100755 --- a/src/Wallabag/CoreBundle/Resources/views/_head.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/_head.html.twig | |||
@@ -1,40 +1,40 @@ | |||
1 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-152.png') }}" sizes="152x152"> | 1 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-152.png') }}" sizes="152x152"> |
2 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-152.png') }}" sizes="152x152"> | 2 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-152.png') }}" sizes="152x152"> |
3 | 3 | ||
4 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-144.png') }}" sizes="144x144"> | 4 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-144.png') }}" sizes="144x144"> |
5 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-144.png') }}" sizes="144x144"> | 5 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-144.png') }}" sizes="144x144"> |
6 | 6 | ||
7 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-120.png') }}" sizes="120x120"> | 7 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-120.png') }}" sizes="120x120"> |
8 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-120.png') }}" sizes="120x120"> | 8 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-120.png') }}" sizes="120x120"> |
9 | 9 | ||
10 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-114.png') }}" sizes="114x114"> | 10 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-114.png') }}" sizes="114x114"> |
11 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-114.png') }}" sizes="114x114"> | 11 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-114.png') }}" sizes="114x114"> |
12 | 12 | ||
13 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-76.png') }}" sizes="76x76"> | 13 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-76.png') }}" sizes="76x76"> |
14 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-76.png') }}" sizes="76x76"> | 14 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-76.png') }}" sizes="76x76"> |
15 | 15 | ||
16 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-72.png') }}" sizes="72x72"> | 16 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-72.png') }}" sizes="72x72"> |
17 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-72.png') }}" sizes="72x72"> | 17 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-72.png') }}" sizes="72x72"> |
18 | 18 | ||
19 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-57.png') }}" sizes="57x57"> | 19 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-57.png') }}" sizes="57x57"> |
20 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-57.png') }}" sizes="57x57"> | 20 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon-57.png') }}" sizes="57x57"> |
21 | 21 | ||
22 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon.png') }}"> | 22 | <link rel="apple-touch-icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon.png') }}"> |
23 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon.png') }}"> | 23 | <link rel="icon" type="image/png" href="{{ asset('themes/_global/img/appicon/apple-touch-icon.png') }}"> |
24 | 24 | ||
25 | <link rel="shortcut icon" type="image/x-icon" href="{{ asset('themes/_global/img/appicon/favicon.ico') }}"> | 25 | <link rel="shortcut icon" type="image/x-icon" href="{{ asset('themes/_global/img/appicon/favicon.ico') }}"> |
26 | 26 | ||
27 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/ratatouille.css') }}" media="all"> | 27 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/ratatouille.css') }}" media="all"> |
28 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/font.css') }}" media="all"> | 28 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/font.css') }}" media="all"> |
29 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/main.css') }}" media="all"> | 29 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/main.css') }}" media="all"> |
30 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/messages.css') }}" media="all"> | 30 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/messages.css') }}" media="all"> |
31 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/print.css') }}" media="print"> | 31 | <link rel="stylesheet" href="{{ asset('themes/baggy/css/print.css') }}" media="print"> |
32 | 32 | ||
33 | <script src="{{ asset('themes/_global/js/jquery-2.0.3.min.js') }}"></script> | 33 | <script src="{{ asset('themes/_global/js/jquery-2.0.3.min.js') }}"></script> |
34 | <script src="{{ asset('themes/_global/js/autoClose.js') }}"></script> | 34 | <script src="{{ asset('themes/_global/js/autoClose.js') }}"></script> |
35 | <script src="{{ asset('themes/baggy/js/jquery.cookie.js') }}"></script> | 35 | <script src="{{ asset('themes/baggy/js/jquery.cookie.js') }}"></script> |
36 | <script src="{{ asset('themes/baggy/js/init.js') }}"></script> | 36 | <script src="{{ asset('themes/baggy/js/init.js') }}"></script> |
37 | <script src="{{ asset('themes/_global/js/saveLink.js') }}"></script> | 37 | <script src="{{ asset('themes/_global/js/saveLink.js') }}"></script> |
38 | <script src="{{ asset('themes/_global/js/popupForm.js') }}"></script> | 38 | <script src="{{ asset('themes/_global/js/popupForm.js') }}"></script> |
39 | <script src="{{ asset('themes/baggy/js/closeMessage.js') }}"></script> | 39 | <script src="{{ asset('themes/baggy/js/closeMessage.js') }}"></script> |
40 | <script src="{{ asset('bundles/wallabagcore/js/bookmarklet.js') }}"></script> | 40 | <script src="{{ asset('bundles/wallabagcore/js/bookmarklet.js') }}"></script> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/_menu.html.twig b/src/Wallabag/CoreBundle/Resources/views/_menu.html.twig index 2e3b6d08..9a3cf053 100644 --- a/src/Wallabag/CoreBundle/Resources/views/_menu.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/_menu.html.twig | |||
@@ -1,14 +1,14 @@ | |||
1 | <button id="menu" class="icon icon-menu desktopHide"><span>Menu</span></button> | 1 | <button id="menu" class="icon icon-menu desktopHide"><span>Menu</span></button> |
2 | <ul id="links" class="links"> | 2 | <ul id="links" class="links"> |
3 | <li><a href="{{ path('unread') }}">{% trans %}unread{% endtrans %}</a></li> | 3 | <li><a href="{{ path('unread') }}">{% trans %}unread{% endtrans %}</a></li> |
4 | <li><a href="{{ path('starred') }}">{% trans %}favorites{% endtrans %}</a></li> | 4 | <li><a href="{{ path('starred') }}">{% trans %}favorites{% endtrans %}</a></li> |
5 | <li><a href="{{ path('archive') }}"}>{% trans %}archive{% endtrans %}</a></li> | 5 | <li><a href="{{ path('archive') }}"}>{% trans %}archive{% endtrans %}</a></li> |
6 | <li><a href="?view=tags">{% trans %}tags{% endtrans %}</a></li> | 6 | <li><a href="?view=tags">{% trans %}tags{% endtrans %}</a></li> |
7 | <li><a href="{{ path('new_entry') }}">{% trans %}save a link{% endtrans %}</a></li> | 7 | <li><a href="{{ path('new_entry') }}">{% trans %}save a link{% endtrans %}</a></li> |
8 | <li style="position: relative;"><a href="javascript: void(null);" id="search">{% trans %}search{% endtrans %}</a> | 8 | <li style="position: relative;"><a href="javascript: void(null);" id="search">{% trans %}search{% endtrans %}</a> |
9 | {% include "WallabagCoreBundle::_search_form.html.twig" %} | 9 | {% include "WallabagCoreBundle::_search_form.html.twig" %} |
10 | </li> | 10 | </li> |
11 | <li><a href="?view=config">{% trans %}config{% endtrans %}</a></li> | 11 | <li><a href="{{ path('config') }}">{% trans %}config{% endtrans %}</a></li> |
12 | <li><a href={{ path('about') }}>{% trans %}about{% endtrans %}</a></li> | 12 | <li><a href="{{ path('about') }}">{% trans %}about{% endtrans %}</a></li> |
13 | <li><a class="icon icon-power" href="{{ path('logout') }}" title="{% trans %}logout{% endtrans %}">{% trans %}logout{% endtrans %}</a></li> | 13 | <li><a class="icon icon-power" href="{{ path('logout') }}" title="{% trans %}logout{% endtrans %}">{% trans %}logout{% endtrans %}</a></li> |
14 | </ul> | 14 | </ul> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/_search_form.html.twig b/src/Wallabag/CoreBundle/Resources/views/_search_form.html.twig index 7eb1b67d..1e6f327d 100644 --- a/src/Wallabag/CoreBundle/Resources/views/_search_form.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/_search_form.html.twig | |||
@@ -1,9 +1,9 @@ | |||
1 | <div id="search-form" class="messages info popup-form"> | 1 | <div id="search-form" class="messages info popup-form"> |
2 | <form method="get" action="index.php"> | 2 | <form method="get" action="index.php"> |
3 | <h2>{% trans %}Search{% endtrans %}</h2> | 3 | <h2>{% trans %}Search{% endtrans %}</h2> |
4 | <a href="javascript: void(null);" id="search-form-close" class="close-button--popup close-button">×</a> | 4 | <a href="javascript: void(null);" id="search-form-close" class="close-button--popup close-button">×</a> |
5 | <input type="hidden" name="view" value="search"></input> | 5 | <input type="hidden" name="view" value="search"></input> |
6 | <input required placeholder="{% trans %}Enter your search here{% endtrans %}" type="text" name="search" id="searchfield"><br> | 6 | <input required placeholder="{% trans %}Enter your search here{% endtrans %}" type="text" name="search" id="searchfield"><br> |
7 | <input id="submit-search" type="submit" value="{% trans %}Search{% endtrans %}"></input> | 7 | <input id="submit-search" type="submit" value="{% trans %}Search{% endtrans %}"></input> |
8 | </form> | 8 | </form> |
9 | </div> | 9 | </div> |
diff --git a/src/Wallabag/CoreBundle/Resources/views/_top.html.twig b/src/Wallabag/CoreBundle/Resources/views/_top.html.twig index 34d925df..9313071d 100755 --- a/src/Wallabag/CoreBundle/Resources/views/_top.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/_top.html.twig | |||
@@ -1,5 +1,5 @@ | |||
1 | <header class="w600p center mbm"> | 1 | <header class="w600p center mbm"> |
2 | <h1> | 2 | <h1> |
3 | {% block logo %}<img width="100" height="100" src="{{ asset('themes/baggy/img/logo-w.png') }}" alt="wallabag logo" />{% endblock %} | 3 | {% block logo %}<img width="100" height="100" src="{{ asset('themes/baggy/img/logo-w.png') }}" alt="wallabag logo" />{% endblock %} |
4 | </h1> | 4 | </h1> |
5 | </header> | 5 | </header> |
diff --git a/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php b/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php index 56f1affe..fcfe418b 100644 --- a/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php +++ b/src/Wallabag/CoreBundle/Security/Authentication/Encoder/WallabagPasswordEncoder.php | |||
@@ -41,10 +41,6 @@ class WallabagPasswordEncoder extends BasePasswordEncoder | |||
41 | */ | 41 | */ |
42 | public function encodePassword($raw, $salt) | 42 | public function encodePassword($raw, $salt) |
43 | { | 43 | { |
44 | if (null === $this->username) { | ||
45 | throw new \LogicException('We can not check the password without a username.'); | ||
46 | } | ||
47 | |||
48 | if ($this->isPasswordTooLong($raw)) { | 44 | if ($this->isPasswordTooLong($raw)) { |
49 | throw new BadCredentialsException('Invalid password.'); | 45 | throw new BadCredentialsException('Invalid password.'); |
50 | } | 46 | } |
@@ -71,6 +67,10 @@ class WallabagPasswordEncoder extends BasePasswordEncoder | |||
71 | */ | 67 | */ |
72 | protected function mergePasswordAndSalt($password, $salt) | 68 | protected function mergePasswordAndSalt($password, $salt) |
73 | { | 69 | { |
70 | if (null === $this->username) { | ||
71 | throw new \LogicException('We can not check the password without a username.'); | ||
72 | } | ||
73 | |||
74 | if (empty($salt)) { | 74 | if (empty($salt)) { |
75 | return $password; | 75 | return $password; |
76 | } | 76 | } |
diff --git a/src/Wallabag/CoreBundle/Security/Validator/WallabagUserPasswordValidator.php b/src/Wallabag/CoreBundle/Security/Validator/WallabagUserPasswordValidator.php new file mode 100644 index 00000000..5586f976 --- /dev/null +++ b/src/Wallabag/CoreBundle/Security/Validator/WallabagUserPasswordValidator.php | |||
@@ -0,0 +1,48 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Security\Validator; | ||
4 | |||
5 | use Symfony\Component\Security\Core\User\UserInterface; | ||
6 | use Symfony\Component\Security\Core\SecurityContextInterface; | ||
7 | use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; | ||
8 | use Symfony\Component\Validator\Constraint; | ||
9 | use Symfony\Component\Validator\ConstraintValidator; | ||
10 | use Symfony\Component\Validator\Exception\ConstraintDefinitionException; | ||
11 | use Symfony\Component\Validator\Exception\UnexpectedTypeException; | ||
12 | use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; | ||
13 | |||
14 | class WallabagUserPasswordValidator extends ConstraintValidator | ||
15 | { | ||
16 | private $securityContext; | ||
17 | private $encoderFactory; | ||
18 | |||
19 | public function __construct(SecurityContextInterface $securityContext, EncoderFactoryInterface $encoderFactory) | ||
20 | { | ||
21 | $this->securityContext = $securityContext; | ||
22 | $this->encoderFactory = $encoderFactory; | ||
23 | } | ||
24 | |||
25 | /** | ||
26 | * {@inheritdoc} | ||
27 | */ | ||
28 | public function validate($password, Constraint $constraint) | ||
29 | { | ||
30 | if (!$constraint instanceof UserPassword) { | ||
31 | throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword'); | ||
32 | } | ||
33 | |||
34 | $user = $this->securityContext->getToken()->getUser(); | ||
35 | |||
36 | if (!$user instanceof UserInterface) { | ||
37 | throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.'); | ||
38 | } | ||
39 | |||
40 | // give username, it's used to hash the password | ||
41 | $encoder = $this->encoderFactory->getEncoder($user); | ||
42 | $encoder->setUsername($user->getUsername()); | ||
43 | |||
44 | if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { | ||
45 | $this->context->addViolation($constraint->message); | ||
46 | } | ||
47 | } | ||
48 | } | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php new file mode 100644 index 00000000..64f6c329 --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/Command/InstallCommandTest.php | |||
@@ -0,0 +1,274 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Tests\Command; | ||
4 | |||
5 | use Wallabag\CoreBundle\Tests\WallabagTestCase; | ||
6 | use Wallabag\CoreBundle\Command\InstallCommand; | ||
7 | use Symfony\Bundle\FrameworkBundle\Console\Application; | ||
8 | use Symfony\Component\Console\Tester\CommandTester; | ||
9 | use Symfony\Component\Console\Input\ArrayInput; | ||
10 | use Symfony\Component\Console\Output\NullOutput; | ||
11 | use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand; | ||
12 | use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand; | ||
13 | |||
14 | class InstallCommandTest extends WallabagTestCase | ||
15 | { | ||
16 | public static function tearDownAfterClass() | ||
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 | |||
62 | public function testRunInstallCommandWithReset() | ||
63 | { | ||
64 | $this->container = static::$kernel->getContainer(); | ||
65 | |||
66 | $application = new Application(static::$kernel); | ||
67 | $application->add(new InstallCommand()); | ||
68 | |||
69 | $command = $application->find('wallabag:install'); | ||
70 | |||
71 | // We mock the DialogHelper | ||
72 | $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper') | ||
73 | ->disableOriginalConstructor() | ||
74 | ->getMock(); | ||
75 | $dialog->expects($this->any()) | ||
76 | ->method('ask') | ||
77 | ->will($this->returnValue('test')); | ||
78 | $dialog->expects($this->any()) | ||
79 | ->method('askConfirmation') | ||
80 | ->will($this->returnValue(true)); | ||
81 | |||
82 | // We override the standard helper with our mock | ||
83 | $command->getHelperSet()->set($dialog, 'dialog'); | ||
84 | |||
85 | $tester = new CommandTester($command); | ||
86 | $tester->execute(array( | ||
87 | 'command' => $command->getName(), | ||
88 | '--reset' => true, | ||
89 | )); | ||
90 | |||
91 | $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay()); | ||
92 | $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay()); | ||
93 | $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay()); | ||
94 | $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay()); | ||
95 | |||
96 | // we force to reset everything | ||
97 | $this->assertContains('Droping database, creating database and schema', $tester->getDisplay()); | ||
98 | } | ||
99 | |||
100 | public function testRunInstallCommandWithDatabaseRemoved() | ||
101 | { | ||
102 | $this->container = static::$kernel->getContainer(); | ||
103 | |||
104 | $application = new Application(static::$kernel); | ||
105 | $application->add(new InstallCommand()); | ||
106 | $application->add(new DropDatabaseDoctrineCommand()); | ||
107 | |||
108 | // drop database first, so the install command won't ask to reset things | ||
109 | $command = new DropDatabaseDoctrineCommand(); | ||
110 | $command->setApplication($application); | ||
111 | $command->run(new ArrayInput(array( | ||
112 | 'command' => 'doctrine:database:drop', | ||
113 | '--force' => true, | ||
114 | )), new NullOutput()); | ||
115 | |||
116 | $command = $application->find('wallabag:install'); | ||
117 | |||
118 | // We mock the DialogHelper | ||
119 | $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper') | ||
120 | ->disableOriginalConstructor() | ||
121 | ->getMock(); | ||
122 | $dialog->expects($this->any()) | ||
123 | ->method('ask') | ||
124 | ->will($this->returnValue('test')); | ||
125 | $dialog->expects($this->any()) | ||
126 | ->method('askConfirmation') | ||
127 | ->will($this->returnValue(true)); | ||
128 | |||
129 | // We override the standard helper with our mock | ||
130 | $command->getHelperSet()->set($dialog, 'dialog'); | ||
131 | |||
132 | $tester = new CommandTester($command); | ||
133 | $tester->execute(array( | ||
134 | 'command' => $command->getName(), | ||
135 | )); | ||
136 | |||
137 | $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay()); | ||
138 | $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay()); | ||
139 | $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay()); | ||
140 | $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay()); | ||
141 | |||
142 | // the current database doesn't already exist | ||
143 | $this->assertContains('Creating database and schema, clearing the cache', $tester->getDisplay()); | ||
144 | } | ||
145 | |||
146 | public function testRunInstallCommandChooseResetSchema() | ||
147 | { | ||
148 | $this->container = static::$kernel->getContainer(); | ||
149 | |||
150 | $application = new Application(static::$kernel); | ||
151 | $application->add(new InstallCommand()); | ||
152 | |||
153 | $command = $application->find('wallabag:install'); | ||
154 | |||
155 | // We mock the DialogHelper | ||
156 | $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper') | ||
157 | ->disableOriginalConstructor() | ||
158 | ->getMock(); | ||
159 | |||
160 | $dialog->expects($this->exactly(3)) | ||
161 | ->method('askConfirmation') | ||
162 | ->will($this->onConsecutiveCalls( | ||
163 | false, // don't want to reset the entire database | ||
164 | true, // do want to reset the schema | ||
165 | false // don't want to create a new user | ||
166 | )); | ||
167 | |||
168 | // We override the standard helper with our mock | ||
169 | $command->getHelperSet()->set($dialog, 'dialog'); | ||
170 | |||
171 | $tester = new CommandTester($command); | ||
172 | $tester->execute(array( | ||
173 | 'command' => $command->getName(), | ||
174 | )); | ||
175 | |||
176 | $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay()); | ||
177 | $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay()); | ||
178 | $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay()); | ||
179 | $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay()); | ||
180 | |||
181 | $this->assertContains('Droping schema and creating schema', $tester->getDisplay()); | ||
182 | } | ||
183 | |||
184 | public function testRunInstallCommandChooseNothing() | ||
185 | { | ||
186 | $this->container = static::$kernel->getContainer(); | ||
187 | |||
188 | $application = new Application(static::$kernel); | ||
189 | $application->add(new InstallCommand()); | ||
190 | $application->add(new DropDatabaseDoctrineCommand()); | ||
191 | $application->add(new CreateDatabaseDoctrineCommand()); | ||
192 | |||
193 | // drop database first, so the install command won't ask to reset things | ||
194 | $command = new DropDatabaseDoctrineCommand(); | ||
195 | $command->setApplication($application); | ||
196 | $command->run(new ArrayInput(array( | ||
197 | 'command' => 'doctrine:database:drop', | ||
198 | '--force' => true, | ||
199 | )), new NullOutput()); | ||
200 | |||
201 | $this->container->get('doctrine')->getManager()->getConnection()->close(); | ||
202 | |||
203 | $command = new CreateDatabaseDoctrineCommand(); | ||
204 | $command->setApplication($application); | ||
205 | $command->run(new ArrayInput(array( | ||
206 | 'command' => 'doctrine:database:create', | ||
207 | '--env' => 'test', | ||
208 | )), new NullOutput()); | ||
209 | |||
210 | $command = $application->find('wallabag:install'); | ||
211 | |||
212 | // We mock the DialogHelper | ||
213 | $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper') | ||
214 | ->disableOriginalConstructor() | ||
215 | ->getMock(); | ||
216 | |||
217 | $dialog->expects($this->exactly(2)) | ||
218 | ->method('askConfirmation') | ||
219 | ->will($this->onConsecutiveCalls( | ||
220 | false, // don't want to reset the entire database | ||
221 | false // don't want to create a new user | ||
222 | )); | ||
223 | |||
224 | // We override the standard helper with our mock | ||
225 | $command->getHelperSet()->set($dialog, 'dialog'); | ||
226 | |||
227 | $tester = new CommandTester($command); | ||
228 | $tester->execute(array( | ||
229 | 'command' => $command->getName(), | ||
230 | )); | ||
231 | |||
232 | $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay()); | ||
233 | $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay()); | ||
234 | $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay()); | ||
235 | $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay()); | ||
236 | |||
237 | $this->assertContains('Creating schema', $tester->getDisplay()); | ||
238 | } | ||
239 | |||
240 | public function testRunInstallCommandNoInteraction() | ||
241 | { | ||
242 | $this->container = static::$kernel->getContainer(); | ||
243 | |||
244 | $application = new Application(static::$kernel); | ||
245 | $application->add(new InstallCommand()); | ||
246 | |||
247 | $command = $application->find('wallabag:install'); | ||
248 | |||
249 | // We mock the DialogHelper | ||
250 | $dialog = $this->getMockBuilder('Symfony\Component\Console\Helper\DialogHelper') | ||
251 | ->disableOriginalConstructor() | ||
252 | ->getMock(); | ||
253 | $dialog->expects($this->any()) | ||
254 | ->method('ask') | ||
255 | ->will($this->returnValue('test')); | ||
256 | $dialog->expects($this->any()) | ||
257 | ->method('askConfirmation') | ||
258 | ->will($this->returnValue(true)); | ||
259 | |||
260 | // We override the standard helper with our mock | ||
261 | $command->getHelperSet()->set($dialog, 'dialog'); | ||
262 | |||
263 | $tester = new CommandTester($command); | ||
264 | $tester->execute(array( | ||
265 | 'command' => $command->getName(), | ||
266 | '--no-interaction' => true, | ||
267 | )); | ||
268 | |||
269 | $this->assertContains('Step 1 of 4. Checking system requirements.', $tester->getDisplay()); | ||
270 | $this->assertContains('Step 2 of 4. Setting up database.', $tester->getDisplay()); | ||
271 | $this->assertContains('Step 3 of 4. Administration setup.', $tester->getDisplay()); | ||
272 | $this->assertContains('Step 4 of 4. Installing assets.', $tester->getDisplay()); | ||
273 | } | ||
274 | } | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php new file mode 100644 index 00000000..9b1a0986 --- /dev/null +++ b/src/Wallabag/CoreBundle/Tests/Controller/ConfigControllerTest.php | |||
@@ -0,0 +1,350 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\CoreBundle\Tests\Controller; | ||
4 | |||
5 | use Wallabag\CoreBundle\Tests\WallabagTestCase; | ||
6 | |||
7 | class ConfigControllerTest extends WallabagTestCase | ||
8 | { | ||
9 | public function testLogin() | ||
10 | { | ||
11 | $client = $this->getClient(); | ||
12 | |||
13 | $client->request('GET', '/new'); | ||
14 | |||
15 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
16 | $this->assertContains('login', $client->getResponse()->headers->get('location')); | ||
17 | } | ||
18 | |||
19 | public function testIndex() | ||
20 | { | ||
21 | $this->logInAs('admin'); | ||
22 | $client = $this->getClient(); | ||
23 | |||
24 | $crawler = $client->request('GET', '/config'); | ||
25 | |||
26 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
27 | |||
28 | $this->assertCount(1, $crawler->filter('button[id=config_save]')); | ||
29 | $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]')); | ||
30 | $this->assertCount(1, $crawler->filter('button[id=user_save]')); | ||
31 | } | ||
32 | |||
33 | public function testUpdate() | ||
34 | { | ||
35 | $this->logInAs('admin'); | ||
36 | $client = $this->getClient(); | ||
37 | |||
38 | $crawler = $client->request('GET', '/config'); | ||
39 | |||
40 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
41 | |||
42 | $form = $crawler->filter('button[id=config_save]')->form(); | ||
43 | |||
44 | $data = array( | ||
45 | 'config[theme]' => 'baggy', | ||
46 | 'config[items_per_page]' => '30', | ||
47 | 'config[language]' => 'fr_FR', | ||
48 | ); | ||
49 | |||
50 | $client->submit($form, $data); | ||
51 | |||
52 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
53 | |||
54 | $crawler = $client->followRedirect(); | ||
55 | |||
56 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.flash-notice')->extract(array('_text'))); | ||
57 | $this->assertContains('Config saved', $alert[0]); | ||
58 | } | ||
59 | |||
60 | public function dataForUpdateFailed() | ||
61 | { | ||
62 | return array( | ||
63 | array(array( | ||
64 | 'config[theme]' => 'baggy', | ||
65 | 'config[items_per_page]' => '', | ||
66 | 'config[language]' => 'fr_FR', | ||
67 | )), | ||
68 | array(array( | ||
69 | 'config[theme]' => 'baggy', | ||
70 | 'config[items_per_page]' => '12', | ||
71 | 'config[language]' => '', | ||
72 | )), | ||
73 | ); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * @dataProvider dataForUpdateFailed | ||
78 | */ | ||
79 | public function testUpdateFailed($data) | ||
80 | { | ||
81 | $this->logInAs('admin'); | ||
82 | $client = $this->getClient(); | ||
83 | |||
84 | $crawler = $client->request('GET', '/config'); | ||
85 | |||
86 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
87 | |||
88 | $form = $crawler->filter('button[id=config_save]')->form(); | ||
89 | |||
90 | $crawler = $client->submit($form, $data); | ||
91 | |||
92 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
93 | |||
94 | $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text'))); | ||
95 | $this->assertContains('This value should not be blank', $alert[0]); | ||
96 | } | ||
97 | |||
98 | public function dataForChangePasswordFailed() | ||
99 | { | ||
100 | return array( | ||
101 | array( | ||
102 | array( | ||
103 | 'change_passwd[old_password]' => 'baggy', | ||
104 | 'change_passwd[new_password][first]' => '', | ||
105 | 'change_passwd[new_password][second]' => '', | ||
106 | ), | ||
107 | 'Wrong value for your current password', | ||
108 | ), | ||
109 | array( | ||
110 | array( | ||
111 | 'change_passwd[old_password]' => 'mypassword', | ||
112 | 'change_passwd[new_password][first]' => '', | ||
113 | 'change_passwd[new_password][second]' => '', | ||
114 | ), | ||
115 | 'This value should not be blank', | ||
116 | ), | ||
117 | array( | ||
118 | array( | ||
119 | 'change_passwd[old_password]' => 'mypassword', | ||
120 | 'change_passwd[new_password][first]' => 'hop', | ||
121 | 'change_passwd[new_password][second]' => '', | ||
122 | ), | ||
123 | 'The password fields must match', | ||
124 | ), | ||
125 | array( | ||
126 | array( | ||
127 | 'change_passwd[old_password]' => 'mypassword', | ||
128 | 'change_passwd[new_password][first]' => 'hop', | ||
129 | 'change_passwd[new_password][second]' => 'hop', | ||
130 | ), | ||
131 | 'Password should by at least', | ||
132 | ), | ||
133 | ); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * @dataProvider dataForChangePasswordFailed | ||
138 | */ | ||
139 | public function testChangePasswordFailed($data, $expectedMessage) | ||
140 | { | ||
141 | $this->logInAs('admin'); | ||
142 | $client = $this->getClient(); | ||
143 | |||
144 | $crawler = $client->request('GET', '/config'); | ||
145 | |||
146 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
147 | |||
148 | $form = $crawler->filter('button[id=change_passwd_save]')->form(); | ||
149 | |||
150 | $crawler = $client->submit($form, $data); | ||
151 | |||
152 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
153 | |||
154 | $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text'))); | ||
155 | $this->assertContains($expectedMessage, $alert[0]); | ||
156 | } | ||
157 | |||
158 | public function testChangePassword() | ||
159 | { | ||
160 | $this->logInAs('admin'); | ||
161 | $client = $this->getClient(); | ||
162 | |||
163 | $crawler = $client->request('GET', '/config'); | ||
164 | |||
165 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
166 | |||
167 | $form = $crawler->filter('button[id=change_passwd_save]')->form(); | ||
168 | |||
169 | $data = array( | ||
170 | 'change_passwd[old_password]' => 'mypassword', | ||
171 | 'change_passwd[new_password][first]' => 'mypassword', | ||
172 | 'change_passwd[new_password][second]' => 'mypassword', | ||
173 | ); | ||
174 | |||
175 | $client->submit($form, $data); | ||
176 | |||
177 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
178 | |||
179 | $crawler = $client->followRedirect(); | ||
180 | |||
181 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.flash-notice')->extract(array('_text'))); | ||
182 | $this->assertContains('Password updated', $alert[0]); | ||
183 | } | ||
184 | |||
185 | public function dataForUserFailed() | ||
186 | { | ||
187 | return array( | ||
188 | array( | ||
189 | array( | ||
190 | 'user[username]' => '', | ||
191 | 'user[name]' => '', | ||
192 | 'user[email]' => '', | ||
193 | ), | ||
194 | 'This value should not be blank.', | ||
195 | ), | ||
196 | array( | ||
197 | array( | ||
198 | 'user[username]' => 'ad', | ||
199 | 'user[name]' => '', | ||
200 | 'user[email]' => '', | ||
201 | ), | ||
202 | 'This value is too short.', | ||
203 | ), | ||
204 | array( | ||
205 | array( | ||
206 | 'user[username]' => 'admin', | ||
207 | 'user[name]' => '', | ||
208 | 'user[email]' => 'test', | ||
209 | ), | ||
210 | 'This value is not a valid email address.', | ||
211 | ), | ||
212 | ); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * @dataProvider dataForUserFailed | ||
217 | */ | ||
218 | public function testUserFailed($data, $expectedMessage) | ||
219 | { | ||
220 | $this->logInAs('admin'); | ||
221 | $client = $this->getClient(); | ||
222 | |||
223 | $crawler = $client->request('GET', '/config'); | ||
224 | |||
225 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
226 | |||
227 | $form = $crawler->filter('button[id=user_save]')->form(); | ||
228 | |||
229 | $crawler = $client->submit($form, $data); | ||
230 | |||
231 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
232 | |||
233 | $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text'))); | ||
234 | $this->assertContains($expectedMessage, $alert[0]); | ||
235 | } | ||
236 | |||
237 | public function testUserUpdate() | ||
238 | { | ||
239 | $this->logInAs('admin'); | ||
240 | $client = $this->getClient(); | ||
241 | |||
242 | $crawler = $client->request('GET', '/config'); | ||
243 | |||
244 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
245 | |||
246 | $form = $crawler->filter('button[id=user_save]')->form(); | ||
247 | |||
248 | $data = array( | ||
249 | 'user[username]' => 'admin', | ||
250 | 'user[name]' => 'new name', | ||
251 | 'user[email]' => 'admin@wallabag.io', | ||
252 | ); | ||
253 | |||
254 | $client->submit($form, $data); | ||
255 | |||
256 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
257 | |||
258 | $crawler = $client->followRedirect(); | ||
259 | |||
260 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.flash-notice')->extract(array('_text'))); | ||
261 | $this->assertContains('Information updated', $alert[0]); | ||
262 | } | ||
263 | |||
264 | public function dataForNewUserFailed() | ||
265 | { | ||
266 | return array( | ||
267 | array( | ||
268 | array( | ||
269 | 'new_user[username]' => '', | ||
270 | 'new_user[password]' => '', | ||
271 | 'new_user[email]' => '', | ||
272 | ), | ||
273 | 'This value should not be blank.', | ||
274 | ), | ||
275 | array( | ||
276 | array( | ||
277 | 'new_user[username]' => 'ad', | ||
278 | 'new_user[password]' => '', | ||
279 | 'new_user[email]' => '', | ||
280 | ), | ||
281 | 'This value is too short.', | ||
282 | ), | ||
283 | array( | ||
284 | array( | ||
285 | 'new_user[username]' => 'wallace', | ||
286 | 'new_user[password]' => '', | ||
287 | 'new_user[email]' => 'test', | ||
288 | ), | ||
289 | 'This value is not a valid email address.', | ||
290 | ), | ||
291 | array( | ||
292 | array( | ||
293 | 'new_user[username]' => 'wallace', | ||
294 | 'new_user[password]' => 'admin', | ||
295 | 'new_user[email]' => 'wallace@wallace.me', | ||
296 | ), | ||
297 | 'Password should by at least', | ||
298 | ), | ||
299 | ); | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * @dataProvider dataForNewUserFailed | ||
304 | */ | ||
305 | public function testNewUserFailed($data, $expectedMessage) | ||
306 | { | ||
307 | $this->logInAs('admin'); | ||
308 | $client = $this->getClient(); | ||
309 | |||
310 | $crawler = $client->request('GET', '/config'); | ||
311 | |||
312 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
313 | |||
314 | $form = $crawler->filter('button[id=new_user_save]')->form(); | ||
315 | |||
316 | $crawler = $client->submit($form, $data); | ||
317 | |||
318 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
319 | |||
320 | $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text'))); | ||
321 | $this->assertContains($expectedMessage, $alert[0]); | ||
322 | } | ||
323 | |||
324 | public function testNewUserCreated() | ||
325 | { | ||
326 | $this->logInAs('admin'); | ||
327 | $client = $this->getClient(); | ||
328 | |||
329 | $crawler = $client->request('GET', '/config'); | ||
330 | |||
331 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); | ||
332 | |||
333 | $form = $crawler->filter('button[id=new_user_save]')->form(); | ||
334 | |||
335 | $data = array( | ||
336 | 'new_user[username]' => 'wallace', | ||
337 | 'new_user[password]' => 'wallace1', | ||
338 | 'new_user[email]' => 'wallace@wallace.me', | ||
339 | ); | ||
340 | |||
341 | $client->submit($form, $data); | ||
342 | |||
343 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); | ||
344 | |||
345 | $crawler = $client->followRedirect(); | ||
346 | |||
347 | $this->assertGreaterThan(1, $alert = $crawler->filter('div.flash-notice')->extract(array('_text'))); | ||
348 | $this->assertContains('User "wallace" added', $alert[0]); | ||
349 | } | ||
350 | } | ||
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php index 7276f8e4..2634141e 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php | |||
@@ -60,7 +60,7 @@ class EntryControllerTest extends WallabagTestCase | |||
60 | $form = $crawler->filter('button[type=submit]')->form(); | 60 | $form = $crawler->filter('button[type=submit]')->form(); |
61 | 61 | ||
62 | $data = array( | 62 | $data = array( |
63 | 'form[url]' => 'https://www.mailjet.com/blog/mailjet-zapier-integrations-made-easy/', | 63 | 'entry[url]' => 'https://www.mailjet.com/blog/mailjet-zapier-integrations-made-easy/', |
64 | ); | 64 | ); |
65 | 65 | ||
66 | $client->submit($form, $data); | 66 | $client->submit($form, $data); |
diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index d77e2303..fcfa8ccf 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php | |||
@@ -47,7 +47,7 @@ class WallabagRestControllerTest extends WallabagTestCase | |||
47 | $client->request('GET', '/api/salts/admin.json'); | 47 | $client->request('GET', '/api/salts/admin.json'); |
48 | $salt = json_decode($client->getResponse()->getContent()); | 48 | $salt = json_decode($client->getResponse()->getContent()); |
49 | 49 | ||
50 | $headers = $this->generateHeaders('admin', 'test', $salt[0]); | 50 | $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); |
51 | 51 | ||
52 | $entry = $client->getContainer() | 52 | $entry = $client->getContainer() |
53 | ->get('doctrine.orm.entity_manager') | 53 | ->get('doctrine.orm.entity_manager') |
@@ -73,7 +73,7 @@ class WallabagRestControllerTest extends WallabagTestCase | |||
73 | $client->request('GET', '/api/salts/admin.json'); | 73 | $client->request('GET', '/api/salts/admin.json'); |
74 | $salt = json_decode($client->getResponse()->getContent()); | 74 | $salt = json_decode($client->getResponse()->getContent()); |
75 | 75 | ||
76 | $headers = $this->generateHeaders('admin', 'test', $salt[0]); | 76 | $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); |
77 | 77 | ||
78 | $entry = $client->getContainer() | 78 | $entry = $client->getContainer() |
79 | ->get('doctrine.orm.entity_manager') | 79 | ->get('doctrine.orm.entity_manager') |
@@ -101,7 +101,7 @@ class WallabagRestControllerTest extends WallabagTestCase | |||
101 | $client->request('GET', '/api/salts/admin.json'); | 101 | $client->request('GET', '/api/salts/admin.json'); |
102 | $salt = json_decode($client->getResponse()->getContent()); | 102 | $salt = json_decode($client->getResponse()->getContent()); |
103 | 103 | ||
104 | $headers = $this->generateHeaders('admin', 'test', $salt[0]); | 104 | $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); |
105 | 105 | ||
106 | $client->request('GET', '/api/entries', array(), array(), $headers); | 106 | $client->request('GET', '/api/entries', array(), array(), $headers); |
107 | 107 | ||
@@ -125,7 +125,7 @@ class WallabagRestControllerTest extends WallabagTestCase | |||
125 | $client->request('GET', '/api/salts/admin.json'); | 125 | $client->request('GET', '/api/salts/admin.json'); |
126 | $salt = json_decode($client->getResponse()->getContent()); | 126 | $salt = json_decode($client->getResponse()->getContent()); |
127 | 127 | ||
128 | $headers = $this->generateHeaders('admin', 'test', $salt[0]); | 128 | $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); |
129 | 129 | ||
130 | $entry = $client->getContainer() | 130 | $entry = $client->getContainer() |
131 | ->get('doctrine.orm.entity_manager') | 131 | ->get('doctrine.orm.entity_manager') |
diff --git a/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php index a80b8bac..22016d8e 100644 --- a/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php +++ b/src/Wallabag/CoreBundle/Tests/WallabagTestCase.php | |||
@@ -4,7 +4,7 @@ namespace Wallabag\CoreBundle\Tests; | |||
4 | 4 | ||
5 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; | 5 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; |
6 | 6 | ||
7 | class WallabagTestCase extends WebTestCase | 7 | abstract class WallabagTestCase extends WebTestCase |
8 | { | 8 | { |
9 | private $client = null; | 9 | private $client = null; |
10 | 10 | ||
@@ -24,7 +24,7 @@ class WallabagTestCase extends WebTestCase | |||
24 | $form = $crawler->filter('button[type=submit]')->form(); | 24 | $form = $crawler->filter('button[type=submit]')->form(); |
25 | $data = array( | 25 | $data = array( |
26 | '_username' => $username, | 26 | '_username' => $username, |
27 | '_password' => 'test', | 27 | '_password' => 'mypassword', |
28 | ); | 28 | ); |
29 | 29 | ||
30 | $this->client->submit($form, $data); | 30 | $this->client->submit($form, $data); |