Completed
Push — master ( 0492f4...65eae2 )
by Edgar
02:13
created

APNSNotification::getRemoteSocketAddress()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
namespace nstdio\notymo;
3
4
use nstdio\notymo\exception\InvalidCert;
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 InvalidCert When cannot find one of certificate files.
54
     */
55 4
    public function __construct($live = false, $apnsCert = null, $apnsSandboxCert = null)
56
    {
57 4
        parent::__construct();
58 4
        $this->live = $live;
59
60 4
        if ($this->live && !is_readable($apnsCert)) {
61 1
            throw new InvalidCert("Cannot find certificate file: " . $apnsCert);
62
        }
63
64 4
        if (!$this->live && !is_readable($apnsSandboxCert)) {
65 1
            throw new InvalidCert("Cannot find certificate file: " . $apnsSandboxCert);
66
        }
67
68 4
        $this->apnsCert = $apnsCert;
69 4
        $this->apnsSandboxCert = $apnsSandboxCert;
70 4
    }
71
72
    /**
73
     * @throws \Exception
74
     */
75 2
    public function send()
76
    {
77 2
        if ($this->messageQueue->isEmpty()) {
78 1
            return;
79
        }
80
81 1
        $this->openConnection()
82 1
            ->write()
83 1
            ->close();
84 1
    }
85
86 1
    private function close()
87
    {
88 1
        $this->stream->close();
89 1
    }
90
91
    /**
92
     * Writes all data to the stream
93
     *
94
     * @return self
95
     */
96 1
    private function write()
97
    {
98
        /** @var MessageInterface $message */
99 1
        foreach ($this->messageQueue as $message) {
100 1
            if ($message->getType() !== MessageInterface::TYPE_IOS) {
101
                continue;
102
            }
103 1
            $payload = $this->createPayload($message);
104 1
            $binMsg = $this->createBinMessage($message, $payload);
105 1
            $this->stream->write(CURLOPT_POSTFIELDS, $binMsg);
106 1
            $this->stream->read();
107 1
        }
108
109 1
        return $this;
110
    }
111
112
    /**
113
     * @param MessageInterface $message
114
     *
115
     * @return string Тhe json encoded string
116
     */
117 1
    final protected function createPayload(MessageInterface $message)
118
    {
119 1
        $payload = array();
120 1
        $payload['aps'] = array(
121 1
            'alert' => $message->getMessage(),
122 1
            'badge' => $message->getBadge(),
123 1
            'sound' => $message->getSound(),
124
        );
125
126
        /**
127
         * @var MessageInterface $value
128
         */
129 1
        foreach ($message->getCustomData() as $key => $value) {
130
            $payload[$key] = $value;
131 1
        }
132
133
134 1
        return json_encode($payload);
135
    }
136
137
    /**
138
     * @param $message
139
     * @param $payload
140
     *
141
     * @return string
142
     */
143 1
    private function createBinMessage(MessageInterface $message, $payload)
144
    {
145 1
        $binMsg = '';
146 1
        if ($message->isMultiple()) {
147 1
            foreach ($message->getToken() as $token) {
148 1
                $binMsg .= $this->buildBinMessage($token, $payload);
149 1
            }
150 1
        } else {
151
            $binMsg = $this->buildBinMessage($message->getToken(), $payload);
152
        }
153
154 1
        return $binMsg;
155
    }
156
157
    /**
158
     * @param $token
159
     * @param $payload
160
     *
161
     * @return string
162
     *
163
     */
164 1
    private function buildBinMessage($token, $payload)
165
    {
166 1
        $token = $this->prepareToken($token);
167
168 1
        return chr(0)
169 1
        . chr(0)
170 1
        . chr(32)
171 1
        . pack('H*', $token)
172 1
        . chr(0)
173 1
        . chr(strlen($payload))
174 1
        . $payload;
175
    }
176
177
    /**
178
     * @param $deviceToken
179
     *
180
     * @return mixed
181
     */
182 1
    private function prepareToken($deviceToken)
183
    {
184 1
        return strtolower(str_replace(array('<', '>', ' '), '', $deviceToken));
185
    }
186
187 1
    protected function getConnectionParams()
188
    {
189
        return array(
190 1
            CURLOPT_URL            => $this->getRemoteSocketAddress(),
191 1
            CURLOPT_RETURNTRANSFER => true,
192 1
            CURLOPT_FOLLOWLOCATION => true,
193 1
            CURLOPT_HEADER         => true,
194 1
            CURLOPT_SSL_VERIFYPEER => true,
195 1
            CURLOPT_SSLCERT        => $this->live ? $this->apnsCert : $this->apnsSandboxCert,
196 1
            CURLOPT_POST           => true,
197 1
        );
198
    }
199
200
    /**
201
     * @return string Full qualified url address of APNS server.
202
     */
203 1
    private function getRemoteSocketAddress()
204
    {
205 1
        return sprintf("%s://%s:%d", $this->scheme, $this->live ? $this->apnsHost : $this->apnsSandboxHost, $this->apnsPort);
206
    }
207
}