PluginProbe
Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager / trunk
Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager vtrunk
0.0.11 0.0.10 0.0.9 0.0.8 0.0.7 0.0.6 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5
cookiez / modules / settings / module.php

module.php in Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager trunk, at modules/settings/module.php

469 lines 12.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Cookiez\Modules\Settings;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 use Cookiez\Classes\Logger;
10 use Cookiez\Classes\Module_Base;
11 use Cookiez\Classes\Utils;
12 use Cookiez\Classes\Utils\Integration_Detect;
13 use Cookiez\Modules\Connect\Classes\Config;
14 use Cookiez\Modules\Connect\Module as Connect;
15 use Cookiez\Modules\Core\Components\Notices;
16 use Cookiez\Modules\Maxmind\Classes\Maxmind_Settings;
17 use Cookiez\Modules\Settings\Banners\Elementor_Birthday_Banner;
18 use Cookiez\Modules\Settings\Classes\Settings;
19 use Throwable;
20 use Exception;
21 use WP_Error;
22
23 /**
24 * Module `Settings`
25 */
26 class Module extends Module_Base {
27 const SETTING_BASE_SLUG = 'cookiez-settings';
28 const SETTING_CAPABILITY = 'manage_options';
29 const WP_CONSENT_API_LEARN_MORE_URL = 'https://go.elementor.com/cookie-consent-with-site-kit';
30
31 public function get_name(): string {
32 return 'Settings';
33 }
34
35 /**
36 * Declare components list
37 *
38 * @return array
39 */
40 public static function component_list(): array {
41 return [
42 'Settings_Pointer',
43 ];
44 }
45
46 /**
47 * Get Plugin ENV
48 * @return string
49 */
50 private static function get_plugin_env(): string {
51 return apply_filters( 'cookiez_settings_plugin_env', 'production' );
52 }
53
54 public function render_app() {
55 ?>
56 <?php Elementor_Birthday_Banner::get_banner( 'https://go.elementor.com/cookiez-10th-bd-sale' ); ?>
57 <!-- The hack required to wrap WP notifications -->
58 <div class="wrap">
59 <h1 style="display: none;" role="presentation"></h1>
60 </div>
61
62 <div id="cookiez-app"></div>
63 <?php
64 }
65
66 public function register_page() {
67 add_submenu_page(
68 'elementor-home',
69 __( 'Cookie Consent', 'cookiez' ),
70 __( 'Cookie Consent', 'cookiez' ),
71 self::SETTING_CAPABILITY,
72 self::SETTING_BASE_SLUG,
73 [ $this, 'render_app' ],
74 30
75 );
76 }
77
78 /**
79 * Enqueue Scripts and Styles
80 */
81 public function enqueue_scripts(): void {
82 if ( ! Utils::is_plugin_page() ) {
83 return;
84 }
85
86 /**
87 * These styles are braking MUI component styling.
88 * Re-registering as empty so wp-admin's dependency doesn't break
89 */
90 wp_deregister_style( 'forms' );
91 wp_register_style( 'forms', false );
92
93 self::refresh_plan_data();
94
95 wp_enqueue_style(
96 'cookiez-admin-fonts',
97 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap',
98 [],
99 COOKIEZ_VERSION
100 );
101
102 Utils\Assets::enqueue_app_assets( 'settings' );
103
104 $settings_data = [
105 'isConnected' => Connect::is_connected(),
106 'isUrlMismatch' => ! Connect::get_connect()->utils()->is_valid_home_url(),
107 'wpRestNonce' => wp_create_nonce( 'wp_rest' ),
108 'restRoot' => rest_url(),
109 'pluginEnv' => self::get_plugin_env(),
110 'isDevelopment' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
111 'appSlug' => Config::PLUGIN_SLUG,
112 'appVersion' => COOKIEZ_VERSION,
113 'wpVersion' => get_bloginfo( 'version' ),
114 'isRTL' => is_rtl(),
115 'dateFormat' => get_option( 'date_format', 'F j, Y' ),
116 'timeFormat' => get_option( 'time_format', 'g:i a' ),
117 'translations' => Utils::get_translations(),
118 'isElementorOne' => self::is_elementor_one(),
119 'hasElementorOneSubscription' => self::has_elementor_one_subscription(),
120 'settings' => Settings::get( Settings::COOKIEZ_SETTINGS ),
121 'maxmindLicenseKey' => Maxmind_Settings::masked(),
122 'content' => Settings::get( Settings::COOKIEZ_CONTENT ),
123 'planData' => get_option( Settings::PLAN_DATA ),
124 'planScope' => get_option( Settings::PLAN_SCOPE ),
125 'isElementorActive' => defined( 'ELEMENTOR_VERSION' ),
126 'isElementorProActive' => defined( 'ELEMENTOR_PRO_VERSION' ),
127 'integrations' => [
128 'wpConsentApiActive' => Integration_Detect::is_wp_consent_api_active(),
129 'siteKitActive' => Integration_Detect::is_site_kit_active(),
130 'siteKitConsentMode' => Integration_Detect::is_site_kit_consent_mode_enabled(),
131 'delegateGcmToSiteKit' => Integration_Detect::should_delegate_gcm_to_site_kit(),
132 'wpConsentApiInstallUrl' => admin_url( 'plugin-install.php?s=wp-consent-api&tab=search&type=term' ),
133 'wpConsentApiLearnMoreUrl' => self::WP_CONSENT_API_LEARN_MORE_URL,
134 ],
135 ];
136
137 $settings_data = apply_filters( 'cookiez/settings/data', $settings_data );
138
139 wp_localize_script(
140 'settings',
141 'cookiezSettingsData',
142 $settings_data
143 );
144 }
145
146 /**
147 * Check if cookie consent is connected to elementor one
148 * @return bool
149 */
150 public static function is_elementor_one(): bool {
151 return Connect::get_connect()->get_config( 'app_type' ) !== Config::APP_TYPE;
152 }
153
154 /**
155 * Check if user generally has an active Elementor One subscription,
156 * @return bool
157 */
158 public static function has_elementor_one_subscription(): bool {
159 $one_facade = \ElementorOne\Admin\Helpers\Utils::get_one_connect();
160 return $one_facade && $one_facade->utils()->is_connected();
161 }
162
163 /**
164 * Get all plugin settings data
165 * @return array
166 * @throws Throwable
167 */
168 public static function get_plugin_settings(): array {
169 $content = Settings::get( Settings::COOKIEZ_CONTENT );
170
171 return array_merge(
172 [
173 'isDevelopment' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
174 'siteUrl' => wp_parse_url( get_site_url(), PHP_URL_HOST ),
175 'settings' => Settings::get( Settings::COOKIEZ_SETTINGS ),
176 'maxmindLicenseKey' => Maxmind_Settings::masked(),
177 ],
178 is_array( $content ) ? $content : []
179 );
180 }
181
182 public static function routes_list(): array {
183 return [
184 'Get_Settings',
185 'Update_Settings',
186 'Get_Consent_Logs',
187 'Export_Consent_Logs',
188 ];
189 }
190
191 /**
192 * @throws Exception
193 */
194 public function on_connect(): void {
195 if ( ! Connect::is_connected() ) {
196 return;
197 }
198
199 self::register_site_with_data();
200 }
201
202 /**
203 * Fetch and save plan data on Elementor One app_cookie connection.
204 * @return void
205 */
206 public function on_app_cookie_connected(): void {
207 if ( ! Connect::is_connected() ) {
208 return;
209 }
210
211 $plan_data = get_option( Settings::PLAN_DATA );
212
213 $response = Utils::get_api_client()->make_request(
214 'POST',
215 'sites/info'
216 );
217
218 self::save_plan_data( $response );
219 }
220
221 /**
222 * On disconnect
223 * @return void
224 */
225 public function on_disconnect() {
226 delete_option( Settings::SUBSCRIPTION_ID );
227 }
228
229 /**
230 * Register or update site data for One connect
231 * @throws Exception
232 */
233 public function on_migration_run() {
234 if ( ! Connect::is_connected() ) {
235 return;
236 }
237
238 $client_id = Settings::get( Settings::CLIENT_ID );
239
240 if ( $client_id ) {
241 try {
242 $migration_response = Utils::get_api_client()->make_request(
243 'POST',
244 'site/migration',
245 [ 'old_client_id' => $client_id ],
246 );
247
248 self::save_plan_data( $migration_response );
249
250 $old_options = [
251 'cookiez_client_secret',
252 'cookiez_home_url',
253 'cookiez_access_token',
254 'cookiez_token_id',
255 'cookiez_refresh_token',
256 'cookiez_user_access_token',
257 'cookiez_owner_user_id',
258 Settings::SUBSCRIPTION_ID,
259 Settings::CLIENT_ID,
260 ];
261
262 foreach ( $old_options as $option ) {
263 delete_option( $option );
264 }
265 } catch ( Throwable $t ) {
266 Logger::error( esc_html( $t->getMessage() ) );
267 }
268 } else {
269 $this->on_connect();
270 }
271 }
272
273 /**
274 * Register the website and save the plan data.
275 * @return void
276 */
277 public static function register_site_with_data(): void {
278 $register_response = Utils::get_api_client()->make_request(
279 'POST',
280 'site/register'
281 );
282
283 if ( is_wp_error( $register_response ) ) {
284 Logger::error( esc_html( $register_response->get_error_message() ) );
285 } else {
286 self::save_plan_data( $register_response );
287 if ( isset( $register_response->scopes ) ) {
288 Settings::set( Settings::PLAN_SCOPE, $register_response->scopes );
289 }
290 }
291 }
292
293 /**
294 * Refresh the plan data if the refresh transient has expired.
295 * @return void
296 */
297 public static function refresh_plan_data(): void {
298 if ( ! Connect::is_connected() ) {
299 return;
300 }
301
302 if ( self::get_plan_data_refresh_transient() ) {
303 return;
304 }
305
306 $plan_data = get_option( Settings::PLAN_DATA );
307
308 if ( empty( $plan_data->public_api_key ) ) {
309 Logger::error( 'Cannot refresh the plan data. No public API key found.' );
310 self::register_site_with_data();
311 return;
312 }
313
314 $response = Utils::get_api_client()->make_request(
315 'POST',
316 'site/info'
317 );
318
319 self::save_plan_data( $response );
320 }
321
322 public static function set_plan_data_refresh_transient(): void {
323 set_transient( Settings::PLAN_DATA_REFRESH_TRANSIENT, true, MINUTE_IN_SECONDS * 15 );
324 }
325
326 public static function get_plan_data_refresh_transient(): bool {
327 return get_transient( Settings::PLAN_DATA_REFRESH_TRANSIENT );
328 }
329
330 public static function delete_plan_data_refresh_transient(): bool {
331 return delete_transient( Settings::PLAN_DATA_REFRESH_TRANSIENT );
332 }
333
334 /**
335 * Save plan data to plan_data option
336 * @param $register_response
337 *
338 * @return void
339 */
340 public static function save_plan_data( $register_response ): void {
341 if ( $register_response && ! is_wp_error( $register_response ) ) {
342 $decoded_response = $register_response;
343
344 update_option( Settings::SUBSCRIPTION_ID, $decoded_response->plan->subscription_id );
345 update_option( Settings::PLAN_DATA, $decoded_response );
346 update_option( Settings::IS_VALID_PLAN_DATA, true );
347
348 self::set_plan_data_refresh_transient();
349 } else {
350 Logger::error( $register_response instanceof WP_Error ? esc_html( $register_response->get_error_message() ) : $register_response );
351 update_option( Settings::IS_VALID_PLAN_DATA, false );
352 }
353 }
354
355 /**
356 * Get upgrade link with UTM parameters
357 *
358 * @param string $campaign Campaign identifier for tracking.
359 * @return string
360 */
361 public static function get_upgrade_link( string $campaign ): string {
362 $subscription_id = get_option( Settings::SUBSCRIPTION_ID );
363
364 if ( $subscription_id ) {
365 return add_query_arg(
366 [
367 'utm_source' => $campaign . '-upgrade',
368 'utm_medium' => 'wp-dash',
369 'subscription_id' => $subscription_id,
370 ],
371 'https://go.elementor.com/' . $campaign
372 );
373 }
374
375 return add_query_arg(
376 [
377 'utm_source' => $campaign . '-upgrade',
378 'utm_medium' => 'wp-dash',
379 ],
380 'https://go.elementor.com/' . $campaign
381 );
382 }
383
384 /**
385 * Cookie consent quota usage percentage (cookie_consents only).
386 *
387 * @return float Percent used (0–100+), or 0 if unavailable.
388 */
389 public static function get_consent_quota_usage_percent(): float {
390 $plan_data = get_option( Settings::PLAN_DATA );
391
392 if ( ! $plan_data || ! isset( $plan_data->quota->cookie_consents ) ) {
393 return 0;
394 }
395
396 $consents = $plan_data->quota->cookie_consents;
397
398 if ( ! isset( $consents->allowed, $consents->used ) || $consents->allowed <= 0 ) {
399 return 0;
400 }
401
402 return round( $consents->used / $consents->allowed * 100, 2 );
403 }
404
405 /**
406 * Register quota notices with the notice manager.
407 *
408 * @param Notices $notice_manager The notice manager instance.
409 * @return void
410 */
411 public function register_notices( Notices $notice_manager ): void {
412 if ( self::is_elementor_one() ) {
413 $this->register_one_notices( $notice_manager );
414 return;
415 }
416
417 if ( ! Connect::is_connected() && ! get_option( Settings::PLAN_DATA ) ) {
418 return;
419 }
420
421 $notices = [
422 'Quota_80',
423 'Quota_100',
424 'Site_Kit_Wp_Consent_Api',
425 ];
426
427 foreach ( $notices as $notice ) {
428 $class_name = 'Cookiez\Modules\Settings\Notices\\' . $notice;
429 $notice_manager->register_notice( new $class_name() );
430 }
431 }
432
433 /**
434 * Register quota notices with the notice manager.
435 *
436 * @param Notices $notice_manager The notice manager instance.
437 * @return void
438 */
439 public function register_one_notices( Notices $notice_manager ): void {
440 if ( ! self::is_elementor_one() ) {
441 return;
442 }
443
444 $notices = [
445 'Site_Kit_Wp_Consent_Api',
446 ];
447
448 foreach ( $notices as $notice ) {
449 $class_name = 'Cookiez\Modules\Settings\Notices\\' . $notice;
450 $notice_manager->register_notice( new $class_name() );
451 }
452 }
453
454 public function __construct() {
455 $this->register_components();
456 $this->register_routes();
457
458 add_action( 'admin_menu', [ $this, 'register_page' ] );
459 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
460
461 add_action( 'elementor_one/' . Config::APP_PREFIX . '_connected', [ $this, 'on_connect' ] );
462 add_action( 'elementor_one/' . Config::APP_PREFIX . '_disconnected', [ $this, 'on_disconnect' ] );
463 add_action( 'elementor_one/' . Config::APP_PREFIX . '_migration_run', [ $this, 'on_migration_run' ] );
464 add_action( 'elementor_one/' . Config::APP_TYPE . '_connected', [ $this, 'on_app_cookie_connected' ] );
465
466 add_action( 'cookiez_register_notices', [ $this, 'register_notices' ] );
467 }
468 }
469