Chrome::send()   B
last analyzed

Complexity

Conditions 5
Paths 1

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7.3471

Importance

Changes 0
Metric Value
dl 0
loc 31
c 0
b 0
f 0
ccs 12
cts 22
cp 0.5455
rs 8.439
cc 5
eloc 18
nc 1
nop 2
crap 7.3471
1
<?php
2
3
namespace Notimatica\Driver\Providers;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Psr7\Request;
7
use GuzzleHttp\Psr7\Response;
8
use Notimatica\Driver\Contracts\Notification;
9
use Notimatica\Driver\Contracts\Subscriber;
10
use Notimatica\Driver\Driver;
11
use Notimatica\Driver\Events\NotificationFailed;
12
use Notimatica\Driver\Events\NotificationSent;
13
14
class Chrome extends AbstractProvider
15
{
16
    const NAME            = 'chrome';
17
    const DEFAULT_TTL     = 2419200;
18
    const DEFAULT_TIMEOUT = 30;
19
20
    /**
21
     * @var array
22
     */
23
    protected static $headers = [
24
        'Content-Type' => 'application/json',
25
    ];
26
27
    /**
28
     * Init Browser.
29
     *
30
     * @param array $config
31
     */
32 2
    protected static function initBrowser(array $config)
33
    {
34 1
        if (static::$browser) {
35
            return;
36
        }
37
38 1
        static::$browser = new Client([
39 1
            'timeout' => isset($config['timeout']) ? $config['timeout'] : static::DEFAULT_TIMEOUT,
40 2
        ]);
41
42 1
        static::$headers['TTL'] = isset($config['ttl']) ? $config['ttl'] : static::DEFAULT_TTL;
43 1
        static::$headers['Authorization'] = 'key=' . $config['api_key'];
44 1
    }
45
46
    /**
47
     * Split endpoints for batch requests.
48
     *
49
     * @param  array $endpoints
50
     * @return array
51
     */
52 2
    protected function batch(array $endpoints)
53
    {
54 2
        return array_chunk($endpoints, (int) $this->config['batch_chunk_size']);
55
    }
56
57
    /**
58
     * Send notification.
59
     *
60
     * @param  Notification $notification
61
     * @param  Subscriber[] $subscribers
62
     */
63 1
    public function send(Notification $notification, array $subscribers)
64
    {
65 1
        static::initBrowser($this->config);
66 1
        $total = count($subscribers);
67
68 1
        $this->flush(
69 1
            $subscribers,
70
            function (Response $response, $index) use ($notification, $total) {
71
                try {
72
                    $response = json_decode($response->getBody());
73
74
                    if (json_last_error() !== JSON_ERROR_NONE) {
75
                        throw new \Exception();
76
                    }
77
78
                    if ($response->success > 0) {
79
                        Driver::emit(new NotificationSent($notification, (int) $response->success));
80
                    }
81
82
                    if ($response->failure > 0) {
83
                        Driver::emit(new NotificationFailed($notification, (int) $response->failure));
84 1
                    }
85
                } catch (\Exception $e) {
86
                    Driver::emit(new NotificationFailed($notification, $this->calculateChunkSize($index, $total)));
87
                }
88 1
            },
89 1
            function ($reason, $index) use ($notification, $total) {
90 1
                Driver::emit(new NotificationFailed($notification, $this->calculateChunkSize($index, $total)));
91 1
            }
92 1
        );
93 1
    }
94
95
    /**
96
     * Send request.
97
     *
98
     * @param  array $subscribers
99
     * @param  null $payload
100
     * @return \Generator
101
     */
102 2
    protected function prepareRequests($subscribers, $payload = null)
103
    {
104 2
        $url = $this->config['url'];
105 2
        $headers = static::$headers;
106
107 2
        foreach ($this->batch($subscribers) as $index => $chunk) {
108 2
            $content = $this->getRequestContent($chunk);
109 2
            $headers['Content-Length'] = strlen($content);
110
111 2
            yield new Request('POST', $url, $headers, $content);
112 2
        }
113 2
    }
114
115
    /**
116
     * Calculate chunk size.
117
     * Problem is, we don't know the latter chunk size.
118
     *
119
     * @param  int $index
120
     * @param  int $total
121
     * @return int
122
     */
123 2
    protected function calculateChunkSize($index, $total)
124
    {
125 2
        $chunkSize = (int) $this->config['batch_chunk_size'];
126
127 2
        $offset = ($index + 1) * $chunkSize;
128 2
        $chunks = ceil($total / $chunkSize);
129
130 2
        if ($offset <= $total) {
131 1
            $return = $chunkSize;
132 2
        } elseif ($offset > $total + $chunkSize) {
133 1
            $return = 0;
134 1
        } else {
135 2
            $return = $total - ($chunks - 1) * $chunkSize;
136
        }
137
138 2
        return (int) $return;
139
    }
140
141
    /**
142
     * Send notification to endpoints.
143
     *
144
     * @param  Subscriber[] $subscribers
145
     * @return array
146
     */
147 3
    protected function getRequestContent(array $subscribers)
148
    {
149 3
        $tokens = [];
150
151
        /** @var Subscriber $subscriber */
152 3
        foreach ($subscribers as $subscriber) {
153 3
            $tokens[] = $subscriber->getToken();
154 3
        }
155
156 3
        return json_encode([
157 3
            'registration_ids' => $tokens,
158 3
        ]);
159
    }
160
161
    /**
162
     * Generate manifest file text.
163
     *
164
     * @return string
165
     */
166 1
    public function manifest()
167
    {
168 1
        return json_encode([
169 1
            'name' => $this->project->name,
170 1
            'gcm_sender_id' => $this->config['sender_id'],
171 1
        ], JSON_PRETTY_PRINT);
172
    }
173
}
174