Skip to content

Conversation

@apinto-uc
Copy link
Collaborator

@apinto-uc apinto-uc commented Jan 27, 2026

User description

User description

Improvements

  • Enhanced script consent handling for WordPress 5.7+, including proper support for inline scripts

Bug fixes

  • Fixed an issue where the consent banner could become disabled after plugin updates or hosting migrations

PR Type

Bug fix, Enhancement


Description

  • Fixed consent banner disabling after plugin updates or hosting migrations

  • Enhanced script consent handling for WordPress 5.7+ with inline script support

  • Improved script tag attribute extraction for proper consent attribute injection

  • Removed banner disable logic from plugin deactivation process


Diagram Walkthrough

flowchart LR
  A["Plugin Activation"] --> B["Check Banner Status"]
  B --> C["Fresh Install?"]
  C -->|Yes| D["Enable Banner"]
  C -->|No| E["Banner Disabled + CBID Set?"]
  E -->|Yes| F["Re-enable Banner"]
  E -->|No| G["Keep Current State"]
  H["Script Tag Processing"] --> I["Extract Handle"]
  I --> J["Check Consent Required"]
  J -->|Yes| K["Add Consent Attributes"]
  J -->|No| L["Check If Ignored"]
  L -->|Yes| M["Add Ignore Attribute"]
  L -->|No| N["Return Unchanged"]
Loading

File Walkthrough

Relevant files
Configuration changes
cookiebot.php
Version bump to 4.6.3                                                                       

cookiebot.php

  • Updated plugin version from 4.6.2 to 4.6.3
+1/-1     
Cookiebot_WP.php
Update version constant                                                                   

src/lib/Cookiebot_WP.php

  • Updated plugin version constant from 4.6.2 to 4.6.3
+1/-1     
Bug fix
Cookiebot_Activated.php
Fix banner disable on updates and migrations                         

src/lib/Cookiebot_Activated.php

  • Added logic to re-enable banner if disabled but CBID is configured
  • Detects when banner was disabled by hosting or plugin update
  • Preserves fresh install behavior while recovering from unintended
    disables
+8/-0     
Cookiebot_Deactivated.php
Remove banner disable on deactivation                                       

src/lib/Cookiebot_Deactivated.php

  • Removed call to disable_banner() from deactivation process
  • Prevents unintended banner disabling when plugin is deactivated
+0/-1     
Enhancement
Script_Loader_Tag.php
Enhance consent attribute handling for inline scripts       

src/lib/script_loader_tag/Script_Loader_Tag.php

  • Enhanced cookiebot_add_consent_attribute_to_script_tag() to handle
    consent-required scripts via add_tag registration
  • Added extract_handle_from_attributes() method to extract script
    handles from tag attributes
  • Improved cookiebot_add_consent_attribute_to_inline_script_tag() to
    support inline scripts with consent requirements
  • Added proper handling for both consent-required and ignored inline
    scripts
  • Updated documentation to clarify WordPress 5.7+ support for both
    external and inline scripts
+53/-3   
Documentation
readme.txt
Update readme with v4.6.3 release notes                                   

readme.txt

  • Updated stable tag from 4.6.2 to 4.6.3
  • Added changelog entry for version 4.6.3 with improvements and bugfixes
  • Documented enhanced script consent handling and banner disable fix
+14/-1   


CodeAnt-AI Description

Restore banner when CBID present and add consent handling for WordPress 5.7+

What Changed

  • If the banner was previously disabled but a Cookiebot ID (CBID) is configured, the banner is now automatically re-enabled so the cookie banner appears after updates or migrations.
  • Plugin deactivation no longer disables the cookie banner, preventing accidental banner removal when the plugin is turned off.
  • Script consent attributes are now applied for WordPress 5.7+: both external scripts and their inline fragments receive proper consent attributes (type set to text/plain and data-cookieconsent with the required categories), and admin/ignored scripts get a data-cookieconsent="ignore" attribute.
  • Version, stable tag, and changelog updated to 4.6.3.

Impact

✅ Banner restored after plugin updates or hosting migrations
✅ Correct consent enforcement for inline scripts on WP 5.7+
✅ Banner not removed on plugin deactivation

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai
Copy link

codeant-ai bot commented Jan 27, 2026

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sonarqubecloud
Copy link

