Completed
Push — master ( 0969e2...d54784 )
by Rafał
20:34
created

CreateOrganizationCommand   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 0
Metric Value
wmc 14
lcom 2
cbo 10
dl 0
loc 133
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 16 1
A execute() 0 21 3
A sendOutput() 0 11 2
A interact() 0 7 2
A askAndValidateInteract() 0 19 3
A createOrganization() 0 10 1
A getObjectManager() 0 4 1
A getOrganizationRepository() 0 4 1
1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher MultiTenancyBundle.
5
 *
6
 * Copyright 2016 Sourcefabric z.ú. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2016 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Bundle\MultiTenancyBundle\Command;
16
17
use Doctrine\Common\Persistence\ObjectManager;
18
use SWP\Component\MultiTenancy\Model\OrganizationInterface;
19
use SWP\Component\MultiTenancy\Repository\OrganizationRepositoryInterface;
20
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
21
use Symfony\Component\Console\Input\InputArgument;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\Console\Question\Question;
26
27
/**
28
 * Class CreateOrganizationCommand.
29
 */
30
class CreateOrganizationCommand extends ContainerAwareCommand
31
{
32
    /**
33
     * {@inheritdoc}
34
     */
35
    protected function configure()
36
    {
37
        $this
38
            ->setName('swp:organization:create')
39
            ->setDescription('Creates a new organization.')
40
            ->setDefinition([
41
                new InputArgument('name', InputArgument::OPTIONAL, 'Organization name'),
42
                new InputOption('disabled', null, InputOption::VALUE_NONE, 'Set the organization as a disabled'),
43
                new InputOption('default', null, InputOption::VALUE_NONE, 'Creates the default organization'),
44
            ])
45
            ->setHelp(
46
                <<<'EOT'
47
                The <info>%command.name%</info> command creates a new organization.
48
EOT
49
            );
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    protected function execute(InputInterface $input, OutputInterface $output)
56
    {
57
        $name = $input->getArgument('name');
58
        $default = $input->getOption('default');
59
        if ($default) {
60
            $name = OrganizationInterface::DEFAULT_NAME;
61
        }
62
63
        $organization = $this->getOrganizationRepository()->findOneByName($name);
64
65
        if (null !== $organization) {
66
            throw new \InvalidArgumentException(sprintf('"%s" organization already exists!', $name));
67
        }
68
69
        $organization = $this->createOrganization($name, $input);
70
71
        $this->getObjectManager()->persist($organization);
72
        $this->getObjectManager()->flush();
73
74
        $this->sendOutput($output, $organization);
75
    }
76
77
    /**
78
     * @param OutputInterface       $output
79
     * @param OrganizationInterface $organization
80
     */
81
    protected function sendOutput(OutputInterface $output, $organization)
82
    {
83
        $output->writeln(
84
            sprintf(
85
                'Organization <info>%s</info> (code: <info>%s</info>) has been created and <info>%s</info>!',
86
                $organization->getName(),
87
                $organization->getCode(),
88
                $organization->isEnabled() ? 'enabled' : 'disabled'
89
            )
90
        );
91
    }
92
93
    /**
94
     * @param InputInterface  $input
95
     * @param OutputInterface $output
96
     */
97
    protected function interact(InputInterface $input, OutputInterface $output)
98
    {
99
        $default = $input->getOption('default');
100
        if (!$default) {
101
            $this->askAndValidateInteract($input, $output, 'name');
102
        }
103
    }
104
105
    /**
106
     * @param InputInterface  $input
107
     * @param OutputInterface $output
108
     * @param string          $name
109
     */
110
    protected function askAndValidateInteract(InputInterface $input, OutputInterface $output, $name)
111
    {
112
        if (!$input->getArgument($name)) {
113
            $question = new Question(sprintf('<question>Please enter %s:</question>', $name));
114
            $question->setValidator(function ($argument) use ($name) {
115
                if (empty($argument)) {
116
                    throw new \RuntimeException(sprintf('The %s can not be empty', $name));
117
                }
118
119
                return $argument;
120
            });
121
122
            $question->setMaxAttempts(3);
123
124
            $argument = $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...
125
126
            $input->setArgument($name, $argument);
127
        }
128
    }
129
130
    /**
131
     * @param string $name
132
     * @param bool   $disabled
0 ignored issues
show
Bug introduced by
There is no parameter named $disabled. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
133
     *
134
     * @return OrganizationInterface
135
     */
136
    protected function createOrganization($name, $input)
137
    {
138
        $organizationFactory = $this->getContainer()->get('swp.factory.organization');
139
        /** @var OrganizationInterface $organization */
140
        $organization = $organizationFactory->createWithCode();
141
        $organization->setName($name);
142
        $organization->setEnabled(!$input->getOption('disabled'));
143
144
        return $organization;
145
    }
146
147
    /**
148
     * @return ObjectManager
149
     */
150
    protected function getObjectManager()
151
    {
152
        return $this->getContainer()->get('swp.object_manager.organization');
153
    }
154
155
    /**
156
     * @return OrganizationRepositoryInterface
157
     */
158
    protected function getOrganizationRepository()
159
    {
160
        return $this->getContainer()->get('swp.repository.organization');
161
    }
162
}
163