Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions acp/wpn_acp_info.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public function module()
'auth' => 'ext_phpbb/webpushnotifications && acl_a_server',
'cat' => ['ACP_CLIENT_COMMUNICATION']
],
'pwa' => [
'title' => 'ACP_WEBPUSH_PWA_SETTINGS',
'auth' => 'ext_phpbb/webpushnotifications && acl_a_board',
'cat' => ['ACP_CLIENT_COMMUNICATION']
],
],
];
}
Expand Down
249 changes: 249 additions & 0 deletions acp/wpn_acp_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,32 @@
use phpbb\symfony_request;
use phpbb\template\template;
use phpbb\user;
use phpbb\webpushnotifications\ext;

class wpn_acp_module
{
public $page_title;
public $tpl_name;
public $u_action;

/** @var \phpbb\cache\service */
protected $cache;

/** @var config $config */
protected $config;

/** @var \phpbb\db\driver\driver_interface */
protected $db;

/** @var language $lang */
protected $lang;

/** @var log $log */
protected $log;

/** @var \FastImageSize\FastImageSize $imagesize */
protected $imagesize;

/** @var request $request */
protected $request;

Expand All @@ -45,6 +55,9 @@ class wpn_acp_module
/** @var user $user */
protected $user;

/** @var string */
protected $root_path;

/** @var array $errors */
protected $errors = [];

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

$this->cache = $phpbb_container->get('cache');
$this->config = $phpbb_container->get('config');
$this->db = $phpbb_container->get('dbal.conn');
$this->imagesize = $phpbb_container->get('upload_imagesize');
$this->lang = $phpbb_container->get('language');
$this->log = $phpbb_container->get('log');
$this->request = $phpbb_container->get('request');
$this->symfony_request = $phpbb_container->get('symfony_request');
$this->template = $phpbb_container->get('template');
$this->user = $phpbb_container->get('user');
$this->root_path = $phpbb_container->getParameter('core.root_path');

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

$this->display_settings();
}
else if ($mode === 'pwa')
{
$this->tpl_name = 'wpn_acp_pwa';

$this->lang->add_lang('webpushnotifications_module_acp', 'phpbb/webpushnotifications');

$this->page_title = $this->lang->lang('ACP_WEBPUSH_PWA_SETTINGS');

if ($this->request->is_set_post('submit'))
{
if (!check_form_key($form_key))
{
trigger_error($this->lang->lang('FORM_INVALID'), E_USER_WARNING);
}

$this->save_pwa_settings();
}

$this->display_pwa_settings();
}
}

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

/**
* Add PWA settings template vars to the form
*/
public function display_pwa_settings()
{
$this->template->assign_vars([
'S_PWA_SHOW_INSTALL_BANNER' => (bool) $this->config['pwa_show_install_banner'],
'PWA_SHORT_NAME' => $this->config['pwa_short_name'],
'PWA_ICON_SMALL' => $this->config['pwa_icon_small'],
'PWA_ICON_LARGE' => $this->config['pwa_icon_large'],
'STYLES' => $this->get_styles(),
'U_ACTION' => $this->u_action,
]);

$this->display_errors();
}

/**
* Save PWA settings data to the database
*
* @return void
*/
public function save_pwa_settings()
{
$config_array = $this->request->variable('config', ['' => ''], true);

$config_array['pwa_short_name'] = $config_array['pwa_short_name'] ?? '';
$config_array['pwa_icon_small'] = $config_array['pwa_icon_small'] ?? '';
$config_array['pwa_icon_large'] = $config_array['pwa_icon_large'] ?? '';

$this->validate_pwa_short_name($config_array['pwa_short_name']);
$this->validate_pwa_icons($config_array['pwa_icon_small'], $config_array['pwa_icon_large']);

$styles = $this->get_styles();
$updates = [];
foreach ($styles as $row)
{
$style_id = $row['style_id'];
$pwa_bg_color = $this->request->variable('pwa_bg_color_' . $style_id, '');
$pwa_theme_color = $this->request->variable('pwa_theme_color_' . $style_id, '');

$updates[$style_id] = [
'pwa_bg_color' => $this->validate_hex_color($pwa_bg_color) ? $pwa_bg_color : $row['pwa_bg_color'],
'pwa_theme_color' => $this->validate_hex_color($pwa_theme_color) ? $pwa_theme_color : $row['pwa_theme_color'],
];
}

if ($this->display_errors())
{
return;
}

$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONFIG_WEBPUSH');

// Ensure 4-byte emoji can be stored correctly
$config_array['pwa_short_name'] = utf8_encode_ucr($config_array['pwa_short_name']);

foreach ([
'pwa_short_name',
'pwa_icon_small',
'pwa_icon_large',
'pwa_show_install_banner',
] as $config_name)
{
$this->config->set($config_name, $config_array[$config_name] ?? 0);
}

$this->set_styles($updates);

trigger_error($this->lang->lang('CONFIG_UPDATED') . adm_back_link($this->u_action), E_USER_NOTICE);
}

