Completed
Pull Request — master (#176)
by Alejandro
04:02
created

ProcessVisitsCommand   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 88.89%

Importance

Changes 0
Metric Value
dl 0
loc 89
ccs 40
cts 45
cp 0.8889
rs 10
c 0
b 0
f 0
wmc 8
lcom 1
cbo 4

3 Methods

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