Skip to content

Add support for registering sites with myDot and exchanging a jwt token that can be used to share site stats - #1315

Merged
pattonwebz merged 95 commits into
developfrom
william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence
Apr 20, 2026
Merged

Add support for registering sites with myDot and exchanging a jwt token that can be used to share site stats#1315
pattonwebz merged 95 commits into
developfrom
william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence

Conversation

@pattonwebz

@pattonwebz pattonwebz commented Dec 20, 2025

Copy link
Copy Markdown
Member

Adds an optional connection that users can establish if they enter a license key to connect their site to myDot for puposes of stats sharing.

Checklist

  • PR is linked to the main issue in the repo
  • Tests are added that cover changes

Summary by CodeRabbit

  • New Features

    • Connected Services admin page to manage licensing and site connections (free key or JWT).
    • Connector enabling license lifecycle, site registration/unregistration, JWT auth with public-key rotation, periodic license checks, and admin notices.
    • REST scans-stats endpoint accepts JWT-based authentication with fallback to existing permissions.
    • Scan stats now include a "top pages with issues" metric.
  • Chores

    • PHP runtime now requires OpenSSL and JSON extensions.
    • Unschedules daily license-check cron on plugin deactivation.

Copilot AI review requested due to automatic review settings December 20, 2025 00:36
@coderabbitai

coderabbitai Bot commented Dec 20, 2025

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a MyDot Connector for licensing, JWT auth with key rotation and site registration; wires it into plugin bootstrap and REST permission checks; introduces a Connected Services admin page; adds top-pages stats; updates composer requirements and unschedules license cron on deactivation; adds a dev API endpoint filter.

Changes

Cohort / File(s) Summary
Dependency Configuration
composer.json
Adds runtime PHP extensions ext-openssl and ext-json; minor formatting adjustments.
MyDot Licensing Integration
includes/classes/MyDot/Connector.php
New Connector class: license activation/deactivation, JWT validation with key rotation, public-key refresh, site register/unregister API wrappers, admin notices, cron scheduling, safe HTTP wrapper, and option persistence. Review for security (JWT, key handling), network error handling, and transient usage.
Plugin Bootstrap
includes/classes/class-plugin.php
Imports and instantiates EqualizeDigital\AccessibilityChecker\MyDot\Connector and calls init() during plugin construction. Check initialization scope (admin vs non-admin).
REST API Permission
includes/classes/class-rest-api.php
Imports Connector and updates /scans-stats route permission callback to accept $request and attempt JWT-based auth via Connector::validate_jwt_token_in_request_with_fallback($request) before falling back to capability checks. Review permission callback signature change and potential performance implications.
Admin UI - Connected Services
admin/AdminPage/ConnectedServicesPage.php
New admin page class registering a "Connected Services" settings tab, rendering license/JWT connect/disconnect flows and admin notices. Inspect nonce/permission handling and UI strings.
Scans Stats Reporting
admin/class-scans-stats.php
Adds get_top_pages_with_issues($limit = 5) and includes top_pages_with_issues in summary output; new DB query aggregates posts by issue count. Review SQL for correctness and performance.
Deactivation Cleanup
includes/deactivation.php
Unschedules daily license check cron via wp_clear_scheduled_hook('edac_check_license_hook') on plugin deactivation.
Dev API Endpoint Override
accessibility-checker.php
Registers edac_mydot_api_endpoint filter returning a dev/testing API URL. Confirm this override is intended in non-dev environments.

Sequence Diagram(s)

sequenceDiagram
    participant Admin as Admin User
    participant UI as Connected Services Page
    participant Connector as MyDot Connector
    participant API as MyDot API
    participant WP as WordPress (Options/Cron)

    Admin->>UI: submit license or JWT
    UI->>Connector: handle submission (activate/register)
    Connector->>API: validate license / request JWT / register site
    API-->>Connector: response (license/JWT/registration, public key)
    Connector->>Connector: validate JWT, verify/rotate keys, persist options
    Connector->>WP: schedule/clear cron, update options
    Connector-->>UI: return status for admin notice
Loading
sequenceDiagram
    participant Client as Client
    participant REST as Plugin REST Endpoint
    participant Connector as MyDot Connector
    participant API as MyDot API
    participant WP as WordPress (capability check)

    Client->>REST: request /scans-stats
    REST->>Connector: validate_jwt_token_in_request_with_fallback(request)
    Connector->>Connector: extract token & verify (iss/aud/exp/nbf/signature)
    alt valid
        Connector-->>REST: grant access
    else invalid/expired
        Connector->>API: fetch public key / refresh
        API-->>Connector: public key
        Connector->>Connector: re-validate token
        alt re-validated
            Connector-->>REST: grant access
        else
            REST->>WP: fallback to current_user_can('edit_posts')
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

codex

Suggested reviewers

  • SteveJonesDev

Poem

🐇

I hop through keys and license streams,
I fetch the tokens, guard your dreams,
I spin the keys with nimble feet,
I post a notice, soft and sweet,
Hooray — the checker hums complete!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main change: adding support for site registration with myDot and JWT token exchange for sharing site stats, which aligns with the core changes adding the Connector class and ConnectedServicesPage.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @pattonwebz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature by integrating the plugin with the myDot service. Users can now establish an optional connection by entering a license key, which facilitates the secure exchange of a JSON Web Token (JWT) for sharing site statistics and enabling additional accessibility services. This integration is managed through a new dedicated license settings page in the WordPress admin, and the underlying API communication is secured using JWT for data access.

Highlights

  • MyDot Integration: Introduced a new system to connect the site with myDot for enhanced accessibility services and stats sharing, activated via a license key.
  • License Management Page: Added a dedicated "License" tab to the admin settings, allowing users to activate/deactivate their license and register/unregister their site with myDot.
  • JWT Token Exchange: Implemented functionality to exchange a license key for a JWT token, which is then used for secure communication and sharing site statistics with myDot.
  • REST API Authentication: Enhanced the get_scans_stats REST API endpoint to accept JWT tokens for authentication, providing a secure way for myDot to access site data.
  • New PHP Dependencies: Added ext-openssl and ext-json to composer.json as required extensions for handling JWT token validation.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces functionality to connect the plugin with a 'myDot' service for license validation and sharing site statistics via JWT. It adds a new license page, handlers for license activation/deactivation, and site registration/unregistration. The changes also include a mechanism to validate JWTs for authenticating REST API requests. My review has identified a few critical issues, such as a hardcoded local API endpoint and usage of an undefined constant, which will prevent the feature from working in production. I've also pointed out some high-severity bugs related to redundant and faulty form handling logic, and some medium-severity issues regarding code style and WordPress best practices. Addressing these points will improve the correctness and maintainability of the new features.

Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread admin/AdminPage/ConnectedServicesPage.php
Comment thread admin/AdminPage/LicensePage.php Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
composer.json (1)

50-53: Good addition of required PHP extensions.

The ext-openssl and ext-json requirements are necessary for JWT validation in the Connector class. This ensures environments have the required extensions before installation.

Note: Line 53 uses a tab for indentation instead of spaces, which is inconsistent with the rest of the file.

🔎 Fix indentation consistency
         "composer/installers": "^1.12.0",
         "ext-openssl": "*",
         "ext-json": "*"
-	},
+    },
includes/classes/MyDot/Connector.php (1)

70-71: Inconsistent hook name prefix.

The cron hook uses edacp_check_license_hook (EDACP prefix) but this is the free plugin which uses edac_ prefix. This creates naming inconsistency and potential conflicts if EDACP (Pro) is also installed.