/**
* Validate PWA short site name
*/
protected function validate_pwa_short_name(string $short_name): void
{
if ($short_name === '')
{
return;
}

$short_name = ext::decode_entities($short_name, ENT_QUOTES);
if (utf8_strlen($short_name) > 12)
{
$this->errors[] = $this->lang->lang('PWA_SHORT_NAME_INVALID');
}
}

/**
* Validate PWA icon filenames and dimensions
*/
protected function validate_pwa_icons(string $small_icon, string $large_icon): void
{
if ($small_icon === '' && $large_icon === '')
{
return;
}

if ($small_icon === '')
{
$this->errors[] = $this->lang->lang('PWA_ICON_NOT_PROVIDED', $this->lang->lang('PWA_ICON_SMALL'));
return;
}

if ($large_icon === '')
{
$this->errors[] = $this->lang->lang('PWA_ICON_NOT_PROVIDED', $this->lang->lang('PWA_ICON_LARGE'));
return;
}

$this->validate_pwa_icon($small_icon, 192);
$this->validate_pwa_icon($large_icon, 512);
}

/**
* Validate one PWA icon file
*/
protected function validate_pwa_icon(string $filename, int $size): void
{
if (basename($filename) !== $filename)
{
$this->errors[] = $this->lang->lang('PWA_ICON_INVALID', $filename);
return;
}

$image = $this->root_path . ext::PWA_ICON_DIR . '/' . $filename;
$image_info = $this->imagesize->getImageSize($image);
if ($image_info === false)
{
$this->errors[] = $this->lang->lang('PWA_ICON_INVALID', $filename);
return;
}

if ($image_info['width'] !== $size || $image_info['height'] !== $size)
{
$this->errors[] = $this->lang->lang('PWA_ICON_SIZE_INVALID', $filename);
}

if ($image_info['type'] !== IMAGETYPE_PNG)
{
$this->errors[] = $this->lang->lang('PWA_ICON_MIME_INVALID', $filename);
}
}

/**
* Validate HTML color hex codes
*/
protected function validate_hex_color(string $code): bool
{
$code = trim($code);

if ($code === '')
{
return true;
}

$test = (bool) preg_match('/^#([0-9A-F]{3}){1,2}$/i', $code);

if ($test === false)
{
$this->errors[] = $this->lang->lang('PWA_INVALID_COLOUR', $code);
}

return $test;
}

/**
* Get style data from the styles table
*
* @return array Style data
*/
protected function get_styles(): array
{
$sql = 'SELECT style_id, style_name, pwa_bg_color, pwa_theme_color
FROM ' . STYLES_TABLE . '
WHERE style_active = 1
ORDER BY style_name';
$result = $this->db->sql_query($sql, 3600);

$rows = $this->db->sql_fetchrowset($result);
$this->db->sql_freeresult($result);

return $rows;
}

/**
* Set style data in the styles table
*
* @param array $rows Array of style table data to update; style_id is key
* @return void
*/
protected function set_styles(array $rows): void
{
if (!empty($rows))
{
$this->db->sql_transaction('begin');

foreach ($rows as $style_id => $row)
{
$sql = 'UPDATE ' . STYLES_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $row) . '
WHERE style_id = ' . (int) $style_id;
$this->db->sql_query($sql);
}

$this->db->sql_transaction('commit');

$this->cache->destroy('sql', STYLES_TABLE);
}
}

/**
* Display any errors
*
Expand Down
18 changes: 0 additions & 18 deletions adm/style/event/acp_overall_footer_after.html

This file was deleted.

29 changes: 29 additions & 0 deletions adm/style/pwa_acp.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
input[type="color"] {
background-color: transparent;
border: solid 1px #d3d3d3;
border-radius: 50%;
width: 24px;
height: 24px;
padding: 2px;
cursor: pointer;
-webkit-appearance: none;
}

input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}

input[type="color"]::-webkit-color-swatch {
border: 0;
border-radius: 50%;
}

input[type="color"]::-moz-color-swatch {
border: 0;
border-radius: 50%;
}

.color-pickers {
display: inline-block;
width: 120px;
}
Loading
Loading