Commit 718248ea authored by Jakob Moser's avatar Jakob Moser
Browse files

Merge branch '19-add-re-usable-code-that-makes-map-embedding-easier' into 'master'

Add privacy consent prompt

See merge request !25
parents 430964c3 5b6d3354
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
@@ -54,4 +54,101 @@ function fscoli_embed_umap($regex_matches, $embed_attrs, $url, $raw_embed_attrs)
    HTML;
}
wp_embed_register_handler('umap', '#^https://umap.openstreetmap.de/[a-z]{2}/map/[^/]*#', 'fscoli_embed_umap');

/**
 * Helper function: Matches the given regex against the given string and
 * returns the $group-th match group of the match. Returns null if there is
 * no such group or there was no match.
 */
function fscoli_regex_match_group($regex, $str, $group) {
    preg_match($regex, $str, $matches);
    /* 
     * Q: Wait, where did $matches suddenly come from?
     * A: We passed it by reference (https://www.php.net/manual/en/language.references.pass.php). This means
     * we told the function it should store its results in a variable we can later access as $matches.
     * Yes, that's a thing in some programming languages.
     */ 
    if(array_key_exists($group, $matches)) {
        return $matches[$group];
    } else {
        return null;
    }
}

/**
 * Helper function: Builds a consent prompt (HTML and JS) using the given parameters, that already have to be extracted
 * from somewhere.
 */
function fscoli_get_consent_prompt($embed_html, $width_attr, $height_attr, $content_name, $provider_url, $provider_domain, $privacy_policy_url) {
    $embed_html = esc_html($embed_html);
    $width_attr = esc_attr($width_attr);
    $height_attr = esc_attr($height_attr);
    $content_name = esc_html($content_name);
    $provider_url = esc_url($provider_url);
    $provider_domain = esc_html($provider_domain);
    
    if($privacy_policy_url !== null) {
        $privacy_policy_url = esc_url($privacy_policy_url);
        $privacy_policy_link = <<<HTML
        <a href="$privacy_policy_url">dort verlinkte Datenschutzerklärung</a>
        HTML;
    } else {
        $privacy_policy_link = "dort verlinkte Datenschutzerklärung";
    }

    /* 
     * We use the heredoc syntax (https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc)
     * to embed a multiline string in this document. Heredocs can be delimited by any string - we chose HTML, but EOT and END
     * are more commonly used options. Funny enough, when we use HTML to delimit the heredoc, at least Visual Studio Code
     * applies HTML syntax highlighting to the string...
     */ 
    return <<<HTML
    <div class="privacy-consent-prompt-area" style="width: $width_attr; height: $height_attr;">
        <div class="unloaded-content">
            $embed_html
        </div>

        <section class="privacy-consent-prompt">
            <button onclick="givePrivacyConsent(this.parentElement.parentElement)">$content_name anzeigen</button>
            <p>Dabei werden Daten an <a href="$provider_url">$provider_domain</a> (und ggfs. weitere Anbieter) übertragen. Es gilt die $privacy_policy_link.</p>
        </section>
    </div>

    <script>
        function givePrivacyConsent(consentPromptArea) {
            consentPromptArea.outerHTML = consentPromptArea.querySelector(".unloaded-content").textContent
        }
    </script>
    HTML;
}

/*
 * Add privacy protection for embed elements: You have to click a button of a consent prompt
 * before the content is loaded.
 */
function fscoli_show_embed_privacy_consent_prompt($embed_html) {
    // Try to guess width and height of the consent prompt to match the dimensions of the embedded content
    // We try to extract them from CSS properties (e.g. width: 150px) or HTML attributes (width="150px").
    $width              = fscoli_regex_match_group('/width ?(:|= ?["\']) ?(\d+ ?px)/', $embed_html, 2);
    $height             = fscoli_regex_match_group('/height ?(:|= ?["\']) ?(\d+ ?px)/', $embed_html, 2);
    if($width === null) { $width = "auto"; }
    if($height === null) { $height = "auto"; }

    // Try to guess the URL of the content provider, its domain and, using a hardcoded list of policies,
    // its privacy policy.
    $provider_url       = fscoli_regex_match_group('#src ?= ?["\'](https?://(.*?))/.*?["\']#', $embed_html, 1);
    $provider_domain    = fscoli_regex_match_group('#src ?= ?["\'](https?://(.*?))/.*?["\']#', $embed_html, 2);

    $privacy_policy_url = null;
    $content_name = "Inhalt";
    if($provider_domain === "umap.openstreetmap.de") {
        $privacy_policy_url = "https://www.fossgis.de/datenschutzerkl%C3%A4rung";
        $content_name = "Karte";
    }

    return fscoli_get_consent_prompt($embed_html, $width, $height, $content_name, $provider_url, $provider_domain, $privacy_policy_url);   
}

// To disable the privacy consent prompts (and always show the content directly), just remove this line
add_filter('embed_handler_html', 'fscoli_show_embed_privacy_consent_prompt');
?>
+1 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 * Author: personads :: Maximilian Müller-Eberstein (ursprüngliche Version und Design); Jakob Moser (Code-Rewrite)
 * Author URI: https://personads.me/
 *
 * Version: 1.9.0
 * Version: 1.10.0
 *
 * License: GNU General Public License v3.0
 * License URI: https://www.gnu.org/licenses/gpl-3.0.html