Changeset 3392903
- Timestamp:
- 11/10/2025 11:30:24 AM (5 weeks ago)
- Location:
- wp-consent-api/trunk
- Files:
-
- 6 edited
-
assets/css/wp-consent-api.css (modified) (2 diffs)
-
assets/js/wp-consent-api.js (modified) (6 diffs)
-
assets/js/wp-consent-api.min.js (modified) (1 diff)
-
readme.md (modified) (1 diff)
-
readme.txt (modified) (5 diffs)
-
wp-consent-api.php (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
wp-consent-api/trunk/assets/css/wp-consent-api.css
r2397444 r3392903 1 2 #health-check-accordion-block-wp-consent-api .title{ 1 #health-check-accordion-block-wp-consent-api .title { 3 2 pointer-events: none; 4 3 font-weight: 600; … … 6 5 padding-top: 10px; 7 6 } 8 #health-check-accordion-block-wp-consent-api .actions{ 7 8 #health-check-accordion-block-wp-consent-api .actions { 9 9 padding: 20px 0px; 10 10 } 11 #health-check-accordion-block-wp-consent-api p{12 11 12 #health-check-accordion-block-wp-consent-api p { 13 13 background: #fff; 14 14 border-left: 4px solid #fff; 15 box-shadow: 0 1px 1px 0 rgba(0, 0,0,.1);15 box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); 16 16 margin: 5px 15px 2px; 17 17 padding: 1px 12px; 18 18 border-left-color: #ffb900; 19 19 margin: 5px 20px 15px 0px; 20 21 20 } -
wp-consent-api/trunk/assets/js/wp-consent-api.js
r2540021 r3392903 6 6 * 7 7 * Edit: chronologically it seems difficult to create a sort of filter for the consent type. 8 * Let's change it so cookiebanners are just required to set it, i tit's not available, we use a default, as defined here.8 * Let's change it so cookiebanners are just required to set it, if it's not available, we use a default, as defined here. 9 9 * 10 10 * This way, if a consent management plugin does not define a consenttype, the one passed here will be used, and it will still work. … … 17 17 18 18 /** 19 * Check if a specific service has consent 20 * @param {string} service 21 */ 22 function wp_has_service_consent(service) { 23 //Check if it's in the consented services cookie 24 let consented_services_json = consent_api_get_cookie(consent_api.cookie_prefix + '_' + 'consented_services'); 25 let consented_services; 26 try { 27 consented_services = JSON.parse(consented_services_json); 28 } catch (e) { 29 consented_services = {}; 30 } 31 32 if ( !consented_services.hasOwnProperty( service ) ){ 33 //default to the category 34 const category = wp_get_service_category(service); 35 return wp_has_consent( category ); 36 } else { 37 return consented_services[service]; 38 } 39 } 40 /** 41 * Check if a specific service is denied 42 * @param {string} service 43 */ 44 function wp_is_service_denied( service ) { 45 //Check if it's in the consented services cookie 46 let consented_services_json = consent_api_get_cookie(consent_api.cookie_prefix + '_' + 'consented_services'); 47 let consented_services; 48 try { 49 consented_services = JSON.parse(consented_services_json); 50 } catch (e) { 51 consented_services = {}; 52 } 53 54 if ( !consented_services.hasOwnProperty( service ) ){ 55 return false; 56 } else { 57 return !consented_services[service]; 58 } 59 } 60 61 /** 62 * Set consent for a specific service 63 * @param {string} service 64 * @param {boolean} consented 65 */ 66 function wp_set_service_consent( service, consented ){ 67 let consented_services_json = consent_api_get_cookie(consent_api.cookie_prefix + '_' + 'consented_services'); 68 let consented_services; 69 try { 70 consented_services = JSON.parse(consented_services_json); 71 } catch (e) { 72 consented_services = {}; 73 } 74 consented_services[service] = consented; 75 consent_api_set_cookie(consent_api.cookie_prefix + '_consented_services', JSON.stringify(consented_services)); 76 77 let details = {}; 78 details.service = service; 79 details.value = consented; 80 let event = new CustomEvent('wp_consent_api_status_change_service', { detail: details }); 81 document.dispatchEvent(event); 82 } 83 84 85 /** 19 86 * Check if a user has given consent for a specific category. 20 87 * 21 * @param {string} category The categoryto check consent against.88 * @param {string} category The item to check consent against. 22 89 */ 23 90 function wp_has_consent(category) { 24 var consent_type; 25 if (typeof (window.wp_consent_type) !== "undefined"){ 91 let has_consent = false; 92 let consent_type; 93 if ( typeof (window.wp_consent_type) !== "undefined" ){ 26 94 consent_type = window.wp_consent_type; 27 95 } else { … … 29 97 } 30 98 31 var has_consent_level = false; 32 var cookie_value = consent_api_get_cookie(consent_api.cookie_prefix + '_' + category); 33 34 if (!consent_type) { 99 let cookie_value = consent_api_get_cookie(consent_api.cookie_prefix + '_' + category); 100 if ( !consent_type ) { 35 101 //if consent_type is not set, there's no consent management, we should return true to activate all cookies 36 has_consent_level = true; 37 102 has_consent = true; 38 103 } else if (consent_type.indexOf('optout') !== -1 && cookie_value === '') { 39 104 //if it's opt out and no cookie is set we should also return true 40 has_consent_level = true; 41 105 has_consent = true; 42 106 } else { 43 107 //all other situations, return only true if value is allow 44 has_consent_level= (cookie_value === 'allow');108 has_consent = (cookie_value === 'allow'); 45 109 } 46 110 47 return has_consent_level; 111 return has_consent; 112 } 113 114 /** 115 * Retrieve the category of a registered service 116 * 117 * @param {string} service 118 * @returns {string} 119 */ 120 function wp_get_service_category( service ) { 121 // Check if services array exists and is valid 122 if (!consent_api.services || !Array.isArray(consent_api.services)) { 123 return 'marketing'; 124 } 125 126 let services = consent_api.services; 127 for (let i = 0; i < services.length; i++) { 128 if (services[i] && 129 services[i].name === service && 130 services[i].category) { 131 return services[i].category; 132 } 133 } 134 return 'marketing'; 48 135 } 49 136 … … 55 142 */ 56 143 function consent_api_set_cookie(name, value) { 57 varsecure = ";secure";58 vardays = consent_api.cookie_expiration;59 vardate = new Date();144 let secure = ";secure"; 145 let days = consent_api.cookie_expiration; 146 let date = new Date(); 60 147 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 61 varexpires = ";expires=" + date.toGMTString();148 let expires = ";expires=" + date.toGMTString(); 62 149 63 150 if (window.location.protocol !== "https:") secure = ''; … … 77 164 for (var i = 0; i < cookies.length; i++) { 78 165 var cookie = cookies[i].trim(); 79 if ( cookie.indexOf(name) == 0)166 if ( cookie.indexOf(name) === 0 ) 80 167 return cookie.substring(name.length, cookie.length); 81 168 } … … 92 179 */ 93 180 function wp_set_consent(category, value) { 94 varevent;95 if (value !== 'allow' && value !== 'deny') return;181 let event; 182 if (value !== 'allow' && value !== 'deny') return; 96 183 var previous_value = consent_api_get_cookie(consent_api.cookie_prefix + '_' + category); 97 consent_api_set_cookie(consent_api.cookie_prefix + '_' + category, value); 98 99 //do not trigger a change event if nothing has changed. 100 if ( previous_value === value ) return; 101 102 var changedConsentCategory = []; 103 changedConsentCategory[category] = value; 104 try { 105 // For modern browsers except IE: 106 event = new CustomEvent('wp_listen_for_consent_change', {detail: changedConsentCategory}); 107 } catch (err) { 108 // If IE 11 (or 10 or 9...?) 109 event = document.createEvent('Event'); 110 event.initEvent('wp_listen_for_consent_change', true, true); 111 event.detail = changedConsentCategory; 112 } 113 // Dispatch/Trigger/Fire the event 114 document.dispatchEvent(event); 115 } 116 117 118 119 120 121 122 123 184 consent_api_set_cookie(consent_api.cookie_prefix + '_' + category, value); 185 186 //do not trigger a change event if nothing has changed. 187 if ( previous_value === value ) return; 188 189 var changedConsentCategory = []; 190 changedConsentCategory[category] = value; 191 try { 192 // For modern browsers except IE: 193 event = new CustomEvent('wp_listen_for_consent_change', {detail: changedConsentCategory}); 194 } catch (err) { 195 // If IE 11 (or 10 or 9...?) 196 event = document.createEvent('Event'); 197 event.initEvent('wp_listen_for_consent_change', true, true); 198 event.detail = changedConsentCategory; 199 } 200 // Dispatch/Trigger/Fire the event 201 document.dispatchEvent(event); 202 } 203 204 205 -
wp-consent-api/trunk/assets/js/wp-consent-api.min.js
r2540021 r3392903 1 "use strict"; window.wp_fallback_consent_type=consent_api.consent_type;window.waitfor_consent_hook=consent_api.waitfor_consent_hook;function wp_has_consent(category){var consent_type;if(typeof window.wp_consent_type!=="undefined"){consent_type=window.wp_consent_type}else{consent_type=window.wp_fallback_consent_type}var has_consent_level=false;var cookie_value=consent_api_get_cookie(consent_api.cookie_prefix+"_"+category);if(!consent_type){has_consent_level=true}else if(consent_type.indexOf("optout")!==-1&&cookie_value===""){has_consent_level=true}else{has_consent_level=cookie_value==="allow"}return has_consent_level}function consent_api_set_cookie(name,value){var secure=";secure";var days=consent_api.cookie_expiration;var date=new Date;date.setTime(date.getTime()+days*24*60*60*1e3);var expires=";expires="+date.toGMTString();if(window.location.protocol!=="https:")secure="";document.cookie=name+"="+value+secure+expires+";path=/"}function consent_api_get_cookie(name){name=name+"=";var cookies=window.document.cookie.split(";");for(var i=0;i<cookies.length;i++){var cookie=cookies[i].trim();if(cookie.indexOf(name)==0)return cookie.substring(name.length,cookie.length)}return""}function wp_set_consent(category,value){var event;if(value!=="allow"&&value!=="deny")return;var previous_value=consent_api_get_cookie(consent_api.cookie_prefix+"_"+category);consent_api_set_cookie(consent_api.cookie_prefix+"_"+category,value);if(previous_value===value)return;var changedConsentCategory=[];changedConsentCategory[category]=value;try{event=new CustomEvent("wp_listen_for_consent_change",{detail:changedConsentCategory})}catch(err){event=document.createEvent("Event");event.initEvent("wp_listen_for_consent_change",true,true);event.detail=changedConsentCategory}document.dispatchEvent(event)}1 "use strict";function wp_has_service_consent(e){var n=consent_api_get_cookie(consent_api.cookie_prefix+"_consented_services");let t;try{t=JSON.parse(n)}catch(e){t={}}return t.hasOwnProperty(e)?t[e]:wp_has_consent(wp_get_service_category(e))}function wp_is_service_denied(e){var n=consent_api_get_cookie(consent_api.cookie_prefix+"_consented_services");let t;try{t=JSON.parse(n)}catch(e){t={}}return!!t.hasOwnProperty(e)&&!t[e]}function wp_set_service_consent(e,n){var t=consent_api_get_cookie(consent_api.cookie_prefix+"_consented_services");let o;try{o=JSON.parse(t)}catch(e){o={}}o[e]=n,consent_api_set_cookie(consent_api.cookie_prefix+"_consented_services",JSON.stringify(o));t={},t.service=e,t.value=n,e=new CustomEvent("wp_consent_api_status_change_service",{detail:t});document.dispatchEvent(e)}function wp_has_consent(e){let n=!1,t;t=void 0!==window.wp_consent_type?window.wp_consent_type:window.wp_fallback_consent_type;e=consent_api_get_cookie(consent_api.cookie_prefix+"_"+e);return n=!t||-1!==t.indexOf("optout")&&""===e||"allow"===e}function wp_get_service_category(n){if(consent_api.services&&Array.isArray(consent_api.services)){var t=consent_api.services;for(let e=0;e<t.length;e++)if(t[e]&&t[e].name===n&&t[e].category)return t[e].category}return"marketing"}function consent_api_set_cookie(e,n){let t=";secure";var o=consent_api.cookie_expiration,i=new Date,o=(i.setTime(i.getTime()+24*o*60*60*1e3),";expires="+i.toGMTString());"https:"!==window.location.protocol&&(t=""),document.cookie=e+"="+n+t+o+";path=/"}function consent_api_get_cookie(e){e+="=";for(var n=window.document.cookie.split(";"),t=0;t<n.length;t++){var o=n[t].trim();if(0===o.indexOf(e))return o.substring(e.length,o.length)}return""}function wp_set_consent(e,n){let t;if("allow"===n||"deny"===n){var o=consent_api_get_cookie(consent_api.cookie_prefix+"_"+e);if(consent_api_set_cookie(consent_api.cookie_prefix+"_"+e,n),o!==n){o=[];o[e]=n;try{t=new CustomEvent("wp_listen_for_consent_change",{detail:o})}catch(e){(t=document.createEvent("Event")).initEvent("wp_listen_for_consent_change",!0,!0),t.detail=o}document.dispatchEvent(t)}}}window.wp_fallback_consent_type=consent_api.consent_type,window.waitfor_consent_hook=consent_api.waitfor_consent_hook; -
wp-consent-api/trunk/readme.md
r3201472 r3392903 9 9 **License**: GPL2 10 10 11 **Tested up to**: 5.312 13 **Requires PHP**: 5.611 **Tested up to**: 6.8 12 13 **Requires PHP**: 7.4 14 14 15 15 **Stable tag**: 1.0.0 -
wp-consent-api/trunk/readme.txt
r3373533 r3392903 6 6 License URI: http://www.gnu.org/licenses/gpl-2.0.html 7 7 Tested up to: 6.8 8 Requires PHP: 7. 28 Requires PHP: 7.4 9 9 Stable tag: 1.0.8 10 10 … … 52 52 53 53 Categories and most other stuff can be extended with a filter. 54 55 = Service-level consent = 56 In addition to category-based consent, the API supports service-level consent control. This allows consent management plugins to grant or deny consent for specific services (like 'google-analytics' or 'facebook-pixel') independently from their category. When checking service consent with wp_has_service_consent(), the API first checks if explicit consent exists for that service. If no explicit consent is set, it falls back to the consent status of the service's category. This enables fine-grained control: a user might accept statistics cookies in general, but explicitly deny a specific analytics service. 57 58 Service consent can be checked and set both server-side (PHP) and client-side (JavaScript): 59 60 PHP: 61 ` 62 //check if a specific service has consent 63 if ( wp_has_service_consent( 'google-analytics' ) ) { 64 //activate google analytics 65 } 66 67 //check if a service is explicitly denied 68 if ( wp_is_service_denied( 'facebook-pixel' ) ) { 69 //service was explicitly denied by user 70 } 71 72 //set service consent 73 wp_set_service_consent( 'google-analytics', true ); //grant consent 74 wp_set_service_consent( 'facebook-pixel', false ); //deny consent 75 76 //listen for service consent changes 77 add_action( 'wp_consent_service_changed', function( $service, $consented ) { 78 error_log( "Service {$service} consent changed to: " . ( $consented ? 'granted' : 'denied' ) ); 79 }, 10, 2 ); 80 ` 81 82 JavaScript: 83 ` 84 //check service consent 85 if ( wp_has_service_consent( 'youtube' ) ) { 86 //activate tracking 87 } 88 89 //check if explicitly denied 90 if ( wp_is_service_denied( 'facebook-pixel' ) ) { 91 //service denied 92 } 93 94 //set service consent 95 wp_set_service_consent( 'youtube', true ); 96 97 //listen for service consent changes 98 document.addEventListener( 'wp_consent_api_status_change_service', function( e ) { 99 console.log( 'Service: ' + e.detail.service + ', consented: ' + e.detail.value ); 100 }); 54 101 55 102 ## Existing integrations … … 103 150 document.dispatchEvent( event ); 104 151 152 //dispatch event when consent type is defined 153 let event = new CustomEvent('wp_consent_type_defined'); 154 document.dispatchEvent( event ); 155 105 156 //consent management plugin sets cookie when consent category value changes 106 157 wp_set_consent('marketing', 'allow'); … … 151 202 } 152 203 ` 153 Any code suggestions? We're on [GitHub](https://github.com/ rlankhorst/wp-consent-level-api) as well!204 Any code suggestions? We're on [GitHub](https://github.com/WordPress/wp-consent-level-api) as well! 154 205 155 206 == Installation == … … 191 242 192 243 == Changelog == 244 = 2.0.0 = 245 * New: Service-level consent API - allows granular consent control per service in addition to category-based consent 246 * New: `wp_has_service_consent()` function to check if a specific service has consent 247 * New: `wp_is_service_denied()` function to check if a specific service is explicitly denied 248 * New: `wp_set_service_consent()` function to set consent for a specific service 249 * New: `wp_consent_service_changed` action hook fires when service consent changes 250 * New: JavaScript functions `wp_has_service_consent()`, `wp_is_service_denied()`, and `wp_set_service_consent()` 251 * New: JavaScript event `wp_consent_api_status_change_service` for service consent changes 252 * Improvement: Added type hints throughout codebase for better code quality and IDE support 253 * Improvement: Added `init()` method for cleaner plugin initialization 254 193 255 = 1.0.8 = 194 256 * Updated tested up to 195 257 * Dropped loading of translations, and loading of plugin_data, to prevent translation loading notices by WordPress 6.7, props @mujuonly 196 258 * Dropped obsolete function wp_has_cookie_info, props @szepeviktor 197 198 = 1.0.7 =199 * Tested up to200 259 201 260 = 1.0.7 = -
wp-consent-api/trunk/wp-consent-api.php
r3235822 r3392903 2 2 /** 3 3 * This file is part of WP Consent API. 4 *5 * Copyright 2020 Rogier Lankhorst and the WordPress Core Privacy team.6 4 * 7 5 * This program is free software: you can redistribute it and/or modify … … 25 23 * Plugin URI: https://wordpress.org/plugins/wp-consent-api 26 24 * Description: Consent Level API to read and register the current consent level for cookie management and improving compliance with privacy laws. 27 * Version: 1.0.828 * Author: wordpressdotorg29 * Author URI: https://github.com/ rlankhorst/wp-consent-level-api25 * Version: 2.0.0 26 * Author: WordPress Contributors 27 * Author URI: https://github.com/WordPress/wp-consent-level-api 30 28 * Requires at least: 5.0 31 * Requires PHP: 5.629 * Requires PHP: 7.4 32 30 * License: GPL2+ 33 31 * License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 39 37 } 40 38 41 42 if ( ! function_exists( 'wp_consent_api_activation_check' ) ) { 39 if ( ! class_exists( 'WP_Consent_API' ) ) { 43 40 /** 44 * Checks if the plugin can safely be activated, at least php 5.6 and wp 5.0 45 * 46 * @since 1.0.0 41 * WP_Consent_API class. 47 42 */ 48 function wp_consent_api_activation_check() { 49 global $wp_version; 50 51 if ( version_compare( PHP_VERSION, '5.6', '<' ) ) { 52 deactivate_plugins( plugin_basename( __FILE__ ) ); 53 wp_die( esc_html( __( 'This plugin requires PHP 5.6 or higher', 'wp-consent-api' ) ) ); 54 } 55 56 if ( version_compare( $wp_version, '5.0', '<' ) ) { 57 deactivate_plugins( plugin_basename( __FILE__ ) ); 58 wp_die( esc_html( __( 'This plugin requires WordPress 5.0 or higher', 'wp-consent-api' ) ) ); 59 } 60 } 61 } 62 register_activation_hook( __FILE__, 'wp_consent_api_activation_check' ); 63 64 if ( ! class_exists( 'WP_CONSENT_API' ) ) { 65 /** 66 * WP_CONSENT_API class. 67 */ 68 class WP_CONSENT_API { 43 class WP_Consent_API { 69 44 /** 70 45 * Instance. … … 72 47 * @since 1.0.0 73 48 * 74 * @var WP_C ONSENT_API|null49 * @var WP_Consent_API|null 75 50 */ 76 51 private static $instance; … … 79 54 * Config. 80 55 * 81 * @var WP_C ONSENT_API_CONFIG56 * @var WP_Consent_API_Config 82 57 */ 83 58 public static $config; … … 87 62 * Site Health Checks. 88 63 * 89 * @var WP_C ONSENT_API_SITE_HEALTH64 * @var WP_Consent_API_Site_Health 90 65 */ 91 66 public static $site_health; … … 94 69 * Cookie info 95 70 * 96 * @var WP_C ONSENT_API_COOKIE_INFO71 * @var WP_Consent_API_Cookie_Info 97 72 */ 98 73 public static $cookie_info; … … 103 78 * @since 1.0.0 104 79 * 105 * @return WP_C ONSENT_API80 * @return WP_Consent_API 106 81 */ 107 82 public static function get_instance() { … … 110 85 } 111 86 return self::$instance; 87 } 88 89 /** 90 * Initialize the plugin. 91 * 92 * @since 1.0.0 93 * 94 * @return void 95 */ 96 public static function init(): void { 97 self::get_instance(); 112 98 } 113 99 … … 123 109 $this->includes(); 124 110 125 self::$config = new WP_C ONSENT_API_CONFIG();126 self::$site_health = new WP_C ONSENT_API_SITE_HEALTH();127 self::$cookie_info = new WP_C ONSENT_API_COOKIE_INFO();111 self::$config = new WP_Consent_API_Config(); 112 self::$site_health = new WP_Consent_API_Site_Health(); 113 self::$cookie_info = new WP_Consent_API_Cookie_Info(); 128 114 } 129 115 … … 139 125 define( 'WP_CONSENT_API_PATH', plugin_dir_path( __FILE__ ) ); 140 126 define( 'WP_CONSENT_API_PLUGIN', plugin_basename( __FILE__ ) ); 141 define( 'WP_CONSENT_API_VERSION', ' 1.0.8' );127 define( 'WP_CONSENT_API_VERSION', '2.0.0' ); 142 128 define( 'WP_CONSENT_API_PLUGIN_FILE', __FILE__ ); 143 129 } … … 151 137 */ 152 138 private function includes() { 153 require_once WP_CONSENT_API_PATH . ' config.php';154 require_once WP_CONSENT_API_PATH . ' cookie-info.php';155 require_once WP_CONSENT_API_PATH . ' api.php';156 require_once WP_CONSENT_API_PATH . ' site-health.php';157 require_once WP_CONSENT_API_PATH . ' wordpress-comments.php';139 require_once WP_CONSENT_API_PATH . 'inc/class-wp-consent-api-config.php'; 140 require_once WP_CONSENT_API_PATH . 'inc/class-wp-consent-api-cookie-info.php'; 141 require_once WP_CONSENT_API_PATH . 'inc/class-wp-consent-api-site-health.php'; 142 require_once WP_CONSENT_API_PATH . 'inc/api-functions.php'; 143 require_once WP_CONSENT_API_PATH . 'inc/wordpress-comments-functions.php'; 158 144 } 159 145 } … … 162 148 * Load the plugins main class. 163 149 */ 164 add_action( 'plugins_loaded', array( WP_C ONSENT_API::class, 'get_instance' ), 9 );150 add_action( 'plugins_loaded', array( WP_Consent_API::class, 'init' ), 9 ); 165 151 }
Note: See TracChangeset
for help on using the changeset viewer.