Skip to content

Commit 6afe99f

Browse files
authored
Merge pull request #130 from iMattPro/pwa-enhanced
Add PWA enhancements
2 parents 388da99 + 3144ca8 commit 6afe99f

31 files changed

Lines changed: 1714 additions & 492 deletions

acp/wpn_acp_info.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public function module()
2323
'auth' => 'ext_phpbb/webpushnotifications && acl_a_server',
2424
'cat' => ['ACP_CLIENT_COMMUNICATION']
2525
],
26+
'pwa' => [
27+
'title' => 'ACP_WEBPUSH_PWA_SETTINGS',
28+
'auth' => 'ext_phpbb/webpushnotifications && acl_a_board',
29+
'cat' => ['ACP_CLIENT_COMMUNICATION']
30+
],
2631
],
2732
];
2833
}

acp/wpn_acp_module.php

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,32 @@
1717
use phpbb\symfony_request;
1818
use phpbb\template\template;
1919
use phpbb\user;
20+
use phpbb\webpushnotifications\ext;
2021

2122
class wpn_acp_module
2223
{
2324
public $page_title;
2425
public $tpl_name;
2526
public $u_action;
2627

28+
/** @var \phpbb\cache\service */
29+
protected $cache;
30+
2731
/** @var config $config */
2832
protected $config;
2933

34+
/** @var \phpbb\db\driver\driver_interface */
35+
protected $db;
36+
3037
/** @var language $lang */
3138
protected $lang;
3239

3340
/** @var log $log */
3441
protected $log;
3542

43+
/** @var \FastImageSize\FastImageSize $imagesize */
44+
protected $imagesize;
45+
3646
/** @var request $request */
3747
protected $request;
3848

@@ -45,6 +55,9 @@ class wpn_acp_module
4555
/** @var user $user */
4656
protected $user;
4757

58+
/** @var string */
59+
protected $root_path;
60+
4861
/** @var array $errors */
4962
protected $errors = [];
5063

@@ -62,13 +75,17 @@ public function main($id, $mode)
6275
{
6376
global $phpbb_container;
6477

78+
$this->cache = $phpbb_container->get('cache');
6579
$this->config = $phpbb_container->get('config');
80+
$this->db = $phpbb_container->get('dbal.conn');
81+
$this->imagesize = $phpbb_container->get('upload_imagesize');
6682
$this->lang = $phpbb_container->get('language');
6783
$this->log = $phpbb_container->get('log');
6884
$this->request = $phpbb_container->get('request');
6985
$this->symfony_request = $phpbb_container->get('symfony_request');
7086
$this->template = $phpbb_container->get('template');
7187
$this->user = $phpbb_container->get('user');
88+
$this->root_path = $phpbb_container->getParameter('core.root_path');
7289

7390
$form_key = 'phpbb/webpushnotifications';
7491
add_form_key($form_key);
@@ -95,6 +112,26 @@ public function main($id, $mode)
95112

96113
$this->display_settings();
97114
}
115+
else if ($mode === 'pwa')
116+
{
117+
$this->tpl_name = 'wpn_acp_pwa';
118+
119+
$this->lang->add_lang('webpushnotifications_module_acp', 'phpbb/webpushnotifications');
120+
121+
$this->page_title = $this->lang->lang('ACP_WEBPUSH_PWA_SETTINGS');
122+
123+
if ($this->request->is_set_post('submit'))
124+
{
125+
if (!check_form_key($form_key))
126+
{
127+
trigger_error($this->lang->lang('FORM_INVALID'), E_USER_WARNING);
128+
}
129+
130+
$this->save_pwa_settings();
131+
}
132+
133+
$this->display_pwa_settings();
134+
}
98135
}
99136

