Skip to content

Commit d1ad7f5

Browse files
committed
feature #615 Added a validator service for commands (javiereguiluz)
This PR was squashed before being merged into the master branch (closes #615). Discussion ---------- Added a validator service for commands I can't merge #567 because of the conflicts, so this is an attempt to merge it. Commits ------- 5b02ca2 Added a validator service for commands
2 parents 0d1ddaf + 5b02ca2 commit d1ad7f5

File tree

6 files changed

+181
-86
lines changed

6 files changed

+181
-86
lines changed

src/AppBundle/Command/AddUserCommand.php

Lines changed: 12 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace AppBundle\Command;
1313

1414
use AppBundle\Entity\User;
15+
use AppBundle\Utils\Validator;
1516
use Doctrine\ORM\EntityManagerInterface;
1617
use Symfony\Component\Console\Command\Command;
1718
use Symfony\Component\Console\Input\InputArgument;
@@ -23,7 +24,7 @@
2324
use Symfony\Component\Stopwatch\Stopwatch;
2425

2526
/**
26-
* A command console that creates users and stores them in the database.
27+
* A console command that creates users and stores them in the database.
2728
*
2829
* To use this command, open a terminal window, enter into your project
2930
* directory and execute the following:
@@ -48,13 +49,15 @@ class AddUserCommand extends Command
4849
private $io;
4950
private $entityManager;
5051
private $passwordEncoder;
52+
private $validator;
5153

52-
public function __construct(EntityManagerInterface $em, UserPasswordEncoderInterface $encoder)
54+
public function __construct(EntityManagerInterface $em, UserPasswordEncoderInterface $encoder, Validator $validator)
5355
{
5456
parent::__construct();
5557

5658
$this->entityManager = $em;
5759
$this->passwordEncoder = $encoder;
60+
$this->validator = $validator;
5861
}
5962

6063
/**
@@ -120,14 +123,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
120123
if (null !== $username) {
121124
$this->io->text(' > <info>Username</info>: '.$username);
122125
} else {
123-
$username = $this->io->ask('Username', null, function ($answer) {
124-
if (empty($answer)) {
125-
throw new \RuntimeException('The username cannot be empty');
126-
}
127-
128-
return $answer;
129-
});
130-
126+
$username = $this->io->ask('Username', null, [$this->validator, 'validateUsername']);
131127
$input->setArgument('username', $username);
132128
}
133129

@@ -136,7 +132,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
136132
if (null !== $password) {
137133
$this->io->text(' > <info>Password</info>: '.str_repeat('*', mb_strlen($password)));
138134
} else {
139-
$password = $this->io->askHidden('Password (your type will be hidden)', null, [$this, 'passwordValidator']);
135+
$password = $this->io->askHidden('Password (your type will be hidden)', null, [$this->validator, 'validatePassword']);
140136
$input->setArgument('password', $password);
141137
}
142138

@@ -145,7 +141,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
145141
if (null !== $email) {
146142
$this->io->text(' > <info>Email</info>: '.$email);
147143
} else {
148-
$email = $this->io->ask('Email', null, [$this, 'emailValidator']);
144+
$email = $this->io->ask('Email', null, [$this->validator, 'validateEmail']);
149145
$input->setArgument('email', $email);
150146
}
151147

@@ -154,7 +150,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
154150
if (null !== $fullName) {
155151
$this->io->text(' > <info>Full Name</info>: '.$fullName);
156152
} else {
157-
$fullName = $this->io->ask('Full Name', null, [$this, 'fullNameValidator']);
153+
$fullName = $this->io->ask('Full Name', null, [$this->validator, 'validateFullName']);
158154
$input->setArgument('full-name', $fullName);
159155
}
160156
}
@@ -199,50 +195,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
199195
}
200196
}
201197

202-
/**
203-
* @internal
204-
*/
205-
public function passwordValidator($plainPassword)
206-
{
207-
if (empty($plainPassword)) {
208-
throw new \Exception('The password can not be empty.');
209-
}
210-
211-
if (mb_strlen(trim($plainPassword)) < 6) {
212-
throw new \Exception('The password must be at least 6 characters long.');
213-
}
214-
215-
return $plainPassword;
216-
}
217-
218-
/**
219-
* @internal
220-
*/
221-
public function emailValidator($email)
222-
{
223-
if (empty($email)) {
224-
throw new \Exception('The email can not be empty.');
225-
}
226-
227-
if (false === mb_strpos($email, '@')) {
228-
throw new \Exception('The email should look like a real email.');
229-
}
230-
231-
return $email;
232-
}
233-
234-
/**
235-
* @internal
236-
*/
237-
public function fullNameValidator($fullName)
238-
{
239-
if (empty($fullName)) {
240-
throw new \Exception('The full name can not be empty.');
241-
}
242-
243-
return $fullName;
244-
}
245-
246198
private function validateUserData($username, $plainPassword, $email, $fullName)
247199
{
248200
$userRepository = $this->entityManager->getRepository(User::class);
@@ -255,9 +207,9 @@ private function validateUserData($username, $plainPassword, $email, $fullName)
255207
}
256208

257209
// validate password and email if is not this input means interactive.
258-
$this->passwordValidator($plainPassword);
259-
$this->emailValidator($email);
260-
$this->fullNameValidator($fullName);
210+
$this->validator->validatePassword($plainPassword);
211+
$this->validator->validateEmail($email);
212+
$this->validator->validateFullName($fullName);
261213

262214
// check if a user with the same email already exists.
263215
$existingEmail = $userRepository->findOneBy(['email' => $email]);

src/AppBundle/Command/DeleteUserCommand.php

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace AppBundle\Command;
1313

1414
use AppBundle\Entity\User;
15+
use AppBundle\Utils\Validator;
1516
use Doctrine\ORM\EntityManagerInterface;
1617
use Symfony\Component\Console\Command\Command;
1718
use Symfony\Component\Console\Input\InputArgument;
@@ -20,7 +21,7 @@
2021
use Symfony\Component\Console\Style\SymfonyStyle;
2122

2223
/**
23-
* A command console that deletes users from the database.
24+
* A console command that deletes users from the database.
2425
*
2526
* To use this command, open a terminal window, enter into your project
2627
* directory and execute the following:
@@ -42,12 +43,14 @@ class DeleteUserCommand extends Command
4243

4344
private $io;
4445
private $entityManager;
46+
private $validator;
4547

46-
public function __construct(EntityManagerInterface $em)
48+
public function __construct(EntityManagerInterface $em, Validator $validator)
4749
{
4850
parent::__construct();
4951

5052
$this->entityManager = $em;
53+
$this->validator = $validator;
5154
}
5255

5356
/**
@@ -103,8 +106,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
103106

104107
protected function execute(InputInterface $input, OutputInterface $output)
105108
{
106-
$username = $input->getArgument('username');
107-
$this->usernameValidator($username);
109+
$username = $this->validator->validateUsername($input->getArgument('username'));
108110

109111
$repository = $this->entityManager->getRepository(User::class);
110112
/** @var User $user */
@@ -124,23 +126,4 @@ protected function execute(InputInterface $input, OutputInterface $output)
124126

125127
$this->io->success(sprintf('User "%s" (ID: %d, email: %s) was successfully deleted.', $user->getUsername(), $userId, $user->getEmail()));
126128
}
127-
128-
/**
129-
* This internal method should be private, but it's declared public to
130-
* maintain PHP 5.3 compatibility when using it in a callback.
131-
*
132-
* @internal
133-
*/
134-
public function usernameValidator($username)
135-
{
136-
if (empty($username)) {
137-
throw new \Exception('The username can not be empty.');
138-
}
139-
140-
if (1 !== preg_match('/^[a-z_]+$/', $username)) {
141-
throw new \Exception('The username must contain only lowercase latin characters and underscores.');
142-
}
143-
144-
return $username;
145-
}
146129
}

