Test Setup Failed
Push — master ( 0c8bf0...b71d97 )
by Herberto
05:57
created

ListUsersCommand::execute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 9.344
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Presentation\Console\Component\User;
16
17
use Acme\App\Core\Component\User\Application\Repository\UserRepositoryInterface;
18
use Acme\App\Core\Component\User\Domain\User\User;
19
use Swift_Mailer;
20
use Symfony\Component\Console\Command\Command;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Input\InputOption;
23
use Symfony\Component\Console\Output\BufferedOutput;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\Console\Style\SymfonyStyle;
26
27
/**
28
 * A console command that lists all the existing users.
29
 *
30
 * To use this command, open a terminal window, enter into your project directory
31
 * and execute the following:
32
 *
33
 *     $ php bin/console app:list-users
34
 *
35
 * See https://symfony.com/doc/current/cookbook/console/console_command.html
36
 * For more advanced uses, commands can be defined as services too. See
37
 * https://symfony.com/doc/current/console/commands_as_services.html
38
 *
39
 * @author Javier Eguiluz <[email protected]>
40
 * @author Herberto Graca <[email protected]>
41
 */
42
class ListUsersCommand extends Command
43
{
44
    /**
45
     * A good practice is to use the 'app:' prefix to group all your custom application commands.
46
     *
47
     * @var string
48
     */
49
    protected static $defaultName = 'app:list-users';
50
51
    /**
52
     * @var Swift_Mailer
53
     */
54
    private $mailer;
55
56
    /**
57
     * @var string
58
     */
59
    private $emailSender;
60
61
    /**
62
     * @var UserRepositoryInterface
63
     */
64
    private $userRepository;
65
66
    public function __construct(
67
        Swift_Mailer $mailer,
68
        string $defaultFromEmailAddress,
69
        UserRepositoryInterface $userRepository
70
    ) {
71
        parent::__construct();
72
73
        $this->mailer = $mailer;
74
        $this->emailSender = $defaultFromEmailAddress;
75
        $this->userRepository = $userRepository;
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    protected function configure(): void
82
    {
83
        $this
84
            ->setDescription('Lists all the existing users')
85
            ->setHelp(<<<'HELP'
86
                The <info>%command.name%</info> command lists all the users registered in the application:
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected EOF
Loading history...
87
88
                  <info>php %command.full_name%</info>
89
90
                By default the command only displays the 50 most recent users. Set the number of
91
                results to display with the <comment>--max-results</comment> option:
92
93
                  <info>php %command.full_name%</info> <comment>--max-results=2000</comment>
94
95
                In addition to displaying the user list, you can also send this information to
96
                the email address specified in the <comment>--send-to</comment> option:
97
98
                  <info>php %command.full_name%</info> <comment>[email protected]</comment>
99
100
                HELP
101
            )
102
            // commands can optionally define arguments and/or options (mandatory and optional)
103
            // see https://symfony.com/doc/current/components/console/console_arguments.html
104
            ->addOption('max-results', null, InputOption::VALUE_OPTIONAL, 'Limits the number of users listed', 50)
105
            ->addOption('send-to', null, InputOption::VALUE_OPTIONAL, 'If set, the result is sent to the given email address');
106
    }
107
108
    /**
109
     * This method is executed after initialize(). It usually contains the logic
110
     * to execute to complete this command task.
111
     */
112
    protected function execute(InputInterface $input, OutputInterface $output): void
113
    {
114
        $maxResults = $input->getOption('max-results');
115
        $allUsers = $this->userRepository->findAll(['id' => 'DESC'], $maxResults);
116
117
        // Doctrine query returns an array of objects and we need an array of plain arrays
118
        $usersAsPlainArrays = array_map(function (User $user) {
119
            return [
120
                $user->getId(),
121
                $user->getFullName(),
122
                $user->getUsername(),
123
                $user->getEmail(),
124
                implode(', ', $user->getRoles()),
125
            ];
126
        }, $allUsers);
127
128
        // In your console commands you should always use the regular output type,
129
        // which outputs contents directly in the console window. However, this
130
        // command uses the BufferedOutput type instead, to be able to get the output
131
        // contents before displaying them. This is needed because the command allows
132
        // to send the list of users via email with the '--send-to' option
133
        $bufferedOutput = new BufferedOutput();
134
        $io = new SymfonyStyle($input, $bufferedOutput);
135
        $io->table(
136
            ['ID', 'Full Name', 'Username', 'Email', 'Roles'],
137
            $usersAsPlainArrays
138
        );
139
140
        // instead of just displaying the table of users, store its contents in a variable
141
        $usersAsATable = $bufferedOutput->fetch();
142
        $output->write($usersAsATable);
143
144
        if (null !== $email = $input->getOption('send-to')) {
145
            $this->sendReport($usersAsATable, $email);
146
        }
147
    }
148
149
    /**
150
     * Sends the given $contents to the $recipient email address.
151
     */
152
    private function sendReport(string $contents, string $recipient): void
153
    {
154
        // See https://symfony.com/doc/current/cookbook/email/email.html
155
        $message = $this->mailer->createMessage()
156
            ->setSubject(sprintf('app:list-users report (%s)', date('Y-m-d H:i:s')))
157
            ->setFrom($this->emailSender)
158
            ->setTo($recipient)
159
            ->setBody($contents, 'text/plain');
160
161
        $this->mailer->send($message);
162
    }
163
}
164