🔎 Suggested fix
-		add_action( 'edacp_check_license_hook', [ $this, 'periodic_check_license' ] );
+		add_action( 'edac_check_license_hook', [ $this, 'periodic_check_license' ] );
 	public function check_license_cron() {
-		if ( ! wp_next_scheduled( 'edacp_check_license_hook' ) ) {
-			wp_schedule_event( time(), 'daily', 'edacp_check_license_hook' );
+		if ( ! wp_next_scheduled( 'edac_check_license_hook' ) ) {
+			wp_schedule_event( time(), 'daily', 'edac_check_license_hook' );
 		}
 	}

Also applies to: 295-298

admin/AdminPage/LicensePage.php (2)

231-245: Use admin_url() for constructing admin URLs.

The license URL is constructed manually using get_bloginfo('url'). This may not work correctly on multisite installations or sites with non-standard admin paths.

🔎 Suggested fix
 	public function admin_notices() {
 		$error       = get_option( 'edac_license_error' );
-		$license_url = get_bloginfo( 'url' ) . '/wp-admin/admin.php?page=accessibility_checker_settings&tab=license';
+		$license_url = admin_url( 'admin.php?page=accessibility_checker_settings&tab=license' );
 		$message     = null;

150-154: Consider moving inline styles to a stylesheet.

The status indicators use inline styles (style="color:green;", style="color:red;"). For consistency and maintainability, consider using CSS classes instead.

Also applies to: 201-203

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 35faecf and 9f16a33.

📒 Files selected for processing (5)
  • admin/AdminPage/LicensePage.php (1 hunks)
  • composer.json (1 hunks)
  • includes/classes/MyDot/Connector.php (1 hunks)
  • includes/classes/class-plugin.php (2 hunks)
  • includes/classes/class-rest-api.php (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
composer.json

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use PSR-4 autoloading with the EqualizeDigital\AccessibilityChecker namespace

Files:

  • composer.json
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress Coding Standards (WPCS) in all PHP files
Class names use CamelCase (ClassNameConvention) for new classes
Use edac_ prefix for all custom action/filter hook names
Ensure PHP 7.4+ compatibility
Use type hints where appropriate (parameters, return types, properties)
Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX
Use the WordPress database API ($wpdb) for all database operations
Prefix functions and classes in the global namespace with edac_
Use WordPress transients for caching temporary data where appropriate
All user-facing text in PHP must be translatable using the accessibility-checker text domain
Use PHPDoc for all public classes, methods, and properties
Document all custom hooks (actions/filters) with docblocks including parameters and types

Files:

  • includes/classes/class-plugin.php
  • includes/classes/class-rest-api.php
  • admin/AdminPage/LicensePage.php
  • includes/classes/MyDot/Connector.php
includes/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place core (non-admin) functionality in the /includes directory

Files:

  • includes/classes/class-plugin.php
  • includes/classes/class-rest-api.php
  • includes/classes/MyDot/Connector.php
**/class-*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/class-*.php: Legacy PHP class files must use WordPress style naming class-class-name.php
Legacy class names use WordPress underscore style (Class_Name_Convention)

Files:

  • includes/classes/class-plugin.php
  • includes/classes/class-rest-api.php
admin/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place admin classes and admin-only PHP code in the /admin directory

Files:

  • admin/AdminPage/LicensePage.php
{admin,includes}/**/[A-Z][A-Za-z0-9]*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

New PHP class files must use CamelCase file names like ClassName.php

Files:

  • admin/AdminPage/LicensePage.php
  • includes/classes/MyDot/Connector.php
🧠 Learnings (2)
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to composer.json : Use PSR-4 autoloading with the EqualizeDigital\AccessibilityChecker namespace

Applied to files:

  • includes/classes/class-plugin.php
  • includes/classes/class-rest-api.php
📚 Learning: 2025-08-27T14:11:05.736Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1171
File: includes/helper-functions.php:808-826
Timestamp: 2025-08-27T14:11:05.736Z
Learning: In the Accessibility Checker Pro plugin, the class '\EqualizeDigital\AccessibilityCheckerPro\VirtualContent\PostType\VirtualPageType' was never released, so backward compatibility checks for this class name are not needed in edac_is_virtual_page() function.

Applied to files:

  • includes/classes/class-plugin.php
🧬 Code graph analysis (2)
includes/classes/class-rest-api.php (1)
includes/classes/MyDot/Connector.php (2)
  • Connector (20-676)
  • validate_jwt_token_in_request (660-675)
admin/AdminPage/LicensePage.php (1)
includes/classes/MyDot/Connector.php (1)
  • Connector (20-676)
🪛 PHPStan (2.1.33)
includes/classes/MyDot/Connector.php

271-271: Constant EDACP_STORE_URL not found.
Learn more at https://phpstan.org/user-guide/discovering-symbols

(constant.notFound)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (6)
includes/classes/class-plugin.php (1)

13-13: LGTM!

The Connector integration is correctly placed. The unconditional initialization is appropriate since:

  1. Connector::init() has an internal guard checking EDACP_VERSION to avoid conflicts
  2. The Connector needs to be active for REST API JWT validation and scheduled cron tasks

Also applies to: 47-48

includes/classes/class-rest-api.php (1)

107-112: LGTM!

The dual authentication strategy is well-implemented:

  1. First checks for a valid JWT token (for external MyDot service requests)
  2. Falls back to WordPress capability check for logged-in admin users

This allows the /scans-stats endpoint to serve both external authenticated services and WordPress administrators.

includes/classes/MyDot/Connector.php (2)

124-149: License handling follows WordPress security best practices.

Good security implementation:

  • Capability check with current_user_can('manage_options')
  • Nonce verification with check_admin_referer()
  • Input sanitization with sanitize_text_field() and wp_unslash()
  • Safe redirect with wp_safe_redirect()

508-549: LGTM!

The register_site() method properly:

  • Validates input before making API calls
  • Handles WP_Error responses
  • Returns structured success/failure arrays
  • Uses proper JSON encoding and Content-Type headers
admin/AdminPage/LicensePage.php (2)

127-184: License form implementation follows WordPress best practices.

The form correctly:

  • Uses admin-post.php as the action target
  • Includes settings_fields() for the option group
  • Uses wp_nonce_field() for CSRF protection
  • Properly escapes all output with esc_attr(), esc_html(), and esc_url()

186-220: Site registration UI is well-structured.

The conditional rendering based on JWT token presence provides clear user feedback about registration status. Forms properly use separate nonces for register and unregister actions.

Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php
There are already post callbacks directly hooked in to register and unregister

[PRO-286]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds MyDot integration for license management and site registration, enabling users with license keys to connect their sites to MyDot for stats sharing and email reports. The implementation includes JWT token-based authentication for secure API access and a dedicated license management page in the WordPress admin.

Key Changes:

  • New MyDot Connector class for license activation/deactivation and JWT-based site registration
  • License management page integrated into plugin settings
  • REST API endpoint permission callback updated to accept JWT tokens for external access
  • Required PHP extensions (openssl, json) added to composer dependencies

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 25 comments.

Show a summary per file
File Description
includes/classes/MyDot/Connector.php Core connector class handling license API calls, JWT token validation, site registration/unregistration, and cron-based license checks
admin/AdminPage/LicensePage.php License settings page UI with forms for license activation and site registration
includes/classes/class-plugin.php Initializes Connector instance during plugin bootstrap
includes/classes/class-rest-api.php Updates /scans-stats endpoint permission callback to accept JWT tokens
composer.json Adds ext-openssl and ext-json as required dependencies
Comments suppressed due to low confidence (1)

includes/classes/MyDot/Connector.php:38

  • The API endpoint is hardcoded to use HTTP instead of HTTPS. This is a security concern as license keys and JWT tokens will be transmitted in plain text over the network. Change the protocol to HTTPS to ensure secure communication with the MyDot API.
	const API_ENDPOINT = 'http://my.equalizedigital.local';

Comment thread includes/classes/MyDot/Connector.php
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php
Comment thread includes/classes/MyDot/Connector.php
Comment thread admin/AdminPage/LicensePage.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
Comment thread includes/classes/MyDot/Connector.php Outdated
This brings it in line to conform with RFC 8725

[PRO-286]
…pro display differences

There is still more work to do to fully integrate with pro

[PRO-286]
…ndle-licence' of github.com:equalizedigital/accessibility-checker into william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In @admin/AdminPage/ConnectedServicesPage.php:
- Line 137: The heading string passed to esc_html_e is incorrect; replace the
text "Connected this site" with "Connect this site" in the esc_html_e call so
the line reads esc_html_e( 'Connect this site', 'accessibility-checker' ) to fix
the grammar in the <h2> heading.

In @includes/classes/MyDot/Connector.php:
- Around line 726-742: In validate_jwt_token_in_request_with_fallback, the
Authorization header is referenced but $parts is never defined; parse the header
first (e.g., trim the header and explode by space into $parts), ensure you
handle case-insensitive "Bearer" (or compare lowercased $parts[0] to 'bearer'),
and only call self::validate_jwt_token_with_fallback($parts[1]) when $parts
count is 2 and the scheme matches; otherwise return false.
- Around line 66-73: The cron hook was registered with the wrong prefix: replace
the Pro prefix `edacp_check_license_hook` with the correct
`edac_check_license_hook` wherever it’s referenced so the scheduled event fires;
update the add_action call that binds `periodic_check_license` (currently using
`edacp_check_license_hook`) and update `check_license_cron()` so the scheduled
event uses `edac_check_license_hook` (and any corresponding
wp_schedule_event/wp_clear_scheduled_hook calls) to match the `edac_` naming
convention.
- Around line 290-294: The check decodes the remote response into $license_data
but only calls update_option('edac_license_status', $license_data->license) when
the license is not 'valid', leaving a renewed/valid license unrecorded; change
the logic in the block that handles wp_remote_retrieve_body($response) and
json_decode(...) so that update_option('edac_license_status',
$license_data->license) is executed for all returned statuses (optionally
sanitizing $license_data->license first) instead of only when 'valid' !==
$license_data->license.
🧹 Nitpick comments (1)
admin/AdminPage/ConnectedServicesPage.php (1)

299-304: Inconsistent URL handling - consider using edac_link_wrapper() for UTM tracking.

The renewal link on line 301 uses a hardcoded URL with inline UTM parameters, while render_page() uses \edac_link_wrapper() for consistent UTM handling. Consider updating for consistency:

🔎 Suggested fix
 			case 'expired':
 				return sprintf(
 				/* translators: %1$s: item name, %2$s: item name */
-					__( 'Your %1$s license has expired. <a href="https://my.equalizedigital.com/?utm_source=wpadmin" target="_blank">Please renew your license</a> to continue accessing additional features and services for %2$s.', 'accessibility-checker' ),
+					__( 'Your %1$s license has expired. <a href="%2$s" target="_blank">Please renew your license</a> to continue accessing additional features and services for %3$s.', 'accessibility-checker' ),
+					Connector::PRODUCT_NAME,
+					esc_url( \edac_link_wrapper( 'https://my.equalizedigital.com/', 'connected-services', 'renew', false ) ),
-					Connector::PRODUCT_NAME,
 					Connector::PRODUCT_NAME
 				);
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9f16a33 and 4b4f37d.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • admin/AdminPage/ConnectedServicesPage.php
  • includes/classes/MyDot/Connector.php
  • includes/classes/class-rest-api.php
🧰 Additional context used
📓 Path-based instructions (5)
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress Coding Standards (WPCS) in all PHP files
Class names use CamelCase (ClassNameConvention) for new classes
Use edac_ prefix for all custom action/filter hook names
Ensure PHP 7.4+ compatibility
Use type hints where appropriate (parameters, return types, properties)
Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX
Use the WordPress database API ($wpdb) for all database operations
Prefix functions and classes in the global namespace with edac_
Use WordPress transients for caching temporary data where appropriate
All user-facing text in PHP must be translatable using the accessibility-checker text domain
Use PHPDoc for all public classes, methods, and properties
Document all custom hooks (actions/filters) with docblocks including parameters and types

Files:

  • includes/classes/MyDot/Connector.php
  • admin/AdminPage/ConnectedServicesPage.php
  • includes/classes/class-rest-api.php
includes/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place core (non-admin) functionality in the /includes directory

Files:

  • includes/classes/MyDot/Connector.php
  • includes/classes/class-rest-api.php
{admin,includes}/**/[A-Z][A-Za-z0-9]*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

New PHP class files must use CamelCase file names like ClassName.php

Files:

  • includes/classes/MyDot/Connector.php
  • admin/AdminPage/ConnectedServicesPage.php
admin/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place admin classes and admin-only PHP code in the /admin directory

Files:

  • admin/AdminPage/ConnectedServicesPage.php
**/class-*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/class-*.php: Legacy PHP class files must use WordPress style naming class-class-name.php
Legacy class names use WordPress underscore style (Class_Name_Convention)

Files:

  • includes/classes/class-rest-api.php
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to accessibility-checker.php : Implement proper plugin activation and deactivation hooks
📚 Learning: 2025-08-26T11:25:48.236Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:401-410
Timestamp: 2025-08-26T11:25:48.236Z
Learning: In the Accessibility Checker plugin, the edac_is_pro() function uses a robust detection pattern by checking both EDACP_VERSION (which comes from the pro plugin) and EDAC_KEY_VALID existence before looking at its value. This prevents PHP notices and ensures reliable pro feature detection.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to **/*.php : Use edac_ prefix for all custom action/filter hook names

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-07-28T17:02:44.387Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1108
File: admin/class-orphaned-issues-cleanup.php:49-52
Timestamp: 2025-07-28T17:02:44.387Z
Learning: The user pattonwebz prefers cron scheduling patterns where `wp_schedule_event()` is called in init_hooks() with conditional checks (like `wp_next_scheduled()`) rather than only in activation hooks, citing that performance impact is negligible due to caching and this is a familiar pattern for developers.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to accessibility-checker.php : Implement proper plugin activation and deactivation hooks

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it, so remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it. This means remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks. This timing works correctly for backwards compatibility scenarios where you need to remove Pro plugin hooks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it. This means remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks. The timing works correctly for backwards compatibility scenarios where you need to remove Pro plugin hooks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to **/*.php : Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-27T14:11:05.736Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1171
File: includes/helper-functions.php:808-826
Timestamp: 2025-08-27T14:11:05.736Z
Learning: In the Accessibility Checker Pro plugin, the class '\EqualizeDigital\AccessibilityCheckerPro\VirtualContent\PostType\VirtualPageType' was never released, so backward compatibility checks for this class name are not needed in edac_is_virtual_page() function.

Applied to files:

  • admin/AdminPage/ConnectedServicesPage.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to composer.json : Use PSR-4 autoloading with the EqualizeDigital\AccessibilityChecker namespace

Applied to files:

  • includes/classes/class-rest-api.php
🧬 Code graph analysis (3)
includes/classes/MyDot/Connector.php (2)
admin/class-admin.php (1)
  • Admin (20-114)
admin/AdminPage/ConnectedServicesPage.php (3)
  • ConnectedServicesPage (24-353)
  • add_page (54-73)
  • get_error_message (296-352)
admin/AdminPage/ConnectedServicesPage.php (1)
includes/classes/MyDot/Connector.php (1)
  • Connector (22-837)
includes/classes/class-rest-api.php (1)
includes/classes/MyDot/Connector.php (2)
  • Connector (22-837)
  • validate_jwt_token_in_request_with_fallback (726-742)
🪛 PHPStan (2.1.33)
includes/classes/MyDot/Connector.php

734-734: Undefined variable: $parts

(variable.undefined)


734-734: Undefined variable: $parts

(variable.undefined)


736-736: Undefined variable: $parts

(variable.undefined)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Integration Test: PHP 8.2 | WP latest (+ ms)
  • GitHub Check: Integration Test: PHP 8.1 | WP latest (+ ms)
🔇 Additional comments (5)
includes/classes/class-rest-api.php (1)

107-113: Permission callback logic is appropriate for JWT-based external access.

The fallback pattern (JWT validation → capability check) correctly enables external service access while maintaining WordPress authentication for admin users. However, note that Connector::validate_jwt_token_in_request_with_fallback() has a critical bug (undefined $parts variable) that will cause this to always return false. Once that's fixed in Connector.php, this will work as intended.

Ensure the scan statistics data exposed via this endpoint doesn't include sensitive information (e.g., user identifiers, emails) since JWT-authenticated requests bypass WordPress user authentication.

admin/AdminPage/ConnectedServicesPage.php (1)

127-260: Well-structured admin page with proper security practices.

The implementation correctly:

  • Uses wp_nonce_field() for CSRF protection on all forms
  • Properly escapes output with esc_html(), esc_attr(), esc_url()
  • Uses wp_kses_post() for links containing HTML
  • Separates free plugin (license key) vs Pro (JWT-based) flows cleanly
includes/classes/MyDot/Connector.php (3)

627-689: JWT validation implements RFC 8725 best practices correctly.

The implementation properly validates:

  • Token structure and RS256 algorithm
  • Signature using stored public key
  • Expiration (exp), issuer (iss), audience (aud), and not-before (nbf) claims

One consideration: the iss and aud validations only trigger if those claims exist in the token. For maximum security per RFC 8725, ensure your issuer (MyDot API) always includes these claims in issued tokens.


56-73: Well-structured initialization with proper WordPress hook patterns.

The init() method correctly:

  • Instantiates the admin page with capability parameter
  • Registers settings via admin_init
  • Uses admin_post_* hooks for form handling (correct pattern)
  • Schedules cron for periodic checks

Based on learnings, the cron scheduling pattern with wp_next_scheduled() check in admin_init is an acceptable and familiar pattern for WordPress developers.


374-430: Admin notices won't display due to redirect timing.

The add_action('admin_notices', ...) calls in handle_site_registration() won't work because handle_jwt_register_post() redirects immediately after calling this method. The notices are registered but never rendered because the page redirects before output.

Consider using transients to persist notices across the redirect:

🔎 Suggested approach
// Instead of add_action(), store in transient:
set_transient( 'edac_admin_notice', [
    'type'    => 'success',
    'message' => __( 'Site registered successfully...', 'accessibility-checker' ),
], 30 );

// Then in a separate method hooked to admin_notices:
public function display_transient_notices() {
    $notice = get_transient( 'edac_admin_notice' );
    if ( $notice ) {
        printf(
            '<div class="notice notice-%s is-dismissible"><p>%s</p></div>',
            esc_attr( $notice['type'] ),
            esc_html( $notice['message'] )
        );
        delete_transient( 'edac_admin_notice' );
    }
}

Likely an incorrect or invalid review comment.

Comment thread admin/AdminPage/ConnectedServicesPage.php Outdated
Comment thread includes/classes/MyDot/Connector.php
Comment thread includes/classes/MyDot/Connector.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @admin/AdminPage/ConnectedServicesPage.php:
- Line 271: The code builds an admin link by concatenating get_bloginfo('url')
with a hard-coded /wp-admin path into $license_url; replace that construction to
use WordPress's admin_url() helper so the URL is correct in multisite and
filtered environments (update the assignment to $license_url in
ConnectedServicesPage:: — or wherever $license_url is set — to call
admin_url('admin.php?page=accessibility_checker_settings&tab=connected-services')
instead of string concatenation).
🧹 Nitpick comments (2)
admin/AdminPage/ConnectedServicesPage.php (2)

222-222: Replace inline styles with CSS classes.

Inline style="margin:0;" attributes are used on the forms. Consider using a CSS class instead for better maintainability and consistency with other styling recommendations.

Also applies to: 233-233


301-301: Use edac_link_wrapper() for consistent UTM tracking.

The URL at line 301 hardcodes ?utm_source=wpadmin instead of using the edac_link_wrapper() helper function that's consistently used elsewhere in this file (lines 132-135). This creates inconsistent UTM parameter handling.

🔎 Proposed fix
-__( 'Your %1$s license has expired. <a href="https://my.equalizedigital.com/?utm_source=wpadmin" target="_blank">Please renew your license</a> to continue accessing additional features and services for %2$s.', 'accessibility-checker' ),
+__( 'Your %1$s license has expired. <a href="' . esc_url( \edac_link_wrapper( 'https://my.equalizedigital.com/', 'license-error', 'renew', false ) ) . '" target="_blank">Please renew your license</a> to continue accessing additional features and services for %2$s.', 'accessibility-checker' ),

Note: Since this is within a translatable string, you may need to refactor this to construct the link outside the translation string and use sprintf() with a placeholder for better maintainability.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4b4f37d and 79614f1.

📒 Files selected for processing (1)
  • admin/AdminPage/ConnectedServicesPage.php
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress Coding Standards (WPCS) in all PHP files
Class names use CamelCase (ClassNameConvention) for new classes
Use edac_ prefix for all custom action/filter hook names
Ensure PHP 7.4+ compatibility
Use type hints where appropriate (parameters, return types, properties)
Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX
Use the WordPress database API ($wpdb) for all database operations
Prefix functions and classes in the global namespace with edac_
Use WordPress transients for caching temporary data where appropriate
All user-facing text in PHP must be translatable using the accessibility-checker text domain
Use PHPDoc for all public classes, methods, and properties
Document all custom hooks (actions/filters) with docblocks including parameters and types

Files:

  • admin/AdminPage/ConnectedServicesPage.php
admin/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place admin classes and admin-only PHP code in the /admin directory

Files:

  • admin/AdminPage/ConnectedServicesPage.php
{admin,includes}/**/[A-Z][A-Za-z0-9]*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

New PHP class files must use CamelCase file names like ClassName.php

Files:

  • admin/AdminPage/ConnectedServicesPage.php
🧠 Learnings (1)
📚 Learning: 2025-08-27T14:11:05.736Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1171
File: includes/helper-functions.php:808-826
Timestamp: 2025-08-27T14:11:05.736Z
Learning: In the Accessibility Checker Pro plugin, the class '\EqualizeDigital\AccessibilityCheckerPro\VirtualContent\PostType\VirtualPageType' was never released, so backward compatibility checks for this class name are not needed in edac_is_virtual_page() function.

Applied to files:

  • admin/AdminPage/ConnectedServicesPage.php
🧬 Code graph analysis (1)
admin/AdminPage/ConnectedServicesPage.php (1)
includes/classes/MyDot/Connector.php (1)
  • Connector (22-837)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Integration Test: PHP 8.2 | WP latest (+ ms)
🔇 Additional comments (4)
admin/AdminPage/ConnectedServicesPage.php (4)

46-73: LGTM!

Hook registration follows WordPress conventions and uses the proper edac_ prefix for custom hooks. The priority of 1001 for in_admin_header ensures notices display correctly.


128-137: LGTM!

Option retrieval and link construction are secure. The use of \edac_link_wrapper() for all external links ensures consistent UTM parameter tracking across the UI.


249-260: LGTM!

Terms and privacy links are properly constructed with UTM tracking and correctly escaped. The i18n implementation with translator comments is appropriate.


22-22: Update @SInCE version tags to match the file header.

Multiple docblocks throughout the class use @since 1.xx.x as a placeholder, but the file header at line 10 specifies @since 1.34.0. Update all @since tags to use the consistent version number 1.34.0.

Also applies to: 29-29, 38-38, 50-50, 78-78, 97-97, 112-112, 123-123, 265-265, 289-289

Likely an incorrect or invalid review comment.

…ndle-licence' of github.com:equalizedigital/accessibility-checker into william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
includes/classes/MyDot/Connector.php (1)

665-682: Consider requiring iss and aud claims rather than optional validation.

RFC 8725 recommends that if the issuer issues JWTs for multiple relying parties, the aud claim must be validated. Currently, these claims are only validated if present. If the MyDot issuer always includes these claims, consider making them required to strengthen security:

 		// RFC 8725: Validate issuer claim to prevent token substitution attacks.
-		if ( isset( $payload['iss'] ) ) {
-			$expected_iss = self::get_jwt_issuer();
-			if ( $payload['iss'] !== $expected_iss ) {
-				return false;
-			}
+		if ( ! isset( $payload['iss'] ) ) {
+			return false; // iss claim is required.
+		}
+		$expected_iss = self::get_jwt_issuer();
+		if ( $payload['iss'] !== $expected_iss ) {
+			return false;
 		}

This prevents accepting tokens without issuer/audience claims, which could be security-relevant if the API is expected to always include them.

Please verify whether the MyDot API always includes iss and aud claims in issued JWTs to determine if they should be required.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 79614f1 and b058479.

📒 Files selected for processing (1)
  • includes/classes/MyDot/Connector.php
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress Coding Standards (WPCS) in all PHP files
Class names use CamelCase (ClassNameConvention) for new classes
Use edac_ prefix for all custom action/filter hook names
Ensure PHP 7.4+ compatibility
Use type hints where appropriate (parameters, return types, properties)
Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX
Use the WordPress database API ($wpdb) for all database operations
Prefix functions and classes in the global namespace with edac_
Use WordPress transients for caching temporary data where appropriate
All user-facing text in PHP must be translatable using the accessibility-checker text domain
Use PHPDoc for all public classes, methods, and properties
Document all custom hooks (actions/filters) with docblocks including parameters and types

Files:

  • includes/classes/MyDot/Connector.php
includes/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place core (non-admin) functionality in the /includes directory

Files:

  • includes/classes/MyDot/Connector.php
{admin,includes}/**/[A-Z][A-Za-z0-9]*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

New PHP class files must use CamelCase file names like ClassName.php

Files:

  • includes/classes/MyDot/Connector.php
🧠 Learnings (8)
📚 Learning: 2025-08-26T11:25:48.236Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:401-410
Timestamp: 2025-08-26T11:25:48.236Z
Learning: In the Accessibility Checker plugin, the edac_is_pro() function uses a robust detection pattern by checking both EDACP_VERSION (which comes from the pro plugin) and EDAC_KEY_VALID existence before looking at its value. This prevents PHP notices and ensures reliable pro feature detection.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to **/*.php : Use edac_ prefix for all custom action/filter hook names

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-07-28T17:02:44.387Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1108
File: admin/class-orphaned-issues-cleanup.php:49-52
Timestamp: 2025-07-28T17:02:44.387Z
Learning: The user pattonwebz prefers cron scheduling patterns where `wp_schedule_event()` is called in init_hooks() with conditional checks (like `wp_next_scheduled()`) rather than only in activation hooks, citing that performance impact is negligible due to caching and this is a familiar pattern for developers.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to accessibility-checker.php : Implement proper plugin activation and deactivation hooks

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it, so remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it. This means remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks. This timing works correctly for backwards compatibility scenarios where you need to remove Pro plugin hooks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-26T13:24:26.788Z
Learnt from: pattonwebz
Repo: equalizedigital/accessibility-checker PR: 1208
File: includes/options-page.php:76-84
Timestamp: 2025-08-26T13:24:26.788Z
Learning: In WordPress, the admin_menu hook fires during the admin_init process, not after it. This means remove_action calls placed inside functions hooked to admin_menu will execute at the appropriate time to affect other admin_init callbacks. The timing works correctly for backwards compatibility scenarios where you need to remove Pro plugin hooks.

Applied to files:

  • includes/classes/MyDot/Connector.php
📚 Learning: 2025-08-29T11:15:35.151Z
Learnt from: CR
Repo: equalizedigital/accessibility-checker PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-29T11:15:35.151Z
Learning: Applies to **/*.php : Sanitize inputs, validate data, and escape outputs following WordPress security best practices; use nonces for forms/AJAX

Applied to files:

  • includes/classes/MyDot/Connector.php
🧬 Code graph analysis (1)
includes/classes/MyDot/Connector.php (1)
admin/AdminPage/ConnectedServicesPage.php (3)
  • ConnectedServicesPage (24-353)
  • add_page (54-73)
  • get_error_message (296-352)
🔇 Additional comments (12)
includes/classes/MyDot/Connector.php (12)

1-50: Acknowledged: Development API endpoint will be updated before release.

The constants and class structure look appropriate. The API_ENDPOINT using a local development URL has been acknowledged by the author as intentional for now.


82-109: LGTM!

Settings registration follows WordPress best practices with proper type definitions and sanitization callbacks.


118-143: LGTM!

The handler properly implements security best practices: capability check, nonce verification via check_admin_referer(), input sanitization, and safe redirect.


152-199: LGTM!

License activation flow handles errors gracefully and automatically triggers site registration on successful activation, which is good UX.


208-247: LGTM!

Deactivation properly unregisters the site before deactivating the license and performs complete cleanup of stored options on success.


332-365: LGTM!

Both JWT registration handlers implement proper security with capability checks, nonce verification, and safe redirects.


489-584: LGTM!

Both register_site() and unregister_site() are well-implemented API wrappers with proper parameter validation, error handling, and consistent request configuration.


593-608: LGTM!

JWT issuer and audience getters are well-designed with filters for customization and protocol-agnostic comparison.


702-716: LGTM!

The fallback pattern is well-designed - try validation, refresh key if needed, retry. This handles key rotation gracefully without user intervention.


726-743: LGTM!

The $parts variable issue from previous reviews has been fixed. The Authorization header parsing and Bearer token extraction are correctly implemented.


757-812: Inconsistent API endpoints and response keys for public key retrieval.

Two methods fetch the public key but use different endpoints and expect different response keys:

Method Endpoint Response Key
verify_and_update_public_key() /public-key jwt_public_key
refresh_public_key_from_issuer() /get-public-key public_key

This inconsistency could cause issues if one endpoint returns a different format or if the API consolidates these endpoints later.

Please verify whether both endpoints are intentional and if the response key difference (jwt_public_key vs public_key) is correct. If they serve the same purpose, consider consolidating to a single endpoint/key name.


823-837: LGTM!

The safe_remote_get() wrapper properly handles VIP environment compatibility with appropriate fallback for non-VIP hosts.

Comment thread includes/classes/MyDot/Connector.php
@github-actions github-actions Bot removed the gha-build label Apr 3, 2026
pattonwebz and others added 19 commits April 6, 2026 10:49
…plugin-to-be-able-to-handle-licence' into william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence
When the Pro license recovers to valid status during periodic checks,
the edacp_license_error option should be cleared to remove persistent
error notices (expired, disabled, etc.) from the admin UI.
This ensures both free and Pro license errors are cleared consistently
when licenses recover to valid status.
Addresses PR #491 review comment regarding missing error cleanup.
@github-actions

Copy link
Copy Markdown
Contributor

✅ Accessibility Checker build (primary only)

@pattonwebz
pattonwebz merged commit 4a1db50 into develop Apr 20, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants