Completed
Push — master ( de4578...34b727 )
by Arthur
23s queued 10s
created

Request::prepareApnsHeaders()   B

Complexity

Conditions 7
Paths 48

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.5386
c 0
b 0
f 0
cc 7
nc 48
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Pushok package.
5
 *
6
 * (c) Arthur Edamov <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Pushok;
13
14
/**
15
 * Class Request
16
 * @package Pushok
17
 *
18
 * @see http://bit.ly/communicating-with-apns
19
 */
20
class Request
21
{
22
    const APNS_DEVELOPMENT_SERVER = 'https://api.development.push.apple.com';
23
    const APNS_PRODUCTION_SERVER = 'https://api.push.apple.com';
24
    const APNS_PORT = 443;
25
    const APNS_PATH_SCHEMA = '/3/device/{token}';
26
27
    const HEADER_APNS_ID = 'apns-id';
28
    const HEADER_APNS_EXPIRATION = 'apns-expiration';
29
    const HEADER_APNS_PRIORITY = 'apns-priority';
30
    const HEADER_APNS_TOPIC = 'apns-topic';
31
    const HEADER_APNS_COLLAPSE_ID = 'apns-collapse-id';
32
    const HEADER_APNS_PUSH_TYPE = 'apns-push-type';
33
34
    /**
35
     * Request headers.
36
     *
37
     * @var array
38
     */
39
    private $headers = [];
40
41
    /**
42
     * Request uri.
43
     *
44
     * @var string
45
     */
46
    private $uri;
47
48
    /**
49
     * Request body.
50
     *
51
     * @var string
52
     */
53
    private $body;
54
55
    /**
56
     * Curl options.
57
     *
58
     * @var array
59
     */
60
    private $options;
61
62
    public function __construct(Notification $notification, $isProductionEnv)
63
    {
64
        $this->uri = $isProductionEnv ? $this->getProductionUrl($notification) : $this->getSandboxUrl($notification);
65
        $this->body = $notification->getPayload()->toJson();
66
67
        if (!defined('CURL_HTTP_VERSION_2')) {
68
            define('CURL_HTTP_VERSION_2', 3);
69
        }
70
71
        $this->options = [
72
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2,
73
            CURLOPT_URL => $this->uri,
74
            CURLOPT_PORT => self::APNS_PORT,
75
            CURLOPT_POST => true,
76
            CURLOPT_POSTFIELDS => $notification->getPayload()->toJson(),
77
            CURLOPT_RETURNTRANSFER => true,
78
            CURLOPT_TIMEOUT => 10,
79
            CURLOPT_HEADER => true,
80
        ];
81
82
        $this->prepareApnsHeaders($notification);
83
    }
84
85
    /**
86
     * Add request header.
87
     *
88
     * @param string $key
89
     * @param $value
90
     */
91
    public function addHeader(string $key, $value)
92
    {
93
        $this->headers[$key] = $value;
94
    }
95
96
    /**
97
     * Add request headers.
98
     *
99
     * @param array $headers
100
     */
101
    public function addHeaders(array $headers)
102
    {
103
        $this->headers = array_merge($this->headers, $headers);
104
    }
105
106
    /**
107
     * Get request headers.
108
     *
109
     * @return array
110
     */
111
    public function getHeaders(): array
112
    {
113
        return $this->headers;
114
    }
115
116
    /**
117
     * Add request option.
118
     *
119
     * @param string $key
120
     * @param $value
121
     */
122
    public function addOption(string $key, $value)
123
    {
124
        $this->options[$key] = $value;
125
    }
126
127
    /**
128
     * Add request options.
129
     *
130
     * @param array $options
131
     */
132
    public function addOptions(array $options)
133
    {
134
        $this->options = array_replace($this->options, $options);
135
    }
136
137
    /**
138
     * Get request options.
139
     *
140
     * @return array
141
     */
142
    public function getOptions(): array
143
    {
144
        return $this->options;
145
    }
146
147
    /**
148
     * Get decorated request headers.
149
     *
150
     * @return array
151
     */
152
    public function getDecoratedHeaders(): array
153
    {
154
        $decoratedHeaders = [];
155
        foreach ($this->headers as $name => $value) {
156
            $decoratedHeaders[] = $name . ': ' . $value;
157
        }
158
        return $decoratedHeaders;
159
    }
160
161
    /**
162
     * Get request uri.
163
     *
164
     * @return string
165
     */
166
    public function getUri(): string
167
    {
168
        return $this->uri;
169
    }
170
171
    /**
172
     * Get request body.
173
     *
174
     * @return string
175
     */
176
    public function getBody(): string
177
    {
178
        return $this->body;
179
    }
180
181
    /**
182
     * Get Url for APNs production server.
183
     *
184
     * @param Notification $notification
185
     * @return string
186
     */
187
    private function getProductionUrl(Notification $notification)
188
    {
189
        return self::APNS_PRODUCTION_SERVER . $this->getUrlPath($notification);
190
    }
191
192
    /**
193
     * Get Url for APNs sandbox server.
194
     *
195
     * @param Notification $notification
196
     * @return string
197
     */
198
    private function getSandboxUrl(Notification $notification)
199
    {
200
        return self::APNS_DEVELOPMENT_SERVER . $this->getUrlPath($notification);
201
    }
202
203
    /**
204
     * Get Url path.
205
     *
206
     * @param Notification $notification
207
     * @return mixed
208
     */
209
    private function getUrlPath(Notification $notification)
210
    {
211
        return str_replace("{token}", $notification->getDeviceToken(), self::APNS_PATH_SCHEMA);
212
    }
213
214
    /**
215
     * Prepare APNs headers before sending request.
216
     *
217
     * @param Notification $notification
218
     */
219
    private function prepareApnsHeaders(Notification $notification)
220
    {
221
        if (!empty($notification->getId())) {
222
            $this->headers[self::HEADER_APNS_ID] =  $notification->getId();
223
        }
224
225
        if ($notification->getExpirationAt() instanceof \DateTime) {
226
            $this->headers[self::HEADER_APNS_EXPIRATION] = $notification->getExpirationAt()->getTimestamp();
227
        }
228
229
        if (is_int($notification->getPriority())) {
230
            $this->headers[self::HEADER_APNS_PRIORITY] =  $notification->getPriority();
231
        } else if ($notification->getPayload()->isContentAvailable()) {
232
            $this->headers[self::HEADER_APNS_PRIORITY] = Notification::PRIORITY_LOW;
233
        }
234
235
        if (!empty($notification->getCollapseId())) {
236
            $this->headers[self::HEADER_APNS_COLLAPSE_ID ] = $notification->getCollapseId();
237
        }
238
        
239
        // new header required to support iOS 13
240
        
241
        $this->headers[self::HEADER_APNS_PUSH_TYPE] = 'alert';
242
        
243
        if ($notification->getPayload()->isContentAvailable()) {
244
            $this->headers[self::HEADER_APNS_PUSH_TYPE] = 'background';
245
        }
246
    }
247
}
248