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
17 changes: 2 additions & 15 deletions adm/style/consentmanager_acp.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,8 @@ <h3>{{ lang('WARNING') }}</h3>
<legend>{{ lang('ACP_CONSENTMANAGER_INTEGRATIONS') }}</legend>
<dl>
<dt><label for="consentmanager_integrations">{{ lang('ACP_CONSENTMANAGER_INTEGRATIONS') ~ lang('COLON') }}</label><br><span>{{ lang('ACP_CONSENTMANAGER_INTEGRATIONS_EXPLAIN') }}</span><br><br>
<span><strong>{{ lang('EXAMPLE') ~ lang('COLON') }}</strong></span>
<pre>
<code>
[
{
"id": "board.analytics",
"category": "analytics",
"label": "Board Analytics",
"description": "Loads a simple analytics library after consent.",
"src": "https://cdn.example.com/analytics.js",
"async": true
}
]
</code>
</pre>
<span><strong>{{ lang('EXAMPLE') ~ lang('COLON') }}</strong></span><br>
<pre><samp class="error">{{ CONSENTMANAGER_INTEGRATIONS_EXAMPLE }}</samp></pre>
</dt>
<dd><textarea id="consentmanager_integrations" name="consentmanager_integrations" rows="14" cols="90">{{ CONSENTMANAGER_INTEGRATIONS|e('html') }}</textarea></dd>
</dl>
Expand Down
21 changes: 18 additions & 3 deletions controller/acp_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,12 @@ public function handle()
*/
public function handle_logs()
{
add_form_key('phpbb_consentmanager_export');
add_form_key('phpbb_consentmanager_logs');
$form_data = $this->get_logs_form_data();

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

$errors = [];
$filters = $this->parse_export_filters($form_data, $errors);
Expand All @@ -144,6 +144,8 @@ public function handle_logs()
}
else if ($this->request->is_set_post('delete_logs'))
{
$this->validate_form_key('phpbb_consentmanager_logs');

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

Expand All @@ -168,7 +170,7 @@ public function handle_logs()
build_hidden_fields(array_merge([
'mode' => 'export',
'delete_logs' => 1,
], $form_data))
], $form_data, $this->get_current_form_token_fields()))
);
}
}
Expand Down Expand Up @@ -277,6 +279,19 @@ protected function get_logs_form_data()
];
}

protected function get_current_form_token_fields()
{
if (!$this->request->is_set_post('creation_time') || !$this->request->is_set_post('form_token'))
{
return [];
}

return [
'creation_time' => $this->request->variable('creation_time', 0),
'form_token' => $this->request->variable('form_token', ''),
];
}

protected function assign_template_vars(array $errors = [])
{
$this->template->assign_vars(array_merge(
Expand Down
4 changes: 3 additions & 1 deletion language/en/acp_consentmanager.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
'ACP_CONSENTMANAGER_MEDIA' => 'Enable embedded media category',
'ACP_CONSENTMANAGER_MEDIA_EXPLAIN' => 'Allows videos, players, widgets, and other iframe-based external media to be loaded after consent.',
'ACP_CONSENTMANAGER_INTEGRATIONS' => 'ACP-managed integrations',
'ACP_CONSENTMANAGER_INTEGRATIONS_EXPLAIN' => 'Use this to add simple third-party analytics, marketing, or scripts directly from the ACP instead of through an extension. These entries appear in the consent UI and are only loaded after consent.<br><br>Provide a JSON array of integrations. Each object must include: <samp class="error">id</samp>, <samp class="error">category</samp>, <samp class="error">src</samp>. The <samp class="error">id</samp> may only use letters, numbers, dots, underscores, colons, and hyphens. <samp class="error">category</samp> must be <samp class="error">necessary</samp>, <samp class="error">analytics</samp>, or <samp class="error">marketing</samp>. <samp class="error">src</samp> must be a valid http, https, or relative script URL. Optional fields: <samp class="error">label</samp>, <samp class="error">description</samp>, <samp class="error">async</samp>, <samp class="error">defer</samp>.',
'ACP_CONSENTMANAGER_INTEGRATIONS_EXPLAIN' => 'Use this to add simple third-party analytics, marketing, or scripts directly from the ACP instead of through an extension. These entries appear in the consent UI and are only loaded after consent.<br><br>Provide a JSON array of integrations.<br><br>Each object must include: <samp class="error">id</samp>, <samp class="error">category</samp>, <samp class="error">src</samp>. The <samp class="error">id</samp> may only use letters, numbers, dots, underscores, colons, and hyphens. The <samp class="error">category</samp> must be <samp class="error">necessary</samp>, <samp class="error">analytics</samp>, or <samp class="error">marketing</samp>. The <samp class="error">src</samp> must be a valid http, https, or relative script URL.<br><br>Optional fields: <samp class="error">label</samp>, <samp class="error">description</samp>, <samp class="error">async</samp>, <samp class="error">defer</samp>.',
'ACP_CONSENTMANAGER_INTEGRATIONS_EXAMPLE_LABEL' => 'Example Analytics',
'ACP_CONSENTMANAGER_INTEGRATIONS_EXAMPLE_DESC' => 'Loads a simple analytics library after consent.',
'ACP_CONSENTMANAGER_VERSION' => 'Current consent version',
'ACP_CONSENTMANAGER_VERSION_EXPLAIN' => 'Increase the version to force a fresh prompt for every visitor when the consent text or integrations materially change.',
'ACP_CONSENTMANAGER_FORCE_REPROMPT' => 'Force re-prompt',
Expand Down
24 changes: 23 additions & 1 deletion service/acp_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ public function get_settings_template_data()
'S_CONSENTMANAGER_ANALYTICS' => (bool) $this->config['consentmanager_analytics_enabled'],
'S_CONSENTMANAGER_MARKETING' => (bool) $this->config['consentmanager_marketing_enabled'],
'S_CONSENTMANAGER_MEDIA' => (bool) $this->config['consentmanager_media_enabled'],
'CONSENTMANAGER_INTEGRATIONS' => $this->get_integrations_json(),
'CONSENTMANAGER_VERSION' => (int) $this->config['consentmanager_consent_version'],
'CONSENTMANAGER_INTEGRATIONS' => $this->get_integrations_json(),
'CONSENTMANAGER_INTEGRATIONS_EXAMPLE' => $this->get_integrations_example_json(),
];
}

Expand Down Expand Up @@ -368,6 +369,27 @@ protected function get_integrations_json()
return $pretty_json;
}

/**
* Return example ACP integrations JSON formatted for template output.
*
* @return string
*/
protected function get_integrations_example_json()
{
$example = [[
'id' => 'example.analytics',
'category' => consent_manager_interface::ANALYTICS_CATEGORY,
'label' => $this->language->lang('ACP_CONSENTMANAGER_INTEGRATIONS_EXAMPLE_LABEL'),
'description' => $this->language->lang('ACP_CONSENTMANAGER_INTEGRATIONS_EXAMPLE_DESC'),
'src' => 'https://cdn.example.com/analytics.js',
'async' => true,
]];

$json = json_encode($example, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

return $json === false ? '' : $json;
}

/**
* Build a WHERE clause for consent log queries.
*
Expand Down
36 changes: 18 additions & 18 deletions service/consent_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ public function get_frontend_template_data($log_url, $log_hash)

$vars = [
'S_CONSENTMANAGER_ENABLED' => $has_optional_categories,
'S_CONSENTMANAGER_ANALYTICS_ENABLED' => !empty($categories['analytics']['enabled']),
'S_CONSENTMANAGER_MARKETING_ENABLED' => !empty($categories['marketing']['enabled']),
'S_CONSENTMANAGER_MEDIA_ENABLED' => !empty($categories['media']['enabled']),
'S_CONSENTMANAGER_ANALYTICS_ENABLED' => !empty($categories[self::ANALYTICS_CATEGORY]['enabled']),
'S_CONSENTMANAGER_MARKETING_ENABLED' => !empty($categories[self::MARKETING_CATEGORY]['enabled']),
'S_CONSENTMANAGER_MEDIA_ENABLED' => !empty($categories[self::MEDIA_CATEGORY]['enabled']),
'CONSENTMANAGER_PAYLOAD' => $has_optional_categories ? json_encode($payload, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) : '',
];

Expand Down Expand Up @@ -332,10 +332,10 @@ public function build_frontend_payload($log_url, $log_hash)
public function get_categories()
{
$lang_keys = [
'necessary' => ['CONSENTMANAGER_CATEGORY_NECESSARY', 'CONSENTMANAGER_CATEGORY_NECESSARY_EXPLAIN'],
'analytics' => ['CONSENTMANAGER_CATEGORY_ANALYTICS', 'CONSENTMANAGER_CATEGORY_ANALYTICS_EXPLAIN'],
'marketing' => ['CONSENTMANAGER_CATEGORY_MARKETING', 'CONSENTMANAGER_CATEGORY_MARKETING_EXPLAIN'],
'media' => ['CONSENTMANAGER_CATEGORY_MEDIA', 'CONSENTMANAGER_CATEGORY_MEDIA_EXPLAIN'],
self::NECESSARY_CATEGORY => ['CONSENTMANAGER_CATEGORY_NECESSARY', 'CONSENTMANAGER_CATEGORY_NECESSARY_EXPLAIN'],
self::ANALYTICS_CATEGORY => ['CONSENTMANAGER_CATEGORY_ANALYTICS', 'CONSENTMANAGER_CATEGORY_ANALYTICS_EXPLAIN'],
self::MARKETING_CATEGORY => ['CONSENTMANAGER_CATEGORY_MARKETING', 'CONSENTMANAGER_CATEGORY_MARKETING_EXPLAIN'],
self::MEDIA_CATEGORY => ['CONSENTMANAGER_CATEGORY_MEDIA', 'CONSENTMANAGER_CATEGORY_MEDIA_EXPLAIN'],
];
$categories = [];

Expand Down Expand Up @@ -519,12 +519,12 @@ public function normalize_integrations($input, array &$errors = [])
*/
public function normalize_categories(array $categories)
{
$normalized = ['necessary'];
$normalized = [self::NECESSARY_CATEGORY];

foreach ($categories as $category)
{
$category = trim((string) $category);
if ($category !== 'necessary' && $this->is_category_enabled($category))
if ($category !== self::NECESSARY_CATEGORY && $this->is_category_enabled($category))
{
$normalized[] = $category;
}
Expand Down Expand Up @@ -625,7 +625,7 @@ public function has_server_consent($category)
*/
public function is_supported_category($category)
{
return in_array($category, ['necessary', 'analytics', 'marketing', 'media'], true);
return in_array($category, [self::NECESSARY_CATEGORY, self::ANALYTICS_CATEGORY, self::MARKETING_CATEGORY, self::MEDIA_CATEGORY], true);
}

/**
Expand Down Expand Up @@ -792,23 +792,23 @@ protected function get_frontend_payload_categories(array $categories)
protected function get_category_config()
{
return $this->category_config ?? ($this->category_config = [
'necessary' => [
'id' => 'necessary',
self::NECESSARY_CATEGORY => [
'id' => self::NECESSARY_CATEGORY,
'required' => true,
'enabled' => true,
],
'analytics' => [
'id' => 'analytics',
self::ANALYTICS_CATEGORY => [
'id' => self::ANALYTICS_CATEGORY,
'required' => false,
'enabled' => (bool) $this->config['consentmanager_analytics_enabled'],
],
'marketing' => [
'id' => 'marketing',
self::MARKETING_CATEGORY => [
'id' => self::MARKETING_CATEGORY,
'required' => false,
'enabled' => (bool) $this->config['consentmanager_marketing_enabled'],
],
'media' => [
'id' => 'media',
self::MEDIA_CATEGORY => [
'id' => self::MEDIA_CATEGORY,
'required' => false,
'enabled' => (bool) $this->config['consentmanager_media_enabled'],
],
Expand Down
5 changes: 5 additions & 0 deletions service/consent_manager_interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@

interface consent_manager_interface
{
public const NECESSARY_CATEGORY = 'necessary';
public const ANALYTICS_CATEGORY = 'analytics';
public const MARKETING_CATEGORY = 'marketing';
public const MEDIA_CATEGORY = 'media';

/**
* Register a consent-aware service definition.
*
Expand Down
7 changes: 3 additions & 4 deletions service/media_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

class media_manager
{
public const MEDIA_CATEGORY = 'media';
public const MEDIA_ALLOWED_PARAMETER = 'S_CONSENTMANAGER_MEDIA_ALLOWED';
public const XSL_NAMESPACE = 'http://www.w3.org/1999/XSL/Transform';

Expand Down Expand Up @@ -44,7 +43,7 @@ public function __construct(consent_manager_interface $consent_manager)
*/
public function configure_iframe_embeds(Configurator $configurator)
{
if (!$this->consent_manager->is_category_enabled(self::MEDIA_CATEGORY))
if (!$this->consent_manager->is_category_enabled(consent_manager_interface::MEDIA_CATEGORY))
{
return;
}
Expand Down Expand Up @@ -81,7 +80,7 @@ public function configure_iframe_renderer($renderer)
{
$renderer->get_renderer()->setParameter(
self::MEDIA_ALLOWED_PARAMETER,
$this->consent_manager->has_server_consent(self::MEDIA_CATEGORY) ? '1' : ''
$this->consent_manager->has_server_consent(consent_manager_interface::MEDIA_CATEGORY) ? '1' : ''
);
}

Expand Down Expand Up @@ -242,7 +241,7 @@ protected function wrap_media_root(\DOMDocument $dom, \DOMElement $media_root)
{
$container = $dom->createElement('span');
$container->setAttribute('data-consent-media-container', '1');
$container->setAttribute('data-consent-category', self::MEDIA_CATEGORY);
$container->setAttribute('data-consent-category', consent_manager_interface::MEDIA_CATEGORY);

$placeholder = $dom->createElement('span');
$placeholder->setAttribute('data-consent-media-placeholder', '1');
Expand Down
Loading
Loading