Test Failed
Branch master (b3e807)
by Alexey
03:28
created

ConsoleApplication::initConsole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.5

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
ccs 2
cts 4
cp 0.5
cc 2
eloc 9
nc 2
nop 2
crap 2.5
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Console;
4
5
use Error;
6
use ErrorException;
7
use Symfony\Component\Console\Application as SymfonyConsoleApplication;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Throwable;
11
use Venta\Contracts\Console\CommandCollection;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Venta\Console\CommandCollection.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use Venta\Contracts\Container\Container;
13
use Venta\Contracts\Kernel\Kernel;
14
15
/**
16
 * Class ConsoleApplication
17
 *
18
 * @package Venta\Console
19
 */
20
final class ConsoleApplication
21
{
22
    /**
23
     * @var SymfonyConsoleApplication
24
     */
25
    private $console;
26
27
    /**
28
     * @var Container
29
     */
30
    private $container;
31
32
    /**
33
     * ConsoleApplication constructor.
34 3
     *
35
     * @param Kernel $kernel
36 3
     */
37
    public function __construct(Kernel $kernel)
38 3
    {
39 3
        $this->container = $kernel->boot();
40
        $this->initConsole('Venta Console', $kernel->getVersion());
41
    }
42
43
    /**
44
     * Runs Console Application.
45
     *
46
     * @param InputInterface $input
47
     * @param OutputInterface $output
48 1
     * @return int
49
     */
50 1
    public function run(InputInterface $input, OutputInterface $output): int
51
    {
52 1
        try {
53
            return $this->console->run($input, $output);
54 1
        } catch (Throwable $e) {
55 1
56
            // todo: call error reporters
57 1
58
            if ($e instanceof Error) {
59 1
                $e = new ErrorException(
60 1
                    $e->getMessage(), 0, $e->getCode(), $e->getFile(), $e->getLine(), $e->getPrevious()
61
                );
62
            }
63
64
            $this->console->renderException($e, $output);
0 ignored issues
show
Bug introduced by
It seems like $e can also be of type object<Throwable>; however, Symfony\Component\Consol...tion::renderException() does only seem to accept object<Exception>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
65 1
66
            return 1;
67
        }
68
    }
69
70
    /**
71
     * Initiates Symfony Console Application.
72
     *
73
     * @param string $name
74 1
     * @param string $version
75 1
     */
76
    private function initConsole(string $name, string $version)
77
    {
78
        $this->console = $this->container->get(SymfonyConsoleApplication::class);
79
        $this->console->setName($name);
80
        $this->console->setVersion($version);
81
        $this->console->setCatchExceptions(false);
82
        $this->console->setAutoExit(false);
83
84
        /** @var CommandCollection $commands */
85 1
        $commands = $this->container->get(CommandCollection::class);
86 1
        foreach ($commands as $command) {
87
            $this->console->add($this->resolveCommand($command));
88
        }
89
    }
90
91
    /**
92
     * Resolves command object from class name.
93
     *
94
     * @param string $commandClass
95
     * @return mixed
96
     */
97 1
    private function resolveCommand(string $commandClass)
98 1
    {
99
        return $this->container->get($commandClass);
100
    }
101
102
}