Completed
Push — master ( 613542...020c5c )
by Julián
03:39
created

ApnsService::feedback()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 24
rs 8.9713
cc 3
eloc 13
nc 3
nop 0
1
<?php
2
/**
3
 * Push notification services abstraction (http://github.com/juliangut/tify)
4
 *
5
 * @link https://github.com/juliangut/tify for the canonical source repository
6
 *
7
 * @license https://github.com/juliangut/tify/blob/master/LICENSE
8
 */
9
10
namespace Jgut\Tify\Service;
11
12
use Jgut\Tify\Exception\NotificationException;
13
use Jgut\Tify\Exception\ServiceException;
14
use Jgut\Tify\Notification\AbstractNotification;
15
use Jgut\Tify\Notification\ApnsNotification;
16
use Jgut\Tify\Result;
17
use Jgut\Tify\Service\Client\ApnsClientBuilder;
18
use Jgut\Tify\Service\Message\ApnsMessageBuilder;
19
use ZendService\Apple\Exception\RuntimeException as ApnsRuntimeException;
20
21
/**
22
 * Class ApnsService
23
 */
24
class ApnsService extends AbstractService implements SendInterface, FeedbackInterface
25
{
26
    const RESULT_OK = 0;
27
28
    /**
29
     * Status codes mapping.
30
     *
31
     * @var array
32
     */
33
    private static $statusCodes = [
34
        0 => 'OK',
35
        1 => 'Processing Error',
36
        2 => 'Missing Recipient Token',
37
        3 => 'Missing Topic',
38
        4 => 'Missing Payload',
39
        5 => 'Invalid Token Size',
40
        6 => 'Invalid Topic Size',
41
        7 => 'Invalid Payload Size',
42
        8 => 'Invalid Token',
43
        10 => 'Shutdown',
44
        255 => 'Unknown Error',
45
    ];
46
47
    /**
48
     * @var \ZendService\Apple\Apns\Client\Message
49
     */
50
    protected $pushClient;
51
52
    /**
53
     * @var \ZendService\Apple\Apns\Client\Feedback
54
     */
55
    protected $feedbackClient;
56
57
    /**
58
     * {@inheritdoc}
59
     *
60
     * @throws \Jgut\Tify\Exception\ServiceException
61
     */
62
    public function __construct(array $parameters = [], $sandbox = false)
63
    {
64
        parent::__construct($parameters, $sandbox);
65
66
        $certificatePath = $this->getParameter('certificate');
67
68
        if ($certificatePath === null || !file_exists($certificatePath) || !is_readable($certificatePath)) {
69
            throw new ServiceException(
70
                sprintf('Certificate file "%s" does not exist or is not readable', $certificatePath)
71
            );
72
        }
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     *
78
     * @throws \InvalidArgumentException
79
     */
80
    public function send(AbstractNotification $notification)
81
    {
82
        if (!$notification instanceof ApnsNotification) {
83
            throw new \InvalidArgumentException('Notification must be an accepted APNS notification');
84
        }
85
86
        $service = $this->getPushService();
87
88
        $results = [];
89
90
        /* @var \Jgut\Tify\Recipient\ApnsRecipient $recipient */
91
        foreach ($notification->getRecipients() as $recipient) {
92
            $message = ApnsMessageBuilder::build($recipient, $notification);
0 ignored issues
show
Compatibility introduced by
$recipient of type object<Jgut\Tify\Recipient\AbstractRecipient> is not a sub-type of object<Jgut\Tify\Recipient\ApnsRecipient>. It seems like you assume a child class of the class Jgut\Tify\Recipient\AbstractRecipient to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
93
94
            $result = new Result($recipient->getToken(), new \DateTime);
95
96
            try {
97
                $response = $service->send($message);
98
99
                if ($response->getCode() !== static::RESULT_OK) {
100
                    $result->setStatus(Result::STATUS_ERROR);
101
                    $result->setStatusMessage(self::$statusCodes[$response->getCode()]);
102
                }
103
            } catch (ApnsRuntimeException $exception) {
104
                $result->setStatus(Result::STATUS_ERROR);
105
                $result->setStatusMessage($exception->getMessage());
106
            }
107
108
            $results[] = $result;
109
        }
110
111
        $notification->setStatus(AbstractNotification::STATUS_SENT, $results);
112
113
        $service->close();
114
        $this->pushClient = null;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     *
120
     * @throws \Jgut\Tify\Exception\NotificationException
121
     */
122
    public function feedback()
123
    {
124
        $service = $this->getFeedbackService();
125
126
        try {
127
            $feedbackResponse = $service->feedback();
128
        } catch (ApnsRuntimeException $exception) {
129
            throw new NotificationException($exception->getMessage(), $exception->getCode(), $exception);
130
        }
131
132
        $responses = [];
133
134
        /** @var \ZendService\Apple\Apns\Response\Feedback $response */
135
        foreach ($feedbackResponse as $response) {
136
            $time = new \DateTime(date('c', $response->getTime()));
137
138
            $responses[$response->getToken()] = $time;
139
        }
140
141
        $service->close();
142
        $this->feedbackClient = null;
143
144
        return $responses;
145
    }
146
147
    /**
148
     * Get opened ServiceClient
149
     *
150
     * @return \ZendService\Apple\Apns\Client\Message
151
     */
152
    protected function getPushService()
153
    {
154
        if ($this->pushClient === null) {
155
            $this->pushClient = ApnsClientBuilder::buildPush(
156
                $this->getParameter('certificate'),
157
                $this->getParameter('pass_phrase'),
158
                $this->sandbox
159
            );
160
        }
161
162
        return $this->pushClient;
163
    }
164
165
    /**
166
     * Get opened ServiceFeedbackClient
167
     *
168
     * @return \ZendService\Apple\Apns\Client\Feedback
169
     */
170
    protected function getFeedbackService()
171
    {
172
        if ($this->feedbackClient === null) {
173
            $this->feedbackClient = ApnsClientBuilder::buildFeedback(
174
                $this->getParameter('certificate'),
175
                $this->getParameter('pass_phrase'),
176
                $this->sandbox
177
            );
178
        }
179
180
        return $this->feedbackClient;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    protected function getDefinedParameters()
187
    {
188
        return ['certificate', 'pass_phrase'];
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    protected function getDefaultParameters()
195
    {
196
        return [
197
            'pass_phrase' => null,
198
        ];
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204
    protected function getRequiredParameters()
205
    {
206
        return ['certificate'];
207
    }
208
}
209