* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace App\Command; use App\Entity\User; use App\Repository\UserRepository; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Mime\Email; /** * 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: * * $ php bin/console app:list-users * * Check out the code of the src/Command/AddUserCommand.php file for * the full explanation about Symfony commands. * * See https://symfony.com/doc/current/console.html * * @author Javier Eguiluz */ class ListUsersCommand extends Command { // a good practice is to use the 'app:' prefix to group all your custom application commands protected static $defaultName = 'app:list-users'; private $mailer; private $emailSender; private $users; public function __construct(MailerInterface $mailer, string $emailSender, UserRepository $users) { parent::__construct(); $this->mailer = $mailer; $this->emailSender = $emailSender; $this->users = $users; } /** * {@inheritdoc} */ protected function configure(): void { $this ->setDescription('Lists all the existing users') ->setHelp(<<<'HELP' The %command.name% command lists all the users registered in the application: php %command.full_name% By default the command only displays the 50 most recent users. Set the number of results to display with the --max-results option: php %command.full_name% --max-results=2000 In addition to displaying the user list, you can also send this information to the email address specified in the --send-to option: php %command.full_name% --send-to=fabien@symfony.com HELP ) // commands can optionally define arguments and/or options (mandatory and optional) // see https://symfony.com/doc/current/components/console/console_arguments.html ->addOption('max-results', null, InputOption::VALUE_OPTIONAL, 'Limits the number of users listed', 50) ->addOption('send-to', null, InputOption::VALUE_OPTIONAL, 'If set, the result is sent to the given email address') ; } /** * This method is executed after initialize(). It usually contains the logic * to execute to complete this command task. */ protected function execute(InputInterface $input, OutputInterface $output): int { $maxResults = $input->getOption('max-results'); // Use ->findBy() instead of ->findAll() to allow result sorting and limiting $allUsers = $this->users->findBy([], ['id' => 'DESC'], $maxResults); // Doctrine query returns an array of objects and we need an array of plain arrays $usersAsPlainArrays = array_map(function (User $user) { return [ $user->getId(), $user->getFullName(), $user->getUsername(), $user->getEmail(), implode(', ', $user->getRoles()), ]; }, $allUsers); // In your console commands you should always use the regular output type, // which outputs contents directly in the console window. However, this // command uses the BufferedOutput type instead, to be able to get the output // contents before displaying them. This is needed because the command allows // to send the list of users via email with the '--send-to' option $bufferedOutput = new BufferedOutput(); $io = new SymfonyStyle($input, $bufferedOutput); $io->table( ['ID', 'Full Name', 'Username', 'Email', 'Roles'], $usersAsPlainArrays ); // instead of just displaying the table of users, store its contents in a variable $usersAsATable = $bufferedOutput->fetch(); $output->write($usersAsATable); if (null !== $email = $input->getOption('send-to')) { $this->sendReport($usersAsATable, $email); } return Command::SUCCESS; } /** * Sends the given $contents to the $recipient email address. */ private function sendReport(string $contents, string $recipient): void { $email = (new Email()) ->from($this->emailSender) ->to($recipient) ->subject(sprintf('app:list-users report (%s)', date('Y-m-d H:i:s'))) ->text($contents); $this->mailer->send($email); } }