diff --git a/src/AppBundle/Command/AddUserCommand.php b/src/AppBundle/Command/AddUserCommand.php index 970d1b1d7..241c2544c 100644 --- a/src/AppBundle/Command/AddUserCommand.php +++ b/src/AppBundle/Command/AddUserCommand.php @@ -12,6 +12,7 @@ namespace AppBundle\Command; use AppBundle\Entity\User; +use AppBundle\Utils\Validator; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -22,7 +23,7 @@ use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; /** - * A command console that creates users and stores them in the database. + * A console command that creates users and stores them in the database. * * To use this command, open a terminal window, enter into your project * directory and execute the following: @@ -46,13 +47,15 @@ class AddUserCommand extends Command private $entityManager; private $passwordEncoder; + private $validator; - public function __construct(EntityManagerInterface $em, UserPasswordEncoderInterface $encoder) + public function __construct(EntityManagerInterface $em, UserPasswordEncoderInterface $encoder, Validator $validator) { parent::__construct(); $this->entityManager = $em; $this->passwordEncoder = $encoder; + $this->validator = $validator; } /** @@ -119,13 +122,7 @@ protected function interact(InputInterface $input, OutputInterface $output) $username = $input->getArgument('username'); if (null === $username) { $question = new Question(' > Username: '); - $question->setValidator(function ($answer) { - if (empty($answer)) { - throw new \RuntimeException('The username cannot be empty'); - } - - return $answer; - }); + $question->setValidator([$this->validator, 'validateUsername']); $question->setMaxAttempts(self::MAX_ATTEMPTS); $username = $console->ask($input, $output, $question); @@ -138,7 +135,7 @@ protected function interact(InputInterface $input, OutputInterface $output) $password = $input->getArgument('password'); if (null === $password) { $question = new Question(' > Password (your type will be hidden): '); - $question->setValidator([$this, 'passwordValidator']); + $question->setValidator([$this->validator, 'validatePassword']); $question->setHidden(true); $question->setMaxAttempts(self::MAX_ATTEMPTS); @@ -152,7 +149,7 @@ protected function interact(InputInterface $input, OutputInterface $output) $email = $input->getArgument('email'); if (null === $email) { $question = new Question(' > Email: '); - $question->setValidator([$this, 'emailValidator']); + $question->setValidator([$this->validator, 'validateEmail']); $question->setMaxAttempts(self::MAX_ATTEMPTS); $email = $console->ask($input, $output, $question); @@ -165,7 +162,7 @@ protected function interact(InputInterface $input, OutputInterface $output) $fullName = $input->getArgument('full-name'); if (null === $fullName) { $question = new Question(' > Full Name: '); - $question->setValidator([$this, 'fullNameValidator']); + $question->setValidator([$this->validator, 'validateFullName']); $question->setMaxAttempts(self::MAX_ATTEMPTS); $fullName = $console->ask($input, $output, $question); @@ -217,50 +214,6 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - /** - * @internal - */ - public function passwordValidator($plainPassword) - { - if (empty($plainPassword)) { - throw new \Exception('The password can not be empty.'); - } - - if (mb_strlen(trim($plainPassword)) < 6) { - throw new \Exception('The password must be at least 6 characters long.'); - } - - return $plainPassword; - } - - /** - * @internal - */ - public function emailValidator($email) - { - if (empty($email)) { - throw new \Exception('The email can not be empty.'); - } - - if (false === mb_strpos($email, '@')) { - throw new \Exception('The email should look like a real email.'); - } - - return $email; - } - - /** - * @internal - */ - public function fullNameValidator($fullName) - { - if (empty($fullName)) { - throw new \Exception('The full name can not be empty.'); - } - - return $fullName; - } - private function validateUserData($username, $plainPassword, $email, $fullName) { $userRepository = $this->entityManager->getRepository(User::class); @@ -273,9 +226,9 @@ private function validateUserData($username, $plainPassword, $email, $fullName) } // validate password and email if is not this input means interactive. - $this->passwordValidator($plainPassword); - $this->emailValidator($email); - $this->fullNameValidator($fullName); + $this->validator->validatePassword($plainPassword); + $this->validator->validateEmail($email); + $this->validator->validateFullName($fullName); // check if a user with the same email already exists. $existingEmail = $userRepository->findOneBy(['email' => $email]); diff --git a/src/AppBundle/Command/DeleteUserCommand.php b/src/AppBundle/Command/DeleteUserCommand.php index 9e3c8eaf7..0d7bb415c 100644 --- a/src/AppBundle/Command/DeleteUserCommand.php +++ b/src/AppBundle/Command/DeleteUserCommand.php @@ -12,6 +12,7 @@ namespace AppBundle\Command; use AppBundle\Entity\User; +use AppBundle\Utils\Validator; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -20,7 +21,7 @@ use Symfony\Component\Console\Question\Question; /** - * A command console that deletes users from the database. + * A console command that deletes users from the database. * * To use this command, open a terminal window, enter into your project * directory and execute the following: @@ -41,12 +42,14 @@ class DeleteUserCommand extends Command const MAX_ATTEMPTS = 5; private $entityManager; + private $validator; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, Validator $validator) { parent::__construct(); $this->entityManager = $em; + $this->validator = $validator; } /** @@ -99,7 +102,7 @@ protected function interact(InputInterface $input, OutputInterface $output) $helper = $this->getHelper('question'); $question = new Question(' > Username: '); - $question->setValidator([$this, 'usernameValidator']); + $question->setValidator([$this->validator, 'validateUsername']); $question->setMaxAttempts(self::MAX_ATTEMPTS); $username = $helper->ask($input, $output, $question); @@ -108,8 +111,7 @@ protected function interact(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output) { - $username = $input->getArgument('username'); - $this->usernameValidator($username); + $username = $this->validator->validateUsername($input->getArgument('username')); $repository = $this->entityManager->getRepository(User::class); /** @var User $user */ @@ -130,23 +132,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln(''); $output->writeln(sprintf('[OK] User "%s" (ID: %d, email: %s) was successfully deleted.', $user->getUsername(), $userId, $user->getEmail())); } - - /** - * This internal method should be private, but it's declared public to - * maintain PHP 5.3 compatibility when using it in a callback. - * - * @internal - */ - public function usernameValidator($username) - { - if (empty($username)) { - throw new \Exception('The username can not be empty.'); - } - - if (1 !== preg_match('/^[a-z_]+$/', $username)) { - throw new \Exception('The username must contain only lowercase latin characters and underscores.'); - } - - return $username; - } } diff --git a/src/AppBundle/Command/ListUsersCommand.php b/src/AppBundle/Command/ListUsersCommand.php index f19791762..eed08cf60 100644 --- a/src/AppBundle/Command/ListUsersCommand.php +++ b/src/AppBundle/Command/ListUsersCommand.php @@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface; /** - * A command console that lists all the existing users. + * A console command that lists all the existing users. * * To use this command, open a terminal window, enter into your project directory * and execute the following: diff --git a/src/AppBundle/Utils/Validator.php b/src/AppBundle/Utils/Validator.php new file mode 100644 index 000000000..770117b10 --- /dev/null +++ b/src/AppBundle/Utils/Validator.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace AppBundle\Utils; + +class Validator +{ + public function validateUsername($username) + { + if (empty($username)) { + throw new \Exception('The username can not be empty.'); + } + + if (1 !== preg_match('/^[a-z_]+$/', $username)) { + throw new \Exception('The username must contain only lowercase latin characters and underscores.'); + } + + return $username; + } + + public function validatePassword($plainPassword) + { + if (empty($plainPassword)) { + throw new \Exception('The password can not be empty.'); + } + + if (mb_strlen(trim($plainPassword)) < 6) { + throw new \Exception('The password must be at least 6 characters long.'); + } + + return $plainPassword; + } + + public function validateEmail($email) + { + if (empty($email)) { + throw new \Exception('The email can not be empty.'); + } + + if (false === mb_strpos($email, '@')) { + throw new \Exception('The email should look like a real email.'); + } + + return $email; + } + + public function validateFullName($fullName) + { + if (empty($fullName)) { + throw new \Exception('The full name can not be empty.'); + } + + return $fullName; + } +} diff --git a/tests/AppBundle/Command/AddUserCommandTest.php b/tests/AppBundle/Command/AddUserCommandTest.php index 6c67f0619..761ed7711 100644 --- a/tests/AppBundle/Command/AddUserCommandTest.php +++ b/tests/AppBundle/Command/AddUserCommandTest.php @@ -13,6 +13,7 @@ use AppBundle\Command\AddUserCommand; use AppBundle\Entity\User; +use AppBundle\Utils\Validator; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Console\Tester\CommandTester; @@ -104,7 +105,7 @@ private function executeCommand(array $arguments, array $inputs = []) self::bootKernel(); $container = self::$kernel->getContainer(); - $command = new AddUserCommand($container->get('doctrine')->getManager(), $container->get('security.password_encoder')); + $command = new AddUserCommand($container->get('doctrine')->getManager(), $container->get('security.password_encoder'), new Validator()); $command->setApplication(new Application(self::$kernel)); $commandTester = new CommandTester($command); diff --git a/tests/AppBundle/Utils/ValidatorTest.php b/tests/AppBundle/Utils/ValidatorTest.php new file mode 100644 index 000000000..0da2315ea --- /dev/null +++ b/tests/AppBundle/Utils/ValidatorTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tests\AppBundle\Utils; + +use AppBundle\Utils\Validator; + +class ValidatorTest extends \PHPUnit_Framework_TestCase +{ + private $object; + + public function __construct() + { + parent::__construct(); + + $this->object = new Validator(); + } + + public function testValidateUsername() + { + $test = 'username'; + + $this->assertSame($test, $this->object->validateUsername($test)); + } + + public function testValidateUsernameEmpty() + { + $this->setExpectedException('Exception', 'The username can not be empty.'); + $this->object->validateUsername(null); + } + + public function testValidateUsernameInvalid() + { + $this->setExpectedException('Exception', 'The username must contain only lowercase latin characters and underscores.'); + $this->object->validateUsername('INVALID'); + } + + public function testValidatePassword() + { + $test = 'password'; + + $this->assertSame($test, $this->object->validatePassword($test)); + } + + public function testValidatePasswordEmpty() + { + $this->setExpectedException('Exception', 'The password can not be empty.'); + $this->object->validatePassword(null); + } + + public function testValidatePasswordInvalid() + { + $this->setExpectedException('Exception', 'The password must be at least 6 characters long.'); + $this->object->validatePassword('12345'); + } + + public function testValidateEmail() + { + $test = '@'; + + $this->assertSame($test, $this->object->validateEmail($test)); + } + + public function testValidateEmailEmpty() + { + $this->setExpectedException('Exception', 'The email can not be empty.'); + $this->object->validateEmail(null); + } + + public function testValidateEmailInvalid() + { + $this->setExpectedException('Exception', 'The email should look like a real email.'); + $this->object->validateEmail('invalid'); + } + + public function testValidateFullName() + { + $test = 'Full Name'; + + $this->assertSame($test, $this->object->validateFullName($test)); + } + + public function testValidateEmailFullName() + { + $this->setExpectedException('Exception', 'The full name can not be empty.'); + $this->object->validateFullName(null); + } +}