100137
/**
@@ -164,6 +201,218 @@ public function save_settings()
164201
trigger_error($this->lang->lang('CONFIG_UPDATED') . adm_back_link($this->u_action), E_USER_NOTICE);
165202
}
166203

204+
/**
205+
* Add PWA settings template vars to the form
206+
*/
207+
public function display_pwa_settings()
208+
{
209+
$this->template->assign_vars([
210+
'S_PWA_SHOW_INSTALL_BANNER' => (bool) $this->config['pwa_show_install_banner'],
211+
'PWA_SHORT_NAME' => $this->config['pwa_short_name'],
212+
'PWA_ICON_SMALL' => $this->config['pwa_icon_small'],
213+
'PWA_ICON_LARGE' => $this->config['pwa_icon_large'],
214+
'STYLES' => $this->get_styles(),
215+
'U_ACTION' => $this->u_action,
216+
]);
217+
218+
$this->display_errors();
219+
}
220+
221+
/**
222+
* Save PWA settings data to the database
223+
*
224+
* @return void
225+
*/
226+
public function save_pwa_settings()
227+
{
228+
$config_array = $this->request->variable('config', ['' => ''], true);
229+
230+
$config_array['pwa_short_name'] = $config_array['pwa_short_name'] ?? '';
231+
$config_array['pwa_icon_small'] = $config_array['pwa_icon_small'] ?? '';
232+
$config_array['pwa_icon_large'] = $config_array['pwa_icon_large'] ?? '';
233+
234+
$this->validate_pwa_short_name($config_array['pwa_short_name']);
235+
$this->validate_pwa_icons($config_array['pwa_icon_small'], $config_array['pwa_icon_large']);
236+
237+
$styles = $this->get_styles();
238+
$updates = [];
239+
foreach ($styles as $row)
240+
{
241+
$style_id = $row['style_id'];
242+
$pwa_bg_color = $this->request->variable('pwa_bg_color_' . $style_id, '');
243+
$pwa_theme_color = $this->request->variable('pwa_theme_color_' . $style_id, '');
244+
245+
$updates[$style_id] = [
246+
'pwa_bg_color' => $this->validate_hex_color($pwa_bg_color) ? $pwa_bg_color : $row['pwa_bg_color'],
247+
'pwa_theme_color' => $this->validate_hex_color($pwa_theme_color) ? $pwa_theme_color : $row['pwa_theme_color'],
248+
];
249+
}
250+
251+
if ($this->display_errors())
252+
{
253+
return;
254+
}
255+
256+
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_WEBPUSH');
257+
258+
// Ensure 4-byte emoji can be stored correctly
259+
$config_array['pwa_short_name'] = utf8_encode_ucr($config_array['pwa_short_name']);
260+
261+
foreach ([
262+
'pwa_short_name',
263+
'pwa_icon_small',
264+
'pwa_icon_large',
265+
'pwa_show_install_banner',
266+
] as $config_name)
267+
{
268+
$this->config->set($config_name, $config_array[$config_name] ?? 0);
269+
}
270+
271+
$this->set_styles($updates);
272+
273+
trigger_error($this->lang->lang('CONFIG_UPDATED') . adm_back_link($this->u_action), E_USER_NOTICE);
274+
}
275+
276+
/**
277+
* Validate PWA short site name
278+
*/
279+
protected function validate_pwa_short_name(string $short_name): void
280+
{
281+
if ($short_name === '')
282+
{
283+
return;
284+
}
285+
286+
$short_name = ext::decode_entities($short_name, ENT_QUOTES);
287+
if (utf8_strlen($short_name) > 12)
288+
{
289+
$this->errors[] = $this->lang->lang('PWA_SHORT_NAME_INVALID');
290+
}
291+
}
292+
293+
/**
294+
* Validate PWA icon filenames and dimensions
295+
*/
296+
protected function validate_pwa_icons(string $small_icon, string $large_icon): void
297+
{
298+
if ($small_icon === '' && $large_icon === '')
299+
{
300+
return;
301+
}
302+
303+
if ($small_icon === '')
304+
{
305+
$this->errors[] = $this->lang->lang('PWA_ICON_NOT_PROVIDED', $this->lang->lang('PWA_ICON_SMALL'));
306+
return;
307+
}
308+
309+
if ($large_icon === '')
310+
{
311+
$this->errors[] = $this->lang->lang('PWA_ICON_NOT_PROVIDED', $this->lang->lang('PWA_ICON_LARGE'));
312+
return;
313+
}
314+
315+
$this->validate_pwa_icon($small_icon, 192);
316+
$this->validate_pwa_icon($large_icon, 512);
317+
}
318+
319+
/**
320+
* Validate one PWA icon file
321+
*/
322+
protected function validate_pwa_icon(string $filename, int $size): void
323+
{
324+
if (basename($filename) !== $filename)
325+
{
326+
$this->errors[] = $this->lang->lang('PWA_ICON_INVALID', $filename);
327+
return;
328+
}
329+
330+
$image = $this->root_path . ext::PWA_ICON_DIR . '/' . $filename;
331+
$image_info = $this->imagesize->getImageSize($image);
332+
if ($image_info === false)
333+
{
334+
$this->errors[] = $this->lang->lang('PWA_ICON_INVALID', $filename);
335+
return;
336+
}
337+
338+
if ($image_info['width'] !== $size || $image_info['height'] !== $size)
339+
{
340+
$this->errors[] = $this->lang->lang('PWA_ICON_SIZE_INVALID', $filename);
341+
}
342+
343+
if ($image_info['type'] !== IMAGETYPE_PNG)
344+
{
345+
$this->errors[] = $this->lang->lang('PWA_ICON_MIME_INVALID', $filename);
346+
}
347+
}
348+
349+
/**
350+
* Validate HTML color hex codes
351+
*/
352+
protected function validate_hex_color(string $code): bool
353+
{
354+
$code = trim($code);
355+
356+
if ($code === '')
357+
{
358+
return true;
359+
}
360+
361+
$test = (bool) preg_match('/^#([0-9A-F]{3}){1,2}$/i', $code);
362+
363+
if ($test === false)
364+
{
365+
$this->errors[] = $this->lang->lang('PWA_INVALID_COLOUR', $code);
366+
}
367+
368+
return $test;
369+
}
370+
371+
/**
372+
* Get style data from the styles table
373+
*
374+
* @return array Style data
375+
*/
376+
protected function get_styles(): array
377+
{
378+
$sql = 'SELECT style_id, style_name, pwa_bg_color, pwa_theme_color
379+
FROM ' . STYLES_TABLE . '
380+
WHERE style_active = 1
381+
ORDER BY style_name';
382+
$result = $this->db->sql_query($sql, 3600);
383+
384+
$rows = $this->db->sql_fetchrowset($result);
385+
$this->db->sql_freeresult($result);
386+
387+
return $rows;
388+
}
389+
390+
/**
391+
* Set style data in the styles table
392+
*
393+
* @param array $rows Array of style table data to update; style_id is key
394+
* @return void
395+
*/
396+
protected function set_styles(array $rows): void
397+
{
398+
if (!empty($rows))
399+
{
400+
$this->db->sql_transaction('begin');
401+
402+
foreach ($rows as $style_id => $row)
403+
{
404+
$sql = 'UPDATE ' . STYLES_TABLE . '
405+
SET ' . $this->db->sql_build_array('UPDATE', $row) . '
406+
WHERE style_id = ' . (int) $style_id;
407+
$this->db->sql_query($sql);
408+
}
409+
410+
$this->db->sql_transaction('commit');
411+
412+
$this->cache->destroy('sql', STYLES_TABLE);
413+
}
414+
}
415+
167416
/**
168417
* Display any errors
169418
*

adm/style/event/acp_overall_footer_after.html

Lines changed: 0 additions & 18 deletions
This file was deleted.

adm/style/pwa_acp.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
input[type="color"] {
2+
background-color: transparent;
3+
border: solid 1px #d3d3d3;
4+
border-radius: 50%;
5+
width: 24px;
6+
height: 24px;
7+
padding: 2px;
8+
cursor: pointer;
9+
-webkit-appearance: none;
10+
}
11+
12+
input[type="color"]::-webkit-color-swatch-wrapper {
13+
padding: 0;
14+
}
15+
16+
input[type="color"]::-webkit-color-swatch {
17+
border: 0;
18+
border-radius: 50%;
19+
}
20+
21+
input[type="color"]::-moz-color-swatch {
22+
border: 0;
23+
border-radius: 50%;
24+
}
25+
26+
.color-pickers {
27+
display: inline-block;
28+
width: 120px;
29+
}

0 commit comments

Comments
 (0)