CheckIpAddressIsBlacklistedCommand   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Test Coverage

Coverage 78.56%

Importance

Changes 5
Bugs 2 Features 0
Metric Value
eloc 92
dl 0
loc 181
ccs 66
cts 84
cp 0.7856
rs 10
c 5
b 2
f 0
wmc 25

5 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 8 1
C execute() 0 66 15
A retry() 0 13 1
A __construct() 0 10 1
B muteNotification() 0 30 7
1
<?php
2
3
namespace Azine\MailgunWebhooksBundle\Command;
4
5
use Azine\MailgunWebhooksBundle\Entity\HetrixToolsBlacklistResponseNotification;
6
use Azine\MailgunWebhooksBundle\Entity\MailgunEvent;
7
use Azine\MailgunWebhooksBundle\Entity\Repositories\MailgunEventRepository;
8
use Azine\MailgunWebhooksBundle\Services\AzineMailgunMailerService;
9
use Azine\MailgunWebhooksBundle\Services\HetrixtoolsService\AzineMailgunHetrixtoolsService;
10
use Azine\MailgunWebhooksBundle\Services\HetrixtoolsService\HetrixtoolsServiceResponse;
11
use Doctrine\Common\Persistence\ManagerRegistry;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Process\Process;
17
18
/**
19
 * Checks if the last ip address from MailgunEvent entity is in blacklist.
20
 */
21
class CheckIpAddressIsBlacklistedCommand extends Command
22
{
23
    const NO_VALID_RESPONSE_FROM_HETRIX = 'No valid response from Hetrixtools service, try later.';
24
    const BLACKLIST_REPORT_WAS_SENT = 'Blacklist report was sent.';
25
    const BLACKLIST_REPORT_IS_SAME_AS_PREVIOUS = 'Blacklist report contains the same info as the last report that was sent.';
26
    const IP_IS_NOT_BLACKLISTED = 'Ip is not blacklisted.';
27
    const STARTING_RETRY = 'Initiating retry of the checking command. Tries left: ';
28
29
    /**
30
     * @var string|null The default command name
31
     */
32
    protected static $defaultName = 'mailgun:check-ip-in-blacklist';
33
34
    /**
35
     * @var ManagerRegistry
36
     */
37
    private $managerRegistry;
38
39
    /**
40
     * @var AzineMailgunHetrixtoolsService
41
     */
42
    private $hetrixtoolsService;
43
44
    /**
45
     * @var AzineMailgunMailerService
46
     */
47
    private $azineMailgunService;
48
49
    /**
50
     * @var string
51
     */
52
    private $kernelEnvironment;
53
54
    /**
55
     * @var int
56
     */
57
    private $muteDays;
58
59
    /**
60
     * CheckIpAddressIsBlacklistedCommand constructor.
61
     *
62
     * @param ManagerRegistry                $managerRegistry
63
     * @param AzineMailgunHetrixtoolsService $hetrixtoolsService
64
     * @param AzineMailgunMailerService      $azineMailgunService
65
     * @param $environment
66
     */
67 7
    public function __construct(ManagerRegistry $managerRegistry, AzineMailgunHetrixtoolsService $hetrixtoolsService,
68
                                AzineMailgunMailerService $azineMailgunService, $environment, $muteDays)
69
    {
70 7
        $this->managerRegistry = $managerRegistry;
71 7
        $this->hetrixtoolsService = $hetrixtoolsService;
72 7
        $this->azineMailgunService = $azineMailgunService;
73 7
        $this->kernelEnvironment = $environment;
74 7
        $this->muteDays = $muteDays;
75
76 7
        parent::__construct();
77 7
    }
78
79 7
    protected function configure()
80
    {
81
        $this
82 7
            ->setName(static::$defaultName)
83 7
            ->setDescription('Checks if the last sending IP address from MailgunEvent entity is in blacklist')
84 7
            ->addArgument('numberOfAttempts',
85 7
                InputArgument::OPTIONAL,
86 7
                'Number of retry attempts in case if there were no response from hetrixtools or the process of checking blacklist was still in progress');
87 7
    }
88
89 7
    protected function execute(InputInterface $input, OutputInterface $output)
90
    {
91 7
        $manager = $this->managerRegistry->getManager();
92
        /** @var MailgunEventRepository $eventRepository */
93 7
        $eventRepository = $manager->getRepository(MailgunEvent::class);
94 7
        $ipAddressData = $eventRepository->getLastKnownSenderIpData();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $ipAddressData is correct as $eventRepository->getLastKnownSenderIpData() targeting Azine\MailgunWebhooksBun...LastKnownSenderIpData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
95 7
        $ipAddress = null;
96
97 7
        if (isset($ipAddressData['ip'])) {
98 7
            $ipAddress = $ipAddressData['ip'];
99 7
            $sendDateTime = new \DateTime();
100 7
            $sendDateTime->setTimestamp($ipAddressData['timestamp']);
101
        }
102 7
        $numberOfAttempts = $input->getArgument('numberOfAttempts');
103
104
        try {
105 7
            $response = $this->hetrixtoolsService->checkIpAddressInBlacklist($ipAddress);
106 1
        } catch (\InvalidArgumentException $ex) {
107 1
            $output->write(self::NO_VALID_RESPONSE_FROM_HETRIX);
108
109 1
            if (null != $numberOfAttempts && $numberOfAttempts > 0) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $numberOfAttempts of type null|string|string[] against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
110
                $output->write(self::STARTING_RETRY.$numberOfAttempts);
0 ignored issues
show
Bug introduced by
Are you sure $numberOfAttempts of type string|string[] can be used in concatenation? ( Ignorable by Annotation )

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

110
                $output->write(self::STARTING_RETRY./** @scrutinizer ignore-type */ $numberOfAttempts);
Loading history...
111
                $this->retry($numberOfAttempts);
112
            }
113
114 1
            return -1;
115
        }
116
117 6
        if (HetrixtoolsServiceResponse::RESPONSE_STATUS_SUCCESS == $response->status) {
118 6
            if (0 == $response->blacklisted_count) {
119 1
                $output->write(self::IP_IS_NOT_BLACKLISTED." ($ipAddress)");
120 5
            } elseif ($this->muteNotification($response)) {
121 1
                $output->write(self::BLACKLIST_REPORT_IS_SAME_AS_PREVIOUS." ($ipAddress)");
122
            } else {
123
                try {
124 4
                    $messagesSent = $this->azineMailgunService->sendBlacklistNotification($response, $ipAddress, $sendDateTime);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sendDateTime does not seem to be defined for all execution paths leading up to this point.
Loading history...
125
126 4
                    if ($messagesSent > 0) {
127 4
                        $output->write(self::BLACKLIST_REPORT_WAS_SENT." ($ipAddress)");
128
                    }
129 4
                    if ($this->muteDays > 0) {
130 3
                        $blacklistResponseNotification = new HetrixToolsBlacklistResponseNotification();
131 3
                        $blacklistResponseNotification->setData($response);
0 ignored issues
show
Bug introduced by
$response of type Azine\MailgunWebhooksBun...rixtoolsServiceResponse is incompatible with the type array expected by parameter $data of Azine\MailgunWebhooksBun...Notification::setData(). ( Ignorable by Annotation )

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

131
                        $blacklistResponseNotification->setData(/** @scrutinizer ignore-type */ $response);
Loading history...
132 3
                        $blacklistResponseNotification->setIp($ipAddress);
133 3
                        $blacklistResponseNotification->setDate($sendDateTime);
134 3
                        $blacklistResponseNotification->setIgnoreUntil(new \DateTime('+'.$this->muteDays.' days'));
135 3
                        $manager = $this->managerRegistry->getManager();
136 3
                        $manager->persist($blacklistResponseNotification);
137 1
                        $manager->flush();
138
                    }
139 3
                } catch (\Exception $e) {
140 6
                    $output->write($e->getMessage(), true);
141
                }
142
            }
143
        } elseif (HetrixtoolsServiceResponse::RESPONSE_STATUS_ERROR == $response->status) {
144
            $output->write($response->error_message);
145
146
            if (null != $numberOfAttempts && $numberOfAttempts > 0 && HetrixtoolsServiceResponse::BLACKLIST_CHECK_IN_PROGRESS == $response->error_message) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $numberOfAttempts of type null|string|string[] against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
147
                $output->write(self::STARTING_RETRY.$numberOfAttempts);
148
                $this->retry($numberOfAttempts);
149
            }
150
151
            return -1;
152
        }
