Completed
Push — master ( f7ceef...6986d0 )
by Alejandro
16s
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\Service\IpLocationResolverInterface;
8
use Shlinkio\Shlink\Common\Util\IpAddress;
9
use Shlinkio\Shlink\Core\Entity\VisitLocation;
10
use Shlinkio\Shlink\Core\Service\VisitServiceInterface;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Style\SymfonyStyle;
15
use Zend\I18n\Translator\TranslatorInterface;
16
use function sleep;
17
use function sprintf;
18
19
class ProcessVisitsCommand extends Command
20
{
21
    public const NAME = 'visit:process';
22
23
    /**
24
     * @var VisitServiceInterface
25
     */
26
    private $visitService;
27
    /**
28
     * @var IpLocationResolverInterface
29
     */
30
    private $ipLocationResolver;
31
    /**
32
     * @var TranslatorInterface
33
     */
34
    private $translator;
35
36 3
    public function __construct(
37
        VisitServiceInterface $visitService,
38
        IpLocationResolverInterface $ipLocationResolver,
39
        TranslatorInterface $translator
40
    ) {
41 3
        $this->visitService = $visitService;
42 3
        $this->ipLocationResolver = $ipLocationResolver;
43 3
        $this->translator = $translator;
44 3
        parent::__construct(null);
45 3
    }
46
47 3
    protected function configure(): void
48
    {
49 3
        $this->setName(self::NAME)
50 3
             ->setDescription(
51 3
                 $this->translator->translate('Processes visits where location is not set yet')
52
             );
53 3
    }
54
55 3
    protected function execute(InputInterface $input, OutputInterface $output): void
56
    {
57 3
        $io = new SymfonyStyle($input, $output);
58 3
        $visits = $this->visitService->getUnlocatedVisits();
59
60 3
        $count = 0;
61 3
        foreach ($visits as $visit) {
62 3
            if (! $visit->hasRemoteAddr()) {
63 1
                $io->writeln(
64 1
                    sprintf('<comment>%s</comment>', $this->translator->translate('Ignored visit with no IP address')),
65 1
                    OutputInterface::VERBOSITY_VERBOSE
66
                );
67 1
                continue;
68
            }
69
70 3
            $ipAddr = $visit->getRemoteAddr();
71 3
            $io->write(sprintf('%s <info>%s</info>', $this->translator->translate('Processing IP'), $ipAddr));
72 3
            if ($ipAddr === IpAddress::LOCALHOST) {
73 1
                $io->writeln(
74 1
                    sprintf(' (<comment>%s</comment>)', $this->translator->translate('Ignored localhost address'))
75
                );
76 1
                continue;
77
            }
78
79 3
            $count++;
80
            try {
81 3
                $result = $this->ipLocationResolver->resolveIpLocation($ipAddr);
82
83 3
                $location = new VisitLocation($result);
84 3
                $visit->setVisitLocation($location);
85 3
                $this->visitService->saveVisit($visit);
86
87 3
                $io->writeln(sprintf(
88 3
                    ' (' . $this->translator->translate('Address located at "%s"') . ')',
89 3
                    $location->getCityName()
90
                ));
91
            } catch (WrongIpException $e) {
92
                $io->writeln(
93
                    sprintf(' <error>%s</error>', $this->translator->translate('An error occurred while locating IP'))
94
                );
95
                if ($io->isVerbose()) {
96
                    $this->getApplication()->renderException($e, $output);
97
                }
98
            }
99
100 3
            if ($count === $this->ipLocationResolver->getApiLimit()) {
101 1
                $count = 0;
102 1
                $seconds = $this->ipLocationResolver->getApiInterval();
103 1
                $io->note(sprintf(
104 1
                    $this->translator->translate('IP location resolver limit reached. Waiting %s seconds...'),
105 1
                    $seconds
106
                ));
107 3
                sleep($seconds);
108
            }
109
        }
110
111 3
        $io->success($this->translator->translate('Finished processing all IPs'));
112 3
    }
113
}
114