BaseCommand   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 9
c 4
b 0
f 1
lcom 1
cbo 6
dl 0
loc 115
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 26 4
A getContainer() 0 4 1
A getCommandBus() 0 4 1
A execute() 0 18 2
A configure() 0 5 1
1
<?php
2
3
/*
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the MIT license. For more information, see
18
 * <https://github.com/baleen/migrations>.
19
 */
20
21
namespace Baleen\Cli;
22
23
use Baleen\Cli\CommandBus\MessageInterface;
24
use Baleen\Cli\Provider\Services;
25
use Baleen\Migrations\Exception\InvalidArgumentException;
26
use League\Container\Container;
27
use League\Container\ContainerInterface;
28
use League\Tactician\CommandBus;
29
use Symfony\Component\Console\Command\Command;
30
use Symfony\Component\Console\Input\InputInterface;
31
use Symfony\Component\Console\Output\OutputInterface;
32
33
/**
34
 * The base Command class used to build all the command definitions for the Application.
35
 *
36
 * @author Gabriel Somoza <[email protected]>
37
 */
38
class BaseCommand extends Command
39
{
40
    /** @var Container */
41
    protected $container;
42
43
    /**
44
     * A reference to the CommandBus in charge of handling Messages.
45
     *
46
     * @var CommandBus
47
     */
48
    protected $commandBus;
49
50
    /** @var string */
51
    protected $serviceAlias;
52
53
    /** @var string */
54
    protected $serviceClass;
55
56
    /**
57
     * @param ContainerInterface $container A reference to the Application's Container.
58
     *
59
     * @param string $serviceAlias The key in the Container for the command that the instance of this class represents.
60
     *
61
     * @param string $serviceClass Needed in order to run certain checks against the class before instantiating it
62
     *                             with the container. This helps us make those checks without triggering all the other
63
     *                             services through the Container's DI functionality.
64
     *
65
     * @throws InvalidArgumentException
66
     */
67
    public function __construct(ContainerInterface $container, $serviceAlias, $serviceClass)
68
    {
69
        $serviceClass = (string) $serviceClass;
70
        if (!class_exists($serviceClass) || !(new $serviceClass()) instanceof MessageInterface) {
71
            throw new InvalidArgumentException(sprintf(
72
                'Message class "%s" must exist and be an instance of %s',
73
                $serviceClass,
74
                MessageInterface::class
75
            ));
76
        }
77
        $this->serviceClass = $serviceClass;
78
79
        $serviceAlias = (string) $serviceAlias;
80
        $this->serviceAlias = $serviceAlias;
81
82
        $commandBus = $container->get(Services::COMMAND_BUS);
83
        if (!$commandBus instanceof CommandBus) {
84
            throw new InvalidArgumentException(sprintf(
85
                'Invalid service: expected an instance of "%s".',
86
                CommandBus::class
87
            ));
88
        }
89
        $this->commandBus = $commandBus;
90
        $this->container = $container;
91
        parent::__construct(null); // name will be set inside configure()
92
    }
93
94
    /**
95
     * @return Container
96
     */
97
    public function getContainer()
98
    {
99
        return $this->container;
100
    }
101
102
    /**
103
     * getCommandBus.
104
     *
105
     * @return CommandBus
106
     */
107
    public function getCommandBus()
108
    {
109
        return $this->commandBus;
110
    }
111
112
    /**
113
     * Executes the current command by retrieving its associated Message from the Container, setting the Input and
114
     * Output according to what was received as parameters, and finally passing that Message to the CommandBus for
115
     * handling.
116
     *
117
     * @param InputInterface $input An InputInterface instance
118
     * @param OutputInterface $output An OutputInterface instance
119
     *
120
     * @return int|null null or 0 if everything went fine, or an error code
121
     *
122
     * @throws InvalidArgumentException
123
     */
124
    protected function execute(InputInterface $input, OutputInterface $output)
125
    {
126
        /** @var MessageInterface $message */
127
        $message = $this->getContainer()->get($this->serviceAlias);
128
129
        if (get_class($message) !== $this->serviceClass) {
130
            throw new InvalidArgumentException(sprintf(
131
                'The specified service alias (%s) and class (%s) do not correspond to each other.',
132
                $this->serviceAlias,
133
                $this->serviceClass
134
            ));
135
        }
136
137
        $message->setCliCommand($this);
138
        $message->setInput($input);
139
        $message->setOutput($output);
140
        $this->getCommandBus()->handle($message);
141
    }
142
143
    /**
144
     * Calls the message's static "configure" public function passing $this as argument to allow the message to
145
     * configure the command.
146
     */
147
    protected function configure()
148
    {
149
        $callable = [$this->serviceClass, 'configure'];
150
        forward_static_call($callable, $this);
151
    }
152
}
153