Skip to content
Merged
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/consentmanager_info.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public function module()
'auth' => 'ext_phpbb/consentmanager && acl_a_board',
'cat' => ['ACP_CONSENTMANAGER'],
],
'export' => [
'title' => 'ACP_CONSENTMANAGER_EXPORT',
'auth' => 'ext_phpbb/consentmanager && acl_a_board',
'cat' => ['ACP_CONSENTMANAGER'],
],
],
];
}
Expand Down
16 changes: 13 additions & 3 deletions acp/consentmanager_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ public function main($id, $mode)
$controller = $phpbb_container->get('phpbb.consentmanager.controller.acp');
$controller->set_page_url($this->u_action);

$this->tpl_name = 'consentmanager_acp';
$this->page_title = 'ACP_CONSENTMANAGER';
switch ($mode)
{
case 'export':
$this->tpl_name = 'consentmanager_acp_export';
$this->page_title = 'ACP_CONSENTMANAGER_EXPORT';
$controller->handle_export();
break;

$controller->handle();
default:
$this->tpl_name = 'consentmanager_acp';
$this->page_title = 'ACP_CONSENTMANAGER';
$controller->handle();
break;
}
}
}
50 changes: 50 additions & 0 deletions adm/style/consentmanager_acp_export.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{% include 'overall_header.html' %}

<h1>{{ lang('ACP_CONSENTMANAGER') }}</h1>

<p>{{ lang('ACP_CONSENTMANAGER_EXPORT_EXPLAIN') }}</p>

{% if S_ERROR %}
<div class="errorbox">
<h3>{{ lang('WARNING') }}</h3>
<p>{{ ERROR_MSG }}</p>
</div>
{% endif %}

<form id="acp_consentmanager_export" method="post" action="{{ U_ACTION }}">
<fieldset>
<legend>{{ lang('ACP_CONSENTMANAGER_EXPORT_FILTERS') }}</legend>
<dl>
<dt>
<label for="export_date_from">{{ lang('ACP_CONSENTMANAGER_EXPORT_DATE_FROM') ~ lang('COLON') }}</label>
<br><span>{{ lang('ACP_CONSENTMANAGER_EXPORT_DATE_EXPLAIN') }}</span>
</dt>
<dd><input type="date" id="export_date_from" name="export_date_from" value="{{ EXPORT_DATE_FROM|e('html') }}"></dd>
</dl>
<dl>
<dt><label for="export_date_to">{{ lang('ACP_CONSENTMANAGER_EXPORT_DATE_TO') ~ lang('COLON') }}</label></dt>
<dd><input type="date" id="export_date_to" name="export_date_to" value="{{ EXPORT_DATE_TO|e('html') }}"></dd>
</dl>
<dl>
<dt>
<label for="export_user_id">{{ lang('ACP_CONSENTMANAGER_EXPORT_USER_ID') ~ lang('COLON') }}</label>
<br><span>{{ lang('ACP_CONSENTMANAGER_EXPORT_USER_ID_EXPLAIN') }}</span>
</dt>
<dd><input type="number" id="export_user_id" name="export_user_id" min="0" value="{{ EXPORT_USER_ID }}"></dd>
</dl>
<dl>
<dt>
<label for="export_consent_version">{{ lang('ACP_CONSENTMANAGER_EXPORT_VERSION') ~ lang('COLON') }}</label>
<br><span>{{ lang('ACP_CONSENTMANAGER_EXPORT_VERSION_EXPLAIN') }}</span>
</dt>
<dd><input type="number" id="export_consent_version" name="export_consent_version" min="0" value="{{ EXPORT_CONSENT_VER }}"></dd>
</dl>
</fieldset>

<fieldset class="submit-buttons">
<input class="button1" type="submit" name="download_csv" value="{{ lang('ACP_CONSENTMANAGER_EXPORT_DOWNLOAD') }}">
{{ S_FORM_TOKEN }}
</fieldset>
</form>

{% include 'overall_footer.html' %}
10 changes: 9 additions & 1 deletion config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ services:

phpbb.consentmanager.log_manager:
class: phpbb\consentmanager\service\log_manager
arguments:
- '@config'
- '@dbal.conn'
- '@user'
- '%tables.phpbb.consentmanager.consent_logs%'

phpbb.consentmanager.acp_manager:
class: phpbb\consentmanager\service\acp_manager
arguments:
- '@config'
- '@dbal.conn'
Expand All @@ -37,7 +45,7 @@ services:
arguments:
- '@language'
- '@phpbb.consentmanager.service'
- '@phpbb.consentmanager.log_manager'
- '@phpbb.consentmanager.acp_manager'
- '@request'
- '@template'

Expand Down
152 changes: 133 additions & 19 deletions controller/acp_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

namespace phpbb\consentmanager\controller;

use phpbb\consentmanager\service\acp_manager;
use phpbb\consentmanager\service\consent_manager_interface;
use phpbb\consentmanager\service\log_manager;
use phpbb\language\language;
use phpbb\request\request;
use phpbb\template\template;
Expand All @@ -24,8 +24,8 @@ class acp_controller
/** @var consent_manager_interface */
protected $consent_manager;

