CheckIpAddressIsBlacklistedCommand::execute()   C
last analyzed

Complexity

Conditions 15
Paths 58

Size

Total Lines 66
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 16.4478

Importance

Changes 5
Bugs 2 Features 0
Metric Value
cc 15
eloc 45
c 5
b 2
f 0
nc 58
nop 2
dl 0
loc 66
ccs 35
cts 43
cp 0.8139
crap 16.4478
rs 5.9166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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