Initial commit: Atomaste website

This commit is contained in:
2025-12-10 12:17:30 -05:00
commit 0b9e5d1605
19260 changed files with 5206382 additions and 0 deletions

View File

@@ -0,0 +1,703 @@
<?php defined( 'ABSPATH' ) or die( "you do not have access to this page!" );
if ( ! class_exists( "CMPLZ_COOKIE" ) ) {
/**
* All properties are public, because otherwise the empty check on a property fails, and requires an intermediate variable assignment.
* https://stackoverflow.com/questions/16918973/php-emptystring-return-true-but-string-is-not-empty
*/
class CMPLZ_COOKIE {
public $ID = false;
public $object = false;
public $name;
/**
* Sync should the cookie stay in sync or not
*
* @var bool
*/
public $sync = true;
/**
* Retention period
*
* @var string
*/
public $retention;
public $type;
public $service;
public $serviceID;
public $collectedPersonalData;
public $cookieFunction;
public $purpose;
public $isTranslationFrom;
public $lastUpdatedDate;
public $lastAddDate;
public $firstAddDate;
public $synced;
public $complete;
public $slug = '';
public $old;
public $domain;
public $isOwnDomainCookie = false;
/**
* in CDB, we can mark a cookie as not relevant to users.
*
* @var int
*/
private $ignored;
/**
* we do not actually delete it , otherwise it would be found on next run again
*
* @var
*/
public $deleted;
/**
* give user the possibility to hide a cookie
*
* @var bool
*/
public $showOnPolicy = true;
public $isMembersOnly;
private $languages;
public $language;
function __construct( $name = false, $language = 'en', $service_name = false ) {
if ( is_object($name) ){
$this->name = $name->name;
$this->ID = $name->ID;
//after the sync, we are still missing the purpose in the objects. We load the cookie from the database to get the purpose.
if ( !empty($name->purpose) ) {
$this->object = $name;
}
} else if ( is_numeric( $name ) ) {
$this->ID = (int) $name;
} else {
$this->name = $this->sanitize_cookie( $name );
}
$this->language = cmplz_sanitize_language( $language );
if ( $service_name ) {
$this->service = $service_name;
}
if ( $this->name !== false ) {
//initialize the cookie with this id.
$this->get();
}
}
/**
* Add a new cookie for each passed language.
*
* @param $name
* @param array $languages
* @param string|bool $return_language
* @param bool $service_name
* @param bool $sync_on
*
* @return bool|int cookie_id
*/
public function add(
$name, $languages = array( 'en' ), $return_language = false, $service_name = false, bool $sync_on = true
) {
//don't add cookies with the site url in the name
if ( strpos($name, site_url())!==false ) {
return false;
}
if ( !cmplz_user_can_manage() ) {
return 0;
}
$this->name = $this->sanitize_cookie( $name );
//the parent cookie gets "en" as default language
$this->language = 'en';
$return_id = 0;
$this->languages = cmplz_sanitize_languages( $languages );
//check if there is a parent cookie for this name
$this->get( true );
//if no ID is found, insert in the database
if ( ! $this->ID ) {
$this->service = $service_name;
$this->sync = $sync_on;
$this->showOnPolicy = true;
}
//we save, to update previous, but also to make sure last add date is saved.
$this->lastAddDate = time();
$this->save();
//we now should have an ID, which will be the parent item
$parent_ID = $this->ID;
if ( $return_language === 'en' ) {
$return_id = $this->ID;
}
//make sure each language is available
foreach ( $this->languages as $language ) {
if ( $language === 'en' ) {
continue;
}
$translated_cookie = new CMPLZ_COOKIE( $name, $language, $service_name );
if ( ! $translated_cookie->ID ) {
$translated_cookie->sync = $sync_on;
$translated_cookie->showOnPolicy = true;
}
$translated_cookie->domain = $this->domain;
$translated_cookie->isTranslationFrom = $parent_ID;
$translated_cookie->service = $service_name;
$translated_cookie->lastAddDate = time();
$translated_cookie->save();
if ( $return_language && $language === $return_language ) {
$return_id = $translated_cookie->ID;
}
}
return $return_id;
}
public function __get( $property ) {
if ( property_exists( $this, $property ) ) {
return $this->$property;
}
}
public function __set( $property, $value ) {
if ( property_exists( $this, $property ) ) {
$this->$property = $value;
}
return $this;
}
/**
* Delete this cookie, and all translations linked to it.
*/
public function delete($permanently=false) {
if ( ! cmplz_user_can_manage() ) {
return;
}
if ( ! $this->ID ) {
return;
}
$translations = $this->get_translations();
global $wpdb;
foreach ( $translations as $ID ) {
if ($permanently){
$wpdb->delete($wpdb->prefix . 'cmplz_cookies', array('ID' => $ID));
} else {
$wpdb->update(
$wpdb->prefix . 'cmplz_cookies',
array( 'deleted' => true ),
array( 'ID' => $ID )
);
}
}
}
/**
* Restore a deleted cookie
*/
public function restore() {
if ( ! cmplz_user_can_manage() ) {
return;
}
if ( ! $this->ID ) {
return;
}
$translations = $this->get_translations();
global $wpdb;
foreach ( $translations as $ID ) {
$wpdb->update(
$wpdb->prefix . 'cmplz_cookies',
array( 'deleted' => false ),
array( 'ID' => $ID )
);
}
}
public function get_translations() {
global $wpdb;
//check if this cookie is a parent
if ( ! $this->isTranslationFrom ) {
//is parent. Get all cookies where translationfrom = this id
$parent_id = $this->ID;
} else {
//not parent.
$parent_id = $this->isTranslationFrom;
}
$sql = $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where isTranslationFrom = %s", $parent_id );
$results = $wpdb->get_results( $sql );
$translations = wp_list_pluck( $results, 'ID' );
//add the parent id
$translations[] = $parent_id;
return $translations;
}
/**
* Retrieve the cookie data from the table
*
* @param bool $parent get only the parent cookie, not a translation
*/
private function get( bool $parent = false ) {
global $wpdb;
if ( ! $this->name && ! $this->ID ) {
return;
}
$sql = '';
if ( $parent ) {
$sql = " AND isTranslationFrom = FALSE";
}
//if the service is set, we check within the service as well.
if ( $this->service ) {
$service = new CMPLZ_SERVICE($this->service, $this->language );
if ($service->ID) {
$sql .= $wpdb->prepare(" AND serviceID = %s", $service->ID);
}
}
if ($this->object){
$cookie = $this->object;
} else if ( $this->ID ) {
$cookie = wp_cache_get('cmplz_cookie_'.$this->ID, 'complianz');
if ( !$cookie ) {
$cookie = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where ID = %s ", $this->ID ) );
wp_cache_set('cmplz_cookie_'.$this->ID, $cookie, 'complianz', HOUR_IN_SECONDS);
}
} else {
$cookie = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where name = %s and language = %s $sql", $this->name, $this->language ) );
//if not found with service, try without service.
if ( !$cookie ) {
$cookie = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where name = %s and language = %s", $this->name, $this->language ) );
}
}
//if there's still no match, try to do a fuzzy match
if ( ! $cookie ) {
$cookies = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where language = %s $sql", $this->language ) );
$cookies = wp_list_pluck( $cookies, 'name', 'ID' );
$cookie_id = $this->get_fuzzy_match( $cookies, $this->name );
//if no cookie_id found yet, try without service
if ( !$cookie_id ) {
$cookies = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where language = %s", $this->language ) );
$cookies = wp_list_pluck( $cookies, 'name', 'ID' );
$cookie_id = $this->get_fuzzy_match( $cookies, $this->name );
}
if ( $cookie_id ) {
$cookie = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where ID = %s", $cookie_id ) );
}
}
if ( $cookie ) {
$this->ID = $cookie->ID;
$this->name = substr($cookie->name, 0, 200); //maximize cookie name length
$this->serviceID = $cookie->serviceID;
$this->sync = (bool) $cookie->sync;
$this->language = $cookie->language;
$this->ignored = (bool) $cookie->ignored;
$this->deleted = (bool) $cookie->deleted;
$this->retention = $cookie->retention;
$this->type = $cookie->type;
$this->isOwnDomainCookie = (bool) $cookie->isOwnDomainCookie;
$this->domain = $cookie->domain;
$this->cookieFunction = $cookie->cookieFunction;
$this->purpose = html_entity_decode($cookie->purpose);
$this->isMembersOnly = $cookie->isMembersOnly && cmplz_get_option('wp_admin_access_users') === 'yes';
$this->collectedPersonalData = $cookie->collectedPersonalData;
$this->isTranslationFrom = $cookie->isTranslationFrom;
$this->showOnPolicy = (bool) $cookie->showOnPolicy;
$this->lastUpdatedDate = $cookie->lastUpdatedDate;
$this->lastAddDate = $cookie->lastAddDate;
$this->firstAddDate = $cookie->firstAddDate;
$this->slug = $cookie->slug;
$this->synced = $cookie->lastUpdatedDate > 0;
$this->old = $cookie->lastAddDate < strtotime( '-3 months' ) && $cookie->lastAddDate > 0;
}
//legacy, upgrade data
if ( empty($this->domain) ) {
if ( $this->isOwnDomainCookie) {
$this->domain = 'self';
} else {
$this->domain = 'thirdparty';
}
}
/**
* Don't translate purpose with Polylang, as polylang does not use the fieldname to translate. This causes mixed up strings when context differs.
* To prevent newly added cookies from getting translated, only translate when not in admin or cron, leaving front-end, where cookies aren't saved.
*/
if ( $this->language !== 'en' && !is_admin() && !wp_doing_cron() ) {
if ( !defined('POLYLANG_VERSION') || !$this->sync ) {
if (!empty($this->purpose) ) $this->purpose = cmplz_translate($this->purpose, 'cookie_purpose');
}
if (!empty( $this->retention ) ) $this->retention = cmplz_translate( $this->retention, 'cookie_retention' );
if (!empty( $this->cookieFunction) ) $this->cookieFunction = cmplz_translate($this->cookieFunction, 'cookie_function');
if (!empty( $this->collectedPersonalData) ) $this->collectedPersonalData = cmplz_translate($this->collectedPersonalData, 'cookie_collected_personal_data');
}
/**
* complianz cookie retention can be retrieved form this site
*/
if ( !empty( $this->name) ) {
if ( strpos( $this->name, 'cmplz' ) !== false || strpos( $this->name, 'complianz' ) !== false ) {
$this->retention = cmplz_sprintf( __( "%s days", "complianz-gdpr" ), cmplz_get_option( 'cookie_expiry' ) );
}
}
//get serviceid from service name
if ( $this->serviceID ) {
$service = new CMPLZ_SERVICE( $this->serviceID, $this->language );
$this->service = $service->name;
}
$this->complete = ( !empty( $this->name )
&& !empty( $this->purpose )
&& !empty( $this->retention )
&& !empty( $this->service )
);
}
/**
* - opslaan service ID met ID uit CDB
* - Als SERVICE ID er nog niet is, toevoegen in tabel
* - Synce services met CDB
*/
/**
* Saves the data for a given Cookie, or creates a new one if no ID was passed.
*
* @param bool $updateAllLanguages
*/
public function save( $updateAllLanguages = false ) {
if ( !cmplz_user_can_manage() ) {
return;
}
//let's skip cookies with this site url in the name
if ( strpos($this->name, site_url())!==false ) {
return;
}
//don't save empty items.
if ( empty( $this->name ) ) {
return;
}
//get serviceid from service name
if ( !empty( $this->service ) ) {
$service = new CMPLZ_SERVICE( $this->service, $this->language );
if ( ! $service->ID ) {
$languages = $this->get_used_languages();
$this->serviceID = $service->add( $this->service, $languages, $this->language );
} else {
$this->serviceID = $service->ID;
}
}
/**
* complianz cookie retention can be retrieved from this site
*/
if ( strpos( $this->name, 'cmplz' ) !== false || strpos( $this->name, 'complianz' ) !== false ) {
$this->retention = cmplz_sprintf( __( "%s days", "complianz-gdpr" ), cmplz_get_option( 'cookie_expiry' ) );
}
/**
* Don't translate with Polylang, as polylang does not use the fieldname to translate. This causes mixed up strings when context differs.
*/
if ( $this->language === 'en' ) {
if ( ! defined( 'POLYLANG_VERSION' ) || ! $this->sync ) {
cmplz_register_translation( $this->purpose, 'cookie_purpose' );
}
cmplz_register_translation( $this->retention, 'cookie_retention' );
cmplz_register_translation( $this->cookieFunction, 'cookie_function' );
cmplz_register_translation( $this->collectedPersonalData, 'cookie_collected_personal_data' );
}
//update legacy data
if ( empty($this->domain) ) {
if ( $this->isOwnDomainCookie ) {
$this->domain = 'self';
} else {
$this->domain = 'thirdparty';
}
}
$update_array = array(
'name' => sanitize_text_field( $this->name ),
'retention' => sanitize_text_field( $this->retention ),
'type' => sanitize_text_field( $this->type ),
'isOwnDomainCookie' => (bool) $this->isOwnDomainCookie,
'serviceID' => (int) $this->serviceID,
'domain' => sanitize_text_field( $this->domain ),
'cookieFunction' => sanitize_text_field( $this->cookieFunction ),
'purpose' => sanitize_text_field( $this->purpose ),
'isMembersOnly' => (bool) $this->isMembersOnly,
'collectedPersonalData' => sanitize_text_field( $this->collectedPersonalData ),
'sync' => $this->sync,
'ignored' => (bool) $this->ignored,
'deleted' => (bool) $this->deleted,
'language' => cmplz_sanitize_language( $this->language ),
'isTranslationFrom' => (int) $this->isTranslationFrom,
'showOnPolicy' => $this->showOnPolicy,
'lastUpdatedDate' => (int) $this->lastUpdatedDate,
'lastAddDate' => (int) $this->lastAddDate,
'slug' => empty($this->slug) ? '' : sanitize_title( $this->slug ),
);
if ( empty( $this->firstAddDate) ) {
$update_array['firstAddDate'] = time();
}
global $wpdb;
//if we have an ID, we update the existing value
if ( $this->ID ) {
$wpdb->update( $wpdb->prefix . 'cmplz_cookies', $update_array, array( 'ID' => $this->ID ) );
} else {
$wpdb->insert( $wpdb->prefix . 'cmplz_cookies', $update_array );
$this->ID = $wpdb->insert_id;
}
if ( $updateAllLanguages ) {
//keep all translations in sync
$translationIDS = $this->get_translations();
foreach ( $translationIDS as $translationID ) {
if ( $this->ID == $translationID ) {
continue;
}
$translation = new CMPLZ_COOKIE( $translationID );
$translation->name = $this->name;
$translation->serviceID = $this->serviceID;
$translation->sync = $this->sync;
$translation->isMembersOnly = $this->isMembersOnly;
$translation->slug = $this->slug;
$translation->showOnPolicy = $this->showOnPolicy;
$translation->deleted = $this->deleted;
$translation->ignored = $this->ignored;
$translation->domain = $this->domain;
$translation->save();
}
}
cmplz_delete_transient('cmplz_cookie_shredder_list');
wp_cache_delete('cmplz_cookie_'.$this->ID, 'complianz');
}
private function get_used_languages() {
global $wpdb;
$sql = "SELECT language FROM {$wpdb->prefix}cmplz_cookies group by language";
$languages = $wpdb->get_results( $sql );
$languages = wp_list_pluck( $languages, 'language' );
return $languages;
}
/**
* Validate a cookie string
*
* @param $cookie
*
* @return string|bool
*/
private function sanitize_cookie( $cookie ) {
if ( ! $this->is_valid_cookie( $cookie ) ) {
return false;
}
$cookie = sanitize_text_field( $cookie );
//100 characters max
$cookie = substr($cookie, 0, 100);
//remove whitespace
$cookie = trim( $cookie );
//strip double and single quotes
$cookie = str_replace( '"', '', $cookie );
return str_replace( "'", '', $cookie );
}
/**
* Check if a cookie is of a valid cookie structure
*
* @param $id
*
* @return bool
*/
private function is_valid_cookie( $id ) {
if ( ! is_string( $id ) || empty($id) ) {
return false;
}
$pattern = '/[a-zA-Z0-9\_\-\*]/i';
return (bool) preg_match( $pattern, $id );
}
private function get_fuzzy_match( $cookies, $search ) {
//to prevent match from wp_comment_123 on wp_*
//we keep track of all matches, and only return the longest match, which is the closest match.
$match = false;
$new_match = false;
$match_length = 0;
$new_match_length = 0;
$partial = '*';
//clear up items without any match possibility
foreach ( $cookies as $post_id => $cookie_name ) {
if ( strpos( $cookie_name, $partial ) === false ) {
unset( $cookies[ $post_id ] );
}
}
foreach ( $cookies as $post_id => $compare_cookie_name ) {
//check if the string "partial" is in the comparison cookie name
//check if it has an underscore before or after the partial. If so, take it into account
//get the substring before or after the partial
$str1 = substr( $compare_cookie_name, 0,
strpos( $compare_cookie_name, $partial ) );
$str2 = substr( $compare_cookie_name,
strpos( $compare_cookie_name, $partial )
+ strlen( $partial ) );
//a partial match is enough on this type
//$str2: match should end with this string
if ( strlen( $str1 ) === 0 ) {
$len = strlen( $search ); //"*test" : 5
$pos = strpos( $search, $str2 ); //"*test" : 1
$sub_len = strlen( $str2 ); // 4
if ( $pos !== false && ( $len - $sub_len == $pos ) ) {
$new_match_length = strlen( $str1 ) + strlen( $str2 );
$new_match = $post_id;
}
//match should start with this string
} elseif ( strlen( $str2 ) === 0 ) {
$pos = strpos( $search, $str1 );
if ( $pos === 0 ) {
$new_match_length = strlen( $str1 ) + strlen( $str2 );
$new_match = $post_id;
}
} else {
$len2 = strlen( $search ); //"*test" : 5
$pos2 = strpos( $search, $str2 ); //"*test" : 1
$sub_len2 = strlen( $str2 ); // 4
if ( strpos( $search, $str1 ) === 0
&& strpos( $search, $str2 ) !== false
&& ( $len2 - $sub_len2 == $pos2 )
) {
$new_match_length = strlen( $str1 ) + strlen( $str2 );
$new_match = $post_id;
}
}
if ( $new_match_length > $match_length ) {
$match_length = $new_match_length;
$match = $new_match;
}
}
return $match;
}
}
}
/**
* Install cookies table
* */
add_action( 'cmplz_install_tables', 'cmplz_install_cookie_table' );
function cmplz_install_cookie_table() {
//only load on front-end if it's a cron job
if ( !is_admin() && !wp_doing_cron() ) {
return;
}
if (!wp_doing_cron() && !cmplz_user_can_manage() ) {
return;
}
if ( get_option( 'cmplz_cookietable_version' ) != cmplz_version ) {
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'cmplz_cookies';
$sql = "CREATE TABLE $table_name (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
`slug` varchar(250) NOT NULL,
`sync` int(11) NOT NULL,
`ignored` int(11) NOT NULL,
`retention` text NOT NULL,
`type` text NOT NULL,
`serviceID` int(11) NOT NULL,
`cookieFunction` text NOT NULL,
`collectedPersonalData` text NOT NULL,
`purpose` text NOT NULL,
`language` varchar(6) NOT NULL,
`isTranslationFrom` int(11) NOT NULL,
`isOwnDomainCookie` int(11) NOT NULL,
`domain` text NOT NULL,
`deleted` int(11) NOT NULL,
`isMembersOnly` int(11) NOT NULL,
`showOnPolicy` int(11) NOT NULL,
`lastUpdatedDate` int(11) NOT NULL,
`lastAddDate` int(11) NOT NULL,
`firstAddDate` int(11) NOT NULL,
PRIMARY KEY (ID)
) $charset_collate;";
dbDelta( $sql );
/**
* Services
*/
$table_name = $wpdb->prefix . 'cmplz_services';
$sql = "CREATE TABLE $table_name (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
`slug` varchar(250) NOT NULL,
`serviceType` varchar(250) NOT NULL,
`category` varchar(250) NOT NULL,
`thirdParty` int(11) NOT NULL,
`sharesData` int(11) NOT NULL,
`secondParty` int(11) NOT NULL,
`privacyStatementURL` varchar(250) NOT NULL,
`language` varchar(6) NOT NULL,
`isTranslationFrom` int(11) NOT NULL,
`sync` int(11) NOT NULL,
`lastUpdatedDate` int(11) NOT NULL,
PRIMARY KEY (ID)
) $charset_collate;";
dbDelta( $sql );
//don't set to preload false, as we need this one in the get_cookies function.
update_option( 'cmplz_cookietable_version', cmplz_version );
}
}