src/AppBundle/Command/ListUsersCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use Symfony\Component\Console\Style\SymfonyStyle;
2222

2323
/**
24-
* A command console that lists all the existing users.
24+
* A console command that lists all the existing users.
2525
*
2626
* To use this command, open a terminal window, enter into your project directory
2727
* and execute the following:

src/AppBundle/Utils/Validator.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace AppBundle\Utils;
13+
14+
class Validator
15+
{
16+
public function validateUsername($username)
17+
{
18+
if (empty($username)) {
19+
throw new \Exception('The username can not be empty.');
20+
}
21+
22+
if (1 !== preg_match('/^[a-z_]+$/', $username)) {
23+
throw new \Exception('The username must contain only lowercase latin characters and underscores.');
24+
}
25+
26+
return $username;
27+
}
28+
29+
public function validatePassword($plainPassword)
30+
{
31+
if (empty($plainPassword)) {
32+
throw new \Exception('The password can not be empty.');
33+
}
34+
35+
if (mb_strlen(trim($plainPassword)) < 6) {
36+
throw new \Exception('The password must be at least 6 characters long.');
37+
}
38+
39+
return $plainPassword;
40+
}
41+
42+
public function validateEmail($email)
43+
{
44+
if (empty($email)) {
45+
throw new \Exception('The email can not be empty.');
46+
}
47+
48+
if (false === mb_strpos($email, '@')) {
49+
throw new \Exception('The email should look like a real email.');
50+
}
51+
52+
return $email;
53+
}
54+
55+
public function validateFullName($fullName)
56+
{
57+
if (empty($fullName)) {
58+
throw new \Exception('The full name can not be empty.');
59+
}
60+
61+
return $fullName;
62+
}
63+
}

tests/AppBundle/Command/AddUserCommandTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use AppBundle\Command\AddUserCommand;
1515
use AppBundle\Entity\User;
16+
use AppBundle\Utils\Validator;
1617
use Symfony\Bundle\FrameworkBundle\Console\Application;
1718
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1819
use Symfony\Component\Console\Tester\CommandTester;
@@ -66,7 +67,7 @@ public function testCreateUserNonInteractive($isAdmin)
6667
public function testCreateUserInteractive($isAdmin)
6768
{
6869
$this->executeCommand(
69-
// these are the arguments (only 1 is passed, the rest are missing)
70+
// these are the arguments (only 1 is passed, the rest are missing)
7071
$isAdmin ? ['--admin' => 1] : [],
7172
// these are the responses given to the questions asked by the command
7273
// to get the value of the missing required arguments
@@ -116,7 +117,7 @@ private function executeCommand(array $arguments, array $inputs = [])
116117
self::bootKernel();
117118

118119
$container = self::$kernel->getContainer();
119-
$command = new AddUserCommand($container->get('doctrine')->getManager(), $container->get('security.password_encoder'));
120+
$command = new AddUserCommand($container->get('doctrine')->getManager(), $container->get('security.password_encoder'), new Validator());
120121
$command->setApplication(new Application(self::$kernel));
121122

122123
$commandTester = new CommandTester($command);

0 commit comments

Comments
 (0)