Skip to content

Added a validator service for commands #615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 12 additions & 60 deletions src/AppBundle/Command/AddUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,7 +24,7 @@
use Symfony\Component\Stopwatch\Stopwatch;

/**
* 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:
Expand All @@ -48,13 +49,15 @@ class AddUserCommand extends Command
private $io;
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;
}

/**
Expand Down Expand Up @@ -120,14 +123,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
if (null !== $username) {
$this->io->text(' > <info>Username</info>: '.$username);
} else {
$username = $this->io->ask('Username', null, function ($answer) {
if (empty($answer)) {
throw new \RuntimeException('The username cannot be empty');
}

return $answer;
});

$username = $this->io->ask('Username', null, [$this->validator, 'validateUsername']);
$input->setArgument('username', $username);
}

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

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

Expand All @@ -154,7 +150,7 @@ protected function interact(InputInterface $input, OutputInterface $output)
if (null !== $fullName) {
$this->io->text(' > <info>Full Name</info>: '.$fullName);
} else {
$fullName = $this->io->ask('Full Name', null, [$this, 'fullNameValidator']);
$fullName = $this->io->ask('Full Name', null, [$this->validator, 'validateFullName']);
$input->setArgument('full-name', $fullName);
}
}
Expand Down Expand Up @@ -199,50 +195,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);
Expand All @@ -255,9 +207,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]);
Expand Down
29 changes: 6 additions & 23 deletions src/AppBundle/Command/DeleteUserCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +21,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* 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:
Expand All @@ -42,12 +43,14 @@ class DeleteUserCommand extends Command

private $io;
private $entityManager;
private $validator;

public function __construct(EntityManagerInterface $em)
public function __construct(EntityManagerInterface $em, Validator $validator)
{
parent::__construct();

$this->entityManager = $em;
$this->validator = $validator;
}

/**
Expand Down Expand Up @@ -103,8 +106,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 */
Expand All @@ -124,23 +126,4 @@ protected function execute(InputInterface $input, OutputInterface $output)

$this->io->success(sprintf('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;
}
}
2 changes: 1 addition & 1 deletion src/AppBundle/Command/ListUsersCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* 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:
Expand Down
63 changes: 63 additions & 0 deletions src/AppBundle/Utils/Validator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* 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;
}
}
5 changes: 3 additions & 2 deletions tests/AppBundle/Command/AddUserCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -66,7 +67,7 @@ public function testCreateUserNonInteractive($isAdmin)
public function testCreateUserInteractive($isAdmin)
{
$this->executeCommand(
// these are the arguments (only 1 is passed, the rest are missing)
// these are the arguments (only 1 is passed, the rest are missing)
$isAdmin ? ['--admin' => 1] : [],
// these are the responses given to the questions asked by the command
// to get the value of the missing required arguments
Expand Down Expand Up @@ -116,7 +117,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);
Expand Down
Loading