PluginProbe ʕ •ᴥ•ʔ
Complianz – GDPR/CCPA Cookie Consent / 7.4.1
Complianz – GDPR/CCPA Cookie Consent v7.4.1
7.4.6 trunk 6.5.6 7.0.4 7.0.5 7.1.0 7.1.4 7.1.5 7.2.0 7.3.0 7.3.1 7.4.0 7.4.0.1 7.4.1 7.4.2 7.4.3 7.4.4 7.4.4.1 7.4.4.2 7.4.5 beta
complianz-gdpr / class-wizard.php
complianz-gdpr Last commit date
DNSMPD 1 year ago assets 11 months ago config 11 months ago cookie 1 year ago cookiebanner 11 months ago cron 2 years ago documents 1 year ago gutenberg 1 year ago integrations 11 months ago languages 1 year ago mailer 1 year ago onboarding 1 year ago placeholders 2 years ago progress 2 years ago proof-of-consent 2 years ago rest-api 1 year ago settings 11 months ago templates 2 years ago upgrade 1 year ago websitescan 11 months ago LICENSE.txt 4 years ago README.md 4 years ago class-admin.php 11 months ago class-company.php 2 years ago class-cookie-blocker.php 2 years ago class-document.php 1 year ago class-export.php 2 years ago class-field.php 1 year ago class-installer.php 2 years ago class-review.php 11 months ago class-wizard.php 1 year ago complianz-gpdr.php 11 months ago composer.json 1 year ago functions-legacy.php 2 years ago functions.php 1 year ago gulpfile.js 1 year ago index.php 7 years ago loco.xml 4 years ago readme.txt 11 months ago security.md 2 years ago system-status.php 1 year ago uninstall.php 11 months ago upgrade.php 1 year ago
class-wizard.php
1197 lines
1 <?php
2 /*100% match*/
3
4 defined( 'ABSPATH' ) or die( "you do not have access to this page!" );
5
6 if ( ! class_exists( "cmplz_wizard" ) ) {
7 class cmplz_wizard {
8 private static $_this;
9 public $position;
10 public $cookies = array();
11 public $total_steps = false;
12 public $last_section;
13 public $page_url;
14 public $percentage_complete = false;
15
16 function __construct() {
17 if ( isset( self::$_this ) ) {
18 wp_die( sprintf( '%s is a singleton class and you cannot create a second instance.',
19 get_class( $this ) ) );
20 }
21
22 self::$_this = $this;
23 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
24
25 //callback from settings
26 add_action( 'cmplz_wizard_last_step', array( $this, 'wizard_last_step_callback' ), 10, 1 );
27
28 //link action to custom hook
29 add_action( 'cmplz_wizard_wizard', array( $this, 'wizard_after_step' ), 10, 1 );
30
31 //process custom hooks
32 add_action( 'admin_init', array( $this, 'process_custom_hooks' ) );
33 add_action( 'complianz_before_save_wizard_option', array( $this, 'before_save_wizard_option' ), 10, 4 );
34 add_action( 'complianz_after_save_wizard_option', array( $this, 'after_save_wizard_option' ), 10, 4 );
35 add_action( 'complianz_after_save_settings_option', array( $this, 'after_save_settings_option' ), 10, 4 );
36 add_action( 'cmplz_after_saved_all_fields', array( $this, 'after_saved_all_fields' ), 10, 1 );
37
38 //dataleaks:
39 add_action( 'cmplz_is_wizard_completed', array( $this, 'is_wizard_completed_callback' ) );
40 }
41
42 static function this() {
43 return self::$_this;
44 }
45
46
47 public function is_wizard_completed_callback() {
48 if (!cmplz_user_can_manage()) return;
49
50 if ( $this->wizard_completed_once() ) {
51 cmplz_notice( __( "Great, the main wizard is completed. This means the general data is already in the system, and you can continue with the next question. This will start a new, empty document.",
52 'complianz-gdpr' ) );
53 } else {
54 $link = '<a href="' . admin_url( 'admin.php?page=cmplz-wizard' )
55 . '">';
56 cmplz_notice( cmplz_sprintf( __( "The wizard isn't completed yet. If you have answered all required questions, you just need to click 'finish' to complete it. In the wizard some general data is entered which is needed for this document. %sPlease complete the wizard first%s.",
57 'complianz-gdpr' ), $link, "</a>" ), 'warning' );
58 }
59 }
60
61
62 public function process_custom_hooks() {
63 if (!cmplz_user_can_manage()) return;
64
65 $wizard_type = ( isset( $_POST['wizard_type'] ) )
66 ? sanitize_title( $_POST['wizard_type'] ) : '';
67 do_action( "cmplz_wizard_$wizard_type" );
68 }
69
70 /**
71 * Initialize a page in the wizard
72 * @param $page
73 */
74 public function initialize( $page ) {
75 if (!cmplz_user_can_manage()) return;
76
77 $this->last_section = $this->last_section( $page, $this->step() );
78 $this->page_url = admin_url( 'admin.php?page=cmplz-' . $page );
79 //if a post id was passed, we copy the contents of that page to the wizard settings.
80 if ( isset( $_GET['post_id'] ) ) {
81 $post_id = intval( $_GET['post_id'] );
82 //get all fields for this page
83 $fields = COMPLIANZ::$config->fields( $page );
84 foreach ( $fields as $fieldname => $field ) {
85 $fieldvalue = get_post_meta( $post_id, $fieldname, true );
86 if ( $fieldvalue ) {
87 if ( ! COMPLIANZ::$field->is_multiple_field( $fieldname ) ) {
88 COMPLIANZ::$field->save_field( $fieldname, $fieldvalue );
89 } else {
90 $field[ $fieldname ] = $fieldvalue;
91 COMPLIANZ::$field->save_multiple( $field );
92 }
93 }
94
95 }
96 }
97 }
98
99 /**
100 * Some actions after the last step has been completed
101 */
102 public function wizard_last_step_callback() {
103 if (!cmplz_user_can_manage()) return;
104
105 $page = $this->wizard_type();
106 cmplz_update_all_banners();
107
108 if ( ! $this->all_required_fields_completed( $page ) ) {
109 echo '<div class="cmplz-wizard-intro">';
110 _e( "Not all required fields are completed yet. Please check the steps to complete all required questions", 'complianz-gdpr' );
111 echo '</div>';
112 } else {
113 echo '<div class="cmplz-wizard-intro">';
114 printf( '<p>' . __( "Click '%s' to complete the configuration. You can come back to change your configuration at any time.", 'complianz-gdpr' ). '</p>', __( "Save", 'complianz-gdpr' ) );
115 echo '</div>';
116
117 if ( COMPLIANZ::$cookie_admin->site_needs_cookie_warning() ) {
118 '<p>'._e( "The cookie banner and the cookie blocker are now ready to be enabled.", "complianz-gdpr"). '</p>'.
119 '<p>'._e( "Please check your website after finishing the wizard to verify that your configuration is working properly.", "complianz-gdpr").'</p>';
120 } else {
121 '<p>'._e( "Your site does not require a cookie banner. If you think you need a cookie banner, please review your wizard settings.", "complianz-gdpr").'</p>';
122 }
123
124 if ( cmplz_get_value('uses_ad_cookies_personalized') === 'yes' ) {
125 global $wpdb;
126 $banner_text = __( "We use technologies like cookies to store and/or access device information. We do this to improve browsing experience and to show (non-) personalized ads. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.", 'complianz-gdpr' );
127 $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->prefix}cmplz_cookiebanners SET message_optin = %s", $banner_text) );
128 }
129 }
130
131 }
132
133
134 /**
135 * Process completion of setup
136 *
137 * */
138
139 public function wizard_after_step() {
140 if ( ! cmplz_user_can_manage() ) {
141 return;
142 }
143
144 //clear document cache
145 COMPLIANZ::$document->clear_shortcode_transients();
146
147 //if the plugins page is reviewed, we can reset the privacy statement suggestions from WordPress.
148 if ( cmplz_wp_privacy_version()
149 && ( $this->step( 'wizard' ) == STEP_MENU )
150 && cmplz_get_value( 'privacy-statement' ) === 'generated'
151 ) {
152 $policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
153 WP_Privacy_Policy_Content::_policy_page_updated( $policy_page_id );
154 //check again, to update the cache.
155 WP_Privacy_Policy_Content::text_change_check();
156 }
157
158 COMPLIANZ::$cookie_admin->reset_plugins_changed();
159 COMPLIANZ::$cookie_admin->reset_cookies_changed();
160 COMPLIANZ::$cookie_admin->reset_plugins_updated();
161
162 //when clicking to the last page, or clicking finish, run the finish sequence.
163 if ( isset( $_POST['cmplz-cookiebanner-settings'] )
164 || isset( $_POST['cmplz-finish'] )
165 || ( isset( $_POST["step"] ) && $_POST['step'] == STEP_MENU
166 && isset( $_POST['cmplz-next'] ) )
167 ) {
168 $this->set_wizard_completed_once();
169 }
170
171
172 //after clicking finish, redirect to dashboard.
173 if ( isset( $_POST['cmplz-finish'] ) ) {
174 wp_redirect( admin_url( 'admin.php?page=complianz' ) );
175 exit();
176 }
177
178 if ( isset( $_POST['cmplz-cookiebanner-settings'] ) ) {
179 wp_redirect( admin_url( 'admin.php?page=cmplz-cookiebanner' ) );
180 exit();
181 }
182 }
183
184 /**
185 * Do stuff before a page from the wizard is saved.
186 *
187 * */
188
189 public function before_save_wizard_option(
190 $fieldname, $fieldvalue, $prev_value, $type
191 ) {
192 if ( ! cmplz_user_can_manage() ) {
193 return;
194 }
195 update_option( 'cmplz_documents_update_date', time(), false );
196
197 //only run when changes have been made
198 if ( $fieldvalue === $prev_value ) {
199 return;
200 }
201
202 $enable_categories = false;
203 $uses_tagmanager = cmplz_get_value( 'compile_statistics' ) === 'google-tag-manager' ? true : false;
204
205 /* if tag manager fires scripts, cats should be enabled for each cookiebanner. */
206 if ( $fieldname === 'compile_statistics' && $fieldvalue === 'google-tag-manager' ) {
207 $enable_categories = true;
208 }
209
210 if ( ( $fieldname === 'consent_for_anonymous_stats' )
211 && $fieldvalue === 'yes'
212 ) {
213 $enable_categories = true;
214 }
215
216 //when ab testing is just enabled icw TM, cats should be enabled for each banner.
217 if ( ( $fieldname == 'a_b_testing_buttons' && $fieldvalue === true
218 && $prev_value == false )
219 ) {
220 if ( $uses_tagmanager ) {
221 $enable_categories = true;
222 }
223 }
224
225 if ( $enable_categories ) {
226 $banners = cmplz_get_cookiebanners();
227 if ( ! empty( $banners ) ) {
228 foreach ( $banners as $banner ) {
229 $banner = new CMPLZ_COOKIEBANNER( $banner->ID );
230 $banner->use_categories = 'view-preferences';
231 $banner->save();
232 }
233 }
234 }
235
236
237 //when region or policy generation type is changed, update cookiebanner version to ensure the changed banner is loaded
238 if ( $fieldname === 'privacy-statement' || $fieldname === 'regions'
239 || $fieldname === 'cookie-statement'
240 ) {
241 cmplz_update_all_banners();
242 }
243
244 //we can check here if certain things have been updated,
245 COMPLIANZ::$cookie_admin->reset_cookies_changed();
246
247 //save last changed date.
248 COMPLIANZ::$cookie_admin->update_cookie_policy_date();
249
250 //if the fieldname is from the "revoke cookie consent on change" list, change the policy if it's changed
251 $fields = COMPLIANZ::$config->fields;
252 $field = $fields[ $fieldname ];
253 if ( ( $fieldvalue != $prev_value )
254 && isset( $field['revoke_consent_onchange'] )
255 && $field['revoke_consent_onchange']
256 ) {
257 COMPLIANZ::$cookie_admin->upgrade_active_policy_id();
258 if ( !get_option( 'cmplz_generate_new_cookiepolicy_snapshot') ) update_option( 'cmplz_generate_new_cookiepolicy_snapshot', time(), false );
259 }
260
261 if ( $fieldname === 'configuration_by_complianz'
262 || $fieldname === 'GTM_code'
263 || $fieldname === 'matomo_url'
264 || $fieldname === 'matomo_tag_url'
265 || $fieldname === 'matomo_site_id'
266 || $fieldname === 'matomo_container_id'
267 || $fieldname === 'UA_code'
268 ) {
269 delete_option( 'cmplz_detected_stats_data' );
270 delete_option( 'cmplz_detected_stats_type' );
271 }
272 }
273
274 /**
275 * Handle some custom options after saving the wizard options
276 *
277 * After all fields have been saved
278 * @param $posted_fields
279 */
280
281 public function after_saved_all_fields($posted_fields){
282 if ( ! cmplz_user_can_manage() ) {
283 return;
284 }
285 //if the region is not EU anymore, and it was previously enabled for EU / eu_consent_regions, reset impressum
286 if ( array_key_exists('cmplz_regions', $posted_fields) && cmplz_get_value('eu_consent_regions') === 'yes' && !cmplz_has_region('eu')
287 ) {
288 cmplz_update_option('wizard', 'eu_consent_regions', 'no' );
289 }
290 }
291
292 public function after_save_settings_option( $fieldname, $fieldvalue, $prev_value, $type ){
293 if ( ! cmplz_user_can_manage() ) {
294 return;
295 }
296 if ( $fieldname ==='safe_mode' ) {
297 $enable_blocker = $fieldvalue ? 'no' : 'yes';
298 cmplz_update_option('wizard', 'enable_cookie_blocker', $enable_blocker);
299 }
300
301 }
302 /**
303 * Handle some custom options after saving the wizard options
304 * @param string $fieldname
305 * @param mixed $fieldvalue
306 * @param mixed $prev_value
307 * @param string $type
308 */
309
310 public function after_save_wizard_option( $fieldname, $fieldvalue, $prev_value, $type ) {
311 if ( ! cmplz_user_can_manage() ) {
312 return;
313 }
314 $generate_css = false;
315 if ( $fieldname == 'us_states' || $fieldname == 'purpose_personaldata' ) {
316 add_action( 'shutdown', 'cmplz_update_cookie_policy_title', 12 );
317 }
318
319 if ( $fieldname === 'children-safe-harbor'
320 && cmplz_get_value( 'targets-children' ) === 'no'
321 ) {
322 cmplz_update_option( 'wizard', 'children-safe-harbor', 'no' );
323 }
324
325 if ( $fieldvalue === $prev_value ) {
326 return;
327 }
328
329 //clear blocked scripts transient on wizard edits.
330 delete_transient('cmplz_blocked_scripts');
331
332 //keep services in sync
333 if ( $fieldname === 'socialmedia_on_site' || $fieldname === 'thirdparty_services_on_site' ) {
334 COMPLIANZ::$cookie_admin->update_services();
335 }
336
337 //update google analytics service depending on anonymization choices
338 if ( $fieldname === 'compile_statistics'
339 || $fieldname === 'compile_statistics_more_info'
340 || $fieldname === 'compile_statistics_more_info_tag_manager'
341 ) {
342 COMPLIANZ::$cookie_admin->maybe_add_statistics_service();
343 $generate_css = true;
344 }
345
346 /**
347 * If TCF was just disabled or enabled, regenerate the css.
348 */
349 if ( $fieldname === 'uses_ad_cookies_personalized' ) {
350 $generate_css = true;
351 }
352
353 if ( $generate_css ){
354 cmplz_update_all_banners();
355 }
356
357 // Disable German imprint appendix option when eu_consent_regions is no
358 if ( $fieldname === 'eu_consent_regions'
359 && cmplz_get_value('eu_consent_regions') === 'no'
360 && cmplz_get_value('german_imprint_appendix') === 'yes') {
361 cmplz_update_option('wizard' , 'german_imprint_appendix', 'no');
362 }
363
364 if ( $fieldname ==='enable_cookie_banner' ) {
365 $banners = cmplz_get_cookiebanners();
366 $disable = $fieldvalue === 'no';
367 if ( $banners ) {
368 foreach ( $banners as $banner_item ) {
369 $banner = new CMPLZ_COOKIEBANNER( $banner_item->ID );
370 $banner->disable_cookiebanner = $disable;
371 $banner->save();
372 }
373 }
374 }
375
376 if ( $fieldname ==='enable_cookie_blocker' ) {
377 $disable_blocker = $fieldvalue === 'no';
378 cmplz_update_option('settings', 'safe_mode', $disable_blocker);
379 }
380
381 }
382
383 /**
384 * Get the next step with fields in it
385 * @param string $page
386 * @param int $step
387 *
388 * @return int
389 */
390 public function get_next_not_empty_step( $page, $step ) {
391 if ( ! cmplz_user_can_manage() ) {
392 return;
393 }
394 if ( ! COMPLIANZ::$field->step_has_fields( $page, $step ) ) {
395 if ( $step >= $this->total_steps( $page ) ) {
396 return $step;
397 }
398 $step ++;
399 $step = $this->get_next_not_empty_step( $page, $step );
400 }
401
402 return $step;
403 }
404
405 /**
406 * Get the next section which is not empty
407 * @param string $page
408 * @param int $step
409 * @param int $section
410 *
411 * @return int|bool
412 */
413 public function get_next_not_empty_section( $page, $step, $section ) {
414
415 if ( ! COMPLIANZ::$field->step_has_fields( $page, $step, $section ) ) {
416 //some keys are missing, so we need to count the actual number of keys.
417 if ( isset( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'] ) ) {
418 $n = array_keys( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'] ); //<---- Grab all the keys of your actual array and put in another array
419 $count = array_search( $section, $n ); //<--- Returns the position of the offset from this array using search
420
421 //this is the actual list up to section key.
422 $new_arr = array_slice( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'], 0, $count + 1, true );//<--- Slice it with the 0 index as start and position+1 as the length parameter.
423 $section_count = count( $new_arr ) + 1;
424 } else {
425 $section_count = $section + 1;
426 }
427 $section ++;
428
429 if ( $section_count > $this->total_sections( $page, $step ) ) {
430 return false;
431 }
432
433 $section = $this->get_next_not_empty_section( $page, $step, $section );
434 }
435
436 return $section;
437 }
438
439 public function get_previous_not_empty_step( $page, $step ) {
440 if ( ! COMPLIANZ::$field->step_has_fields( $page, $step ) ) {
441 if ( $step <= 1 ) {
442 return $step;
443 }
444 $step --;
445 $step = $this->get_previous_not_empty_step( $page, $step );
446 }
447
448 return $step;
449 }
450
451 public function get_previous_not_empty_section( $page, $step, $section
452 ) {
453
454 if ( ! COMPLIANZ::$field->step_has_fields( $page, $step,
455 $section )
456 ) {
457 $section --;
458 if ( $section < 1 ) {
459 return false;
460 }
461 $section = $this->get_previous_not_empty_section( $page, $step,
462 $section );
463 }
464
465 return $section;
466 }
467
468 /*
469 * Lock the wizard for further use while it's being edited by the current user.
470 *
471 *
472 * */
473
474 public function lock_wizard() {
475 $user_id = get_current_user_id();
476 set_transient( 'cmplz_wizard_locked_by_user', $user_id,
477 apply_filters( "cmplz_wizard_lock_time",
478 2 * MINUTE_IN_SECONDS ) );
479 }
480
481
482 /*
483 * Check if the wizard is locked by another user
484 *
485 *
486 * */
487
488 public function wizard_is_locked() {
489 $user_id = get_current_user_id();
490 $lock_user_id = $this->get_lock_user();
491 if ( $lock_user_id && $lock_user_id != $user_id ) {
492 return true;
493 }
494
495 return false;
496 }
497
498 public function get_lock_user() {
499 return get_transient( 'cmplz_wizard_locked_by_user' );
500 }
501
502
503 public function wizard( $page, $wizard_title = '' )
504 {
505
506 if (!cmplz_user_can_manage()) {
507 return;
508 }
509
510 if ($this->wizard_is_locked()) {
511 $user_id = $this->get_lock_user();
512 $user = get_user_by("id", $user_id);
513 $lock_time = apply_filters("cmplz_wizard_lock_time",
514 2 * MINUTE_IN_SECONDS) / 60;
515
516 cmplz_notice(sprintf(__("The wizard is currently being edited by %s",
517 'complianz-gdpr'), $user->user_nicename) . '<br />'
518 . cmplz_sprintf(__("If this user stops editing, the lock will expire after %s minutes.",
519 'complianz-gdpr'), $lock_time), 'warning');
520
521 return;
522 }
523 //lock the wizard for other users.
524 $this->lock_wizard();
525
526
527 $this->initialize($page);
528
529 $section = $this->section();
530 $step = $this->step();
531
532 if ($this->section_is_empty($page, $step, $section)
533 || (isset($_POST['cmplz-next'])
534 && !COMPLIANZ::$field->has_errors())
535 ) {
536 if (COMPLIANZ::$config->has_sections($page, $step)
537 && ($section < $this->last_section)
538 ) {
539 $section = $section + 1;
540 } else {
541 $step++;
542 $section = $this->first_section($page, $step);
543 }
544
545 $step = $this->get_next_not_empty_step($page, $step);
546 $section = $this->get_next_not_empty_section($page, $step,
547 $section);
548 //if the last section is also empty, it will return false, so we need to skip the step too.
549 if (!$section) {
550 $step = $this->get_next_not_empty_step($page,
551 $step + 1);
552 $section = 1;
553 }
554 }
555
556 if (isset($_POST['cmplz-previous'])) {
557 if (COMPLIANZ::$config->has_sections($page, $step)
558 && $section > $this->first_section($page, $step)
559 ) {
560 $section--;
561 } else {
562 $step--;
563 $section = $this->last_section($page, $step);
564 }
565
566 $step = $this->get_previous_not_empty_step($page, $step);
567 $section = $this->get_previous_not_empty_section($page, $step,
568 $section);
569 }
570
571 $menu = $this->wizard_menu( $page, $wizard_title, $step, $section );
572 $content = $this->wizard_content($page, $step, $section );
573
574 $args = array(
575 'page' => 'wizard',
576 'content' => $menu.$content,
577 );
578 echo cmplz_get_template('admin_wrap.php', $args );
579 }
580
581 /**
582 * Generate menu
583 * @param string $page
584 * @param string $wizard_title
585 * @param int $active_step
586 * @param int $active_section
587 *
588 * @return false|string
589 */
590 public function wizard_menu( $page, $wizard_title, $active_step, $active_section )
591 {
592 if ( ! cmplz_user_can_manage() ) {
593 return '';
594 }
595 $args_menu['steps'] = "";
596 for ($i = 1; $i <= $this->total_steps($page); $i++)
597 {
598 $args['title'] = $i . '. ' . COMPLIANZ::$config->steps[$page][$i]['title'];
599 $args['active'] = ($i == $active_step) ? 'active' : '';
600 $args['completed'] = $this->required_fields_completed($page, $i, false) ? 'complete' : 'incomplete';
601 $args['url'] = add_query_arg(array('step' => $i), $this->page_url);
602 if ($this->post_id())
603 {
604 $args['url'] = add_query_arg(array('post_id' => $this->post_id()), $args['url']);
605 }
606 $args['sections'] = ($args['active'] == 'active') ? $this->wizard_sections($page, $active_step, $active_section) : '';
607
608 $args_menu['steps'] .= cmplz_get_template( 'wizard/step.php' , $args);
609 }
610
611 $args_menu['percentage-complete'] = $this->wizard_percentage_complete( false );
612 $args_menu['title'] = !empty( $wizard_title ) ? $wizard_title : __( "The Wizard", 'complianz-gdpr' );
613
614 return cmplz_get_template( 'wizard/menu.php', $args_menu );
615 }
616
617 /**
618 * @param string $page
619 * @param int $step
620 * @param int $active_section
621 *
622 * @return string
623 */
624 public function wizard_sections( $page, $step, $active_section ) {
625 $sections = "";
626 if ( ! cmplz_user_can_manage() ) {
627 return '';
628 }
629 if ( COMPLIANZ::$config->has_sections( $page, $step )) {
630
631 for ($i = $this->first_section( $page, $step ); $i <= $this->last_section( $page, $step ); $i ++) {
632 $icon = cmplz_icon('circle', 'disabled', '', 11);
633
634 if ( $this->section_is_empty( $page, $step, $i ) ) continue;
635 if ( $i < $this->get_next_not_empty_section( $page, $step, $i ) ) continue;
636
637 $active = ( $i == $active_section ) ? 'active' : '';
638 if ( $active == 'active' ) {
639 $icon = cmplz_icon('chevron-right', 'default', '', 11);
640 } else if ($this->required_fields_completed( $page, $step, $i )) {
641 $icon = cmplz_icon('check', 'success', '', 11);
642 }
643
644 $completed = ( $this->required_fields_completed( $page, $step, $i ) ) ? "cmplz-done" : "cmplz-to-do";
645 $url = add_query_arg( array('step' => $step, 'section' => $i), $this->page_url );
646 if ( $this->post_id() ) {
647 $url = add_query_arg( array( 'post_id' => $this->post_id() ), $url );
648 }
649
650 $title = COMPLIANZ::$config->steps[ $page ][ $step ]['sections'][ $i ]['title'];
651 $regions = $this->get_section_regions( $page, $step, $i );
652 if (count(cmplz_get_regions()) > count($regions)) {
653 $title .= $regions ? ' - ' . implode( ' | ', $regions ) : '';
654 }
655 $args = array(
656 'active' => $active,
657 'completed' => $completed,
658 'icon' => $icon,
659 'url' => $url,
660 'title' => $title,
661 );
662 $sections .= cmplz_get_template( 'wizard/section.php', $args );
663 }
664 }
665
666 return $sections;
667 }
668
669 public function wizard_content( $page, $step, $section ) {
670 if ( ! cmplz_user_can_manage() ) {
671 return '';
672 }
673 $regions = $this->get_section_regions( $page, $step, $section );
674 $args = array(
675 'title' => '',
676 'page' => $page,
677 'step' => $step,
678 'section' => $section,
679 'flags' => cmplz_flag( $regions, false ),
680 'save_as_notice' => '',
681 'learn_notice' => '',
682 'cookie_or_finish_button' => '',
683 'previous_button' => '',
684 'next_button' => '',
685 'save_button' => '',
686 'intro' => $this->get_intro( $page, $step, $section ),
687 'page_url' => $this->page_url,
688 'post_id' => $this->post_id() ? '<input type="hidden" value="' . $this->post_id() . '" name="post_id">' : '',
689 );
690 if ( isset(COMPLIANZ::$config->steps[$page][$step]['sections'][$section]['title'])) {
691 $args['title'] = COMPLIANZ::$config->steps[$page][$step]['sections'][$section]['title'];
692 } else {
693 $args['title'] .= COMPLIANZ::$config->steps[$page][$step]['title'];
694 }
695
696
697 if ( $page != 'wizard' ) {
698 if ( $step == 1 ) {
699 delete_option( 'complianz_options_' . $page );
700 }
701 }
702
703 ob_start();
704 COMPLIANZ::$field->get_fields( $page, $step, $section );
705 $args['fields'] = ob_get_clean();
706
707 if ( $step > 1 || $section > 1 ) {
708 $args['previous_button'] = '<input class="button button-link cmplz-previous" type="submit" name="cmplz-previous" value="'. __( "Previous", 'complianz-gdpr' ) . '">';
709 }
710
711 if ( $step < $this->total_steps( $page ) ) {
712 $args['next_button'] = '<input class="button button-primary cmplz-next" type="submit" name="cmplz-next" value="'. __( "Save and Continue", 'complianz-gdpr' ) . '">';
713 }
714
715 $hide_finish_button = false;
716 if ( strpos( $page, 'dataleak' ) !== false ) {
717 if ( !COMPLIANZ::$dataleak->dataleak_has_to_be_reported_to_involved() ) {
718 $hide_finish_button = true;
719 }
720 }
721
722 $label = ( strpos( $page, 'dataleak' ) !== false || strpos( $page, 'processing' ) !== false )
723 ? __( "View document", 'complianz-gdpr' )
724 : __( "Finish", 'complianz-gdpr' );
725
726 if ( ! $hide_finish_button && ( $step == $this->total_steps( $page ) ) && $this->all_required_fields_completed( $page )) {
727 /**
728 * Only for the wizard type, should there optional be a button redirecting to the cookie settings page
729 * */
730
731 if ( $page == 'wizard' && COMPLIANZ::$cookie_admin->site_needs_cookie_warning() ) {
732 $target = apply_filters('cmplz_finish_wizard_target', 'cmplz-cookiebanner-settings');
733 $args['cookie_or_finish_button'] = '<input class="button button-primary '.$target.'" type="submit" name="'.$target.'" value="'. __( "Save and Style Cookie Banner", 'complianz-gdpr' ) . '">';
734 } else {
735 $args['cookie_or_finish_button'] = '<input class="button button-primary cmplz-finish" type="submit" name="cmplz-finish" value="'. $label . '">';
736 }
737 }
738
739 if ( ( $step > 1 || $page == 'wizard' ) && $step < $this->total_steps( $page )) {
740 if ( ! ($step == STEP_COOKIES && $section == 6) ) {
741 $args['save_button'] = '<input class="button button-secondary cmplz-save" type="submit" name="cmplz-save" value="'. __( "Save", 'complianz-gdpr' ) . '">';
742 }
743 }
744
745 return cmplz_get_template( 'wizard/content.php', $args );
746 }
747
748 /**
749 * If a section does not contain any fields to be filled, just drop it from the menu.
750 * @return bool
751 *
752 * */
753
754 public function section_is_empty( $page, $step, $section ) {
755 $section_compare = $this->get_next_not_empty_section( $page, $step, $section );
756 if ( $section != $section_compare ) {
757 return true;
758 }
759
760 return false;
761 }
762
763 /**
764 * Enqueue assets
765 * @param $hook
766 */
767 public function enqueue_assets( $hook ) {
768
769 $minified = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
770
771 if ( strpos( $hook, 'cmplz-wizard' ) === false &&
772 strpos( $hook, 'cmplz-cookiebanner' ) === false &&
773 strpos( $hook, 'cmplz-proof-of-consent' ) === false &&
774 strpos( $hook, 'cmplz-script-center' ) === false &&
775 strpos( $hook, 'cmplz-processing' ) === false &&
776 strpos( $hook, 'cmplz-dataleak' ) === false &&
777 strpos( $hook, 'cmplz-settings' ) === false &&
778 ( !is_network_admin() || strpos( $hook, 'complianz' ) === false)
779 ) {
780 return;
781 }
782
783 //also skip the wizard for root pages of dataleaks and processing
784 if ( strpos( $hook, 'post_type' ) !== false ) {
785 return;
786 }
787
788 wp_register_style( 'cmplz-wizard', CMPLZ_URL . "assets/css/wizard$minified.css", false, CMPLZ_VERSION );
789 wp_enqueue_style( 'cmplz-wizard' );
790 }
791
792
793 /**
794 * Foreach required field, check if it's been answered
795 * if section is false, check all fields of the step.
796 * @param string $page
797 * @param int $step
798 * @param int $section
799 *
800 * @return bool
801 */
802
803
804 public function required_fields_completed( $page, $step, $section ) {
805 if ( ! cmplz_user_can_manage() ) {
806 return false;
807 }
808 //get all required fields for this section, and check if they're filled in
809 $fields = COMPLIANZ::$config->fields( $page, $step, $section );
810
811 //get
812 $fields = cmplz_array_filter_multidimensional( $fields, 'required', true );
813 foreach ( $fields as $fieldname => $args ) {
814 //if a condition exists, only check for this field if the condition applies.
815 if ( isset( $args['condition'] )
816 || isset( $args['callback_condition'] )
817 && ! COMPLIANZ::$field->condition_applies( $args )
818 ) {
819 continue;
820 }
821 $value = COMPLIANZ::$field->get_value( $fieldname );
822 if ( empty( $value ) ) {
823 return false;
824 }
825 }
826 return true;
827 }
828
829 public function all_required_fields_completed_wizard(){
830 if ( ! cmplz_user_can_manage() ) {
831 return false;
832 }
833 return $this->all_required_fields_completed('wizard');
834 }
835
836 /**
837 * Check if all required fields are filled
838 * @return bool
839 *
840 * */
841
842 public function all_required_fields_completed( $page ) {
843 if ( ! cmplz_user_can_manage() ) {
844 return false;
845 }
846 $total_fields = 0;
847 $completed_fields = 0;
848 $total_steps = $this->total_steps( $page );
849 for ( $i = 1; $i <= $total_steps; $i ++ ) {
850 $fields = COMPLIANZ::$config->fields( $page, $i, false );
851
852 foreach ( $fields as $fieldname => $field ) {
853 //is field required
854 $required = isset( $field['required'] ) ? $field['required'] : false;
855 if ( ( isset( $field['condition'] )
856 || isset( $field['callback_condition'] ) )
857 && ! COMPLIANZ::$field->condition_applies( $field )
858 ) {
859 $required = false;
860 }
861 if ( $required ) {
862 $value = cmplz_get_value( $fieldname );
863 $total_fields ++;
864 if ( ! empty( $value ) ) {
865 $completed_fields ++;
866 }
867 }
868 }
869 }
870
871 if ( $completed_fields == $total_fields ) {
872 return true;
873 } else {
874 return false;
875 }
876 }
877
878 /**
879 *
880 * Get the current selected post id for documents
881 * @return int
882 *
883 * */
884
885 public function post_id() {
886 $post_id = false;
887 if ( isset( $_GET['post_id'] ) || isset( $_POST['post_id'] ) ) {
888 $post_id = ( isset( $_GET['post_id'] ) )
889 ? intval( $_GET['post_id'] ) : intval( $_POST['post_id'] );
890 }
891
892 return $post_id;
893 }
894
895 /**
896 * Get selected wizard type
897 * @return string
898 */
899 public function wizard_type() {
900 if ( ! cmplz_user_can_manage() ) {
901 return '';
902 }
903 $wizard_type = 'wizard';
904 if ( isset( $_POST['wizard_type'] )
905 || isset( $_POST['wizard_type'] )
906 ) {
907 $wizard_type = isset( $_POST['wizard_type'] )
908 ? $_POST['wizard_type'] : $_GET['wizard_type'];
909 } else {
910 if ( isset( $_GET['page'] ) ) {
911 $wizard_type = str_replace( 'cmplz-', '', $_GET['page'] );
912 }
913 }
914
915 return $wizard_type;
916 }
917
918
919 /**
920 * Get a notice style header with an intro above a step or section
921 *
922 * @param string $page
923 * @param int $step
924 * @param int $section
925 *
926 * @return string
927 */
928
929 public function get_intro( $page, $step, $section ) {
930 //only show when in action
931 $intro = '';
932 if ( COMPLIANZ::$config->has_sections( $page, $step ) ) {
933 if ( isset( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'][ $section ]['intro'] ) ) {
934 $intro .= COMPLIANZ::$config->steps[ $page ][ $step ]['sections'][ $section ]['intro'];
935 }
936 } else {
937 if ( isset( COMPLIANZ::$config->steps[ $page ][ $step ]['intro'] ) ) {
938 $intro .= COMPLIANZ::$config->steps[ $page ][ $step ]['intro'];
939 }
940 }
941
942 if ( !empty( $intro ) ) {
943 $intro = '<div class="cmplz-wizard-intro">'
944 . $intro
945 . '</div>';
946 }
947
948 return $intro;
949 }
950
951
952 /**
953 * Retrieves the region to which this step applies
954 *
955 * @param $page
956 * @param $step
957 * @param $section
958 *
959 * @return array|bool
960 */
961 public function get_section_regions( $page, $step, $section ) {
962 if ( ! cmplz_user_can_manage() ) {
963 return false;
964 }
965 //only show when in action
966 $regions = array();
967
968 if ( COMPLIANZ::$config->has_sections( $page, $step ) ) {
969 if ( isset( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'][ $section ]['region'] ) ) {
970 $regions = COMPLIANZ::$config->steps[ $page ][ $step ]['sections'][ $section ]['region'];
971 }
972 } else {
973 if ( isset( COMPLIANZ::$config->steps[ $page ][ $step ]['region'] ) ) {
974 $regions = COMPLIANZ::$config->steps[ $page ][ $step ]['region'];
975 }
976 }
977
978 if ( $regions ) {
979 if ( ! is_array( $regions ) ) {
980 $regions = array( $regions );
981 }
982
983 foreach ( $regions as $index => $region ) {
984 if ( ! cmplz_has_region( $region ) ) {
985 unset( $regions[ $index ] );
986 }
987 }
988
989 }
990 if ( $regions ) {
991 $regions = array_map( 'strtoupper', $regions );
992 }
993 return $regions;
994 }
995
996
997 public function get_type( $post_id = false ) {
998 $page = false;
999 if ( $post_id ) {
1000 $region = COMPLIANZ::$document->get_region( $post_id );
1001 $post_type = get_post_type( $post_id );
1002 $page = str_replace( 'cmplz-', '', $post_type ) . '-'
1003 . $region;
1004 }
1005 if ( isset( $_GET['page'] ) ) {
1006 $page = str_replace( 'cmplz-', '',
1007 sanitize_title( $_GET['page'] ) );
1008 }
1009
1010 return $page;
1011 }
1012
1013
1014 public function wizard_completed_once() {
1015 return get_option( 'cmplz_wizard_completed_once' );
1016 }
1017
1018
1019 public function set_wizard_completed_once() {
1020 update_option( 'cmplz_wizard_completed_once', true, false );
1021 }
1022
1023 public function step( $page = false ) {
1024 if ( ! cmplz_user_can_manage() ) {
1025 return false;
1026 }
1027 $step = 1;
1028 if ( ! $page ) {
1029 $page = $this->wizard_type();
1030 }
1031
1032 $total_steps = $this->total_steps( $page );
1033
1034 if ( isset( $_GET["step"] ) ) {
1035 $step = intval( $_GET['step'] );
1036 }
1037
1038 if ( isset( $_POST["step"] ) ) {
1039 $step = intval( $_POST['step'] );
1040 }
1041
1042 if ( $step > $total_steps ) {
1043 $step = $total_steps;
1044 }
1045
1046 if ( $step <= 1 ) {
1047 $step = 1;
1048 }
1049
1050 return $step;
1051 }
1052
1053 public function section() {
1054 if ( ! cmplz_user_can_manage() ) {
1055 return false;
1056 }
1057 $section = 1;
1058 if ( isset( $_GET["section"] ) ) {
1059 $section = intval( $_GET['section'] );
1060 }
1061
1062 if ( isset( $_POST["section"] ) ) {
1063 $section = intval( $_POST['section'] );
1064 }
1065
1066 if ( $section > $this->last_section ) {
1067 $section = $this->last_section;
1068 }
1069
1070 if ( $section <= 1 ) {
1071 $section = 1;
1072 }
1073
1074 return $section;
1075 }
1076
1077 /**
1078 * Get total number of steps for a page
1079 *
1080 * @param $page
1081 *
1082 * @return int
1083 */
1084
1085 public function total_steps( $page ) {
1086 return count( COMPLIANZ::$config->steps[ $page ] );
1087 }
1088
1089 public function total_sections( $page, $step ) {
1090 if ( ! isset( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'] ) ) {
1091 return 0;
1092 }
1093
1094 return count( COMPLIANZ::$config->steps[ $page ][ $step ]['sections'] );
1095 }
1096
1097
1098 public function last_section( $page, $step ) {
1099 if ( ! isset( COMPLIANZ::$config->steps[ $page ][ $step ]["sections"] ) ) {
1100 return 1;
1101 }
1102
1103 $array = COMPLIANZ::$config->steps[ $page ][ $step ]["sections"];
1104
1105 return max( array_keys( $array ) );
1106
1107 }
1108
1109 public function first_section( $page, $step ) {
1110 if ( ! isset( COMPLIANZ::$config->steps[ $page ][ $step ]["sections"] ) ) {
1111 return 1;
1112 }
1113
1114 $arr = COMPLIANZ::$config->steps[ $page ][ $step ]["sections"];
1115 $first_key = key( $arr );
1116
1117 return $first_key;
1118 }
1119
1120 /**
1121 *
1122 * Check which percentage of the wizard is completed
1123 * @param bool $count_warnings
1124 *
1125 * @return int
1126 * */
1127
1128 public function wizard_percentage_complete( $count_warnings = true )
1129 {
1130 //store to make sure it only runs once.
1131 if ( $this->percentage_complete !== false ) {
1132 return $this->percentage_complete;
1133 }
1134
1135 $total_fields = 0;
1136 $completed_fields = 0;
1137 $total_steps = $this->total_steps( 'wizard' );
1138 for ( $i = 1; $i <= $total_steps; $i ++ ) {
1139 $fields = COMPLIANZ::$config->fields( 'wizard', $i, false );
1140
1141 foreach ( $fields as $fieldname => $field ) {
1142 //is field required
1143 $required = isset( $field['required'] ) ? $field['required']
1144 : false;
1145 if ( ( isset( $field['condition'] )
1146 || isset( $field['callback_condition'] ) )
1147 && ! COMPLIANZ::$field->condition_applies( $field )
1148 ) {
1149 $required = false;
1150 }
1151 if ( $required ) {
1152 $value = cmplz_get_value( $fieldname );
1153 $total_fields ++;
1154 if ( ! empty( $value ) ) {
1155 $completed_fields ++;
1156 }
1157 }
1158 }
1159 }
1160
1161 if ( $count_warnings ) {
1162 $args = array(
1163 'cache' => false,
1164 'status' => 'all',
1165 'progress_items_only' => true,
1166 );
1167 $total_warnings = count( COMPLIANZ::$admin->get_warnings( $args ) );
1168 $args = array(
1169 'cache' => false,
1170 'status' => 'completed',
1171 'progress_items_only' => true,
1172 );
1173 $completed_warnings = count( COMPLIANZ::$admin->get_warnings( $args ) );
1174 $completed_fields += $completed_warnings;
1175 $total_fields += $total_warnings;
1176 }
1177
1178 $pages = COMPLIANZ::$document->get_required_pages();
1179 foreach ( $pages as $region => $region_pages ) {
1180 foreach ( $region_pages as $type => $page ) {
1181 if ( COMPLIANZ::$document->page_exists( $type, $region ) ) {
1182 $completed_fields ++;
1183 }
1184 $total_fields ++;
1185 }
1186 }
1187
1188 $percentage = round( 100 * ( $completed_fields / $total_fields ) + 0.45 );
1189 $this->percentage_complete = $percentage;
1190 return $percentage;
1191 }
1192
1193 }
1194
1195
1196 } //class closure
1197