|
1
|
|
|
<?php |
|
2
|
|
|
declare(strict_types=1); |
|
3
|
|
|
|
|
4
|
|
|
namespace SKien\PNServer; |
|
5
|
|
|
|
|
6
|
|
|
/** |
|
7
|
|
|
* Class representing payload for push notification. |
|
8
|
|
|
* |
|
9
|
|
|
* the class provides functions to define the properties of a push |
|
10
|
|
|
* notification. As result, a JSON string is generated to push to the client. |
|
11
|
|
|
* |
|
12
|
|
|
* Most properties directly map the showNotification() options and are |
|
13
|
|
|
* passed on directly within the service worker. |
|
14
|
|
|
* |
|
15
|
|
|
* @package PNServer |
|
16
|
|
|
* @author Stefanius <[email protected]> |
|
17
|
|
|
* @copyright MIT License - see the LICENSE file for details |
|
18
|
|
|
*/ |
|
19
|
|
|
class PNPayload |
|
20
|
|
|
{ |
|
21
|
|
|
use PNServerHelper; |
|
22
|
|
|
|
|
23
|
|
|
/** @var array<mixed> */ |
|
24
|
|
|
protected array $aPayload; |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* Create instance of payload with title, text and icon to display. |
|
28
|
|
|
* - title should be short and meaningfull. |
|
29
|
|
|
* - The text should not increase 200 characters - the different browsers and |
|
30
|
|
|
* platforms limit the display differently (partly according to the number of |
|
31
|
|
|
* lines, others according to the number of characters) |
|
32
|
|
|
* - icon should be square (if not, some browsers/platforms cut a square). There |
|
33
|
|
|
* is no exact specification for the 'optimal' size, 64dp (px * device pixel ratio) |
|
34
|
|
|
* should be a good decision (... 192px for highest device pixel ratio) |
|
35
|
|
|
* |
|
36
|
|
|
* @param string $strTitle Title to display |
|
37
|
|
|
* @param string $strText A string representing an extra content to display within the notification. |
|
38
|
|
|
* @param string $strIcon containing the URL of an image to be used as an icon by the notification. |
|
39
|
|
|
*/ |
|
40
|
|
|
public function __construct(string $strTitle, ?string $strText = null, ?string $strIcon = null) |
|
41
|
|
|
{ |
|
42
|
|
|
$this->aPayload = array( |
|
43
|
|
|
'title' => $strTitle, |
|
44
|
|
|
'opt' => array( |
|
45
|
|
|
'body' => $strText, |
|
46
|
|
|
'icon' => $strIcon, |
|
47
|
|
|
), |
|
48
|
|
|
); |
|
49
|
|
|
} |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* Note: the URL is no part of the JS showNotification() - Options! |
|
53
|
|
|
* @param string $strURL URL to open when user click on the notification. |
|
54
|
|
|
*/ |
|
55
|
|
|
public function setURL(string $strURL) : void |
|
56
|
|
|
{ |
|
57
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
58
|
|
|
if (!isset($this->aPayload['opt']['data']) || !is_array($this->aPayload['opt']['data'])) { |
|
59
|
|
|
$this->aPayload['opt']['data'] = array(); |
|
60
|
|
|
} |
|
61
|
|
|
$this->aPayload['opt']['data']['url'] = $strURL; |
|
62
|
|
|
} |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* An ID for a given notification that allows you to find, replace, or remove the notification using |
|
67
|
|
|
* a script if necessary. |
|
68
|
|
|
* If set, multiple notifications with the same tag will only reappear if $bReNotify is set to true. |
|
69
|
|
|
* Usualy the last notification with same tag is displayed in this case. |
|
70
|
|
|
* |
|
71
|
|
|
* @param string $strTag |
|
72
|
|
|
* @param bool $bReNotify |
|
73
|
|
|
*/ |
|
74
|
|
|
public function setTag(string $strTag, bool $bReNotify = false) : void |
|
75
|
|
|
{ |
|
76
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
77
|
|
|
$this->aPayload['opt']['tag'] = $strTag; |
|
78
|
|
|
$this->aPayload['opt']['renotify'] = $bReNotify; |
|
79
|
|
|
} |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* containing the URL of an larger image to be displayed in the notification. |
|
84
|
|
|
* Size, position and cropping vary with the different browsers and platforms |
|
85
|
|
|
* @param string $strImage |
|
86
|
|
|
*/ |
|
87
|
|
|
public function setImage(string $strImage) : void |
|
88
|
|
|
{ |
|
89
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
90
|
|
|
$this->aPayload['opt']['image'] = $strImage; |
|
91
|
|
|
} |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* containing the URL of an badge assigend to the notification. |
|
96
|
|
|
* The badge is a small monochrome icon that is used to portray a little |
|
97
|
|
|
* more information to the user about where the notification is from. |
|
98
|
|
|
* So far I have only found Chrome for Android that supports the badge... |
|
99
|
|
|
* ... in most cases the browsers icon is displayed. |
|
100
|
|
|
* |
|
101
|
|
|
* @param string $strBadge |
|
102
|
|
|
*/ |
|
103
|
|
|
public function setBadge(string $strBadge) : void |
|
104
|
|
|
{ |
|
105
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
106
|
|
|
$this->aPayload['opt']['badge'] = $strBadge; |
|
107
|
|
|
} |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
/** |
|
111
|
|
|
* Add action to display in the notification. |
|
112
|
|
|
* |
|
113
|
|
|
* The count of action that can be displayed vary between browser/platform. On |
|
114
|
|
|
* the client it can be detected with javascript: Notification.maxActions |
|
115
|
|
|
* |
|
116
|
|
|
* Appropriate responses have to be implemented within the notificationclick event. |
|
117
|
|
|
* the event.action property contains the $strAction clicked on |
|
118
|
|
|
* |
|
119
|
|
|
* @param string $strAction identifying a user action to be displayed on the notification. |
|
120
|
|
|
* @param string $strTitle containing action text to be shown to the user. |
|
121
|
|
|
* @param string $strIcon containing the URL of an icon to display with the action. |
|
122
|
|
|
* @param string $strCustom custom info - not part of the showNotification()- Options! |
|
123
|
|
|
*/ |
|
124
|
|
|
public function addAction(string $strAction, string $strTitle, ?string $strIcon = null, string $strCustom = '') : void |
|
125
|
|
|
{ |
|
126
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
127
|
|
|
if (!isset($this->aPayload['opt']['actions']) || !is_array($this->aPayload['opt']['actions'])) { |
|
128
|
|
|
$this->aPayload['opt']['actions'] = array(); |
|
129
|
|
|
} |
|
130
|
|
|
$this->aPayload['opt']['actions'][] = array('action' => $strAction, 'title' => $strTitle, 'icon' => $strIcon, 'custom' => $strCustom); |
|
131
|
|
|
} |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Set the time when the notification was created. |
|
136
|
|
|
* It can be used to indicate the time at which a notification is actual. For example, this could |
|
137
|
|
|
* be in the past when a notification is used for a message that couldn’t immediately be delivered |
|
138
|
|
|
* because the device was offline, or in the future for a meeting that is about to start. |
|
139
|
|
|
* |
|
140
|
|
|
* @param mixed $timestamp DateTime object, UNIX timestamp or English textual datetime description |
|
141
|
|
|
*/ |
|
142
|
|
|
public function setTimestamp($timestamp) : void |
|
143
|
|
|
{ |
|
144
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
145
|
|
|
$iTimestamp = $timestamp; |
|
146
|
|
|
if (self::className($timestamp) == 'DateTime') { |
|
147
|
|
|
// DateTime -object |
|
148
|
|
|
$iTimestamp = $timestamp->getTimestamp(); |
|
149
|
|
|
} else if (is_string($timestamp)) { |
|
150
|
|
|
// string |
|
151
|
|
|
$iTimestamp = strtotime($timestamp); |
|
152
|
|
|
} |
|
153
|
|
|
// timestamp in milliseconds! |
|
154
|
|
|
$this->aPayload['opt']['timestamp'] = bcmul((string) $iTimestamp, '1000'); |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* Indicates that on devices with sufficiently large screens, a notification should remain active until |
|
160
|
|
|
* the user clicks or dismisses it. If this value is absent or false, the desktop version of Chrome |
|
161
|
|
|
* will auto-minimize notifications after approximately twenty seconds. Implementation depends on |
|
162
|
|
|
* browser and plattform. |
|
163
|
|
|
* |
|
164
|
|
|
* @param bool $bSet |
|
165
|
|
|
*/ |
|
166
|
|
|
public function requireInteraction(bool $bSet = true) : void |
|
167
|
|
|
{ |
|
168
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
169
|
|
|
$this->aPayload['opt']['requireInteraction'] = $bSet; |
|
170
|
|
|
} |
|
171
|
|
|
} |
|
172
|
|
|
|
|
173
|
|
|
/** |
|
174
|
|
|
* Indicates that no sounds or vibrations should be made. |
|
175
|
|
|
* If this 'mute' function is activated, a previously set vibration is reset to prevent a TypeError exception. |
|
176
|
|
|
* @param bool $bSet |
|
177
|
|
|
*/ |
|
178
|
|
|
public function setSilent(bool $bSet = true) : void |
|
179
|
|
|
{ |
|
180
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
181
|
|
|
$this->aPayload['opt']['silent'] = $bSet; |
|
182
|
|
|
if ($bSet && isset($this->aPayload['opt']['vibrate'])) { |
|
183
|
|
|
// silent=true and defined vibation causes TypeError |
|
184
|
|
|
unset($this->aPayload['opt']['vibrate']); |
|
185
|
|
|
} |
|
186
|
|
|
} |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
|
/** |
|
190
|
|
|
* A vibration pattern to run with the display of the notification. |
|
191
|
|
|
* A vibration pattern can be an array with as few as one member. The values are times in milliseconds |
|
192
|
|
|
* where the even indices (0, 2, 4, etc.) indicate how long to vibrate and the odd indices indicate |
|
193
|
|
|
* how long to pause. For example, [300, 100, 400] would vibrate 300ms, pause 100ms, then vibrate 400ms. |
|
194
|
|
|
* |
|
195
|
|
|
* @param array<int> $aPattern |
|
196
|
|
|
*/ |
|
197
|
|
|
public function setVibration(array $aPattern) : void |
|
198
|
|
|
{ |
|
199
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
200
|
|
|
$this->aPayload['opt']['vibrate'] = $aPattern; |
|
201
|
|
|
if (isset($this->aPayload['opt']['silent'])) { |
|
202
|
|
|
// silent=true and vibation pattern causes TypeError |
|
203
|
|
|
$this->aPayload['opt']['silent'] = false; |
|
204
|
|
|
} |
|
205
|
|
|
} |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
/** |
|
209
|
|
|
* containing the URL of an sound - file (mp3 or wav). |
|
210
|
|
|
* currently not found any browser supports sounds |
|
211
|
|
|
* @param string $strSound |
|
212
|
|
|
*/ |
|
213
|
|
|
public function setSound(string $strSound) : void |
|
214
|
|
|
{ |
|
215
|
|
|
if (is_array($this->aPayload) && isset($this->aPayload['opt']) && is_array($this->aPayload['opt'])) { |
|
216
|
|
|
$this->aPayload['opt']['sound'] = $strSound; |
|
217
|
|
|
} |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
/** |
|
221
|
|
|
* Get the Payload data as array |
|
222
|
|
|
* @return array<mixed> |
|
223
|
|
|
*/ |
|
224
|
|
|
public function getPayload() : array |
|
225
|
|
|
{ |
|
226
|
|
|
return $this->aPayload; |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Convert payload dasta to JSON string. |
|
231
|
|
|
* @return string JSON string representing payloal |
|
232
|
|
|
*/ |
|
233
|
|
|
public function toJSON() : string |
|
234
|
|
|
{ |
|
235
|
|
|
$strJson = json_encode($this->aPayload); |
|
236
|
|
|
return utf8_encode($strJson !== false ? $strJson : ''); |
|
237
|
|
|
} |
|
238
|
|
|
|
|
239
|
|
|
/** |
|
240
|
|
|
* @return string JSON string representing payloal |
|
241
|
|
|
*/ |
|
242
|
|
|
public function __toString() : string |
|
243
|
|
|
{ |
|
244
|
|
|
return $this->toJSON(); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
} |
|
248
|
|
|
|