/** @var log_manager */
protected $log_manager;
/** @var acp_manager */
protected $acp_manager;

/** @var request */
protected $request;
Expand All @@ -41,15 +41,15 @@ class acp_controller
*
* @param language $language Language service
* @param consent_manager_interface $consent_manager Consent manager service
* @param log_manager $log_manager Consent log manager
* @param acp_manager $acp_manager ACP manager service
* @param request $request Request service
* @param template $template Template service
*/
public function __construct(language $language, consent_manager_interface $consent_manager, log_manager $log_manager, request $request, template $template)
public function __construct(language $language, consent_manager_interface $consent_manager, acp_manager $acp_manager, request $request, template $template)
{
$this->language = $language;
$this->consent_manager = $consent_manager;
$this->log_manager = $log_manager;
$this->acp_manager = $acp_manager;
$this->request = $request;
$this->template = $template;

Expand Down Expand Up @@ -79,7 +79,7 @@ public function handle()

if ($this->request->is_set_post('submit'))
{
$this->validate_form_key();
$this->validate_form_key('phpbb_consentmanager_acp');

$errors = [];
$saved = $this->consent_manager->save_acp_settings([
Expand All @@ -94,16 +94,16 @@ public function handle()
return;
}

$this->log_manager->log_admin_settings_updated();
$this->acp_manager->log_admin_settings_updated();
trigger_error($this->language->lang('CONFIG_UPDATED') . adm_back_link($this->u_action));
}

if ($this->request->is_set_post('reset_consent'))
{
$this->validate_form_key();
$this->validate_form_key('phpbb_consentmanager_acp');

$this->consent_manager->reset_consent_version();
$this->log_manager->log_admin_reprompt();
$this->acp_manager->log_admin_reprompt();

trigger_error($this->language->lang('ACP_CONSENTMANAGER_REPROMPT_SUCCESS') . adm_back_link($this->u_action));
}
Expand All @@ -112,12 +112,131 @@ public function handle()
}

/**
* Assign consent manager settings to the ACP template.
* Handle the ACP export page request.
*
* @param array $errors Validation errors to display
* Displays the filter form on GET. On POST with download_csv, streams a
* CSV file of consent log records matching the supplied filters.
*
* @return void
*/
public function handle_export()
{
add_form_key('phpbb_consentmanager_export');

if ($this->request->is_set_post('download_csv'))
{
$this->validate_form_key('phpbb_consentmanager_export');

$errors = [];
$filters = $this->parse_export_filters($errors);

if (!empty($errors))
{
$this->assign_export_template_vars($errors);
return;
}

$this->acp_manager->log_admin_export();
$this->send_csv_download($filters);
}

$this->assign_export_template_vars();
}

/**
* Parse and validate filter inputs from the export form.
*
* @param array $errors Reference — validation errors are appended here
*
* @return array Validated filter map (date_from, date_to, user_id, consent_version)
*/
protected function parse_export_filters(array &$errors)
{
$date_from_str = trim($this->request->variable('export_date_from', ''));
$date_to_str = trim($this->request->variable('export_date_to', ''));
$user_id = $this->request->variable('export_user_id', 0);
$consent_ver = $this->request->variable('export_consent_version', 0);

$filters = [];
$date_from = $this->acp_manager->parse_date_filter($date_from_str);
$date_to = $this->acp_manager->parse_date_filter($date_to_str, true);

if ($date_from_str !== '' && $date_from === false)
{
$errors[] = $this->language->lang('ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_FROM');
}

if ($date_to_str !== '' && $date_to === false)
{
$errors[] = $this->language->lang('ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_TO');
}

if ($date_from !== false && $date_to !== false && $date_from > $date_to)
{
$errors[] = $this->language->lang('ACP_CONSENTMANAGER_EXPORT_DATE_RANGE_INVALID');
}

if (empty($errors))
{
if ($date_from !== false)
{
$filters['date_from'] = $date_from;
}

if ($date_to !== false)
{
$filters['date_to'] = $date_to;
}
}

if ($user_id > 0)
{
$filters['user_id'] = $user_id;
}

if ($consent_ver > 0)
{
$filters['consent_version'] = $consent_ver;
}

return $filters;
}

protected function send_csv_download(array $filters)
{
if (ob_get_level())
{
ob_end_clean();
}

header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="consent_logs.csv"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

$handle = fopen('php://output', 'w');
fwrite($handle, "\xEF\xBB\xBF"); // UTF-8 BOM for Excel compatibility
fputcsv($handle, ['anonymized_id', 'timestamp', 'consent_version', 'categories']);
$this->acp_manager->stream_logs_csv($handle, $filters);
fclose($handle);

exit;
}

protected function assign_export_template_vars(array $errors = [])
{
$this->template->assign_vars([
'S_ERROR' => !empty($errors),
'ERROR_MSG' => implode('<br>', $errors),
'EXPORT_DATE_FROM' => $this->request->variable('export_date_from', ''),
'EXPORT_DATE_TO' => $this->request->variable('export_date_to', ''),
'EXPORT_USER_ID' => $this->request->variable('export_user_id', 0),
'EXPORT_CONSENT_VER' => $this->request->variable('export_consent_version', 0),
'U_ACTION' => $this->u_action,
]);
}

protected function assign_template_vars(array $errors = [])
{
$this->template->assign_vars(array_merge(
Expand All @@ -130,14 +249,9 @@ protected function assign_template_vars(array $errors = [])
));
}

/**
* Ensure the ACP form key is valid before processing changes.
*
* @return void
*/
protected function validate_form_key()
protected function validate_form_key($form_key)
{
if (!check_form_key('phpbb_consentmanager_acp'))
if (!check_form_key($form_key))
{
trigger_error($this->language->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING);
}
Expand Down
15 changes: 15 additions & 0 deletions language/en/acp_consentmanager.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,19 @@
'ACP_CONSENTMANAGER_INVALID_INTEGRATIONS' => 'The integrations field must contain a valid JSON array.',
'ACP_CONSENTMANAGER_INVALID_INTEGRATION_ENTRY' => 'Integration entry %1$s is invalid. Each entry must include a safe id, supported category, and valid script source URL.',
'EXAMPLE' => 'Example',

// Export consent logs
'ACP_CONSENTMANAGER_EXPORT_EXPLAIN' => 'Download a CSV file of stored consent log records. All fields are optional; leave them blank to export the full log.',
'ACP_CONSENTMANAGER_EXPORT_FILTERS' => 'Export filters',
'ACP_CONSENTMANAGER_EXPORT_DATE_FROM' => 'Date from',
'ACP_CONSENTMANAGER_EXPORT_DATE_TO' => 'Date to',
'ACP_CONSENTMANAGER_EXPORT_DATE_EXPLAIN' => 'Use the browser date picker when available. If you cannot pick a date, enter it in YYYY-MM-DD format. Dates are interpreted in UTC. Leave blank to omit this boundary.',
'ACP_CONSENTMANAGER_EXPORT_USER_ID' => 'User ID',
'ACP_CONSENTMANAGER_EXPORT_USER_ID_EXPLAIN' => 'Enter a registered user ID to restrict the export to that user\'s consent records. Leave blank to include all users. Note: records for guests use a session-based identifier and cannot be filtered by user ID.',
'ACP_CONSENTMANAGER_EXPORT_VERSION' => 'Consent version',
'ACP_CONSENTMANAGER_EXPORT_VERSION_EXPLAIN' => 'Restrict the export to a specific consent version. Leave blank for all versions.',
'ACP_CONSENTMANAGER_EXPORT_DOWNLOAD' => 'Download CSV',
'ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_FROM' => 'The "Date from" value is not a valid date. Use the browser date picker when available, or enter the date in YYYY-MM-DD format.',
'ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_TO' => 'The "Date to" value is not a valid date. Use the browser date picker when available, or enter the date in YYYY-MM-DD format.',
'ACP_CONSENTMANAGER_EXPORT_DATE_RANGE_INVALID' => '"Date from" must not be later than "Date to".',
]);
2 changes: 2 additions & 0 deletions language/en/info_acp_consentmanager.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
$lang = array_merge($lang, [
'ACP_CONSENTMANAGER' => 'Consent Manager',
'ACP_CONSENTMANAGER_SETTINGS' => 'Settings',
'ACP_CONSENTMANAGER_EXPORT' => 'Export Consent Logs',
'LOG_CONSENTMANAGER_UPDATED' => '<strong>Updated Consent Manager settings</strong>',
'LOG_CONSENTMANAGER_REPROMPT' => '<strong>Forced Consent Manager re-prompt by increasing the consent version</strong>',
'LOG_CONSENTMANAGER_EXPORT' => '<strong>Exported Consent Manager logs as CSV</strong>',
]);
3 changes: 2 additions & 1 deletion migrations/m1_initial.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function update_data()
['module.add', ['acp', 'ACP_CAT_DOT_MODS', 'ACP_CONSENTMANAGER']],
['module.add', ['acp', 'ACP_CONSENTMANAGER', [
'module_basename' => '\phpbb\consentmanager\acp\consentmanager_module',
'modes' => ['settings'],
'modes' => ['settings', 'export'],
]]],
];
}
Expand All @@ -75,6 +75,7 @@ public function revert_data()
['config.remove', ['consentmanager_marketing_enabled']],
['config.remove', ['consentmanager_consent_version']],
['config_text.remove', ['consentmanager_integrations']],
['module.remove', ['acp', 'ACP_CONSENTMANAGER', 'ACP_CONSENTMANAGER_EXPORT']],
['module.remove', ['acp', 'ACP_CONSENTMANAGER', 'ACP_CONSENTMANAGER_SETTINGS']],
['module.remove', ['acp', 'ACP_CAT_DOT_MODS', 'ACP_CONSENTMANAGER']],
];
Expand Down
Loading
Loading