CheckCommand::execute()   F
last analyzed

Complexity

Conditions 18
Paths 1368

Size

Total Lines 81
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 81
rs 0.7
cc 18
nc 1368
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace BenTools\Shh\Command;
4
5
use BenTools\Shh\Shh;
6
use Symfony\Component\Console\Attribute\AsCommand;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Style\SymfonyStyle;
12
13
#[AsCommand(
14
    name: 'shh:check',
15
)]
16
final class CheckCommand extends Command
17
{
18
    /**
19
     * @var string
20
     */
21
    private $publicKeyFile;
22
23
    /**
24
     * @var ?string
25
     */
26
    private $privateKeyFile;
27
28
    /**
29
     * @var string|null
30
     */
31
    private $passphrase;
32
33
    /**
34
     * CheckCommand constructor.
35
     */
36
    public function __construct(string $publicKeyFile, ?string $privateKeyFile, ?string $passphrase = null)
37
    {
38
        $this->publicKeyFile = $publicKeyFile;
39
        $this->privateKeyFile = $privateKeyFile;
40
        $this->passphrase = $passphrase;
41
        parent::__construct();
42
    }
43
44
    protected function configure(): void
45
    {
46
        $this
47
            ->setDescription('Checks the app is ready for decrypting and / or encrypting payloads.')
48
            ->addOption('decrypt-only', null, InputOption::VALUE_NONE, 'Only checks decryption.')
49
            ->addOption('encrypt-only', null, InputOption::VALUE_NONE, 'Only checks encryption.')
50
            ->addOption('payload', null, InputOption::VALUE_OPTIONAL, '(Optionnal) Check this payload for decryption.');
51
    }
52
53
    protected function execute(InputInterface $input, OutputInterface $output): int
54
    {
55
        $io = new SymfonyStyle($input, $output);
56
        $shh = new Shh($this->publicKeyFile, $this->privateKeyFile, $this->passphrase);
57
58
        $errors = [];
59
60
        // Public key is required for both encrypting and decrypting.
61
        if (!\is_readable($this->publicKeyFile)) {
62
            $errors[] = \sprintf('The public key file is not readable: %s', $this->publicKeyFile);
63
            $io->error(\end($errors));
64
        }
65
66
        // Private key is not required for encrypting.
67
        if (false === $input->getOption('encrypt-only')) {
68
            if (!\is_readable((string) $this->privateKeyFile)) {
69
                $errors[] = sprintf('The private key file is not readable: %s', $this->privateKeyFile);
70
                $io->error(\end($errors));
71
            }
72
        }
73
74
        if (false === $input->getOption('decrypt-only')) {
75
            try {
76
                $encrypted = $shh->encrypt('foo');
77
            } catch (\Throwable $e) {
78
                $errors[] = 'Encrypting a payload failed.';
79
                $io->error(\end($errors));
80
                if ($io->isDebug()) {
81
                    $io->error($e->getMessage());
82
                }
83
            }
84
85
            if (isset($encrypted) && false === $input->getOption('encrypt-only')) {
86
                try {
87
                    $decrypted = $shh->decrypt($encrypted);
88
89
                    if ('foo' !== $decrypted) {
90
                        throw new \RuntimeException('Unexpected decrypted value.');
91
                    }
92
                } catch (\Throwable $e) {
93
                    $errors[] = 'Decrypting a payload failed. Is the passphrase correct?';
94
                    $io->error(\end($errors));
95
                    if ($io->isDebug()) {
96
                        $io->error($e->getMessage());
97
                    }
98
                }
99
            }
100
        }
101
102
        if (null !== $input->getOption('payload')) {
103
            try {
104
                $shh->decrypt($input->getOption('payload'));
105
            } catch (\Throwable $e) {
106
                $errors[] = 'The given payload could not be decrypted.';
107
                $io->error(\end($errors));
108
                if ($io->isDebug()) {
109
                    $io->error($e->getMessage());
110
                }
111
            }
112
        }
113
114
        $success = [] === $errors;
115
116
        if ($success) {
117
            $io->success('Your configuration seems correct. 😎');
118
119
            if (true === $input->getOption('decrypt-only') && null === $input->getOption('payload')) {
120
                $io->comment(
121
                    'Hint: to be sure payloads can be properly decoded, 
122
try this command with the <info>--payload</info> option.'
123
                );
124
                $io->comment(
125
                    'You can run the <info>shh:encrypt</info> on the server having the private key 
126
to get an encrypted payload to test.'
127
                );
128
            }
129
130
            return 0;
131
        }
132
133
        return 1;
134
    }
135
}
136