ConsumeWebhookQueueCommand::setHttpClient()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Loevgaard\DandomainAltapayBundle\Command;
4
5
use Doctrine\Common\Collections\Criteria;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\ClientInterface;
8
use GuzzleHttp\Exception\TransferException;
9
use GuzzleHttp\Psr7\Request;
10
use GuzzleHttp\RequestOptions;
11
use JMS\Serializer\SerializerInterface;
12
use Loevgaard\DandomainAltapayBundle\Entity\WebhookExchange;
13
use Loevgaard\DandomainAltapayBundle\Entity\WebhookExchangeRepository;
14
use Loevgaard\DandomainAltapayBundle\Entity\WebhookQueueItem;
15
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
16
use Symfony\Component\Console\Command\LockableTrait;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Output\OutputInterface;
19
20
class ConsumeWebhookQueueCommand extends ContainerAwareCommand
21
{
22
    use LockableTrait;
23
24
    /**
25
     * @var OutputInterface
26
     */
27
    private $output;
28
29
    /**
30
     * @var WebhookExchangeRepository
31
     */
32
    private $webhookExchangeRepository;
33
34
    /**
35
     * @var SerializerInterface
36
     */
37
    private $serializer;
38
39
    /**
40
     * @var Client
41
     */
42
    private $httpClient;
43
44
    public function __construct(WebhookExchangeRepository $webhookExchangeRepository, SerializerInterface $serializer)
45
    {
46
        $this->webhookExchangeRepository = $webhookExchangeRepository;
47
        $this->serializer = $serializer;
48
49
        parent::__construct();
50
    }
51
52
    public function setHttpClient(ClientInterface $client)
53
    {
54
        $this->httpClient = $client;
0 ignored issues
show
Documentation Bug introduced by
$client is of type object<GuzzleHttp\ClientInterface>, but the property $httpClient was declared to be of type object<GuzzleHttp\Client>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
55
    }
56
57
    protected function configure()
58
    {
59
        $this->setName('loevgaard:dandomain:altapay:consume-webhook-queue')
60
            ->setDescription('Will consume the webhook queue and do the HTTP requests')
61
        ;
62
    }
63
64
    protected function execute(InputInterface $input, OutputInterface $output)
65
    {
66
        if (!($this->lock())) {
67
            $output->writeln('The command is already running in another process.');
68
69
            return 0;
70
        }
71
72
        $this->output = $output;
73
74
        /** @var WebhookExchange[] $webhookExchanges */
75
        $webhookExchanges = $this->webhookExchangeRepository->findAll();
76
77
        foreach ($webhookExchanges as $webhookExchange) {
78
            $now = new \DateTimeImmutable();
79
80
            $criteria = Criteria::create()
81
                ->where(
82
                    Criteria::expr()->orX(
83
                        Criteria::expr()->eq('status', WebhookQueueItem::STATUS_PENDING),
84
                        Criteria::expr()->eq('status', WebhookQueueItem::STATUS_ERROR)
85
                    )
86
                )->andWhere(Criteria::expr()->lte('nextTry', $now))
87
                ->setMaxResults(50)
88
            ;
89
90
            /** @var WebhookQueueItem[] $webhookQueueItems */
91
            $webhookQueueItems = $webhookExchange->getWebhookQueueItems()->matching($criteria);
92
93
            foreach ($webhookQueueItems as $webhookQueueItem) {
94
                try {
95
                    if ($this->doRequest($webhookQueueItem)) {
96
                        $webhookQueueItem->markAsSuccess();
97
                    }
98
                } catch (\Exception $e) {
99
                    $webhookQueueItem->markAsError($e->getMessage());
100
                }
101
102
                $this->webhookExchangeRepository->flush();
103
            }
104
        }
105
106
        $this->release();
107
108
        return 0;
109
    }
110
111
    /**
112
     * @param WebhookQueueItem $webhookQueueItem
113
     *
114
     * @return bool
115
     */
116
    private function doRequest(WebhookQueueItem $webhookQueueItem): bool
117
    {
118
        if (!$this->httpClient) {
119
            $this->httpClient = new Client([
120
                RequestOptions::ALLOW_REDIRECTS => false,
121
                RequestOptions::CONNECT_TIMEOUT => 15,
122
                RequestOptions::TIMEOUT => 30,
123
                RequestOptions::HTTP_ERRORS => false,
124
            ]);
125
        }
126
127
        $request = new Request('post', $webhookQueueItem->getWebhookExchange()->getUrl(), ['Content-Type' => 'application/json'], $webhookQueueItem->getContent());
128
        $webhookQueueItem->setRequest($request);
0 ignored issues
show
Documentation introduced by
$request is of type object<GuzzleHttp\Psr7\Request>, but the function expects a null|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
129
130
        try {
131
            $response = $this->httpClient->send($request);
132
            $webhookQueueItem->setResponse($response);
133
        } catch (TransferException $e) {
134
            $this->output->writeln('[Webhook Queue Item: '.$webhookQueueItem->getId().'] Webhook URL ('.$webhookQueueItem->getWebhookExchange()->getUrl().') returned an error: '.$e->getMessage(), OutputInterface::VERBOSITY_VERBOSE);
135
            $webhookQueueItem->markAsError($e->getMessage());
136
137
            return false;
138
        }
139
140
        if (200 !== $response->getStatusCode()) {
141
            $this->output->writeln('[Webhook Queue Item: '.$webhookQueueItem->getId().'] Webhook URL ('.$webhookQueueItem->getWebhookExchange()->getUrl().') returned status code: '.$response->getStatusCode(), OutputInterface::VERBOSITY_VERBOSE);
142
            $webhookQueueItem->markAsError('Status code was '.$response->getStatusCode());
143
144
            return false;
145
        }
146
147
        return true;
148
    }
149
}
150