Passed
Push — master ( 296be2...aa3afb )
by Damien
02:30
created

RoutingCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
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
            ->setHelp(
52
                <<<'HELP'
53
The <info>navigation:routing</info> command will compute a route from the given addresses.
54
55
You can choose a provider with the "provider" option.
56
57
<info>php bin/console navigation:routing --waypoint="45.834278,1.260816" --waypoint="44.830109,-0.603649" --provider=here</info>
58
HELP
59
            );
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    protected function execute(InputInterface $input, OutputInterface $output)
66
    {
67
        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

67
        if (\count(/** @scrutinizer ignore-type */ $input->getOption('waypoint')) < 2) {
Loading history...
68
            throw new InvalidArgumentException('A route needs at least two waypoints (start and end locations).');
69
        }
70
71
        if ($input->getOption('provider')) {
72
            $this->manager->using($input->getOption('provider'));
73
        }
74
75
        $query = $this->manager->createRoutingQuery();
76
77
        foreach ($input->getOption('waypoint') as $waypoint) {
78
            $query->addWaypoint($waypoint);
79
        }
80
        $response = $query->execute();
81
82
        $io = new SymfonyStyle($input, $output);
83
84
        $routes = $response->getRoutes();
85
86
        $io->section('Summary');
87
88
        $data = [];
89
        foreach ($routes as $index => $route) {
90
            /**
91
             * @var Summary $summary
92
             */
93
            $summary = $route->getSummary();
94
            $data[] = [$index + 1, $summary->getDistance()->getAsText(), $summary->getTravelTime()->getAsText()];
95
        }
96
97
        $table = new Table($output);
98
        $table
99
            ->setHeaders(['route', 'distance', 'duration'])
100
            ->setRows($data)
101
        ;
102
        $table->render();
103
104
        $io->newLine();
105
106
        foreach ($routes as $routeIndex => $route) {
107
            $io->section('Route #'.($routeIndex + 1));
108
109
            $legs = $route->getLegs();
110
            foreach ($legs as $legIndex => $leg) {
111
                $steps = $leg->getSteps();
112
                $io->writeln(sprintf('<comment>Leg #%d</comment> - %d steps.', $legIndex + 1, \count($steps)));
113
114
                $data = [];
115
                foreach ($steps as $stepIndex => $step) {
116
                    $data[] = [
117
                        $stepIndex + 1,
118
                        implode(', ', $step->getPosition()),
119
                        $step->getDistance()->getAsText(),
120
                        $step->getDuration()->getAsText(),
121
                        $step->getInstruction()
122
                    ];
123
                }
124
125
                $table = new Table($output);
126
                $table
127
                    ->setHeaders(['step', 'position', 'distance', 'duration', 'instruction'])
128
                    ->setRows($data)
129
                    ->setColumnMaxWidth(4, 100)
130
                ;
131
                $table->render();
132
                $io->newLine();
133
            }
134
        }
135
    }
136
137
    /**
138
     * @throws \LogicException
139
     *
140
     * @return ContainerInterface
141
     */
142
    protected function getContainer(): ContainerInterface
143
    {
144
        if (null === $this->container) {
145
            $application = $this->getApplication();
146
            if (null === $application) {
147
                throw new \LogicException('The container cannot be retrieved as the application instance is not yet set.');
148
            }
149
150
            $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

150
            $this->container = $application->/** @scrutinizer ignore-call */ getKernel()->getContainer();
Loading history...
151
        }
152
153
        return $this->container;
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    public function setContainer(ContainerInterface $container = null): void
160
    {
161
        $this->container = $container;
162
    }
163
}
164