Completed
Push — master ( 96ea8b...1276b9 )
by Alexis
08:08
created

CreateUserCommand::interact()   C

Complexity

Conditions 8
Paths 16

Size

Total Lines 46
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 46
rs 5.5555
c 0
b 0
f 0
cc 8
eloc 27
nc 16
nop 2
1
<?php
2
3
/*
4
 * This file is part of the awurth/silex-user package.
5
 *
6
 * (c) Alexis Wurth <[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 AWurth\Silex\User\Command;
13
14
use Exception;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Question\Question;
20
21
/**
22
 * @author Matthieu Bontemps <[email protected]>
23
 * @author Thibault Duplessis <[email protected]>
24
 * @author Luis Cordova <[email protected]>
25
 */
26
class CreateUserCommand extends ContainerAwareCommand
27
{
28
    /**
29
     * {@inheritdoc}
30
     */
31
    protected function configure()
32
    {
33
        $this
34
            ->setName('silex-user:create')
35
            ->setDescription('Create a user.')
36
            ->setDefinition([
37
                new InputArgument('username', InputArgument::REQUIRED, 'The username'),
38
                new InputArgument('email', InputArgument::REQUIRED, 'The email'),
39
                new InputArgument('password', InputArgument::REQUIRED, 'The password'),
40
                new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'),
41
                new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive')
42
            ])
43
            ->setHelp(<<<'EOT'
44
The <info>silex-user:create</info> command creates a user:
45
46
  <info>php %command.full_name% matthieu</info>
47
48
This interactive shell will ask you for an email and then a password.
49
50
You can alternatively specify the email and password as the second and third arguments:
51
52
  <info>php %command.full_name% matthieu [email protected] mypassword</info>
53
54
You can create a super admin via the super-admin flag:
55
56
  <info>php %command.full_name% admin --super-admin</info>
57
58
You can create an inactive user (will not be able to log in):
59
60
  <info>php %command.full_name% thibault --inactive</info>
61
62
EOT
63
            );
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    protected function execute(InputInterface $input, OutputInterface $output)
70
    {
71
        $username = $input->getArgument('username');
72
        $email = $input->getArgument('email');
73
        $password = $input->getArgument('password');
74
        $inactive = $input->getOption('inactive');
75
        $superadmin = $input->getOption('super-admin');
76
77
        $manipulator = $this->container['silex_user.util.user_manipulator'];
78
        $manipulator->create($username, $password, $email, !$inactive, $superadmin);
79
80
        $output->writeln(sprintf('Created user <comment>%s</comment>', $username));
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    protected function interact(InputInterface $input, OutputInterface $output)
87
    {
88
        $questions = [];
89
90
        if (!$input->getArgument('username')) {
91
            $question = new Question('Please choose a username:');
92
            $question->setValidator(function ($username) {
93
                if (empty($username)) {
94
                    throw new Exception('Username can not be empty');
95
                }
96
97
                return $username;
98
            });
99
            $questions['username'] = $question;
100
        }
101
102
        if (!$input->getArgument('email')) {
103
            $question = new Question('Please choose an email:');
104
            $question->setValidator(function ($email) {
105
                if (empty($email)) {
106
                    throw new Exception('Email can not be empty');
107
                }
108
109
                return $email;
110
            });
111
            $questions['email'] = $question;
112
        }
113
114
        if (!$input->getArgument('password')) {
115
            $question = new Question('Please choose a password:');
116
            $question->setValidator(function ($password) {
117
                if (empty($password)) {
118
                    throw new Exception('Password can not be empty');
119
                }
120
121
                return $password;
122
            });
123
            $question->setHidden(true);
124
            $questions['password'] = $question;
125
        }
126
127
        foreach ($questions as $name => $question) {
128
            $answer = $this->getHelper('question')->ask($input, $output, $question);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method ask() does only exist in the following implementations of said interface: Symfony\Component\Console\Helper\QuestionHelper, Symfony\Component\Consol...r\SymfonyQuestionHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
129
            $input->setArgument($name, $answer);
130
        }
131
    }
132
}
133