MailChimpClientImpl::getMemberHash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlexCk\MailchimpBundle\Service\MailChimp;
6
7
use AlexCk\MailchimpBundle\Model\MailChimp\BatchOperation;
8
use AlexCk\MailchimpBundle\Model\MailChimp\BatchRequest;
9
use AlexCk\MailchimpBundle\Model\MailChimp\BatchResponse;
10
use AlexCk\MailchimpBundle\Model\MailChimp\ListItem;
11
use AlexCk\MailchimpBundle\Model\MailChimp\MailChimpResponse;
12
use AlexCk\MailchimpBundle\Model\MailChimp\MailChimpWebHook;
13
use AlexCk\MailchimpBundle\Model\MailChimp\MailChimpWebHooksEvent;
14
use AlexCk\MailchimpBundle\Model\MailChimp\MailChimpWebHooksSources;
15
use AlexCk\MailchimpBundle\Model\MailChimp\Member;
16
use AlexCk\MailchimpBundle\Service\GuzzleClient\GuzzleClient;
17
use AlexCk\MailchimpBundle\Service\GuzzleClient\GuzzleClientConfig;
18
use AlexCk\MailchimpBundle\Service\GuzzleClient\GuzzleClientException;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Serializer\SerializerAwareInterface;
21
use Symfony\Component\Serializer\SerializerAwareTrait;
22
23
class MailChimpClientImpl implements MailChimpClient, SerializerAwareInterface
24
{
25
    use SerializerAwareTrait;
26
27
    const MAIL_CHIMP_API_HOST = 'https://';
28
    const MAIL_CHIMP_API_DOMAIN = 'api.mailchimp.com/';
29
30
    /** @var GuzzleClient $client */
31
    private $guzzleClient;
32
33
    /** @var GuzzleClient $client */
34
    private $client;
35
36
    /**
37
     * MailChimpClient constructor.
38
     * @param GuzzleClient $guzzleClient
39
     */
40
    public function __construct(GuzzleClient $guzzleClient)
41
    {
42
       $this->guzzleClient = $guzzleClient;
43
    }
44
45
    public function configure(string $username, string $key, string $version): MailChimpClient
46
    {
47
        if (!$this->client) {
48
            $config = new GuzzleClientConfig();
49
            $config
50
                ->setUsername($username)
51
                ->setPassword($key)
52
                ->setVersion($version)
53
                ->setBaseUri(self::MAIL_CHIMP_API_HOST . $this->getDCFromApiKey($key) . '.' . self::MAIL_CHIMP_API_DOMAIN . $version . '/')
54
                ->setAccept('application/json')
55
                ->setContentType('application/json');
56
57
            $this->client = $this->guzzleClient->baseAuthentication($config);
58
        }
59
60
        return $this;
61
    }
62
63
    private function getClient(): GuzzleClient
64
    {
65
        if (!$this->client) {
66
            throw new MailChimpException(Response::HTTP_INTERNAL_SERVER_ERROR, "Mailchimp client should be configured");
67
        }
68
69
        return $this->client;
70
    }
71
72
    private function getDCFromApiKey(?string $key): string
73
    {
74
        if ($key) {
75
            $index = strrpos($key, '-');
76
77
            return $index ? trim(substr($key, $index + 1)) : '';
78
        }
79
80
        return '';
81
    }
82
83
    public function createList(ListItem $listItem): ListItem
84
    {
85
        $data = $this->serializer->normalize($listItem, 'json', []);
0 ignored issues
show
Bug introduced by
The method normalize() does not exist on Symfony\Component\Serializer\SerializerInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Symfony\Component\Serial...rializerCollectionDummy. Are you sure you never get one of those? ( Ignorable by Annotation )

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

85
        /** @scrutinizer ignore-call */ 
86
        $data = $this->serializer->normalize($listItem, 'json', []);
Loading history...
86
87
        try {
88
            $response = $this->getClient()->post('lists', $data);
89
90
            return $this->serializer->denormalize($response->getBody()->getContents(), ListItem::class, 'json', []);
0 ignored issues
show
Bug introduced by
The method denormalize() does not exist on Symfony\Component\Serializer\SerializerInterface. It seems like you code against a sub-type of Symfony\Component\Serializer\SerializerInterface such as Symfony\Component\Serializer\Serializer or Symfony\Component\Serial...rializerCollectionDummy. ( Ignorable by Annotation )

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

90
            return $this->serializer->/** @scrutinizer ignore-call */ denormalize($response->getBody()->getContents(), ListItem::class, 'json', []);
Loading history...
91
        } catch (GuzzleClientException $e) {
92
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
93
        }
94
    }
95
96
    public function getLists(): MailChimpResponse
97
    {
98
        try {
99
            $response = $this->getClient()->get('lists');
100
101
            return $this->serializer->denormalize($response->getBody()->getContents(), MailChimpResponse::class, 'json', []);
102
        } catch (GuzzleClientException $e) {
103
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
104
        }
105
    }
106
107
    public function createMember(Member $member, string $listId, ?string $unsubscribeUrl = null): Member
108
    {
109
        $data = $this->serializer->normalize($member, 'json', []);
110
111
        try {
112
            $response = $this->getClient()->post(
113
                'lists/' . $listId . '/members',
114
                $data
115
            );
116
117
            if ($unsubscribeUrl) {
118
                $this->createWebHookEventUnsubscribe($listId, $unsubscribeUrl);
119
            }
120
121
            return $this->serializer->denormalize($response->getBody()->getContents(), Member::class, 'json', []);
122
        } catch (GuzzleClientException $e) {
123
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
124
        }
125
    }
126
127
    public function updateMember(Member $member, string $listId, string $oldEmail, ?string $unsubscribeUrl = null): Member
128
    {
129
        $data = $this->serializer->normalize($member, 'json', []);
130
131
        try {
132
            $response = $this->getClient()->put(
133
                'lists/' . $listId . '/members/' . $this->getMemberHash($oldEmail),
134
                $data
135
            );
136
137
            if ($unsubscribeUrl) {
138
                $this->createWebHookEventUnsubscribe($listId, $unsubscribeUrl);
139
            }
140
141
            return $this->serializer->denormalize($response->getBody()->getContents(), Member::class, 'json', []);
142
        } catch (GuzzleClientException $e) {
143
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
144
        }
145
    }
146
147
    private function getMemberHash($email)
148
    {
149
        return md5(strtolower($email));
150
    }
151
152
    public function deleteMember(Member $member, string $listId): bool
153
    {
154
        try {
155
            $this->getClient()->delete(
156
                'lists/' . $listId . '/members/' . $this->getMemberHash($member->getEmail()),
157
                []
158
            );
159
160
            return true;
161
        } catch (GuzzleClientException $e) {
162
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
163
        }
164
    }
165
166
    public function listWebHookEvent(string $listId): MailChimpResponse
167
    {
168
        try {
169
            $response = $this->getClient()->get('lists/' . $listId . '/webhooks');
170
171
            return $this->serializer->denormalize($response->getBody()->getContents(), MailChimpResponse::class, 'json', []);
172
        } catch (GuzzleClientException $e) {
173
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
174
        }
175
    }
176
177
    public function createWebHookEventUnsubscribe(string $listId, string $unsubscribeUrl): MailChimpWebHook
178
    {
179
        $isFind = $this->checkIsExistsUnsubscribeWebhook($listId);
180
181
        if (!$isFind) {
182
            $webhookSources = new MailChimpWebHooksSources();
183
184
            $webhookEvent = new MailChimpWebHooksEvent();
185
            $webhookEvent
186
                ->setSubscribe(false)
187
                ->setUnsubscribe(true);
188
189
            $webhook = new MailChimpWebHook();
190
            $webhook
191
                ->setEvents($webhookEvent)
192
                ->setSources($webhookSources)
193
                ->setUrl($unsubscribeUrl);
194
195
            $data = $this->serializer->normalize($webhook, 'json', []);
196
197
            try {
198
                $response = $this->getClient()->post(
199
                    'lists/' . $listId . '/webhooks',
200
                    $data
201
                );
202
203
                return $this->serializer->denormalize($response->getBody()->getContents(), MailChimpWebHook::class, 'json', []);
204
            } catch (GuzzleClientException $e) {
205
                throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
206
            }
207
        }
208
209
        return new MailChimpWebHook();
210
    }
211
212
    private function checkIsExistsUnsubscribeWebhook(string $listId): bool
213
    {
214
        $isFind = false;
215
216
        try {
217
            $mailChimpResponse = $this->listWebHookEvent($listId);
218
219
            /** @var MailChimpWebHook $webhook */
220
            foreach ($mailChimpResponse->getWebhooks() as $webhook) {
221
                if ($webhook->getEvents() && $webhook->getEvents()->isUnsubscribe()) {
222
                    $isFind = true;
223
                }
224
            }
225
        } catch (GuzzleClientException $exception) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
226
227
        return $isFind;
228
    }
229
230
    public function createBatchMember(string $listId, iterable $members, ?string $unsubscribeUrl = null): BatchResponse
231
    {
232
        $batchReq = new BatchRequest();
233
234
        foreach ($members as $member) {
235
            if ($member instanceof Member) {
236
                $batchOperation = new BatchOperation();
237
                $batchOperation
238
                    ->setMethod("POST")
239
                    ->setPath('lists/' . $listId . '/members')
240
                    ->setBody(\GuzzleHttp\json_encode($this->serializer->normalize($member, 'json', [])));
241
242
                $batchReq->addOperation($batchOperation);
243
            }
244
        }
245
246
        $data = $this->serializer->normalize($batchReq, 'json', []);
247
248
        try {
249
            $response = $this->getClient()->post('batches', $data);
250
251
            if ($unsubscribeUrl) {
252
                $this->createWebHookEventUnsubscribe($listId, $unsubscribeUrl);
253
            }
254
255
            return $this->serializer->denormalize($response->getBody()->getContents(), BatchResponse::class, 'json', []);
256
        } catch (GuzzleClientException $e) {
257
            throw new MailChimpException($e->getStatusCode(), $e->getMessage(), $e->getExceptionContents());
258
        }
259
    }
260
}
261