Passed
Pull Request — master (#275)
by Alejandro
02:37
created

ProcessVisitsCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
ccs 4
cts 4
cp 1
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Command\Visit;
5
6
use Shlinkio\Shlink\Common\Exception\WrongIpException;
7
use Shlinkio\Shlink\Common\IpGeolocation\IpLocationResolverInterface;
8
use Shlinkio\Shlink\Common\Util\IpAddress;
9
use Shlinkio\Shlink\Core\Entity\Visit;
10
use Shlinkio\Shlink\Core\Entity\VisitLocation;
11
use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException;
12
use Shlinkio\Shlink\Core\Service\VisitServiceInterface;
13
use Symfony\Component\Console\Command\Command;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Style\SymfonyStyle;
17
use Zend\I18n\Translator\TranslatorInterface;
18
use function sprintf;
19
20
class ProcessVisitsCommand extends Command
21
{
22
    public const NAME = 'visit:process';
23
24
    /**
25
     * @var VisitServiceInterface
26
     */
27
    private $visitService;
28
    /**
29
     * @var IpLocationResolverInterface
30
     */
31
    private $ipLocationResolver;
32
    /**
33
     * @var TranslatorInterface
34
     */
35
    private $translator;
36
37 5
    public function __construct(
38
        VisitServiceInterface $visitService,
39
        IpLocationResolverInterface $ipLocationResolver,
40
        TranslatorInterface $translator
41
    ) {
42 5
        $this->visitService = $visitService;
43 5
        $this->ipLocationResolver = $ipLocationResolver;
44 5
        $this->translator = $translator;
45 5
        parent::__construct();
46
    }
47
48 5
    protected function configure(): void
49
    {
50 5
        $this->setName(self::NAME)
51 5
             ->setDescription(
52 5
                 $this->translator->translate('Processes visits where location is not set yet')
53
             );
54
    }
55
56 5
    protected function execute(InputInterface $input, OutputInterface $output): void
57
    {
58
        $this->visitService->locateVisits(function (Visit $visit) use ($output) {
59 5
            if (! $visit->hasRemoteAddr()) {
60 2
                $output->writeln(
61 2
                    sprintf('<comment>%s</comment>', $this->translator->translate('Ignored visit with no IP address')),
62 2
                    OutputInterface::VERBOSITY_VERBOSE
63
                );
64 2
                throw new IpCannotBeLocatedException('Ignored visit with no IP address');
65
            }
66
67 3
            $ipAddr = $visit->getRemoteAddr();
68 3
            $output->write(sprintf('%s <fg=blue>%s</>', $this->translator->translate('Processing IP'), $ipAddr));
69 3
            if ($ipAddr === IpAddress::LOCALHOST) {
70 1
                $output->writeln(
71 1
                    sprintf(' [<comment>%s</comment>]', $this->translator->translate('Ignored localhost address'))
72
                );
73 1
                throw new IpCannotBeLocatedException('Ignored localhost address');
74
            }
75
76
            try {
77 2
                return $this->ipLocationResolver->resolveIpLocation($ipAddr);
78 1
            } catch (WrongIpException $e) {
79 1
                $output->writeln(
80 1
                    sprintf(
81 1
                        ' [<fg=red>%s</>]',
82 1
                        $this->translator->translate('An error occurred while locating IP. Skipped')
83
                    )
84
                );
85 1
                if ($output->isVerbose()) {
86 1
                    $this->getApplication()->renderException($e, $output);
87
                }
88
89 1
                throw new IpCannotBeLocatedException('An error occurred while locating IP', 0, $e);
90
            }
91
        }, function (VisitLocation $location) use ($output) {
92 1
            $output->writeln(sprintf(
93 1
                ' [<info>' . $this->translator->translate('Address located at "%s"') . '</info>]',
94 1
                $location->getCountryName()
95
            ));
96 5
        });
97
98 1
        $io = new SymfonyStyle($input, $output);
99 1
        $io->success($this->translator->translate('Finished processing all IPs'));
100
    }
101
}
102