View File

@@ -0,0 +1,883 @@
<?php
defined( 'ABSPATH' ) or die();
if ( ! class_exists( "cmplz_scan" ) ) {
class cmplz_scan {
private static $_this;
function __construct() {
if ( isset( self::$_this ) ) {
wp_die( sprintf( '%s is a singleton class and you cannot create a second instance.',
get_class( $this ) ) );
}
self::$_this = $this;
if ( cmplz_scan_in_progress() ) {
add_action( 'wp_print_footer_scripts', array( $this, 'test_cookies' ), PHP_INT_MAX, 2 );
}
add_action( 'cmplz_every_day_hook', array( $this, 'track_cookie_changes' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
add_action( 'admin_footer', array( $this, 'run_cookie_scan' ) );
add_filter( 'cmplz_do_action', array( $this, 'get_scan_progress' ), 10, 3 );
add_filter( 'cmplz_do_action', array( $this, 'reset_scan' ), 11, 3 );
add_filter( 'cmplz_every_five_minutes_hook', array( $this, 'background_remote_scan' ), 11, 3 );
}
static function this() {
return self::$_this;
}
/**
* If the remote scan is active, or has started, and we're not on a complianz page, run this on cron in the background
* @return void
*/
public function background_remote_scan(){
if ( !wp_doing_cron() ) {
return;
}
if ( isset($_GET['page'] ) && $_GET['page'] === 'complianz' ) {
return;
}
$url = $this->get_next_page_url();
if ( ! $url ) {
return;
}
if ( $url === 'remote' && !COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
//as the wsc cookie scan has a wait of 10 seconds on each request, we do this on cron
do_action('cmplz_remote_cookie_scan');
}
}
/**
* Check if there are any new cookies added
*/
public function track_cookie_changes() {
if ( ! cmplz_user_can_manage() ) {
return;
}
//only run if all pages are scanned.
if ( ! $this->scan_complete() ) {
return;
}
//check if anything was changed
$new_cookies = COMPLIANZ::$banner_loader->get_cookies( array( 'new' => true ) );
if ( count( $new_cookies ) > 0 ) {
$this->set_cookies_changed();
}
}
/**
* Set the cookies as having been changed
*/
public function set_cookies_changed() {
update_option( 'cmplz_changed_cookies', 1 , false);
}
/**
* Check if cookies have been changed
*
* @return bool
*/
public function cookies_changed() {
return ( get_option( 'cmplz_changed_cookies' ) == 1 );
}
/**
* Delete the transient that contains the pages list
*
* @param int $post_id
* @param bool $post_after
* @param bool $post_before
*/
public function clear_pages_list( int $post_id, $post_after = false, $post_before = false ) {
delete_transient( 'cmplz_pages_list' );
}
/**
* Clean up duplicate cookie names
*
* @return void
*/
public function clear_double_cookienames() {
if ( ! cmplz_user_can_manage() ) {
return;
}
global $wpdb;
$languages = COMPLIANZ::$banner_loader->get_supported_languages();
//first, delete all cookies with a language not in the $languages array
$wpdb->query( "DELETE from {$wpdb->prefix}cmplz_cookies where language NOT IN ('" . implode( "','", $languages ) . "')" );
foreach ( $languages as $language ) {
$settings = array(
'language' => $language,
'isMembersOnly' => 'all',
);
$cookies = COMPLIANZ::$banner_loader->get_cookies( $settings );
foreach ( $cookies as $cookie ) {
$same_name_cookies
= $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where name = %s and language = %s and serviceID = %s ",
$cookie->name, $language, $cookie->serviceID ) );
if ( count( $same_name_cookies ) > 1 ) {
array_shift( $same_name_cookies );
$IDS = wp_list_pluck( $same_name_cookies, 'ID' );
$sql = implode( ' OR ID =', $IDS );
$sql = "DELETE from {$wpdb->prefix}cmplz_cookies where ID=" . $sql;
$wpdb->query( $sql );
}
}
$settings = array(
'language' => $language,
);
$services = COMPLIANZ::$banner_loader->get_services( $settings );
foreach ( $services as $service ) {
$same_name_services = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_services where name = %s and language = %s", $service->name, $language ) );
if ( count( $same_name_services ) > 1 ) {
array_shift( $same_name_services );
$IDS = wp_list_pluck( $same_name_services, 'ID' );
$sql = implode( ' OR ID =', $IDS );
$sql = "DELETE from {$wpdb->prefix}cmplz_services where ID=" . $sql;
$wpdb->query( $sql );
}
}
}
}
/**
* Here we add scripts and styles for the wysywig editor on the backend
* @param string $hook
*
* */
public function enqueue_admin_assets( $hook ) {
if ( isset( $_GET['page'] ) && $_GET['page'] === 'complianz' ) {
//script to check for ad blockers
wp_enqueue_script( 'cmplz-ad-checker', cmplz_url . "assets/js/ads.js", array(), cmplz_version, true );
}
}
/**
* Get all cookies, and post back to site with ajax.
* This script is only inserted when a valid token is passed, so will never run for other visitors than the site admin
*
* */
public function test_cookies() {
if ( $this->scan_complete() ) {
return;
}
if (!isset($_GET['complianz_scan_token']) || !isset($_GET['complianz_id'])){
return;
}
$token = sanitize_title( $_GET['complianz_scan_token'] );
$id = sanitize_title( $_GET['complianz_id'] );
$admin_url = esc_url_raw( rest_url('complianz/v1/') );
$nonce = wp_create_nonce( 'wp_rest' );
$javascript = cmplz_get_template( 'test-cookies.js' );
$javascript = str_replace( array(
'{admin_url}',
'{token}',
'{id}',
'{nonce}'
), array(
esc_url_raw( $admin_url ),
esc_attr( $token ),
esc_attr( $id ),
$nonce
), $javascript );
?>
<script>
<?php echo $javascript;?>
</script>
<?php
}
/**
* Insert an iframe to retrieve front-end cookies
*
*
* */
public function run_cookie_scan(): void {
if ( ! cmplz_admin_logged_in() ) {
return;
}
if ( get_option('cmplz_activation_time') > strtotime('-30 minutes') ) {
return;
}
if ( defined( 'CMPLZ_DO_NOT_SCAN' ) && CMPLZ_DO_NOT_SCAN ) {
return;
}
if ( isset( $_GET['complianz_scan_token'] ) ) {
return;
}
//if the last cookie scan date is more than a month ago, we re-scan.
$last_scan_date = COMPLIANZ::$banner_loader->get_last_cookie_scan_date( true );
$scan_interval = apply_filters( 'cmplz_scan_interval', 3 );
$one_month_ago = strtotime( "-".$scan_interval." month" );
if (
( $one_month_ago > $last_scan_date )
&& $this->scan_complete()
&& !$this->automatic_cookiescan_disabled()
) {
$this->reset_pages_list();
}
if ( ! $this->scan_complete() ) {
if ( ! get_option( 'cmplz_synced_cookiedatabase_once' ) ) {
update_option( 'cmplz_sync_cookies_complete', false );
update_option( 'cmplz_sync_cookies_after_services_complete', false );
update_option( 'cmplz_sync_services_complete', false );
update_option( 'cmplz_synced_cookiedatabase_once', true );
}
//store the date
$timezone_offset = get_option( 'gmt_offset' );
$time = time() + ( 60 * 60 * $timezone_offset );
update_option( 'cmplz_last_cookie_scan', $time );
$url = $this->get_next_page_url();
if ( ! $url ) {
return;
}
if ( $url === 'remote' ) {
//as the wsc cookie scan has a wait of 10 seconds on each request, we do this on cron instead
//do_action('cmplz_remote_cookie_scan');
} else if ( strpos( $url, 'complianz_id' ) !== false ) {
//get the html of this page.
$response = wp_remote_get( $url );
if ( ! is_wp_error( $response ) ) {
$html = $response['body'];
$this->parse_html($html);
}
}
//load in iframe so the scripts run.
echo '<iframe id="cmplz_cookie_scan_frame" class="hidden" src="' . $url . '"></iframe>';
}
}
private function parse_html($html){
$stored_social_media = cmplz_scan_detected_social_media();
if ( ! $stored_social_media ) {
$stored_social_media = array();
}
$social_media = COMPLIANZ::$banner_loader->parse_for_social_media( $html );
$social_media = array_unique( array_merge( $stored_social_media, $social_media ), SORT_REGULAR );
update_option( 'cmplz_detected_social_media', $social_media );
$stored_thirdparty_services = cmplz_scan_detected_thirdparty_services();
if ( ! $stored_thirdparty_services ) {
$stored_thirdparty_services = array();
}
$thirdparty = $this->parse_for_thirdparty_services( $html );
$thirdparty = array_unique( array_merge( $stored_thirdparty_services, $thirdparty ), SORT_REGULAR );
update_option( 'cmplz_detected_thirdparty_services', $thirdparty );
//parse for google analytics and tagmanager, but only if the wizard wasn't completed before.
//with this data we prefill the settings and give warnings when tracking is doubled
if ( ! COMPLIANZ::$banner_loader->wizard_completed_once() ) {
$this->parse_for_statistics_settings( $html );
}
if ( preg_match_all( '/ga\.js/', $html ) > 1
|| preg_match_all( '/analytics\.js/', $html ) > 1
|| preg_match_all( '/googletagmanager\.com\/gtm\.js/', $html ) > 1
|| preg_match_all( '/piwik\.js/', $html ) > 1
|| preg_match_all( '/matomo\.js/', $html ) > 1
|| preg_match_all( '/getclicky\.com\/js/', $html ) > 1
|| preg_match_all( '/mc\.yandex\.ru\/metrika\/watch\.js/', $html ) > 1
) {
update_option( 'cmplz_double_stats', true );
} else {
delete_option( 'cmplz_double_stats' );
}
$stored_stats = cmplz_scan_detected_stats();
if ( ! $stored_stats ) {
$stored_stats = array();
}
$stats = $this->parse_for_stats( $html );
$stats = array_unique( array_merge( $stored_stats, $stats ), SORT_REGULAR );
update_option( 'cmplz_detected_stats', $stats );
}
/**
* Check a string for statistics
*
* @param string $html
* @param bool $single_key //return a single string instead of array
*
* @return array|string $thirdparty
*
* */
public function parse_for_stats( $html, $single_key = false ) {
$stats = array();
$stats_markers = COMPLIANZ::$config->stats_markers;
foreach ( $stats_markers as $key => $markers ) {
foreach ( $markers as $marker ) {
if ( $single_key && strpos( $html, $marker ) !== false ) {
return $key;
}
if ( strpos( $html, $marker ) !== false && ! in_array( $key, $stats ) ) {
if ( $single_key ) {
return $key;
}
$stats[] = $key;
}
}
}
if ( $single_key ) {
return false;
}
return $stats;
}
/**
* Run once to retrieve the settings for most used stats tools
*
* @param $html
*/
private function parse_for_statistics_settings( $html ) {
if ( strpos( $html, 'gtm.js' ) !== false || strpos( $html, 'gtm.start' ) !== false
) {
update_option( 'cmplz_detected_stats_type', true );
$pattern = '/(\'|")(GTM-[A-Z]{7})(\'|")/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[2] ) ) {
cmplz_update_option_no_hooks('gtm_code', sanitize_text_field( $matches[2] ) );
update_option( 'cmplz_detected_stats_data', true );
cmplz_update_option('compile_statistics', 'google-tag-manager' );
}
}
if ( strpos( $html, 'analytics.js' ) !== false || strpos( $html, 'ga.js' ) !== false || strpos( $html, '_getTracker' ) !== false ) {
update_option( 'cmplz_detected_stats_type', true );
$pattern = '/(\'|")(UA-[0-9]{8}-[0-9]{1})(\'|")/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[2] ) ) {
cmplz_update_option('ua_code', sanitize_text_field( $matches[2] ) );
cmplz_update_option('compile_statistics', 'google-analytics' );
}
//gtag
$pattern = '/(\'|")(G-[0-9a-zA-Z]{10})(\'|")/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[2] ) ) {
cmplz_update_option('ua_code', sanitize_text_field( $matches[2] ) );
cmplz_update_option('compile_statistics', 'google-analytics' );
}
$pattern = '/\'anonymizeIp|anonymize_ip\'|:[ ]{0,1}true/i';
preg_match( $pattern, $html, $matches );
if ( $matches ) {
$value = cmplz_get_option( 'compile_statistics_more_info' );
if ( ! is_array( $value ) ) {
$value = array();
}
if ( !in_array( 'ip-addresses-blocked', $value, true )) {
$value[] = 'ip-addresses-blocked';
}
cmplz_update_option('compile_statistics_more_info', $value );
}
}
if ( strpos( $html, 'piwik.js' ) !== false || strpos( $html, 'matomo.js' ) !== false ) {
update_option( 'cmplz_detected_stats_type', true );
$pattern = '/(var u=")((https|http):\/\/.*?)"/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[2] ) ) {
cmplz_update_option('matomo_url', sanitize_text_field( $matches[2] ) );
update_option( 'cmplz_detected_stats_data', true );
}
$pattern = '/\[\'setSiteId\', \'([0-9]){1,3}\'\]\)/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[1] ) ) {
cmplz_update_option('matomo_site_id', intval( $matches[1] ) );
update_option( 'cmplz_detected_stats_data', true );
}
cmplz_update_option('compile_statistics', 'matomo' );
}
if ( strpos( $html, 'static.getclicky.com/js' ) !== false ) {
update_option( 'cmplz_detected_stats_type', true );
$pattern = '/clicky_site_ids\.push\(([0-9]{1,3})\)/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[1] ) ) {
cmplz_update_option('clicky_site_id', intval( $matches[1] ) );
update_option( 'cmplz_detected_stats_data', true );
cmplz_update_option('compile_statistics', 'clicky' );
}
}
if ( strpos( $html, 'mc.yandex.ru/metrika/watch.js' ) !== false ) {
update_option( 'cmplz_detected_stats_type', true );
$pattern = '/w.yaCounter([0-9]{1,10}) = new/i';
preg_match( $pattern, $html, $matches );
if ( $matches && isset( $matches[1] ) ) {
cmplz_update_option('yandex_id', intval( $matches[1] ) );
update_option( 'cmplz_detected_stats_data', true );
cmplz_update_option('compile_statistics', 'yandex' );
}
}
}
/**
* Check a string for third party services
*
* @param string $html
* @param bool $single_key //return a single string instead of array
*
* @return array|string $thirdparty
*
* */
public function parse_for_thirdparty_services( $html, $single_key = false ) {
$thirdparty = array();
$thirdparty_markers = COMPLIANZ::$config->thirdparty_service_markers;
foreach ( $thirdparty_markers as $key => $markers ) {
foreach ( $markers as $marker ) {
if ( $single_key && strpos( $html, $marker ) !== false ) {
return $key;
}
if ( strpos( $html, $marker ) !== false && ! in_array( $key, $thirdparty ) ) {
$thirdparty[] = $key;
}
}
}
if ( $single_key ) {
return false;
}
return $thirdparty;
}
private function get_next_page_url() {
if ( ! cmplz_user_can_manage() ) {
return '';
}
$token = wp_create_nonce( 'complianz_scan_token' );
$pages = array_filter($this->pages_to_process());
if ( count( $pages ) === 0 ) {
return false;
}
$id_to_process = reset( $pages );
//in case of remote, we want to wait until the process has completed before moving on to the next.
if ( $id_to_process !== 'remote' ) {
$this->set_page_as_processed( $id_to_process );
} else if ( COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
$this->set_page_as_processed( $id_to_process );
}
switch ( $id_to_process ) {
case 'remote':
return 'remote';
case 'home':
$url = site_url();
break;
case 'loginpage':
$url = wp_login_url();
break;
default:
$url = get_permalink( $id_to_process );
}
$url = add_query_arg( array(
"complianz_scan_token" => $token,
'complianz_id' => $id_to_process
), $url );
if ( is_ssl() ) {
$url = str_replace( "http://", "https://", $url );
}
return apply_filters("cmplz_next_page_url", $url);
}
/**
* Get the list of posttypes to process
* @return array
*/
public function get_scannable_post_types(){
$args = array(
'public' => true,
);
$post_types = get_post_types( $args );
unset(
$post_types['elementor_font'],
$post_types['attachment'],
$post_types['revision'],
$post_types['nav_menu_item'],
$post_types['custom_css'],
$post_types['customize_changeset'],
$post_types['cmplz-dataleak'],
$post_types['cmplz-processing'],
$post_types['user_request'],
$post_types['cookie'],
$post_types['product']
);
return apply_filters('cmplz_cookiescan_post_types',$post_types );
}
/**
*
* Get list of page id's that we want to process this set of scan requests, which weren't included in the scan before
*
* @return array $pages
* *@since 1.0
*/
public function get_pages_list_single_run() {
if ( !cmplz_user_can_manage() ) {
return [];
}
$posts = get_transient( 'cmplz_pages_list' );
if ( ! $posts ) {
$posts = ['home', 'remote'];
$all_types_posts = [];
$post_types = $this->get_scannable_post_types();
//from each post type, get one, for faster results.
foreach ( $post_types as $post_type ) {
$args = array(
'post_type' => $post_type,
'posts_per_page' => 1,
'meta_query' => array(
array(
'key' => '_cmplz_scanned_post',
'compare' => 'NOT EXISTS'
),
)
);
$new_posts = get_posts( $args );
$all_types_posts = $all_types_posts + $new_posts;
}
$all_types_array = count($all_types_posts)>0 ? wp_list_pluck($all_types_posts, 'ID') : [];
$posts = array_merge( $posts, $all_types_array );
foreach ( $post_types as $post_type ) {
$args = array(
'post__not_in' => $all_types_array,
'post_type' => $post_type,
'posts_per_page' => 5,
'meta_query' => array(
array(
'key' => '_cmplz_scanned_post',
'compare' => 'NOT EXISTS'
),
)
);
$new_posts = get_posts( $args );
$new_posts_array = count($new_posts)>0 ? wp_list_pluck($new_posts, 'ID') : [];
$posts = $posts + $new_posts_array;
}
if ( count( $posts ) === 0 && ! $this->automatic_cookiescan_disabled() ) {
/*
* If we didn't find any posts, we reset the post meta that tracks if all posts have been scanned.
* This way we will find some posts on the next scan attempt
* */
$this->reset_scanned_post_batches();
//now we need to reset the scanned pages list too
$this->reset_pages_list();
} else {
foreach ( $posts as $post_id ) {
update_post_meta( $post_id, '_cmplz_scanned_post', true );
}
}
if ( cmplz_get_option( 'wp_admin_access_users' ) === 'yes' ) {
$posts[] = 'loginpage';
}
set_transient( 'cmplz_pages_list', $posts, MONTH_IN_SECONDS );
}
return array_filter($posts);
}
/**
* Reset the list of pages
*
* @param bool $delay
* @param bool $manual //if it's manual, we always reset. If automatic scan is disabled, we do not reset.
*
* @return void
*
* @since 2.1.5
*/
public function reset_pages_list( $delay = false, $manual = false ) {
if ( ! $manual && $this->automatic_cookiescan_disabled() ) {
return;
}
if ( $manual ) {
$this->reset_scanned_post_batches();
}
if ( $delay ) {
$current_list = get_transient( 'cmplz_pages_list' );
$processed_pages = get_transient( 'cmplz_processed_pages_list' );
set_transient( 'cmplz_pages_list', $current_list, HOUR_IN_SECONDS );
set_transient( 'cmplz_processed_pages_list', $processed_pages, HOUR_IN_SECONDS );
} else {
delete_transient( 'cmplz_pages_list' );
delete_transient( 'cmplz_processed_pages_list' );
}
}
/**
* The scanned post meta is used to create batches of posts. A batch that is being processed is set to scanned.
* This is only reset when all posts have been processed, or if user has disabled automatic scanning, and the manual scan is fired.
* */
public function reset_scanned_post_batches() {
if ( ! function_exists( 'delete_post_meta_by_key' ) ) {
require_once ABSPATH . WPINC . '/post.php';
}
delete_post_meta_by_key( '_cmplz_scanned_post' );
}
/**
* Check if the automatic scan is disabled
*
* @return bool
*/
public function automatic_cookiescan_disabled() {
return cmplz_get_option( 'disable_automatic_cookiescan' ) == 1;
}
/**
* Get list of pages that were processed before
*
* @return array $pages
*/
public function get_processed_pages_list() {
$pages = get_transient( 'cmplz_processed_pages_list' );
if ( ! is_array( $pages ) ) {
$pages = array();
}
return array_filter($pages);
}
/**
* Check if the scan is complete
*
* @param void
*
* @return bool
* @since 1.0
*
* */
public function scan_complete() {
$pages = array_filter($this->pages_to_process());
return count( $pages ) === 0;
}
/**
*
* Get list of pages that still have to be processed
*
* @param void
*
* @return array $pagåes
* @since 1.0
*/
private function pages_to_process(): array {
$pages_list = $this->get_pages_list_single_run();
$processed_pages_list = $this->get_processed_pages_list();
return array_diff( $pages_list, $processed_pages_list );
}
/**
* Set a page as being processed
*
* @param $id
*
* @return void
* @since 1.0
*/
public function set_page_as_processed( $id ): void {
if ( ! cmplz_user_can_manage() ) {
return;
}
if ( $id !== 'home' && $id !== 'loginpage' && $id !== 'remote' && ! is_numeric( $id ) ) {
return;
}
$pages = $this->get_processed_pages_list();
if ( ! in_array( $id, $pages, true ) ) {
$pages[] = $id;
$expiration = $this->automatic_cookiescan_disabled() ? 10 * YEAR_IN_SECONDS : MONTH_IN_SECONDS;
set_transient( 'cmplz_processed_pages_list', $pages, $expiration );
}
}
/**
* Update the cookie policy date
*/
public function update_cookie_policy_date() {
update_option( 'cmplz_publish_date', time() );
//also reset the email notification, so it will get sent next year.
update_option( 'cmplz_update_legal_documents_mail_sent', false );
}
/**
* Get progress of the current scan to output with ajax
*
* @param array $data
* @param string $action
* @param WP_REST_Request $request
*
* @return array
*/
public function get_scan_progress( array $data, string $action, WP_REST_Request $request): array {
if (!cmplz_user_can_manage()) {
return [];
}
if ( $action === 'get_scan_progress' ) {
$timezone_offset = get_option( 'gmt_offset' );
$time = time() + ( 60 * 60 * $timezone_offset );
update_option( 'cmplz_last_cookie_scan', $time );
$next_url = $this->get_next_page_url();
if ($next_url==='remote') {
do_action('cmplz_remote_cookie_scan');
//only proceed to next page if remote scan is complete
if ( COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
$next_url = $this->get_next_page_url();
}
} else if ( strpos( $next_url, 'complianz_id' ) !== false ) {
$response = wp_remote_get( $next_url );
if ( ! is_wp_error( $response ) ) {
$html = $response['body'];
$this->parse_html($html);
}
}
$this->clear_double_cookienames();
$cookies = COMPLIANZ::$banner_loader->get_cookies();
$progress = $this->get_progress_count();
$total = count($cookies);
$current = (int) ( $progress / 100 * $total );
$cookies = array_slice( $cookies, 0, $current);
$cookies = count($cookies) > 0 ? wp_list_pluck( $cookies, 'name' ) : [];
$data = [
"progress" => $progress,
"next_page" => $next_url,
'cookies' => $cookies,
'token' => wp_create_nonce( 'complianz_scan_token' ),
];
}
return $data;
}
/**
* Rescan after a manual "rescan" command from the user
*/
public function reset_scan($data, $action, $request) {
if ( !cmplz_user_can_manage() ) {
return [];
}
if ( $action === 'scan' ) {
$scan_type = sanitize_title($request->get_param('scan_action'));
if ( $scan_type==='reset' ) {
global $wpdb;
$table_names = array( $wpdb->prefix . 'cmplz_cookies');
foreach ( $table_names as $table_name ) {
if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name ) {
$wpdb->query( "TRUNCATE TABLE $table_name" );
}
}
update_option( 'cmplz_detected_social_media', false );
update_option( 'cmplz_detected_thirdparty_services', false );
update_option( 'cmplz_detected_stats', false );
}
if ( $scan_type==='reset' || $scan_type==='restart' ) {
COMPLIANZ::$wsc_scanner->wsc_scan_reset();
$this->reset_pages_list( false, true );
COMPLIANZ::$sync->resync();
}
$data = [];
}
return $data;
}
/**
* Get progress of the scan in percentage
*
* @return float
*/
public function get_progress_count() {
$remote_scan_total = 100;
$remote_scan_progress = COMPLIANZ::$wsc_scanner->wsc_scan_progress();
$local_done = count($this->get_processed_pages_list());
$local_total = count($this->get_pages_list_single_run());
//convert local to a 100 scale
//prevent division by zero
$local_total = $local_total === 0 ? $local_done : $local_total;
$local_done = 100 * ( $local_done / $local_total);
$total = 200;
$done = $remote_scan_progress + $local_done;
$progress = 100 * ( $done / $total);
if ( $progress > 100 ) {
$progress = 100;
}
return $progress;
}
}
} //class closure

