APNSNotification::createPayload()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 1
crap 2
1
<?php
2
namespace nstdio\notymo;
3
4
use nstdio\notymo\exception\InvalidCertException;
5
6
/**
7
 * Class APNSNotificationComponent
8
 */
9
class APNSNotification extends AbstractNotification
10
{
11
    /**
12
     * @var string APNS live server.
13
     */
14
    private $apnsHost = 'gateway.push.apple.com';
15
16
    /**
17
     * @var string APNS sandbox server
18
     */
19
    private $apnsSandboxHost = 'gateway.sandbox.push.apple.com';
20
21
    /**
22
     * @var int APNS server port to connect.
23
     */
24
    private $apnsPort = 2195;
25
26
    /**
27
     * @var string
28
     */
29
    private $apnsCert = 'apns-production.pem';
30
31
    /**
32
     * @var string
33
     */
34
    private $apnsSandboxCert = 'apns-dev.pem';
35
36
    /**
37
     * @var string
38
     */
39
    private $scheme = 'https';
40
41
    /**
42
     * @var bool Connect to APNS sandbox or live server.
43
     */
44
    private $live = false;
45
46
    /**
47
     * APNSNotification constructor.
48
     *
49
     * @param bool        $live
50
     * @param string|null $apnsCert
51
     * @param string|null $apnsSandboxCert
52
     *
53
     * @throws InvalidCertException When cannot find one of certificate files.
54
     */
55 5
    public function __construct($live = false, $apnsCert = null, $apnsSandboxCert = null)
56
    {
57 5
        parent::__construct();
58 5
        $this->live = $live;
59
60 5
        if ($this->live && !is_readable($apnsCert)) {
61 1
            throw new InvalidCertException("Cannot find live certificate file: " . var_export($apnsCert, true));
62
        }
63
64 5
        if (!$this->live && !is_readable($apnsSandboxCert)) {
65 1
            throw new InvalidCertException("Cannot find sandbox certificate file: " . var_export($apnsSandboxCert, true));
66
        }
67
68 5
        $this->apnsCert = $apnsCert;
69 5
        $this->apnsSandboxCert = $apnsSandboxCert;
70 5
    }
71
72
    /**
73
     * Writes all data to the stream
74
     *
75
     * @param MessageInterface $message
76
     */
77 2
    protected function sendImpl(MessageInterface $message)
78
    {
79 2
        if ($message->getType() !== MessageInterface::TYPE_IOS) {
80 1
            return;
81
        }
82 1
        $payload = $this->createPayload($message);
83 1
        $binMsg = $this->createBinMessage($message, $payload);
84 1
        $this->stream->write(CURLOPT_POSTFIELDS, $binMsg);
85
86 1
        $this->notifyOnEachSent($message, $this->stream->read());
87
88 1
        $this->messageQueue->dequeue();
89 1
    }
90
91
    /**
92
     * @param MessageInterface $message
93
     *
94
     * @return string Тhe json encoded string
95
     */
96 1
    final protected function createPayload(MessageInterface $message)
97
    {
98 1
        $payload = array();
99 1
        $payload['aps'] = array(
100 1
            'alert' => $message->getMessage(),
101 1
            'badge' => $message->getBadge(),
102 1
            'sound' => $message->getSound(),
103
        );
104
105
        /**
106
         * @var MessageInterface $value
107
         */
108 1
        foreach ($message->getCustomData() as $key => $value) {
109 1
            $payload[$key] = $value;
110 1
        }
111
112
113 1
        return json_encode($payload);
114
    }
115
116
    /**
117
     * @param $message
118
     * @param $payload
119
     *
120
     * @return string
121
     */
122 1
    private function createBinMessage(MessageInterface $message, $payload)
123
    {
124 1
        $binMsg = '';
125 1
        if ($message->isMultiple()) {
126 1
            foreach ($message->getToken() as $token) {
127 1
                $binMsg .= $this->buildBinMessage($token, $payload);
128 1
            }
129 1
        } else {
130 1
            $binMsg = $this->buildBinMessage($message->getToken(), $payload);
131
        }
132
133 1
        return $binMsg;
134
    }
135
136
    /**
137
     * @param $token
138
     * @param $payload
139
     *
140
     * @return string
141
     *
142
     */
143 1
    private function buildBinMessage($token, $payload)
144
    {
145 1
        $token = $this->prepareToken($token);
146
147 1
        return chr(0)
148 1
        . chr(0)
149 1
        . chr(32)
150 1
        . pack('H*', $token)
151 1
        . chr(0)
152 1
        . chr(strlen($payload))
153 1
        . $payload;
154
    }
155
156
    /**
157
     * @param $deviceToken
158
     *
159
     * @return mixed
160
     */
161 1
    private function prepareToken($deviceToken)
162
    {
163 1
        return strtolower(str_replace(array('<', '>', ' '), '', $deviceToken));
164
    }
165
166 2
    protected function getConnectionParams()
167
    {
168
        return array(
169 2
            CURLOPT_URL            => $this->getRemoteSocketAddress(),
170 2
            CURLOPT_RETURNTRANSFER => true,
171 2
            CURLOPT_FOLLOWLOCATION => true,
172 2
            CURLOPT_HEADER         => true,
173 2
            CURLOPT_SSL_VERIFYPEER => true,
174 2
            CURLOPT_SSLCERT        => $this->live ? $this->apnsCert : $this->apnsSandboxCert,
175 2
            CURLOPT_POST           => true,
176 2
        );
177
    }
178
179
    /**
180
     * @return string Full qualified url address of APNS server.
181
     */
182 2
    private function getRemoteSocketAddress()
183
    {
184 2
        return sprintf("%s://%s:%d", $this->scheme, $this->live ? $this->apnsHost : $this->apnsSandboxHost, $this->apnsPort);
185
    }
186
}