      1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246:

    <?php

    namespace WPGMZA;

    /**
     * This module handles all GDPR functionality for the plugin, including
     * displaying notices, settings and handling logic
     */
    class GDPRCompliance
    {
        private static $filtersBound = false;

        public function __construct()
        {
            if(!GDPRCompliance::$filtersBound)
            {
                add_filter('wpgmza_global_settings_tabs', array($this, 'onGlobalSettingsTabs'));
                add_filter('wpgmza_global_settings_tab_content', array($this, 'onGlobalSettingsTabContent'), 10, 1);

                add_filter('wpgmza_plugin_get_default_settings', array($this, 'onPluginGetDefaultSettings'));

                GDPRCompliance::$filtersBound = true;
            }

            add_action('wp_ajax_wpgmza_gdpr_privacy_policy_notice_dismissed', array($this, 'onPrivacyPolicyNoticeDismissed'));

            //add_action('admin_notices', array($this, 'onAdminNotices'));
            //add_action('admin_post_wpgmza_dismiss_admin_gdpr_warning', array($this, 'onDismissAdminWarning'));

            //$this->setDefaultSettings();
        }

        /**
         * Gets the default GDPR settings
         * @return array An array of key value pairs where the key is the setting name
         */
        public function getDefaultSettings()
        {
            return array(
                'wpgmza_gdpr_enabled'           => 1,
                'wpgmza_gdpr_default_notice'    => apply_filters('wpgmza_gdpr_notice',
                                                __('<p>
        I agree for my personal data to be processed by <span name="wpgmza_gdpr_company_name"></span>, for the purpose(s) of <span name="wpgmza_gdpr_retention_purpose"></span>.
    </p>

    <p>
        I agree for my personal data, provided via map API calls, to be processed by the API provider, for the purposes of geocoding (converting addresses to coordinates), reverse geocoding and   generating directions.
    </p>
    <p>
        Some visual components of WP Google Maps use 3rd party libraries which are loaded over the network. At present the libraries are Google Maps, Open Street Map, jQuery DataTables and FontAwesome. When loading resources over a network, the 3rd party server will receive your IP address and User Agent string amongst other details. Please refer to the Privacy Policy of the respective libraries for details on how they use data and the process to exercise your rights under the GDPR regulations.
    </p>
    <p>
        WP Google Maps uses jQuery DataTables to display sortable, searchable tables, such as that seen in the Advanced Marker Listing and on the Map Edit Page. jQuery DataTables in certain circumstances uses a cookie to save and later recall the "state" of a given table - that is, the search term, sort column and order and current page. This data is held in local storage and retained until this is cleared manually. No libraries used by WP Google Maps transmit this information.
    </p>
    <p>
        Please <a href="https://developers.google.com/maps/terms">see here</a> and <a href="https://maps.google.com/help/terms_maps.html">here</a> for Google\'s terms. Please also see <a href="https://policies.google.com/privacy?hl=en-GB&amp;gl=uk">Google\'s Privacy Policy</a>. We do not send the API provider any personally identifying information, or information that could uniquely identify your device.
    </p>
    <p>
        Where this notice is displayed in place of a map, agreeing to this notice will store a cookie recording your agreement so you are not prompted again.
    </p>'), 'wp-google-maps'),

                'wpgmza_gdpr_company_name'      => get_bloginfo('name'),
                'wpgmza_gdpr_retention_purpose' => 'displaying map tiles, geocoding addresses and calculating and display directions.'
            );
        }

        /**
         * Hooks into wpgmza_plugin_get_default_settings filter, to add the default GDPR settings
         * @param array The settings array passed in by the Plugin instance
         */
        public function onPluginGetDefaultSettings($settings)
        {
            return array_merge($settings, $this->getDefaultSettings());
        }

        /**
         * Called when the user dismisses the "check our updated privacy policy" admin notice, this call is made over AJAX. This sets a flag so the notice isn't displayed again.
         * @return void
         */
        public function onPrivacyPolicyNoticeDismissed()
        {
            $wpgmza_other_settings = get_option('WPGMZA_OTHER_SETTINGS');
            $wpgmza_other_settings['privacy_policy_notice_dismissed'] = true;

            update_option('WPGMZA_OTHER_SETTINGS', $wpgmza_other_settings);

            wp_send_json(array(
                'success' => 1
            ));

            exit;
        }

        /**
         * Called by onGlobalSettingsTabContent to add the content to our GDPR tab on the settings page, triggered by the filter wpgmza_global_settings_tab_content.
         * @return DOMDocument The GDPR tab content
         */
        protected function getSettingsTabContent()
        {
            global $wpgmza;

            $settings = array_merge(
                (array)$this->getDefaultSettings(),
                get_option('WPGMZA_OTHER_SETTINGS')
            );

            $document = new DOMDocument();
            $document->loadPHPFile(plugin_dir_path(__DIR__) . 'html/gdpr-compliance-settings.html.php');

            $document = apply_filters('wpgmza_gdpr_settings_tab_content', $document);

            $document->populate($settings);

            return $document;
        }

        /**
         * Gets the HTML for the GDPR notice to display on the front end.
         * @param bool $checkbox Whether to include a consent checkbox.
         * @return string The HTML string for the GDPR notice
         */
        public function getNoticeHTML($checkbox=true)
        {
            $wpgmza_other_settings = array_merge( (array)$this->getDefaultSettings(), get_option('WPGMZA_OTHER_SETTINGS') );

            $html = $wpgmza_other_settings['wpgmza_gdpr_default_notice'];

            if(!empty($wpgmza_other_settings['wpgmza_gdpr_override_notice']) && !empty($wpgmza_other_settings['wpgmza_gdpr_notice_override_text']))
                $html = $wpgmza_other_settings['wpgmza_gdpr_notice_override_text'];

            $company_name           = (empty($wpgmza_other_settings['wpgmza_gdpr_company_name']) ? '' : $wpgmza_other_settings['wpgmza_gdpr_company_name']);
            $retention_period_days  = (empty($wpgmza_other_settings['wpgmza_gdpr_retention_period_days']) ? '' : $wpgmza_other_settings['wpgmza_gdpr_retention_period_days']);
            $retention_purpose      = (empty($wpgmza_other_settings['wpgmza_gdpr_retention_purpose']) ? '' : $wpgmza_other_settings['wpgmza_gdpr_retention_purpose']);

            $html = preg_replace('/{COMPANY_NAME}/i', $company_name, $html);
            $html = preg_replace('/{RETENTION_PERIOD}/i', $retention_period_days, $html);
            $html = preg_replace('/{RETENTION_PURPOSE}/i', $retention_purpose, $html);

            if($checkbox)
                $html = '<input type="checkbox" name="wpgmza_ugm_gdpr_consent" required/> ' . $html;

            $html = apply_filters('wpgmza_gdpr_notice_html', $html);

            $document = new DOMDocument();
            @$document->loadHTML( utf8_decode($html) );
            $document->populate($wpgmza_other_settings);

            return $document->saveInnerBody();
        }

        /**
         * Gets the HTML for the back end "check our updated privacy policy" notice. This will return an empty string if the notice has already been dismissed.
         * @return string The notice HTML.
         */
        public function getPrivacyPolicyNoticeHTML()
        {
            global $wpgmza;

            // Dropped in 7.11.*
            return '';

            if(!empty($wpgmza->settings->privacy_policy_notice_dismissed))
                return '';

            return "
                <div id='wpgmza-gdpr-privacy-policy-notice' class='notice notice-info is-dismissible'>
                    <p>" . __('In light of recent EU GDPR regulation, we strongly recommend reviewing the <a target="_blank" href="https://www.wpgmaps.com/privacy-policy">WP Google Maps Privacy Policy</a>', 'wp-google-maps') . "</p>
                </div>
                ";
        }

        /**
         * Gets the consent prompt HTML, including the consent button.
         * @return string The prompt HTML.
         */
        public function getConsentPromptHTML()
        {
            return '<div class="wpgmza-gdpr-compliance">' . $this->getNoticeHTML(false) . "<p class='wpgmza-centered'><button class='wpgmza-api-consent'>" . __('I agree', 'wp-google-maps') . "</button></div></p>";
        }

        /**
         * Callback for the wpgmza_global_settings_tabs filter. This adds the GDPR tab. Please note this is the tab itself, as opposed to the tab content.
         * @param string $input The HTML string passed in by the filter.
         * @return string The HTML for the tab.
         */
        public function onGlobalSettingsTabs($input)
        {
            return $input . "<li><a href=\"#wpgmza-gdpr-compliance\">".__("GDPR Compliance","wp-google-maps")."</a></li>";
        }

        /**
         * Callback for the wpgmza_global_settings_tab_content filter. This adds the GPDR tab content. Please note this is for the tab content, as opposed to the tab itself.
         * @param string $input The HTML string passed in by the filter.
         * @return string The HTML for the tab content.
         */
        public function onGlobalSettingsTabContent($input)
        {
            $document = $this->getSettingsTabContent();
            return $input . $document->saveInnerBody();
        }

        /**
         * Handles POST data when the settings page saves.
         * @return void
         */
        public function onPOST()
        {
            $document = $this->getSettingsTabContent();
            $document->populate($_POST);

            $wpgmza_other_settings = get_option('WPGMZA_OTHER_SETTINGS');
            if(!$wpgmza_other_settings)
                $wpgmza_other_settings = array();

            foreach($document->querySelectorAll('input, select, textarea') as $input)
            {
                $name = $input->getAttribute('name');

                if(!$name)
                    continue;

                switch($input->getAttribute('type'))
                {
                    case 'checkbox':
                        if($input->getValue())
                        {
                            $wpgmza_other_settings[$name] = 1;
                        }
                        else
                        {
                            unset($wpgmza_other_settings[$name]);
                        }
                        break;

                    default:
                        $wpgmza_other_settings[$name] = stripslashes( $input->getValue() );
                        break;
                }
            }

            update_option('WPGMZA_OTHER_SETTINGS', $wpgmza_other_settings);
        }
    }

    $wpgmzaGDPRCompliance = new GDPRCompliance();