View File

@@ -0,0 +1,422 @@
<?php defined( 'ABSPATH' ) or die( "you do not have access to this page!" );
if ( ! class_exists( "CMPLZ_SERVICE" ) ) {
/**
* All properties are public, because otherwise the empty check on a property fails, and requires an intermediate variable assignment.
* https://stackoverflow.com/questions/16918973/php-emptystring-return-true-but-string-is-not-empty
*/
class CMPLZ_SERVICE {
public $ID = false;
public $name;
public $serviceType;
public $category;
public $sharesData;
public $thirdParty;
public $secondParty; //service that share data, but have cookies on the sites domain
public $sync;
public $synced;
public $privacyStatementURL;
public $isTranslationFrom;
public $lastUpdatedDate;
public $language;
public $languages;
public $complete;
public $slug;
function __construct( $ID = false, $language = 'en' ) {
$this->language = cmplz_sanitize_language( $language );
if ( $ID ) {
if ( is_numeric( $ID ) ) {
$this->ID = intval( $ID );
} else {
$this->name = $this->sanitize_service( $ID );
}
}
if ( $this->name !== false || $this->ID !== false ) {
//initialize the cookie with this id.
$this->get();
}
}
public function __get( $property ) {
if ( property_exists( $this, $property ) ) {
return $this->$property;
}
}
public function __set( $property, $value ) {
if ( property_exists( $this, $property ) ) {
$this->$property = $value;
}
return $this;
}
/**
* retrieve list of cookies with this service
*
* @return array() $cookies
*/
public function get_cookies() {
if ( ! $this->ID ) {
return array();
}
global $wpdb;
$cookies = wp_cache_get('cmplz_service_cookies_'.$this->ID, 'complianz');
if ( !$cookies ) {
$cookies = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where serviceID = %s ", $this->ID ) );
wp_cache_set('cmplz_service_cookies_'.$this->ID, $cookies, 'complianz', HOUR_IN_SECONDS);
}
return $cookies;
}
/**
* Retrieve the service data from the table
*
* @param $parent //if it should be the parent itme
*/
private function get( $parent = false ) {
global $wpdb;
if ( ! $this->name && ! $this->ID ) {
return;
}
$sql = '';
if ( $parent ) {
$sql = " AND isTranslationFrom = FALSE";
}
if ( $this->ID ) {
$service = wp_cache_get('cmplz_service_'.$this->ID, 'complianz');
if ( !$service ) {
$service = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_services where ID = %s ", $this->ID ) );
wp_cache_set('cmplz_service_'.$this->ID, $service, 'complianz', HOUR_IN_SECONDS);
}
} else {
$service = $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_services where name = %s and language = %s " . $sql, $this->name,
$this->language ) );
}
if ( $service ) {
$this->ID = $service->ID;
$this->name = $service->name;
$this->serviceType = html_entity_decode($service->serviceType);
$this->sharesData
= $service->thirdParty; //legacy, sharesData was first called thirdparty
$this->secondParty = $service->secondParty;
$this->thirdParty = $this->sharesData
&& ! $service->secondParty;
$this->sync = $service->sync;
$this->privacyStatementURL = $service->privacyStatementURL;
$this->language = $service->language;
$this->category = $service->category;
$this->isTranslationFrom = $service->isTranslationFrom;
$this->lastUpdatedDate = $service->lastUpdatedDate;
$this->synced = $this->sync && $service->lastUpdatedDate > 0 ? true : false;
$this->slug = $service->slug;
$this->complete = ! ( empty( $this->name )
|| ( empty( $this->privacyStatementURL )
&& $this->sharesData )
|| empty( $this->serviceType )
|| empty( $this->name ) );
}
}
/**
* Saves the data for a given service, ore creates a new one if no ID was passed.
* @param bool $updateAllLanguages
* @param bool $forceWizardUpdate
*/
public function save( $updateAllLanguages = false, $forceWizardUpdate = true) {
if ( !cmplz_user_can_manage() ) {
return;
}
if ( empty( $this->name ) ) {
return;
}
if ($forceWizardUpdate) {
$this->add_to_wizard( $this->name );
}
if ( $this->language === 'en' ) {
cmplz_register_translation( $this->serviceType, 'service_type' );
}
$update_array = array(
'name' => sanitize_text_field( $this->name ),
'thirdParty' => (bool) $this->sharesData,
//legacy, sharesData was first called third party.
'sharesData' => (bool) $this->sharesData,
//fluid upgrade
'secondParty' => (bool) $this->secondParty,
'sync' => (bool) $this->sync,
'serviceType' => sanitize_text_field( $this->serviceType ),
'privacyStatementURL' => sanitize_text_field( $this->privacyStatementURL ),
'language' => cmplz_sanitize_language( $this->language ),
'category' => sanitize_text_field( $this->category ),
'isTranslationFrom' => sanitize_text_field( $this->isTranslationFrom ),
'lastUpdatedDate' => (int) $this->lastUpdatedDate,
'slug' => empty($this->slug) ? '' : sanitize_title( $this->slug ),
);
global $wpdb;
//if we have an ID, we update the existing value
if ( $this->ID ) {
$wpdb->update( $wpdb->prefix . 'cmplz_services',
$update_array,
array( 'ID' => $this->ID )
);
} else {
$wpdb->insert(
$wpdb->prefix . 'cmplz_services',
$update_array
);
$this->ID = $wpdb->insert_id;
}
if ( $updateAllLanguages ) {
//keep all translations in sync
$translationIDS = $this->get_translations();
foreach ( $translationIDS as $translationID ) {
if ( $this->ID == $translationID ) {
continue;
}
$translation = new CMPLZ_SERVICE( $translationID );
$translation->name = $this->name;
$translation->sync = $this->sync;
$translation->serviceType = $this->serviceType;
$translation->sharesData = $this->sharesData;
$translation->showOnPolicy = $this->showOnPolicy;
$translation->lastUpdatedDate = $this->lastUpdatedDate;
$translation->save(false, false);
}
}
cmplz_delete_transient('cmplz_cookie_shredder_list');
wp_cache_delete('cmplz_service_cookies_'.$this->ID, 'complianz');
wp_cache_delete('cmplz_service_'.$this->ID, 'complianz');
}
/**
* Delete this service, and all translations linked to it.
*/
public function delete() {
if ( !cmplz_user_can_manage() ) {
return;
}
if ( ! $this->ID ) {
return;
}
//get all related cookies, and delete them.
$cookies = $this->get_cookies();
foreach ( $cookies as $service_cookie ) {
$cookie = new CMPLZ_COOKIE( $service_cookie->ID );
$cookie->delete(true);
}
$this->drop_from_wizard( $this->name );
$translations = $this->get_translations();
global $wpdb;
foreach ( $translations as $ID ) {
$wpdb->delete(
$wpdb->prefix . 'cmplz_services',
array( 'ID' => $ID )
);
}
}
/**
* Keep services in sync with the services in the list of the wizard.
*
* @param $service
*/
private function drop_from_wizard( $service ) {
if ( !cmplz_user_can_manage() ) {
return;
}
$slug = $this->get_service_slug( $service );
$services = cmplz_get_option( 'thirdparty_services_on_site' );
if (!is_array($services)) $services = array();
if ( in_array($slug, $services, true ) ) {
$index = array_search($slug, $services, true);
unset($services[$index]);
cmplz_update_option_no_hooks('thirdparty_services_on_site', $services);
}
$social = cmplz_get_option( 'socialmedia_on_site' );
if (!is_array($social)) $social = array();
if ( in_array($slug, $social, true ) ) {
$index = array_search($slug, $social, true);
unset($social[$index]);
cmplz_update_option_no_hooks('socialmedia_on_site', $social);
}
}
/**
* Keep services in sync with the services in the list of the wizard.
*
* @param $service
*/
private function add_to_wizard( $service ) {
if ( !cmplz_user_can_manage() ) {
return;
}
$slug = $this->get_service_slug( $service );
$registered_services = COMPLIANZ::$config->thirdparty_services;
$services = cmplz_get_option('thirdparty_services_on_site');
if ( !is_array($services) ) $services = array();
if ( isset( $registered_services[ $slug ] ) && !in_array($slug, $services, true ) ) {
$services[] = $slug;
cmplz_update_option_no_hooks( 'thirdparty_services_on_site', $services );
}
$registered_social = COMPLIANZ::$config->thirdparty_socialmedia;
$social = cmplz_get_option('socialmedia_on_site');
if ( !is_array($social) ) $social = array();
if ( isset( $registered_social[ $slug ] ) && !in_array($slug, $social, true ) ) {
$social[] = $slug;
cmplz_update_option_no_hooks( 'socialmedia_on_site', $social );
}
}
/**
* Get slug from service
*
* @param $name
*
* @return bool|false|int|string
*/
private function get_service_slug( $name ) {
$services = COMPLIANZ::$config->thirdparty_services;
if ( ( $slug = array_search( $name, $services ) ) !== false ) {
return $slug;
}
$social = COMPLIANZ::$config->thirdparty_socialmedia;
if ( ( $slug = array_search( $name, $social ) ) !== false ) {
return $slug;
}
return false;
}
public function get_translations() {
global $wpdb;
//check if this cookie is a parent
if ( ! $this->isTranslationFrom ) {
//is parent. Get all cookies where translationfrom = this id
$parent_id = $this->ID;
} else {
//not parent.
$parent_id = $this->isTranslationFrom;
}
$sql
= $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_services where isTranslationFrom = %s",
$parent_id );
$results = $wpdb->get_results( $sql );
$translations = wp_list_pluck( $results, 'ID' );
//add the parent id
$translations[] = $parent_id;
return $translations;
}
/**
* Add service to the database
*
* @param $name
* @param array $languages
* @param string $return_language
* @param string $categoryc
* @param bool $sync_on
*
* @return bool|int
*/
public function add(
$name, $languages = array( 'en' ), $return_language = 'en',
$category = '', $sync_on = true
) {
if ( !cmplz_user_can_manage() ) {
return false;
}
$return_id = false;
//insert for each language
$this->languages = cmplz_sanitize_languages( $languages );
$this->name = $name;
//check if there is a parent cookie for this name
$this->get( true );
//if no ID is found, insert in the database
if ( ! $this->ID ) {
$this->sync = $sync_on;
$this->category = $category;
$this->save(false, false );
}
$parent_ID = $this->ID;
if ( $return_language === 'en' ) {
$return_id = $this->ID;
}
//make sure each language is available
foreach ( $this->languages as $language ) {
if ( $language === 'en' ) {
continue;
}
$translated_service = new CMPLZ_SERVICE( $name, $language );
if ( ! $translated_service->ID ) {
$translated_service->sync = $sync_on;
}
$translated_service->category = $category;
$translated_service->isTranslationFrom = $parent_ID;
$translated_service->save(false, false);
if ( $return_language && $language == $return_language ) {
$return_id = $translated_service->ID;
}
}
return $return_id;
}
/**
* Validate a service string
*
* @param $service
*
* @return string|bool
*/
private function sanitize_service( $service ) {
return sanitize_text_field( $service );
}
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.