Completed
Push — develop ( 8a6508...c3baa7 )
by Nic
18s
created

execute()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 59
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 59
rs 9.597
cc 3
eloc 40
nc 5
nop 2

How to fix   Long Method   

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
/**
4
 * Copyright 2014 SURFnet bv
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace Surfnet\StepupMiddleware\MiddlewareBundle\Console\Command;
20
21
use Exception;
22
use Rhumsaa\Uuid\Uuid;
23
use Surfnet\Stepup\Identity\Value\Institution;
24
use Surfnet\Stepup\Identity\Value\NameId;
25
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\BootstrapIdentityWithYubikeySecondFactorCommand
26
    as BootstrapIdentityWithYubikeySecondFactorIdentityCommand;
27
use Symfony\Component\Console\Command\Command;
28
use Symfony\Component\Console\Input\InputArgument;
29
use Symfony\Component\Console\Input\InputInterface;
30
use Symfony\Component\Console\Output\OutputInterface;
31
use Symfony\Component\DependencyInjection\Container;
32
33
final class BootstrapIdentityWithYubikeySecondFactorCommand extends Command
34
{
35
    protected function configure()
36
    {
37
        $this
38
            ->setName('middleware:bootstrap:identity-with-yubikey')
39
            ->setDescription('Creates an identity with a vetted Yubikey second factor')
40
            ->addArgument('name-id', InputArgument::REQUIRED, 'The NameID of the identity to create')
41
            ->addArgument('institution', InputArgument::REQUIRED, 'The institution of the identity to create')
42
            ->addArgument('common-name', InputArgument::REQUIRED, 'The Common Name of the identity to create')
43
            ->addArgument('email', InputArgument::REQUIRED, 'The e-mail address of the identity to create')
44
            ->addArgument('preferred-locale', InputArgument::REQUIRED, 'The preferred locale of the identity to create')
45
            ->addArgument(
46
                'yubikey',
47
                InputArgument::REQUIRED,
48
                'The public ID of the Yubikey. Remove the last 32 characters of a Yubikey OTP to acquire this.'
49
            );
50
    }
51
52
    protected function execute(InputInterface $input, OutputInterface $output)
53
    {
54
        /** @var Container $container */
55
        $container            = $this->getApplication()->getKernel()->getContainer();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Console\Application as the method getKernel() does only exist in the following sub-classes of Symfony\Component\Console\Application: Symfony\Bundle\FrameworkBundle\Console\Application. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
56
        $projectionRepository = $container->get('surfnet_stepup_middleware_api.repository.identity');
57
        $pipeline             = $container->get('surfnet_stepup_middleware_command_handling.pipeline.transaction_aware_pipeline');
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
58
        $eventBus             = $container->get('surfnet_stepup_middleware_command_handling.event_bus.buffered');
59
        $connection           = $container->get('surfnet_stepup_middleware_middleware.dbal_connection_helper');
60
61
        $nameId      = new NameId($input->getArgument('name-id'));
62
        $institution = new Institution($input->getArgument('institution'));
63
64
        if ($projectionRepository->hasIdentityWithNameIdAndInstitution($nameId, $institution)) {
65
            $output->writeln(
66
                sprintf(
67
                    '<error>An identity with name ID "%s" from institution "%s" already exists</error>',
68
                    $nameId->getNameId(),
69
                    $institution->getInstitution()
70
                )
71
            );
72
73
            return 1;
74
        }
75
76
        $command                  = new BootstrapIdentityWithYubikeySecondFactorIdentityCommand();
77
        $command->UUID            = (string) Uuid::uuid4();
78
        $command->identityId      = (string) Uuid::uuid4();
79
        $command->nameId          = $input->getArgument('name-id');
80
        $command->institution     = $input->getArgument('institution');
81
        $command->commonName      = $input->getArgument('common-name');
82
        $command->email           = $input->getArgument('email');
83
        $command->preferredLocale = $input->getArgument('preferred-locale');
84
        $command->secondFactorId  = (string) Uuid::uuid4();
85
        $command->yubikeyPublicId = $input->getArgument('yubikey');
86
87
        $connection->beginTransaction();
88
89
        try {
90
            $command = $pipeline->process($command);
91
            $eventBus->flush();
92
93
            $connection->commit();
94
        } catch (Exception $e) {
95
            $output->writeln(sprintf(
96
                '<error>An Error occurred when trying to bootstrap the identity: "%s"</error>',
97
                $e->getMessage()
98
            ));
99
100
            $connection->rollBack();
101
102
            throw $e;
103
        }
104
105
        $output->writeln(sprintf(
106
            '<info>Successfully created identity with UUID %s and second factor with UUID %s</info>',
107
            $command->identityId,
108
            $command->secondFactorId
109
        ));
110
    }
111
}
112