153
154 6
        return 0;
155
    }
156
157
    private function retry($numberOfAttempts)
158
    {
159
        --$numberOfAttempts;
160
161
        $cmd = sprintf(
162
            '%s/console %s %s --env=%s',
163
            static::$defaultName,
164
            $numberOfAttempts,
165
            $this->kernelEnvironment
166
        );
167
168
        $process = new Process($cmd);
169
        $process->start();
170
    }
171
172 5
    private function muteNotification($response)
173
    {
174 5
        if (0 == $this->muteDays) {
175
            // don't mute if feature is disabled
176 1
            return false;
177
        }
178
179 4
        $ip = substr($response->links['api_report_link'], strrpos($response->links['api_report_link'], '/', -3) + 1, -1);
180 4
        $responseRepository = $this->managerRegistry->getManager()->getRepository(HetrixToolsBlacklistResponseNotification::class);
181
        /** @var HetrixToolsBlacklistResponseNotification $lastNotifiedResponse */
182 4
        $lastNotifiedResponses = $responseRepository->findBy(array('ip' => $ip), array('ignoreUntil' => 'desc'));
183
184 4
        if (0 == sizeof($lastNotifiedResponses)) {
185
            // don't mute if this is the first check for this ip
186 1
            return false;
187
        }
188
189 3
        if ($lastNotifiedResponses[0]->getIgnoreUntil() < new \DateTime()) {
190
            // don't mute if the last notification it too long ago
191 1
            return false;
192
        }
193
194 2
        $newBlackLists = $response->blacklisted_on;
195 2
        $oldBlacklists = $lastNotifiedResponses[0]->getData()['blacklisted_on'];
196
197 2
        $blacklistsUnchanged = is_array($newBlackLists) && is_array($oldBlacklists)
198 2
            && count($newBlackLists) == count($oldBlacklists)
199 2
            && $newBlackLists == $oldBlacklists;
200
201 2
        return $blacklistsUnchanged;
202
    }
203
}
204