205 lines
8.3 KiB
PHP
205 lines
8.3 KiB
PHP
|
<?php namespace ProcessWire;
|
||
|
|
||
|
/**
|
||
|
* PrivacyWire
|
||
|
* This module adds management options for GDPR-relevant elements (loading maps, videos etc. only after accepting
|
||
|
* external media) and cookies.
|
||
|
*
|
||
|
* @author blaueQuelle
|
||
|
*
|
||
|
* ProcessWire 3.x
|
||
|
* Copyright (C) 2011 by Ryan Cramer
|
||
|
* Licensed under GNU/GPL v2, see LICENSE.TXT
|
||
|
*
|
||
|
* http://www.processwire.com
|
||
|
* http://www.ryancramer.com
|
||
|
*
|
||
|
*/
|
||
|
class PrivacyWire extends WireData implements Module, ConfigurableModule
|
||
|
{
|
||
|
|
||
|
var $modulePath;
|
||
|
var $moduleUrl;
|
||
|
var $headContent = "";
|
||
|
var $bodyContent = "";
|
||
|
var $lang;
|
||
|
|
||
|
public static function getModuleInfo()
|
||
|
{
|
||
|
return [
|
||
|
'title' => "PrivacyWire",
|
||
|
'summary' => "This module adds management options for GDPR-relevant elements (loading maps, videos etc. only after accepting external media) and cookies.",
|
||
|
'author' => "blaueQuelle",
|
||
|
'href' => "https://github.com/blaueQuelle/privacywire",
|
||
|
'version' => "1.1.6",
|
||
|
'autoload' => true,
|
||
|
'singular' => true,
|
||
|
'requires' => ["PHP>=7.2", "ProcessWire>=3.0.110"],
|
||
|
'installs' => ["TextformatterPrivacyWire"],
|
||
|
'icon' => 'eye-slash'
|
||
|
];
|
||
|
}
|
||
|
|
||
|
public function ready()
|
||
|
{
|
||
|
if (
|
||
|
$this->wire('page')->template == 'admin' || // exclude admin pages
|
||
|
$this->wire('page')->template == 'form-builder' || // exclude from form-builder iframe
|
||
|
! $this->is_active // exclude, if PrivacyWire is NOT active
|
||
|
) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 1. - 5. within initiatePrivacyWire method
|
||
|
$this->wire('page')->addHookBefore('render', $this, 'initiatePrivacyWire');
|
||
|
|
||
|
// 6. Render everything!
|
||
|
/*
|
||
|
* Hint: If you want to render everything manually, make sure to insert the PrivacyWireConfig (step 2), PrivacyWireCore (step 3), Banner Markup (step 4) and if you want to display the ask-for-consent windows also the consent blueprint (step 5) somewhere in your template.
|
||
|
* The banner markup and consent window blueprint can be loaded anywhere, for example at the end of the body tag.
|
||
|
*/
|
||
|
if (!$this->render_manually) {
|
||
|
$this->wire('page')->addHookAfter('render', $this, 'render', ['priority' => 101]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function initiatePrivacyWire(HookEvent $event)
|
||
|
{
|
||
|
|
||
|
$this->modulePath = $this->wire('config')->paths->$this;
|
||
|
$this->moduleUrl = $this->wire('config')->urls->$this;
|
||
|
$this->lang = ($this->wire('languages') && !$this->wire('user')->language->isDefault()) ? '__' . $this->wire('user')->language->id : '';
|
||
|
|
||
|
// 1. Add some styling via inline CSS (if wanted, configured via backend)
|
||
|
if ($this->add_basic_css_styling) {
|
||
|
$this->headContent .= $this->renderPrivacyWireStyles();
|
||
|
}
|
||
|
|
||
|
// 2. Insert PrivacyWire Configuration Object as inline JS (hookable method if you want to override something)
|
||
|
$this->headContent .= $this->renderPrivacyWireConfigAsInlineJs();
|
||
|
|
||
|
// 3. Insert JS File (hookable method) - either modern ES6 version or legacy version with IE support.
|
||
|
// Output modes: a) regular script tag b) ProCache script tag c) inline script
|
||
|
$this->headContent .= $this->renderPrivacyWireCoreJs();
|
||
|
|
||
|
// 4. Insert PrivacyWire Banner Markup
|
||
|
$this->bodyContent .= $this->renderPrivacyWireBannerTemplate();
|
||
|
|
||
|
// 5. Insert PrivacyWire Blueprint for Consent Window Markup
|
||
|
$this->bodyContent .= $this->renderPrivacyWireConsentBlueprint();
|
||
|
|
||
|
// 6. (within ready method)
|
||
|
|
||
|
}
|
||
|
|
||
|
public function render(HookEvent $event)
|
||
|
{
|
||
|
$event->return = str_replace("</head>", "{$this->headContent}</head>", $event->return);
|
||
|
$event->return = str_replace("</body>", "{$this->bodyContent}</body>", $event->return);
|
||
|
}
|
||
|
|
||
|
public function ___renderPrivacyWireStyles()
|
||
|
{
|
||
|
$file = $this->getPrivacyWireStyles();
|
||
|
return "<style>" . file_get_contents($file->path) . "</style>";
|
||
|
}
|
||
|
|
||
|
public function ___renderPrivacyWireConfigAsInlineJs()
|
||
|
{
|
||
|
return "<script>var PrivacyWireSettings={$this->getPrivacyWireConfigObject()};</script>";
|
||
|
}
|
||
|
|
||
|
public function ___renderPrivacyWireCoreJs()
|
||
|
{
|
||
|
if ($this->output_mode === "inline") {
|
||
|
$output = "<script type='module'>" . file_get_contents($this->modulePath . "js/PrivacyWire.js") . "</script>";
|
||
|
$output .= "<script nomodule type='text/javascript'>" . file_get_contents($this->modulePath . "js/ie_polyfill.js") . "</script>";
|
||
|
$output .= "<script nomodule type='text/javascript'>" . file_get_contents($this->modulePath . "js/PrivacyWire_legacy.js") . "</script>";
|
||
|
return $output;
|
||
|
}
|
||
|
|
||
|
$output = "<script type='module' src='" . $this->moduleUrl . "js/PrivacyWire.js" . "'></script>";
|
||
|
$output .= "<script nomodule type='text/javascript' src='" . $this->moduleUrl . "js/ie_polyfill.js" . "'></script>";
|
||
|
$output .= "<script nomodule type='text/javascript' src='" . $this->moduleUrl . "js/PrivacyWire_legacy.js" . "'></script>";
|
||
|
return $output;
|
||
|
|
||
|
}
|
||
|
|
||
|
public function ___renderPrivacyWireBannerTemplate()
|
||
|
{
|
||
|
return $this->renderTemplate('PrivacyWireBanner.php', $this->alternate_banner_template);
|
||
|
}
|
||
|
|
||
|
public function ___renderPrivacyWireConsentBlueprint()
|
||
|
{
|
||
|
return $this->renderTemplate('PrivacyWireConsentBlueprint.php', $this->alternate_inline_consent_template);
|
||
|
}
|
||
|
|
||
|
protected function renderTemplate($filename, $alternatePath = '')
|
||
|
{
|
||
|
$filePath = $this->wire('config')->paths->$this . $filename;
|
||
|
|
||
|
$alternatePath = ltrim($alternatePath, '/');
|
||
|
|
||
|
if (
|
||
|
!empty($alternatePath) &&
|
||
|
file_exists($this->wire('config')->paths->root . $alternatePath)) {
|
||
|
$filePath = $this->wire('config')->paths->root . $alternatePath;
|
||
|
}
|
||
|
|
||
|
return wireRenderFile($filePath, ['module' => $this]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the PrivacyWire stylesheet as Object with path and url
|
||
|
* @return \StdClass $file with $file->path and $file->url
|
||
|
*/
|
||
|
public function ___getPrivacyWireStyles(): \StdClass
|
||
|
{
|
||
|
$file = new \StdClass;
|
||
|
$file->name = "css/PrivacyWire.css";
|
||
|
$file->path = $this->modulePath . $file->name;
|
||
|
$file->url = $this->moduleUrl . $file->name;
|
||
|
return $file;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param bool $legacy
|
||
|
* @return \StdClass $file with $file->path and $file->url
|
||
|
* @deprecated since version 1.0.2
|
||
|
* Get the PrivacyWire Core file as Object with path and url
|
||
|
*/
|
||
|
public function ___getPrivacyWireCore(bool $legacy = false): \StdClass
|
||
|
{
|
||
|
$file = new \StdClass;
|
||
|
$file->name = "js/PrivacyWire" . ($legacy ? '_legacy' : '') . ".js";
|
||
|
$file->path = $this->modulePath . $file->name;
|
||
|
$file->url = $this->moduleUrl . $file->name;
|
||
|
|
||
|
return $file;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the current PrivacyWire config options and output them as JSON Object
|
||
|
* @return string JSON Object of PrivacyWire config options
|
||
|
*/
|
||
|
public function ___getPrivacyWireConfigObject(): string
|
||
|
{
|
||
|
$privacyWireSettings = new \StdClass;
|
||
|
$privacyWireSettings->version = $this->version;
|
||
|
$privacyWireSettings->dnt = ($this->respectDNT) ? "1" : "0";
|
||
|
$privacyWireSettings->bots = ($this->checkForBots) ? "1" : "0";
|
||
|
$privacyWireSettings->customFunction = ($this->wire('sanitizer')->text($this->trigger_custom_js_function)) ?? "";
|
||
|
$privacyWireSettings->messageTimeout = ($this->messageTimeout && intval($this->messageTimeout) > 1) ? intval($this->messageTimeout) : 1500;
|
||
|
$privacyWireSettings->consentByClass = ($this->detect_consents_by_class) ? "1" : "0";
|
||
|
$privacyWireSettings->cookieGroups = [
|
||
|
'necessary' => $this->get("cookies_necessary_label{$this->lang}|cookies_necessary_label"),
|
||
|
'functional' => $this->get("cookies_functional_label{$this->lang}|cookies_functional_label"),
|
||
|
'statistics' => $this->get("cookies_statistics_label{$this->lang}|cookies_statistics_label"),
|
||
|
'marketing' => $this->get("cookies_marketing_label{$this->lang}|cookies_marketing_label"),
|
||
|
'external_media' => $this->get("cookies_external_media_label{$this->lang}|cookies_external_media_label"),
|
||
|
];
|
||
|
return json_encode($privacyWireSettings);
|
||
|
}
|
||
|
}
|