Completed
Branch v1 (ffe92e)
by Julián
02:44
created

GcmAdapter::getDefinedParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
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\Adapter\Gcm;
11
12
use Jgut\Tify\Adapter\AbstractAdapter;
13
use Jgut\Tify\Adapter\SendAdapter;
14
use Jgut\Tify\Notification;
15
use Jgut\Tify\Receiver\GcmReceiver;
16
use Jgut\Tify\Result;
17
use ZendService\Google\Exception\RuntimeException as GcmRuntimeException;
18
19
/**
20
 * Class GcmAdapter
21
 */
22
class GcmAdapter extends AbstractAdapter implements SendAdapter
23
{
24
    /**
25
     * Status codes mapping.
26
     *
27
     * @see https://developers.google.com/cloud-messaging/http-server-ref
28
     *
29
     * @var array
30
     */
31
    protected static $statusCodes = [
32
        'MissingRegistration' => 'Missing Registration Token',
33
        'InvalidRegistration' => 'Invalid Registration Token',
34
        'NotRegistered' => 'Unregistered Device',
35
        'InvalidPackageName' => 'Invalid Package Name',
36
        'MismatchSenderId' => 'Mismatched Sender',
37
        'MessageTooBig' => 'Message Too Big',
38
        'InvalidDataKey' => 'Invalid Data Key',
39
        'InvalidTtl' => 'Invalid Time to Live',
40
        'Unavailable' => 'Timeout',
41
        'InternalServerError' => 'Internal Server Error',
42
        'DeviceMessageRateExceeded' => 'Device Message Rate Exceeded',
43
        'TopicsMessageRateExceeded' => 'Topics Message Rate Exceeded',
44
        'UnknownError' => 'Unknown Error',
45
    ];
46
47
    /**
48
     * GCM service builder.
49
     *
50
     * @var \Jgut\Tify\Adapter\Gcm\GcmBuilder
51
     */
52
    protected $builder;
53
54
    /**
55
     * @var \ZendService\Google\Gcm\Client
56
     */
57
    protected $pushClient;
58
59
    /**
60
     * @param array                             $parameters
61
     * @param \Jgut\Tify\Adapter\Gcm\GcmBuilder $builder
0 ignored issues
show
Documentation introduced by
Should the type for parameter $builder not be null|GcmBuilder?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
62
     *
63
     * @throws \Jgut\Tify\Exception\AdapterException
64
     */
65
    public function __construct(array $parameters = [], GcmBuilder $builder = null)
66
    {
67
        parent::__construct($parameters);
68
69
        // @codeCoverageIgnoreStart
70
        if ($builder === null) {
71
            $builder = new GcmBuilder;
72
        }
73
        // @codeCoverageIgnoreEnd
74
        $this->builder = $builder;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     *
80
     * @throws \InvalidArgumentException
81
     * @throws \RuntimeException
82
     */
83
    public function send(Notification $notification)
84
    {
85
        $client = $this->getPushClient();
86
87
        /* @var \ZendService\Google\Gcm\Message $message */
88
        foreach ($this->getPushMessages($notification) as $message) {
89
            $time = new \DateTime('now', new \DateTimeZone('UTC'));
90
91
            try {
92
                $pushResponses = $client->send($message)->getResults();
93
94
                foreach ($message->getRegistrationIds() as $token) {
95
                    $result = new Result($token, $time);
96
97
                    if (!array_key_exists($token, $pushResponses)
98
                        || array_key_exists('error', $pushResponses[$token])
99
                    ) {
100
                        $result->setStatus(Result::STATUS_ERROR);
101
102
                        $errorCode = array_key_exists($token, $pushResponses)
103
                            ? $pushResponses[$token]['error']
104
                            : 'UnknownError';
105
                        $result->setStatusMessage(self::$statusCodes[$errorCode]);
106
                    }
107
108
                    $notification->addResult($result);
109
                }
110
            // @codeCoverageIgnoreStart
111
            } catch (GcmRuntimeException $exception) {
112
                foreach ($message->getRegistrationIds() as $token) {
113
                    $notification->addResult(new Result($token, $time, Result::STATUS_ERROR, $exception->getMessage()));
114
                }
115
            }
116
            // @codeCoverageIgnoreEnd
117
        }
118
    }
119
120
    /**
121
     * Get opened client.
122
     *
123
     * @return \ZendService\Google\Gcm\Client
124
     */
125
    protected function getPushClient()
126
    {
127
        if ($this->pushClient === null) {
128
            $this->pushClient = $this->builder->buildPushClient($this->getParameter('api_key'));
129
        }
130
131
        return $this->pushClient;
132
    }
133
134
    /**
135
     * Get push service formatted messages.
136
     *
137
     * @param \Jgut\Tify\Notification $notification
138
     *
139
     * @throws \InvalidArgumentException
140
     * @throws \RuntimeException
141
     *
142
     * @return \ZendService\Google\Gcm\Message
0 ignored issues
show
Documentation introduced by
Should the return type not be \Generator?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
143
     */
144
    protected function getPushMessages(Notification $notification)
145
    {
146
        /* @var \Jgut\Tify\Receiver\GcmReceiver[] $receivers */
147
        $receivers = array_filter(
148
            $notification->getReceivers(),
149
            function ($receiver) {
150
                return $receiver instanceof GcmReceiver;
151
            }
152
        );
153
154
        $tokens = array_map(
155
            function ($receiver) {
156
                /* @var \Jgut\Tify\Receiver\GcmReceiver $receiver */
157
                return $receiver->getToken();
158
            },
159
            $receivers
160
        );
161
162
        foreach (array_chunk($tokens, 100) as $tokensRange) {
163
            yield $this->builder->buildPushMessage($tokensRange, $notification);
164
        }
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170
    protected function getDefinedParameters()
171
    {
172
        return ['api_key'];
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    protected function getRequiredParameters()
179
    {
180
        return ['api_key'];
181
    }
182
}
183