Passed
Push — master ( 34bc8c...92daf4 )
by
unknown
02:28
created

HookHandleService::processNewWebhooks()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
/**
3
 * Created by Graham Owens ([email protected])
4
 * Company: PartFire Ltd (www.partfire.co.uk)
5
 * Console: Discovery
6
 *
7
 * User:    gra
8
 * Date:    20/01/17
9
 * Time:    09:52
10
 * Project: PartFire MangoPay Bundle
11
 * File:    HookHandleService.php
12
 *
13
 **/
14
15
namespace PartFire\MangoPayBundle\Services;
16
17
use Composer\EventDispatcher\Event;
18
use PartFire\CommonBundle\Services\Output\CommonOutputInterface;
19
use PartFire\MangoPayBundle\Entity\Hook;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, PartFire\MangoPayBundle\Services\Hook.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
20
use PartFire\MangoPayBundle\Entity\Repository\HookRepository;
21
use PartFire\MangoPayBundle\Entity\Repository\MangoPayRepositoryFactory;
22
use PartFire\MangoPayBundle\Event\MangoPayWebhookEvent;
23
use PartFire\MangoPayBundle\MangoPayConstants;
24
use PartFire\SlackBundle\Services\SlackService;
25
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
26
27
class HookHandleService
28
{
29
    /**
30
     * @var IdentityCheckFactoryRepository
31
     */
32
    protected $mangoPayRepositoryFactory;
33
    protected $slackService;
34
35
    const       CHECK_COMPLETE          = "check.completed";
36
    const       REPORT_COMPLETE         = "report.completed";
37
38
39
    public function __construct(
40
        MangoPayRepositoryFactory $mangoPayRepositoryFactory,
41
        SlackService $slackService,
42
        EventDispatcherInterface $event
43
    )
44
    {
45
        $this->mangoPayRepositoryFactory = $mangoPayRepositoryFactory;
46
        $this->slackService = $slackService;
47
        $this->event = $event;
0 ignored issues
show
Bug introduced by
The property event does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
48
    }
49
50
    public function processRequest($bodyJson)
51
    {
52
        $formattedJson = json_encode($bodyJson);
53
        $this->sendMessage(
54
            "New Webhook received from MangoPay \n ```" . $formattedJson . "```",
55
            ':leftwards_arrow_with_hook:'
56
        );
57
58
        $hookQueueEntity = new Hook();
59
        $hookQueueEntity->setHookId($bodyJson->Id);
60
        $hookQueueEntity->setHookCreationDate($bodyJson->CreationDate);
61
        $hookQueueEntity->setHookTag($bodyJson->Tag);
62
        $hookQueueEntity->setHookUrl($bodyJson->Url);
63
        $hookQueueEntity->setHookStatus($bodyJson->Status);
64
        $hookQueueEntity->setHookValidity($bodyJson->Validity);
65
        $hookQueueEntity->setHookEventType($bodyJson->EventType);
66
67
        $hookQueueEntity->setRawHookData($formattedJson);
68
69
        $this->mangoPayRepositoryFactory->saveAndGetEntity($hookQueueEntity);
70
71
        return true;
72
    }
73
74
    public function processNewWebhooks(CommonOutputInterface $output)
75
    {
76
        $output->info(count($this->getAllNewWebhooks()) . " new hooks to check");
77
78
        foreach($this->getAllNewWebhooks() as $webHook) {
79
            $output->infoid(" Processing hook ID " . $webHook->getId() . " - Action Type = " . $webHook->getHookEventType());
80
            try {
81
                $this->processWebhook($webHook, $output);
82
            } catch (\Exception $e) {
83
                $output->error($e->getMessage());
84
            }
85
86
        }
87
    }
88
89
    private function processWebhook(Hook $hook, CommonOutputInterface $commonOutput)
90
    {
91
        $hook = $this->setWebhookInProgress($hook);
92
        if (MangoPayConstants::isEventTypeOk($hook->getHookEventType())) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
93
94
        } else {
95
            $this->sendErrorMessage(
96
                "Received webhook from MangoPay *" . $hook->getHookEventType() ."*, which is unknown. Firing event anyway \n ```" . json_encode($hook->getRawHookData()) . "```",
97
                ':anguished:'
98
            );
99
        }
100
101
        $webhookEvent = new MangoPayWebhookEvent();
102
        $webhookEvent->setOutput($commonOutput);
103
        $webhookEvent->setHook($hook);
104
105
        $this->event->dispatch(MangoPayWebhookEvent::NAME, $webhookEvent);
106
        $this->setWebhookToActioned($hook);
107
    }
108
109
    private function setWebhookInProgress(Hook $hook) : Hook
110
    {
111
        $hook->setStatus(MangoPayConstants::HOOK_IN_PROGRESS);
112
        return $this->mangoPayRepositoryFactory->saveAndGetEntity($hook);
113
    }
114
115
    private function setWebhookToActioned(Hook $hook)
116
    {
117
        $hook->setStatus(MangoPayConstants::HOOK_ACTIONED);
118
        $this->mangoPayRepositoryFactory->saveAndGetEntity($hook);
119
    }
120
121
    private function getIdentityCheckReportByOnfidoReportId(OnfidoHookQueue $onfidoHookQueue) : ?IdentityCheckReport
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
122
    {
123
        return $this->mangoPayRepositoryFactory->getIdentityCheckReport()->findOneByOnfidoReportId(
124
            $onfidoHookQueue->getResourceId()
125
        );
126
    }
127
128
    private function getAllNewWebhooks()
129
    {
130
        return $this->getHookRepo()->findBy(
131
            [
132
                'status'      => MangoPayConstants::HOOK_NEW
133
            ]
134
        );
135
    }
136
137
    private function getHookRepo() : HookRepository
138
    {
139
        return $this->mangoPayRepositoryFactory->getHook();
140
    }
141
142
    // Made public so tests pass
143
144
    public function isValidOnfidoRequest($bodyJson)
145
    {
146
        if ($bodyJson instanceof \stdClass) {
147
148
            if (!isset($bodyJson->payload->resource_type)) {
149
                return false;
150
            }
151
152
            if (!isset($bodyJson->payload->action)) {
153
                return false;
154
            }
155
156
            if (!isset($bodyJson->payload->object->id)) {
157
                return false;
158
            }
159
160
            if (!isset($bodyJson->payload->object->href) ||
161
                !strstr($bodyJson->payload->object->href, 'api.onfido.com/v') === true
162
            ) {
163
                return false;
164
            }
165
166
            return true;
167
        }
168
        return false;
169
    }
170
171
    private function sendMessage(string $message, string $emoji)
172
    {
173
        $this->slackService->sendMessage($message, 'ff-mangopay-webhooks', $emoji);
174
    }
175
176
    private function sendErrorMessage(string $message, string $emoji)
177
    {
178
        $this->slackService->sendMessage($message, FFConstants::SLACK_CHANNEL_ERROR, $emoji);
179
    }
180
181
}
182