@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit logging: The PR adds/changes persistent state updates (e.g.,
update_option('cookiebot-banner-enabled', ...)) without any corresponding audit
logging that would allow reconstruction of who/when/why the banner state changed.

Referred Code
private function set_banner_enabled_by_default() {
	$enabled = get_option( 'cookiebot-banner-enabled', 'default' );
	$cbid    = Cookiebot_WP::get_cbid();

	// Set to enabled if it's a fresh install (default)
	if ( $enabled === 'default' ) {
		$enabled = '1';
		update_option( 'cookiebot-banner-enabled', $enabled );
	}

	// If banner is disabled but CBID is configured, it was disabled by hosting or plugin update. Re-enable it.
	if ( $enabled === '0' && ! empty( $cbid ) ) {
		update_option( 'cookiebot-banner-enabled', '1' );
	}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Attribute type assumptions: New logic assumes $attributes['id'] is a string (uses substr/preg_replace)
without guarding against unexpected types, which could trigger warnings on malformed
inputs or non-standard filter usage.

Referred Code
private function extract_handle_from_attributes( $attributes ) {
	if ( ! isset( $attributes['id'] ) ) {
		return null;
	}

	$id = $attributes['id'];

	// Remove the '-js' suffix that WordPress adds
	if ( substr( $id, -3 ) === '-js' ) {
		return substr( $id, 0, -3 );
	}

	// If no -js suffix, return the ID as-is (some scripts may not follow convention)
	return $id;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Weak input validation: The new handle extraction and inline-id parsing operate on filter-provided $attributes
without validating expected formats (e.g., ensuring id is a non-empty string matching
WordPress conventions), which may be exploitable or brittle in the presence of third-party
modifications.

Referred Code
public function cookiebot_add_consent_attribute_to_inline_script_tag( $attributes ) {
	if ( ! isset( $attributes['id'] ) ) {
		return $attributes;
	}

	// Check if inline script belongs to a consent-required parent script
	$base_handle = $this->extract_base_id_from_inline_id( $attributes['id'] );

	if ( $base_handle && array_key_exists( $base_handle, $this->tags ) && ! empty( $this->tags[ $base_handle ] ) ) {
		$attributes['type']               = 'text/plain';
		$attributes['data-cookieconsent'] = implode( ',', $this->tags[ $base_handle ] );
		return $attributes;
	}

	// Check if inline script belongs to an ignored parent script
	if ( $this->is_inline_of_ignored_script( $attributes['id'] ) ) {
		$attributes['data-cookieconsent'] = 'ignore';
	}

	return $attributes;
}


 ... (clipped 73 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@codeant-ai codeant-ai bot added the size:M This PR changes 30-99 lines, ignoring generated files label Jan 27, 2026
@qodo-code-review
Copy link

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: PHP 7.4 Lint

Failed stage: Run PHPCS [❌]

Failed test name: ""

Failure summary:

The action failed because the phpcs code style check (tests/vendor/bin/phpcs) reported linting
errors and exited with code 2.
- Trailing whitespace errors
(Squiz.WhiteSpace.SuperfluousWhitespace.EndLine) in src/lib/script_loader_tag/Script_Loader_Tag.php
at lines 114 and 144.
- Trailing whitespace errors (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
in src/lib/Cookiebot_Activated.php at lines 90 and 96.
The log indicates these violations are
automatically fixable by phpcbf, but they were present during the check, causing the job to fail.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

591:  Generating autoload files
592:  26 packages you are using are looking for funding.
593:  Use the `composer fund` command to find out more!
594:  PHP CodeSniffer Config installed_paths set to ../../phpcompatibility/php-compatibility,../../phpcompatibility/phpcompatibility-paragonie,../../phpcompatibility/phpcompatibility-wp,../../wp-coding-standards/wpcs
595:  ##[group]Run tests/vendor/bin/phpcs
596:  �[36;1mtests/vendor/bin/phpcs�[0m
597:  shell: /usr/bin/bash -e {0}
598:  env:
599:  COMPOSER_PROCESS_TIMEOUT: 0
600:  COMPOSER_NO_INTERACTION: 1
601:  COMPOSER_NO_AUDIT: 1
602:  ##[endgroup]
603:  .....�[32mE�[0m�[32mE�[0m. 8 / 8 (100%)
604:  �[1mFILE: src/lib/script_loader_tag/Script_Loader_Tag.php�[0m
605:  ----------------------------------------------------------------------
606:  �[1mFOUND 2 ERRORS AFFECTING 2 LINES�[0m
607:  ----------------------------------------------------------------------
608:  114 | �[31mERROR�[0m | [x] �[1mWhitespace found at end of line�[0m
609:  |       |     (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
610:  144 | �[31mERROR�[0m | [x] �[1mWhitespace found at end of line�[0m
611:  |       |     (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
612:  ----------------------------------------------------------------------
613:  �[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY�[0m
614:  ----------------------------------------------------------------------
615:  �[1mFILE: src/lib/Cookiebot_Activated.php�[0m
616:  ----------------------------------------------------------------------
617:  �[1mFOUND 2 ERRORS AFFECTING 2 LINES�[0m
618:  ----------------------------------------------------------------------
619:  90 | �[31mERROR�[0m | [x] �[1mWhitespace found at end of line�[0m
620:  |       |     (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
621:  96 | �[31mERROR�[0m | [x] �[1mWhitespace found at end of line�[0m
622:  |       |     (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
623:  ----------------------------------------------------------------------
624:  �[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY�[0m
625:  ----------------------------------------------------------------------
626:  Time: 5.47 secs; Memory: 12MB
627:  ##[error]Process completed with exit code 2.
628:  Post job cleanup.

@pantoaibot
Copy link

pantoaibot bot commented Jan 27, 2026

PR Summary:

Release v4.6.3 — Adds improved WordPress 5.7+ script consent handling (including inline scripts) and fixes banner disablement issues after updates/migrations.

  • cookiebot.php: plugin version bumped to 4.6.3.
  • readme.txt: stable tag bumped and changelog added (notes: enhanced script consent handling for WP 5.7+, bugfix to prevent banner becoming disabled).
  • src/lib/Cookiebot_Activated.php:
    • set_banner_enabled_by_default(): now checks Cookiebot ID (CBID) and
      • enables banner on fresh installs (default behavior),
      • re-enables banner if it was previously disabled but a CBID is configured (addresses hosting/plugin-update migrations).
  • src/lib/Cookiebot_Deactivated.php:
    • Removed disabling of the banner on plugin deactivation (deactivation no longer flips cookie banner option).
  • src/lib/Cookiebot_WP.php: plugin version constant updated to 4.6.3.
  • src/lib/script_loader_tag/Script_Loader_Tag.php:
    • Added support for WordPress 5.7+ script attribute filtering:
      • cookiebot_add_consent_attribute_to_script_tag() handles enqueued scripts (adds type="text/plain" and data-cookieconsent for consent-required handles, or data-cookieconsent="ignore" for ignored scripts).
      • cookiebot_add_consent_attribute_to_inline_script_tag() handles inline scripts by mapping inline IDs to parent handles, applying consent attributes for both consent-required and ignored inline blocks.
      • Helpers: extract_handle_from_attributes(), extract_base_id_from_inline_id(), is_inline_of_ignored_script(), check_ignore_script().
      • Improved handling to avoid modifying unrelated/inner script tags (fixes Gutenberg editor issues).
  • Behavior changes to note:
    • Banner is no longer forcibly disabled on plugin deactivation.
    • Banner will be automatically re-enabled if a CBID exists but banner was previously turned off (intentional recovery from hosting/plugin update issues).
    • Script attribute injection now supports WP 5.7+ script filter mechanisms and inline script cases — verify compatibility with any custom script-handling plugins/themes.

Reviewed by Panto AI

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Preserve custom script types

In cookiebot_add_consent_attribute_to_script_tag, avoid unconditionally
overwriting the script type attribute to text/plain; only do so if the type is
not set or is a standard JavaScript type.

src/lib/script_loader_tag/Script_Loader_Tag.php [115-119]

 if ( $handle && array_key_exists( $handle, $this->tags ) && ! empty( $this->tags[ $handle ] ) ) {
-    $attributes['type']               = 'text/plain';
+    if ( ! isset( $attributes['type'] ) || $attributes['type'] === 'text/javascript' ) {
+        $attributes['type'] = 'text/plain';
+    }
     $attributes['data-cookieconsent'] = implode( ',', $this->tags[ $handle ] );
     return $attributes;
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out that unconditionally overwriting the type attribute could break scripts with non-standard types (e.g., module), improving compatibility.

Low
Combine banner‐enable conditions

Refactor the logic in set_banner_enabled_by_default to combine the fresh-install
and re-enable conditions into a single if statement to avoid a duplicate
update_option call.

src/lib/Cookiebot_Activated.php [92-100]

-if ( $enabled === 'default' ) {
-    $enabled = '1';
-    update_option( 'cookiebot-banner-enabled', $enabled );
-}
-
-if ( $enabled === '0' && ! empty( $cbid ) ) {
+if ( $enabled === 'default' || ( $enabled === '0' && ! empty( $cbid ) ) ) {
     update_option( 'cookiebot-banner-enabled', '1' );
 }
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: The suggestion improves code conciseness and reduces redundancy by combining two conditional blocks that perform the same action into one.

Low
Possible issue
Prevent bug with incorrect inline handles

In cookiebot_add_consent_attribute_to_inline_script_tag, add a check to ensure
extract_base_id_from_inline_id successfully modified the script ID before
proceeding, preventing potential bugs with non-standard IDs.

src/lib/script_loader_tag/Script_Loader_Tag.php [137-157]

 	public function cookiebot_add_consent_attribute_to_inline_script_tag( $attributes ) {
 		if ( ! isset( $attributes['id'] ) ) {
 			return $attributes;
 		}
 
 		// Check if inline script belongs to a consent-required parent script
 		$base_handle = $this->extract_base_id_from_inline_id( $attributes['id'] );
+
+		if ( $base_handle === $attributes['id'] ) {
+			// Not a standard WP inline script ID format, or no suffix was stripped.
+			return $attributes;
+		}
 		
-		if ( $base_handle && array_key_exists( $base_handle, $this->tags ) && ! empty( $this->tags[ $base_handle ] ) ) {
+		if ( array_key_exists( $base_handle, $this->tags ) && ! empty( $this->tags[ $base_handle ] ) ) {
 			$attributes['type']               = 'text/plain';
 			$attributes['data-cookieconsent'] = implode( ',', $this->tags[ $base_handle ] );
 			return $attributes;
 		}
 
 		// Check if inline script belongs to an ignored parent script
 		if ( $this->is_inline_of_ignored_script( $attributes['id'] ) ) {
 			$attributes['data-cookieconsent'] = 'ignore';
 		}
 
 		return $attributes;
 	}
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a potential edge case where a non-standard script ID could be processed incorrectly, and the proposed change adds a safeguard to prevent this.

Low
  • More

@codeant-ai
Copy link

codeant-ai bot commented Jan 27, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Auto re-enable behavior
    The new logic will unconditionally re-enable the banner when the option is '0' but a CBID exists. This may override an administrator's deliberate choice to keep the banner disabled (for privacy/hosting reasons). Confirm this is intended and consider logging or notifying admins when the banner is programmatically re-enabled.

  • Filter arg / handle resolution
    The new WP 5.7+ handling parses the handle from the attributes array rather than using the handle parameter provided by WordPress filters. In the constructor the filter registration for 'wp_script_attributes' requests only 1 arg, while the filter actually provides the handle. This makes handle resolution fragile (parsing 'id') and inconsistent with the registered filter arguments — it can miss the canonical handle or mismatch registered tags.

  • Inline ID handling
    The helper that derives a base handle from inline script IDs (extract_base_id_from_inline_id) strips '-js-extra|after|before' but does not remove a plain '-js' suffix. Inline scripts with IDs like 'handle-js' will not map back to the registered handle 'handle', so consent attributes may not be applied to inline blocks whose parent handle uses the normal '-js' suffix.

  • CBID validation
    The code checks only !empty($cbid). If get_cbid() can return whitespace or unexpected values, this check could produce false positives and re-enable the banner incorrectly. Validate / normalize the CBID before using it to decide state changes.

  • Duplicate/Conflicting Version Definitions
    The file defines CYBOT_COOKIEBOT_VERSION as a global define near the top and now also declares a class constant COOKIEBOT_PLUGIN_VERSION. Verify whether the global define is intentionally kept and ensure consistent updates during releases to avoid runtime inconsistencies in enqueued assets and any version checks.

Comment on lines 88 to 101
$enabled = get_option( 'cookiebot-banner-enabled', 'default' );
$cbid = Cookiebot_WP::get_cbid();

// Set to enabled if it's a fresh install (default)
if ( $enabled === 'default' ) {
$enabled = '1';
update_option( 'cookiebot-banner-enabled', $enabled );
}

// If banner is disabled but CBID is configured, it was disabled by hosting or plugin update. Re-enable it.
if ( $enabled === '0' && ! empty( $cbid ) ) {
update_option( 'cookiebot-banner-enabled', '1' );
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] This change forcefully re-enables the banner when option 'cookiebot-banner-enabled' === '0' and a CBID exists (lines 98-100). Two issues: (1) On multisite installations the code uses update_option() which will not update the network/site option if the setting is stored as a site option — use update_site_option() when is_multisite() to keep behavior consistent with set_to_mode_auto_when_no_cookiebot_id_is_set(). (2) This unconditional re-enable can override an administrator's intentional decision to disable the banner. Instead, scope the auto re-enable to only known-recovery scenarios (for example: during activation/migration flows protected by a transient, or when detecting a recent plugin-version change) and/or log/admin-notice the action so admins are aware. Example fix snippet: if ( $enabled === '0' && ! empty( $cbid ) && get_transient( 'cookiebot_reenable_banner_recovery' ) ) { if ( is_multisite() ) { update_site_option( 'cookiebot-banner-enabled', '1' ); } else { update_option( 'cookiebot-banner-enabled', '1' ); } }

private function set_banner_enabled_by_default() {
	$enabled = get_option( 'cookiebot-banner-enabled', 'default' );
	$cbid    = Cookiebot_WP::get_cbid();

	// Set to enabled if it's a fresh install (default)
	if ( $enabled === 'default' ) {
		$enabled = '1';
		update_option( 'cookiebot-banner-enabled', $enabled );
	}

	// Only attempt automatic recovery when explicitly in a recovery window
	if ( $enabled === '0' && ! empty( $cbid ) && get_transient( 'cookiebot_reenable_banner_recovery' ) ) {
		if ( is_multisite() ) {
			update_site_option( 'cookiebot-banner-enabled', '1' );
		} else {
			update_option( 'cookiebot-banner-enabled', '1' );
		}

		Cookiebot_WP::debug_log( 'Banner was automatically re-enabled as part of recovery flow.' );
	}
}

Comment on lines 111 to +119
public function cookiebot_add_consent_attribute_to_script_tag( $attributes ) {
// First, check if this script requires consent (registered via add_tag)
$handle = $this->extract_handle_from_attributes( $attributes );

if ( $handle && array_key_exists( $handle, $this->tags ) && ! empty( $this->tags[ $handle ] ) ) {
$attributes['type'] = 'text/plain';
$attributes['data-cookieconsent'] = implode( ',', $this->tags[ $handle ] );
return $attributes;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] In cookiebot_add_consent_attribute_to_script_tag you force attributes['type'] = 'text/plain' for scripts that require consent (lines 116-117). Overriding the type unconditionally can break legitimate script types (e.g. type='module') or other non-JS content. Change the logic to: (1) detect and preserve module scripts (if isset($attributes['type']) && $attributes['type'] === 'module' then skip or handle differently), (2) only override type when no type is set or when it's safe to change, and (3) consider adding a whitelist/opt-in for types you can convert to text/plain. Example: if ( empty( $attributes['type'] ) || $attributes['type'] === 'text/javascript' ) { $attributes['type'] = 'text/plain'; }

public function cookiebot_add_consent_attribute_to_script_tag( $attributes ) {
	$handle = $this->extract_handle_from_attributes( $attributes );

	if ( $handle && array_key_exists( $handle, $this->tags ) && ! empty( $this->tags[ $handle ] ) ) {
		// Preserve module scripts and other explicit non-JS types
		if ( empty( $attributes['type'] ) || $attributes['type'] === 'text/javascript' || $attributes['type'] === 'application/javascript' ) {
			$attributes['type'] = 'text/plain';
		}

		$attributes['data-cookieconsent'] = implode( ',', $this->tags[ $handle ] );
		return $attributes;
	}

	if ( isset( $attributes['src'] ) && $this->check_ignore_script( $attributes['src'] ) ) {
		$attributes['data-cookieconsent'] = 'ignore';
	}

	return $attributes;
}

Comment on lines +216 to +230
private function extract_handle_from_attributes( $attributes ) {
if ( ! isset( $attributes['id'] ) ) {
return null;
}

$id = $attributes['id'];

// Remove the '-js' suffix that WordPress adds
if ( substr( $id, -3 ) === '-js' ) {
return substr( $id, 0, -3 );
}

// If no -js suffix, return the ID as-is (some scripts may not follow convention)
return $id;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[REFACTORING] extract_handle_from_attributes strips only the literal '-js' suffix (lines 223-225) and returns the id as-is for other patterns. Improve robustness by removing '-js' and optional extra/after/before suffixes in one step (same as extract_base_id_from_inline_id suggestion). Example: $id = preg_replace('/-js(?:-(?:extra|after|before))?$/', '', $id); return $id !== '' ? $id : null; This will better handle varied ID conventions and make handle extraction more reliable.

private function extract_handle_from_attributes( $attributes ) {
	if ( ! isset( $attributes['id'] ) ) {
		return null;
	}

	$id = $attributes['id'];

	// Remove the '-js' suffix and optional inline suffixes that WordPress may add
	$handle = preg_replace( '/-js(?:-(?:extra|after|before))?$/', '', $id );

	return $handle !== '' ? $handle : null;
}

@pantoaibot
Copy link

pantoaibot bot commented Jan 27, 2026

Reviewed up to commit:2396a4f1bcfcb3bd824d0cc44f729061187b01c6

Additional Suggestion
src/lib/Cookiebot_Deactivated.php, line:14-15 You removed the call that disabled the banner on deactivation (previously disable_banner()). This will keep the banner option intact when the plugin is deactivated. If this was intentional as part of the bugfix (to avoid disabling the banner after updates/migrations), please document the decision. If not intentional, re-check whether deactivation should still clear/disable front-facing behavior or provide an admin-facing toggle to control this behavior. Also ensure uninstall() still cleans up expected options when a full uninstall is requested.
// In src/lib/Cookiebot_Deactivated.php
class Cookiebot_Deactivated {

	/**
	 * Plugin deactivation hook.
	 *
	 * Note: We intentionally keep the `cookiebot-banner-enabled` option
	 * unchanged on deactivation so that the banner configuration is
	 * preserved across plugin updates and hosting migrations.
	 *
	 * Full removal of options (including banner state) is handled by
	 * the uninstall routine instead.
	 *
	 * @throws Exception
	 */
	public function run() {
		$this->run_addons_deactivation_hooks();
		// Intentionally do not disable the banner here to avoid
		// unintentionally turning it off across updates/migrations.
	}

	/**
	 * @throws Exception
	 */
	private function run_addons_deactivation_hooks() {
		$cookiebot_addons = Cookiebot_Addons::instance();
		$cookiebot_addons->cookiebot_deactivated();
	}
}
src/lib/script_loader_tag/Script_Loader_Tag.php, line:177-205 extract_base_id_from_inline_id currently strips only '-js-(extra|after|before)' suffix (line 179/205). It won't remove a plain '-js' suffix (e.g. 'my-handle-js'), which means mapping inline scripts to their base handle can fail. Use a single regex to remove '-js' and optional '-js-' forms. Example replacement: return preg_replace('/-js(?:-(?:extra|after|before))?$/', '', $inline_script_id); This will improve matching of inline script IDs to registered handles.
private function extract_base_id_from_inline_id( $inline_script_id ) {
	// Strip -js and optional -js-(extra|after|before) suffix to get the base ID.
	return preg_replace( '/-js(?:-(?:extra|after|before))?$/', '', $inline_script_id );
}

Reviewed by Panto AI

@codeant-ai
Copy link

codeant-ai bot commented Jan 27, 2026

CodeAnt AI finished reviewing your PR.

@apinto-uc apinto-uc merged commit e4c6515 into master Jan 27, 2026
10 of 11 checks passed
@apinto-uc apinto-uc deleted the v4.6.3 branch January 27, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review effort 2/5 size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants