Files
ogre-consent/inc/abstract-service.php
Cooper Dalrymple b8902b4afa
Validate Build / validate-build (push) Canceled after 0s
More work on this, incomplete!
2026-10-06 17:00:20 -05:00

174 lines
4.7 KiB
PHP

<?php
/**
* @package ogre-consent
* @author cleverogre
* @copyright 2026 CleverOgre
* @license GLP-3.0-or-later
* @version 0.0.0
* @since 0.0.0
*/
namespace Ogre\Consent;
use Override;
use Ogre\Singleton;
use WP_Block;
use WP_HTML_Tag_Processor;
defined('ABSPATH') || exit;
abstract class Service {
use Singleton;
protected string $name;
protected string $title;
protected bool $contextualConsentOnly = false;
protected function __construct(string $name, string $title = '') {
$this->name = $name;
$this->title = !empty($title) ? $title : $name;
Services::instance()->register($this);
}
public function get_name(): string
{
return $this->name;
}
public function get_title(): string
{
return $this->title;
}
abstract public function get_purposes(): array;
public function get_purpose(): string
{
$purposes = $this->get_purposes();
if (empty($purposes)) return 'analytics';
return array_values($purposes)[0];
}
public function get_config(): array
{
$config = [
'name' => $this->name,
'title' => $this->title,
'purposes' => $this->get_purposes(),
];
if ($this->contextualConsentOnly) $config['contextualConsentOnly'] = true;
return $config;
}
public function is_enabled(): bool
{
return Settings::instance()->is_service_enabled($this);
}
}
abstract class ScriptService extends Service {
protected string $handle;
protected function __construct(string $handle, string $name = '', string $title = '') {
$this->handle = $handle;
parent::__construct(!empty($name) ? $name : $handle, $title);
add_filter('script_loader_tag', [$this, 'script_loader_tag'], 10, 3);
}
public function script_loader_tag(string $tag, string $handle, string $src): string
{
if ($handle !== $this->handle) return $tag;
$tags = new WP_HTML_Tag_Processor($tag);
if ($tags->next_tag('script')) {
$tags->set_attribute('type', 'text/plain');
$tags->set_attribute('data-name', $this->name);
if (!str_starts_with(($src = $tags->get_attribute('src')), site_url())) {
$tags->remove_attribute('src');
$tags->set_attribute('data-src', $src);
}
}
return $tag;
}
}
abstract class BlockService extends Service {
protected string $blockName;
protected function __construct(string $blockName, string $name = '', string $title = '') {
$this->blockName = $blockName;
parent::__construct(!empty($name) ? $name : $blockName, $title);
add_filter("render_block_{$blockName}", [$this, 'render_block'], 10, 3);
}
abstract public function render_block(string $block_content, array $block, WP_Block $instance): string;
}
abstract class GoogleTagManagerService extends ScriptService {
protected string $consent_id;
protected function __construct(string $handle, string $name = '', string $consent_id = '', string $title = '') {
$this->consent_id = !empty($consent_id) ? $consent_id : (!empty($name) ? $name : $handle);
parent::__construct($handle, $name, $title);
}
#[Override]
public function get_config(): array
{
return array_merge(
parent::get_config(),
[
'cookies' => [
'/^_ga(_.*)?/'
],
'onAccept' => sprintf(
"gtag('consent', 'update', {'%s': 'granted'})",
esc_js($this->consent_id)
),
'onDecline' => sprintf(
"gtag('consent', 'update', {'%s': 'denied'})",
esc_js($this->consent_id)
),
]
);
}
}
abstract class EmbedBlockService extends BlockService {
protected function __construct(string $name, string $title = '') {
parent::__construct('core/embed', $name, $title);
}
#[Override]
public function get_purposes(): array
{
return [
'marketing'
];
}
#[Override]
public function render_block(string $block_content, array $block, WP_Block $instance): string
{
if ($block['name'] !== $this->name) return $block_content;
$tags = new WP_HTML_Tag_Processor($block_content);
if ($tags->next_tag('iframe')) {
$tags->set_attribute('data-name', $this->name);
$src = $tags->get_attribute('src');
$tags->remove_attribute('src');
$tags->set_attribute('data-src', $src);
}
return $tags->get_updated_html();
}
}