Skip to content

Commit 02babec

Browse files
authored
Merge pull request #79 from iMattPro/updates
Updates!
2 parents 674b9cb + fe74605 commit 02babec

7 files changed

Lines changed: 155 additions & 42 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This is the repository for the development of the phpBB Browser Push Notifications extension.
44

5-
[![Build Status](https://github.com/phpbb-extensions/webpushnotifications/workflows/Tests/badge.svg)](https://github.com/phpbb-extensions/webpushnotifications/actions)
5+
[![Build Status](https://github.com/phpbb-extensions/webpushnotifications/actions/workflows/tests.yml/badge.svg)](https://github.com/phpbb-extensions/webpushnotifications/actions)
66

77
An official phpBB extension that allows board users to receive browser-based push notifications.
88

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "phpbb-extension",
44
"description": "An official phpBB extension that allows board users to receive browser-based push notifications.",
55
"homepage": "https://www.phpbb.com/customise/db/extension/webpushnotifications/",
6-
"version": "1.0.0",
6+
"version": "1.0.1-dev",
77
"license": "GPL-2.0-only",
88
"authors": [
99
{

controller/manifest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function handle(): JsonResponse
6565

6666
$manifest = [
6767
'name' => $this->config['sitename'],
68-
'short_name' => $this->config['pwa_short_name'] ?: substr($this->config['sitename'], 0, 12),
68+
'short_name' => $this->config['pwa_short_name'] ?: utf8_substr(preg_replace('/[^\x20-\x7E]/', '', $this->config['sitename']), 0, 12),
6969
'display' => 'standalone',
7070
'orientation' => 'portrait',
7171
'dir' => $this->language->lang('DIRECTION'),

event/listener.php

Lines changed: 95 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public function pwa_manifest()
142142
$this->template->assign_vars([
143143
'U_MANIFEST_URL' => $this->controller_helper->route('phpbb_webpushnotifications_manifest_controller'),
144144
'U_TOUCH_ICON' => $this->config['pwa_icon_small'],
145+
'SHORT_SITE_NAME' => $this->config['pwa_short_name'] ?: $this->get_shortname($this->config['sitename']),
145146
]);
146147
}
147148

@@ -159,9 +160,9 @@ public function acp_pwa_options($event)
159160

160161
$my_config_vars = [
161162
'legend_pwa_settings'=> 'PWA_SETTINGS',
162-
'pwa_short_name' => ['lang' => 'PWA_SHORT_NAME', 'validate' => 'string', 'type' => 'text:40:12', 'explain' => true],
163-
'pwa_icon_small' => ['lang' => 'PWA_ICON_SMALL', 'validate' => 'pwa_options', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
164-
'pwa_icon_large' => ['lang' => 'PWA_ICON_LARGE', 'validate' => 'pwa_options', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
163+
'pwa_short_name' => ['lang' => 'PWA_SHORT_NAME', 'validate' => 'pwa_options:string', 'type' => 'custom', 'function' => [$this, 'pwa_short_sitename'], 'explain' => true],
164+
'pwa_icon_small' => ['lang' => 'PWA_ICON_SMALL', 'validate' => 'pwa_options:icons', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
165+
'pwa_icon_large' => ['lang' => 'PWA_ICON_LARGE', 'validate' => 'pwa_options:icons', 'type' => 'custom', 'function' => [$this, 'pwa_icon_name'], 'explain' => true],
165166
];
166167

167168
$event->update_subarray('display_vars', 'vars', phpbb_insert_config_array($event['display_vars']['vars'], $my_config_vars, ['before' => 'legend4']));
@@ -180,6 +181,20 @@ public function pwa_icon_name($value, $key)
180181
return $this->config['icons_path'] . '/<input id="' . $key . '" type="text" size="40" maxlength="255" name="config[' . $key . ']" value="' . $value . '">';
181182
}
182183

184+
/**
185+
* Return HTML for PWA short site name setting
186+
*
187+
* @param string $value Value of config
188+
* @param string $key Name of config
189+
* @return string
190+
*/
191+
public function pwa_short_sitename($value, $key)
192+
{
193+
$placeholder = $this->get_shortname($this->config['sitename']);
194+
195+
return '<input id="' . $key . '" type="text" size="40" maxlength="12" name="config[' . $key . ']" value="' . $value . '" placeholder="' . $placeholder . '">';
196+
}
197+
183198
/**
184199
* Validate PWA options
185200
*
@@ -188,40 +203,79 @@ public function pwa_icon_name($value, $key)
188203
*/
189204
public function validate_pwa_options($event)
190205
{
191-
// Ignore validation if icon fields are empty
192-
if ($event['config_definition']['validate'] !== 'pwa_options' || (empty($event['cfg_array']['pwa_icon_small']) && empty($event['cfg_array']['pwa_icon_large'])))
193-
{
194-
return;
195-
}
206+
$type = 0;
207+
$mode = 1;
196208

197-
$value = $event['cfg_array'][$event['config_name']];
209+
$validator = explode(':', $event['config_definition']['validate']);
198210

199-
// Don't allow empty values, if one icon is set, both must be set.
200-
if (empty($value))
211+
if ($validator[$type] !== 'pwa_options')
201212
{
202-
$this->add_error($event, 'PWA_IMAGE_NOT_PROVIDED', $this->language->lang(strtoupper($event['config_name'])));
203213
return;
204214
}
205215

206-
// Check if image is valid
207-
$image = $this->root_path . $this->config['icons_path'] . '/' . $value;
208-
$image_info = $this->imagesize->getImageSize($image);
209-
if ($image_info !== false)
216+
switch ($validator[$mode])
210217
{
211-
if (($event['config_name'] === 'pwa_icon_small' && $image_info['width'] !== 192 && $image_info['height'] !== 192) ||
212-
($event['config_name'] === 'pwa_icon_large' && $image_info['width'] !== 512 && $image_info['height'] !== 512))
213-
{
214-
$this->add_error($event, 'PWA_ICON_SIZE_INVALID', $value);
215-
}
216-
217-
if ($image_info['type'] !== IMAGETYPE_PNG)
218-
{
219-
$this->add_error($event, 'PWA_ICON_MIME_INVALID', $value);
220-
}
221-
}
222-
else
223-
{
224-
$this->add_error($event, 'PWA_IMAGE_INVALID', $value);
218+
case 'string':
219+
// Ignore validation if icon fields are empty
220+
if (empty($event['cfg_array']['pwa_short_name']))
221+
{
222+
return;
223+
}
224+
225+
$short_name = $event['cfg_array']['pwa_short_name'];
226+
227+
// Do not allow multibyte characters or emoji
228+
if (strlen($short_name) !== mb_strlen($short_name, 'UTF-8'))
229+
{
230+
$this->add_error($event, 'PWA_SHORT_NAME_INVALID');
231+
return;
232+
}
233+
234+
// Do not allow strings longer than 12 characters
235+
if (strlen($short_name) > 12)
236+
{
237+
$this->add_error($event, 'PWA_SHORT_NAME_INVALID');
238+
return;
239+
}
240+
break;
241+
242+
case 'icons':
243+
// Ignore validation if icon fields are empty
244+
if (empty($event['cfg_array']['pwa_icon_small']) && empty($event['cfg_array']['pwa_icon_large']))
245+
{
246+
return;
247+
}
248+
249+
$value = $event['cfg_array'][$event['config_name']];
250+
251+
// Don't allow empty values, if one icon is set, both must be set.
252+
if (empty($value))
253+
{
254+
$this->add_error($event, 'PWA_IMAGE_NOT_PROVIDED', $this->language->lang(strtoupper($event['config_name'])));
255+
return;
256+
}
257+
258+
// Check if image is valid
259+
$image = $this->root_path . $this->config['icons_path'] . '/' . $value;
260+
$image_info = $this->imagesize->getImageSize($image);
261+
if ($image_info !== false)
262+
{
263+
if (($event['config_name'] === 'pwa_icon_small' && $image_info['width'] !== 192 && $image_info['height'] !== 192) ||
264+
($event['config_name'] === 'pwa_icon_large' && $image_info['width'] !== 512 && $image_info['height'] !== 512))
265+
{
266+
$this->add_error($event, 'PWA_ICON_SIZE_INVALID', $value);
267+
}
268+
269+
if ($image_info['type'] !== IMAGETYPE_PNG)
270+
{
271+
$this->add_error($event, 'PWA_ICON_MIME_INVALID', $value);
272+
}
273+
}
274+
else
275+
{
276+
$this->add_error($event, 'PWA_IMAGE_INVALID', $value);
277+
}
278+
break;
225279
}
226280
}
227281

@@ -251,4 +305,15 @@ protected function can_use_notifications()
251305
&& ANONYMOUS !== $this->user->id()
252306
&& USER_IGNORE !== (int) $this->user->data['user_type'];
253307
}
308+
309+
/**
310+
* Get short name from a string (strip out multibyte characters and trim to 12 characters)
311+
*
312+
* @param string $name
313+
* @return string 12 max characters string
314+
*/
315+
protected function get_shortname($name)
316+
{
317+
return utf8_substr(preg_replace('/[^\x20-\x7E]/', '', $name), 0, 12);
318+
}
254319
}

language/en/webpushnotifications_common_acp.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
$lang = array_merge($lang, [
4141
'PWA_SETTINGS' => 'Progressive web application options',
4242
'PWA_SHORT_NAME' => 'Short site name',
43-
'PWA_SHORT_NAME_EXPLAIN' => 'Your site name in 12 characters or less, which may be used as a label for an icon on a mobile device’s home screen.',
43+
'PWA_SHORT_NAME_EXPLAIN' => 'Your site name in 12 characters or fewer, which may be used as a label for an icon on a mobile device’s home screen. (If this field is left empty, the first 12 characters of the <samp>Site name</samp> will be used.)',
44+
'PWA_SHORT_NAME_INVALID' => '“Short site name” contains illegal characters or exceeds the 12 character limit.',
4445
'PWA_ICON_SMALL' => 'Small mobile device icon',
4546
'PWA_ICON_SMALL_EXPLAIN' => 'File name of a 192px x 192px PNG image. This file must be uploaded to your board’s <samp>icons</samp> directory.',
4647
'PWA_ICON_LARGE' => 'Large mobile device icon',

styles/all/template/event/overall_header_head_append.html

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1+
<!-- Ensure the app can be added to the home screen on iOS -->
12
<meta name="apple-mobile-web-app-capable" content="yes">
3+
4+
<!-- Ensure the app can be added to the home screen on Chrome -->
5+
<meta name="mobile-web-app-capable" content="yes">
6+
7+
<!-- Sets the status bar style when the app is launched from the home screen on iOS -->
28
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
3-
<meta name="apple-mobile-web-app-title" content="{{ SITENAME }}">
9+
10+
<!-- The name of your app when saved to the iOS home screen -->
11+
<meta name="apple-mobile-web-app-title" content="{{ SHORT_SITE_NAME }}">
12+
13+
<!-- The name of your app when saved to other browsers and platforms -->
14+
<meta name="application-name" content="{{ SHORT_SITE_NAME }}">
15+
16+
<!-- Link to app's configuration manifest -->
417
<link rel="manifest" href="{{ U_MANIFEST_URL }}">
18+
19+
<!-- App icon for iOS, a fallback to icons defined in the manifest -->
520
{% if U_TOUCH_ICON %}<link rel="apple-touch-icon" href="{{ T_ICONS_PATH ~ U_TOUCH_ICON }}">{% endif %}
621

722
{% if NOTIFICATIONS_WEBPUSH_ENABLE %}

tests/event/listener_test.php

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public function test_load_template_data($user_id, $method_data, $subscriptions,
262262
public function test_pwa_manifest()
263263
{
264264
$this->config['pwa_icon_small'] = 'icon-192x192.png';
265+
$this->config['pwa_short_name'] = 'Test';
265266

266267
$this->set_listener();
267268

@@ -270,6 +271,7 @@ public function test_pwa_manifest()
270271
->with([
271272
'U_MANIFEST_URL' => $this->controller_helper->route('phpbb_webpushnotifications_manifest_controller'),
272273
'U_TOUCH_ICON' => 'icon-192x192.png',
274+
'SHORT_SITE_NAME' => 'Test',
273275
]);
274276

275277
$dispatcher = new \phpbb\event\dispatcher();
@@ -332,48 +334,78 @@ public function validate_pwa_options_data()
332334
{
333335
return [
334336
[
337+
'pwa_options:icons',
335338
['pwa_icon_small' => '192.png', 'pwa_icon_large' => '512.png'],
336339
[],
337340
],
338341
[
342+
'pwa_options:icons',
339343
['pwa_icon_small' => '1.png', 'pwa_icon_large' => '512.png'],
340344
['PWA_ICON_SIZE_INVALID'],
341345
],
342346
[
347+
'pwa_options:icons',
343348
['pwa_icon_small' => '1.png', 'pwa_icon_large' => '12.png'],
344349
['PWA_ICON_SIZE_INVALID'],
345350
],
346351
[
352+
'pwa_options:icons',
347353
['pwa_icon_small' => '192.jpg', 'pwa_icon_large' => '512.gif'],
348354
['PWA_ICON_MIME_INVALID'],
349355
],
350356
[
357+
'pwa_options:icons',
351358
['pwa_icon_small' => '', 'pwa_icon_large' => ''],
352359
[],
353360
],
361+
[
362+
'pwa_options:string',
363+
['pwa_short_name' => 'foo'],
364+
[],
365+
],
366+
[
367+
'pwa_options:string',
368+
['pwa_short_name' => ''],
369+
[],
370+
],
371+
[
372+
'pwa_options:string',
373+
['pwa_short_name' => 'foo❤️'],
374+
['PWA_SHORT_NAME_INVALID'],
375+
],
376+
[
377+
'pwa_options:string',
378+
['pwa_short_name' => str_repeat('a', 50)],
379+
['PWA_SHORT_NAME_INVALID'],
380+
],
354381
];
355382
}
356383

357384
/**
358385
* @dataProvider validate_pwa_options_data
359386
*/
360-
public function test_validate_pwa_options($cfg_array, $expected_error)
387+
public function test_validate_pwa_options($validate, $cfg_array, $expected_error)
361388
{
362389
$this->config['icons_path'] = 'images/icons';
363390
$config_name = key($cfg_array);
364-
$config_definition = ['validate' => 'pwa_options'];
365-
$small_image = $cfg_array['pwa_icon_small'] ? explode('.', $cfg_array['pwa_icon_small']) : ['', ''];
366-
$large_image = $cfg_array['pwa_icon_large'] ? explode('.', $cfg_array['pwa_icon_large']) : ['', ''];
391+
$config_definition = ['validate' => $validate];
392+
393+
$pwa_icon_small = isset($cfg_array['pwa_icon_small']) ? $cfg_array['pwa_icon_small'] : '';
394+
$pwa_icon_large = isset($cfg_array['pwa_icon_large']) ? $cfg_array['pwa_icon_large'] : '';
395+
396+
[$small_image_name, $small_image_ext] = $pwa_icon_small ? explode('.', $pwa_icon_small, 2) : ['', ''];
397+
[$large_image_name, $large_image_ext] = $pwa_icon_large ? explode('.', $pwa_icon_large, 2) : ['', ''];
398+
367399
$error = [];
368400

369401
$this->set_listener();
370402

371-
$this->imagesize->expects(self::any())
403+
$this->imagesize->expects($pwa_icon_small && $pwa_icon_large ? self::once() : self::never())
372404
->method('getImageSize')
373405
->willReturnMap([
374406
[$this->root_path . $this->config['icons_path'] . '/', '', false],
375-
[$this->root_path . $this->config['icons_path'] . '/' . $cfg_array['pwa_icon_small'], '', ['width' => (int) $small_image[0], 'height' => (int) $small_image[0], 'type' => $small_image[1] === 'png' ? IMAGETYPE_PNG : IMAGETYPE_UNKNOWN]],
376-
[$this->root_path . $this->config['icons_path'] . '/' . $cfg_array['pwa_icon_large'], '', ['width' => (int) $large_image[0], 'height' => (int) $large_image[0], 'type' => $large_image[1] === 'png' ? IMAGETYPE_PNG : IMAGETYPE_UNKNOWN]],
407+
[$this->root_path . $this->config['icons_path'] . '/' . $pwa_icon_small, '', ['width' => (int) $small_image_name, 'height' => (int) $small_image_name, 'type' => $small_image_ext === 'png' ? IMAGETYPE_PNG : IMAGETYPE_UNKNOWN]],
408+
[$this->root_path . $this->config['icons_path'] . '/' . $pwa_icon_large, '', ['width' => (int) $large_image_name, 'height' => (int) $large_image_name, 'type' => $large_image_ext === 'png' ? IMAGETYPE_PNG : IMAGETYPE_UNKNOWN]],
377409
]);
378410

379411
$dispatcher = new \phpbb\event\dispatcher();

0 commit comments

Comments
 (0)