Passed
Push — master ( b23d7b...67a73d )
by Damien
02:23
created

RoutingCommand::execute()   F

Complexity

Conditions 12
Paths 513

Size

Total Lines 89
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 53
c 3
b 0
f 0
nc 513
nop 2
dl 0
loc 89
rs 3.4763

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 DH\NavigationBundle\Command;
4
5
use DH\NavigationBundle\Model\Routing\Summary;
6
use DH\NavigationBundle\NavigationManager;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Exception\InvalidArgumentException;
9
use Symfony\Component\Console\Helper\Table;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Console\Style\SymfonyStyle;
14
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
17
class RoutingCommand extends Command implements ContainerAwareInterface
18
{
19
    protected static $defaultName = 'navigation:routing';
20
21
    /**
22
     * @var null|ContainerInterface
23
     */
24
    private $container;
25
26
    /**
27
     * @var NavigationManager
28
     */
29
    private $manager;
30
31
    /**
32
     * @param NavigationManager $manager
33
     */
34
    public function __construct(NavigationManager $manager)
35
    {
36
        $this->manager = $manager;
37
38
        parent::__construct();
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    protected function configure()
45
    {
46
        $this
47
            ->setName('navigation:routing')
48
            ->setDescription('Computes a route')
49
            ->addOption('provider', null, InputOption::VALUE_REQUIRED)
50
            ->addOption('waypoint', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Point de passage')
51
            ->addOption('departure', null, InputOption::VALUE_REQUIRED, 'Departure date and time (YYYY-MM-DDD HH:II:SS)')
52
            ->addOption('arrival', null, InputOption::VALUE_REQUIRED, 'Arrival date and time (YYYY-MM-DDD HH:II:SS)')
53
            ->addOption('traffic', null, InputOption::VALUE_REQUIRED, 'Traffic mode (enabled/disabled/default depending on provider)')
54
            ->addOption('language', null, InputOption::VALUE_REQUIRED, 'Language (fr-FR, en-US, etc.)')
55
            ->setHelp(
56
                <<<'HELP'
57
The <info>navigation:routing</info> command will compute a route from the given addresses.
58
59
You can choose a provider with the "provider" option.
60
61
<info>php bin/console navigation:routing --waypoint="45.834278,1.260816" --waypoint="44.830109,-0.603649" --provider=here</info>
62
HELP
63
            );
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    protected function execute(InputInterface $input, OutputInterface $output)
70
    {
71
        if (\count($input->getOption('waypoint')) < 2) {
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('waypoint') can also be of type boolean and string; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
        if (\count(/** @scrutinizer ignore-type */ $input->getOption('waypoint')) < 2) {
Loading history...
72
            throw new InvalidArgumentException('A route needs at least two waypoints (start and end locations).');
73
        }
74
75
        if ($input->getOption('provider')) {
76
            $this->manager->using($input->getOption('provider'));
77
        }
78
79
        $query = $this->manager->createRoutingQuery();
80
81
        foreach ($input->getOption('waypoint') as $waypoint) {
82
            $query->addWaypoint($waypoint);
83
        }
84
85
        if ($input->getOption('departure')) {
86
            $query->setDepartureTime(new \DateTime($input->getOption('departure')));
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('departure') can also be of type string[]; however, parameter $time of DateTime::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

86
            $query->setDepartureTime(new \DateTime(/** @scrutinizer ignore-type */ $input->getOption('departure')));
Loading history...
87
        }
88
89
        if ($input->getOption('arrival')) {
90
            $query->setArrivalTime(new \DateTime($input->getOption('arrival')));
91
        }
92
93
        if ($input->getOption('traffic')) {
94
            $query->setTrafficMode($input->getOption('traffic'));
0 ignored issues
show
Bug introduced by
The method setTrafficMode() does not exist on DH\NavigationBundle\Cont...g\RoutingQueryInterface. It seems like you code against a sub-type of DH\NavigationBundle\Cont...g\RoutingQueryInterface such as DH\NavigationBundle\Prov...re\Routing\RoutingQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
            $query->/** @scrutinizer ignore-call */ 
95
                    setTrafficMode($input->getOption('traffic'));
Loading history...
95
        }
96
97
        if ($input->getOption('language')) {
98
            $query->setLanguage($input->getOption('language'));
99
        }
100
101
        $response = $query->execute();
102
103
        $io = new SymfonyStyle($input, $output);
104
105
        $routes = $response->getRoutes();
106
107
        $io->section('Summary');
108
109
        $data = [];
110
        foreach ($routes as $index => $route) {
111
            /**
112
             * @var Summary $summary
113
             */
114
            $summary = $route->getSummary();
115
            $data[] = [
116
                $index + 1,
117
                $summary->getDistance()->getFormattedValue(2),
118
                $summary->getTravelTime()->getFormattedValue(2),
119
            ];
120
        }
121
122
        $table = new Table($output);
123
        $table
124
            ->setHeaders(['route', 'distance', 'duration'])
125
            ->setRows($data)
126
        ;
127
        $table->render();
128
129
        $io->newLine();
130
131
        foreach ($routes as $routeIndex => $route) {
132
            $io->section('Route #'.($routeIndex + 1));
133
134
            $legs = $route->getLegs();
135
            foreach ($legs as $legIndex => $leg) {
136
                $steps = $leg->getSteps();
137
                $io->writeln(sprintf('<comment>Leg #%d</comment> - %d steps.', $legIndex + 1, \count($steps)));
138
139
                $data = [];
140
                foreach ($steps as $stepIndex => $step) {
141
                    $data[] = [
142
                        $stepIndex + 1,
143
                        implode(', ', $step->getPosition()),
144
                        $step->getDistance()->getFormattedValue(2),
145
                        $step->getDuration()->getFormattedValue(2),
146
                        $step->getInstruction()
147
                    ];
148
                }
149
150
                $table = new Table($output);
151
                $table
152
                    ->setHeaders(['step', 'position', 'distance', 'duration', 'instruction'])
153
                    ->setRows($data)
154
                    ->setColumnMaxWidth(4, 100)
155
                ;
156
                $table->render();
157
                $io->newLine();
158
            }
159
        }
160
    }
161
162
    /**
163
     * @throws \LogicException
164
     *
165
     * @return ContainerInterface
166
     */
167
    protected function getContainer(): ContainerInterface
168
    {
169
        if (null === $this->container) {
170
            $application = $this->getApplication();
171
            if (null === $application) {
172
                throw new \LogicException('The container cannot be retrieved as the application instance is not yet set.');
173
            }
174
175
            $this->container = $application->getKernel()->getContainer();
0 ignored issues
show
Bug introduced by
The method getKernel() does not exist on Symfony\Component\Console\Application. It seems like you code against a sub-type of Symfony\Component\Console\Application such as Symfony\Bundle\FrameworkBundle\Console\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
            $this->container = $application->/** @scrutinizer ignore-call */ getKernel()->getContainer();
Loading history...
176
        }
177
178
        return $this->container;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function setContainer(ContainerInterface $container = null): void
185
    {
186
        $this->container = $container;
187
    }
188
}
189