-
Notifications
You must be signed in to change notification settings - Fork 19
Add support for registering sites with myDot and exchanging a jwt token that can be used to share site stats #1315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
pattonwebz
merged 95 commits into
develop
from
william/pro-286-update-the-free-plugin-to-be-able-to-handle-licence
Apr 20, 2026
Merged
Changes from 7 commits
Commits
Show all changes
95 commits
Select commit
Hold shift + click to select a range
108be2a
Add a license page and connector activating a free license to myDot
pattonwebz 6cb0b73
Implement periodic license checks and SSL verification
pattonwebz 5fec71e
Init the connector in the main plugin class
pattonwebz 2acb695
Update the LicensePage with a secondary form for registering sites fo…
pattonwebz e8895ac
Update the Connector to handle registering and unregistering sites fo…
pattonwebz e798fb1
Allow a jwt token in request to validate for getting scan stats
pattonwebz 9f16a33
Include ext-openssl as a requrement for the plugin as well as ext-json
pattonwebz f6e3cf1
Update composer.lock after changing requirement packages to include i…
pattonwebz 3efe96e
Remove handle_jwt_registration() method as it is redundant
pattonwebz 50231be
Correct the endpoint and option key used to connect to and store lice…
pattonwebz 0df4710
Add key cycling handling and verify `iss`, `aud` and `nbf` values on key
pattonwebz 4a4463b
Fix expected array key that will hold the public key when revalidating
pattonwebz cc7d926
Rename the License tab to Connected Services and handle some free vs …
pattonwebz 095f889
Update some links on connected services page to use the helper for li…
pattonwebz 4b4f37d
Merge branch 'william/pro-286-update-the-free-plugin-to-be-able-to-ha…
pattonwebz 79614f1
Fix typo in tab header copy
pattonwebz 5aa493d
Handle the parts splitting for bearer checking more safely
pattonwebz b058479
Merge branch 'william/pro-286-update-the-free-plugin-to-be-able-to-ha…
pattonwebz c20eb30
Use link helper wrapper function for expired license key link
pattonwebz d8a1dd5
Use edac rather than edacp for schedule to check license
pattonwebz 1c77fb1
Check if the license_data has a license key before accesing it
pattonwebz 512fdec
Merge branch 'william/pro-286-update-the-free-plugin-to-be-able-to-ha…
pattonwebz 2a2ed34
Update a since tag to reflect not yet known release version
pattonwebz 518d038
Define a default capability for viewing connected services page
pattonwebz cff4290
Handle some admin notice display on the connected services page for e…
pattonwebz ce98297
Hook the admin notices in at a later action to avoid them being unhooked
pattonwebz 45af7d6
When the pro plugin has license deactivated we should unregister the …
pattonwebz 0800d3e
Don't get the option twice when doing periodic_check_license
pattonwebz 7ef9049
Add helper to figure out if we are using the free key or the pro key …
pattonwebz 3f57bcb
Calculate the top 5 posts with issues when generating the scan stats
pattonwebz 543f666
Fix mismatched key for top post
pattonwebz fdc1452
Fix typo in docblock
pattonwebz b0e986a
For top 5 posts get only those in the scannable types or status array…
pattonwebz cb2c23d
Fix some of the status notices for adding and removing sites from con…
pattonwebz ab0602e
Show the connected services page to those with manage_options capability
pattonwebz 48cf076
Fix order of vip_safe_wp_remote_get params
pattonwebz 02989fe
Handle base64url_decode in a strict way
pattonwebz ffebe5c
Validate only if there is an aud, exp and iss value
pattonwebz 027ddfa
Fix mismatched filter name in docblock
pattonwebz 15e22e4
Clear the license checking cron when deactivated
pattonwebz cb1950e
Swap to init for the license check cron scheduler
pattonwebz 0103f65
Set the prod url for the API_ENDPOINT and filter it when using
pattonwebz 5f60721
Use the strict base64url decode method for signature
pattonwebz b38b1e0
Use prefix on a filter for the mydot api endpoint
pattonwebz ef2e00d
Align vip_safe_wp_remote_get timeout and reties with expected boundary
pattonwebz 8fb2f7a
Never need to store the jwt token on this site, can decrypt with the …
pattonwebz bac44fb
Disable free periodic check for license when pro is enabled
pattonwebz 0f52eab
Make unregister method public so it can be added to an action
pattonwebz 5856ef4
Use site id rather than a no longer stored jwt for connected check
pattonwebz ceb87f5
Handle showing correct button when pro is enabled and site is connected
pattonwebz 3cefde3
Pass the site id when unregistering
pattonwebz acdcec7
Bump version to a phony alpha for testing sake
pattonwebz 5a3b4e2
Add a filter with a test url for mydot endpoint that will be used in …
pattonwebz 6362687
Merge remote-tracking branch 'origin/develop' into william/pro-286-up…
pattonwebz 7232377
Add a note about a testing api remap
pattonwebz 432f5be
Merge branch 'develop' into william/pro-286-update-the-free-plugin-to…
pattonwebz bc9ed1d
Updating composer lock after backmerge of develop here - both branche…
pattonwebz 78ebbd3
Add escaping to post title and permalinks passed through rest in top_…
pattonwebz ee1c1f5
Verify a 200 status code from periodic_check_license()
pattonwebz cb5b420
Enforce numeric not before value (nbf)
pattonwebz 6b463a6
Clamp the max timeout for vip_safe_wp_remote_get to max of 5
pattonwebz 677e531
Make sure that the limit is set at a positive int otherwise return em…
pattonwebz 84717fa
Swap to single shared key of edacp across free and pro plugins
pattonwebz 9861bf8
Bump DB version for new key to 1.0.7 to trigger migration
pattonwebz acbf0d0
Make the product id filterable for easier local and staging site testing
pattonwebz f9969ed
Use item_id as the product identifier instead of name
pattonwebz da52157
Add method to store top issues found on site in the site stats data
pattonwebz 87e5998
Add Accessibility Reports settings page and UI enhancements
SteveJonesDev f1f5b04
For top issues get them based on severity first, then by count.
pattonwebz 9793b90
Agent-Logs-Url: https://github.com/equalizedigital/accessibility-chec…
Copilot e026b99
Fix undefined $preview_data in AccessibilityReportsPage::render_page()
Copilot 8cad96c
Merge pull request #1605 from equalizedigital/codex/accessibility-rep…
pattonwebz 2bb0fa9
Cleanup the license key on activation and it's state always
pattonwebz 7ba2c42
Bump version to 1.40.0-alpha
pattonwebz 553fc59
Update product id for free reports to 24
pattonwebz 5d929d0
Determine if we are using a pro key or not
pattonwebz d48231a
Fix SVG viewBox casing and update report summary text; adjust status …
SteveJonesDev 29d17c5
Update next report date calculation and change button link to manage …
SteveJonesDev 70315b7
fix(mydot): implement free/pro fallback state handling and metadata r…
pattonwebz 451a981
test(mydot): add coverage for fallback, cleanup, and metadata inference
pattonwebz e6001b1
docs(mydot): add free-pro license state machine documentation
pattonwebz 95122e6
Merge remote-tracking branch 'origin/william/pro-286-update-the-free-…
pattonwebz 5c60210
Fix local disconnect cleanup to clear stale Pro license state
pattonwebz a9cb69e
Make accessibility reports UI fallback-aware for Pro-to-free transitions
pattonwebz 6b06d43
Use effective license context in connected services and notices
pattonwebz 52d2b2b
Add free->pro enrollment handoff and clear fallback marker on free re…
pattonwebz 195a62f
Guard reports fallback UI from stale connected state and use stored n…
pattonwebz ab13d4c
Guard connected services fallback UI from stale connected state
pattonwebz a1aa1a9
Preserve active Pro license when disabling email reports
pattonwebz 1567a9b
Use deactivation hook license args for connector unregistration
pattonwebz 9ae7e66
Fix: Clear Pro license error on recovery during periodic checks
pattonwebz b6a0562
Remove a testing filter added when working on dev for this
pattonwebz 9ade581
Don't respond with stats if site is unregistered even if JWT is valid
pattonwebz d4285bc
Try handle pro degraded license state better
pattonwebz 46a89da
Remove a dev-only planning file from repo
pattonwebz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,315 @@ | ||
| <?php | ||
| /** | ||
| * License Page and Notices for Accessibility Checker | ||
| * | ||
| * Handles the rendering and functionality of the license settings page | ||
| * in the WordPress admin, including form submission, error notices, and | ||
| * license status management. | ||
| * | ||
| * @package Accessibility_Checker | ||
| * @since 1.34.0 | ||
| */ | ||
|
|
||
| namespace EqualizeDigital\AccessibilityChecker\Admin\AdminPage; | ||
|
|
||
| use EqualizeDigital\AccessibilityChecker\MyDot\Connector; | ||
|
|
||
| /** | ||
| * Class LicensePage | ||
| * | ||
| * Manages license page display and functionality within the admin settings area. | ||
| * | ||
| * @since 1.xx.x | ||
| */ | ||
| class LicensePage implements PageInterface { | ||
|
|
||
| /** | ||
| * The capability required to access the settings page. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @var string | ||
| */ | ||
| private string $settings_capability; | ||
|
|
||
| /** | ||
| * Constructor | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @param string $settings_capability The capability required to view/edit license settings. | ||
| */ | ||
| public function __construct( $settings_capability ) { | ||
| $this->settings_capability = $settings_capability; | ||
| } | ||
|
|
||
| /** | ||
| * Register hooks to add the license page to the settings tabs | ||
| * and handle license-related notices. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @return void | ||
| */ | ||
| public function add_page() { | ||
| // Add license tab to settings page. | ||
| add_filter( | ||
| 'edac_filter_settings_tab_items', | ||
| [ $this, 'add_license_tab' ] | ||
| ); | ||
|
|
||
| // Render license tab content when active. | ||
| add_action( | ||
| 'edac_settings_tab_content', | ||
| [ $this, 'maybe_render_tab_content' ] | ||
| ); | ||
|
|
||
| // Register admin notice display with higher priority than default. | ||
| add_action( | ||
| 'in_admin_header', | ||
| [ $this, 'register_admin_notices' ], | ||
| 1001 | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Add license tab to settings tabs array. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @param array $tabs Array of registered settings tabs. | ||
| * | ||
| * @return array Modified tabs array with license tab added. | ||
| */ | ||
| public function add_license_tab( $tabs ) { | ||
| $tabs[] = [ | ||
| 'slug' => 'license', | ||
| 'label' => esc_html__( 'License', 'accessibility-checker' ), | ||
| 'order' => 99, // License is always last tab. | ||
| 'capability' => $this->settings_capability, | ||
| ]; | ||
| return $tabs; | ||
| } | ||
|
|
||
| /** | ||
| * Conditionally render the license tab content if the current tab is 'license'. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @param string $settings_tab The current active settings tab. | ||
| * | ||
| * @return void | ||
| */ | ||
| public function maybe_render_tab_content( $settings_tab ) { | ||
| if ( 'license' === $settings_tab ) { | ||
| $this->render_page(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Register the admin notices function to display license-related messages. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @return void | ||
| */ | ||
| public function register_admin_notices() { | ||
| add_action( 'admin_notices', [ $this, 'admin_notices' ] ); | ||
| } | ||
|
|
||
| /** | ||
| * Render the license settings page content. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @return void | ||
| */ | ||
| public function render_page() { | ||
| $license = get_option( 'edac_license_key' ); | ||
| $status = get_option( 'edac_license_status' ); | ||
| $jwt_token = get_option( 'edac_jwt_token' ); | ||
| ?> | ||
| <h2><?php esc_html_e( 'License Settings', 'accessibility-checker' ); ?></h2> | ||
| <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> | ||
| <?php settings_fields( 'edac_license' ); ?> | ||
| <table class="form-table"> | ||
| <tbody> | ||
| <tr valign="top"> | ||
| <th scope="row" valign="top"> | ||
| <?php esc_html_e( 'License Key', 'accessibility-checker' ); ?> | ||
| </th> | ||
| <td> | ||
| <input | ||
| id="edac_license_key" | ||
| name="edac_license_key" | ||
| type="text" | ||
| class="regular-text" | ||
| value="<?php echo esc_attr( $license ); ?>" | ||
| /> | ||
| <label class="description" for="edac_license_key"> | ||
| <?php if ( false !== $status && 'valid' === $status ) : ?> | ||
| <span style="color:green;"> <?php esc_html_e( 'active', 'accessibility-checker' ); ?></span> | ||
| <?php elseif ( false !== $status && 'expired' === $status ) : ?> | ||
| <span style="color:red;"> <?php esc_html_e( 'expired', 'accessibility-checker' ); ?></span> | ||
| <?php else : ?> | ||
| <?php esc_html_e( 'Enter your license key', 'accessibility-checker' ); ?> | ||
| <?php endif; ?> | ||
| </label> | ||
| </td> | ||
| </tr> | ||
| <tr valign="top"> | ||
| <th scope="row" valign="top"></th> | ||
| <td> | ||
| <input type="hidden" name="action" value="edac_license" /> | ||
| <?php wp_nonce_field( 'edac_license_nonce', 'edac_license_nonce' ); ?> | ||
| <?php if ( false !== $status && 'valid' === $status ) : ?> | ||
| <input | ||
| type="submit" | ||
| class="button-primary" | ||
| name="edac_license_deactivate" | ||
| value="<?php esc_attr_e( 'Deactivate License', 'accessibility-checker' ); ?>" | ||
| > | ||
| <?php else : ?> | ||
| <input | ||
| type="submit" | ||
| class="button-primary" | ||
| name="edac_license_activate" | ||
| value="<?php esc_attr_e( 'Activate License', 'accessibility-checker' ); ?>" | ||
| /> | ||
| <?php endif; ?> | ||
| </td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| </form> | ||
|
|
||
| <?php if ( false !== $status && 'valid' === $status ) : ?> | ||
| <h3><?php esc_html_e( 'Site Registration', 'accessibility-checker' ); ?></h3> | ||
| <p><?php esc_html_e( 'Register this site to use additional accessibility services.', 'accessibility-checker' ); ?></p> | ||
|
|
||
| <?php if ( $jwt_token ) : ?> | ||
| <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> | ||
| <?php wp_nonce_field( 'edac_jwt_unregister', 'edac_jwt_unregister_nonce' ); ?> | ||
| <input type="hidden" name="action" value="edac_jwt_unregister" /> | ||
| <p> | ||
| <input | ||
| type="submit" | ||
| class="button-secondary" | ||
| name="edac_jwt_unregister" | ||
| value="<?php esc_attr_e( 'Unregister Site', 'accessibility-checker' ); ?>" | ||
| /> | ||
| <span class="description" style="margin-left: 10px; color: green;"> | ||
|
pattonwebz marked this conversation as resolved.
Outdated
|
||
| <?php esc_html_e( 'Site is registered', 'accessibility-checker' ); ?> | ||
| </span> | ||
| </p> | ||
| </form> | ||
| <?php else : ?> | ||
| <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"> | ||
| <?php wp_nonce_field( 'edac_jwt_register', 'edac_jwt_register_nonce' ); ?> | ||
| <input type="hidden" name="action" value="edac_jwt_register" /> | ||
| <p> | ||
| <input | ||
| type="submit" | ||
| class="button-secondary" | ||
| name="edac_jwt_register" | ||
| value="<?php esc_attr_e( 'Register Site', 'accessibility-checker' ); ?>" | ||
| /> | ||
| </p> | ||
| </form> | ||
| <?php endif; ?> | ||
| <?php endif; ?> | ||
| <?php | ||
| } | ||
|
|
||
| /** | ||
| * Display admin notices when the license added is invalid or expired. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @return void | ||
| */ | ||
| 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'; | ||
|
pattonwebz marked this conversation as resolved.
Outdated
|
||
| $message = null; | ||
|
|
||
| if ( $error ) { | ||
| $message = $this->get_error_message( $error, $license_url ); | ||
| } | ||
|
|
||
| if ( isset( $message ) ) { | ||
| printf( | ||
| '<div class="notice notice-error"><p>%s</p></div>', | ||
| wp_kses_post( $message ) | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Get appropriate error message based on the license error code. | ||
| * | ||
| * @since 1.xx.x | ||
| * | ||
| * @param string $error_code The license error code. | ||
| * @param string $license_url URL to the license settings page. | ||
| * | ||
| * @return string The formatted error message. | ||
| */ | ||
| private function get_error_message( $error_code, $license_url ) { | ||
| switch ( $error_code ) { | ||
| 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' ), | ||
| Connector::PRODUCT_NAME, | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| case 'disabled': | ||
| case 'revoked': | ||
| return sprintf( | ||
| /* translators: %s: item name */ | ||
| __( 'Your %s license key has been disabled. Please contact our support team if you believe this is an error or would like to continue accessing additional features.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| case 'missing': | ||
| return sprintf( | ||
| /* translators: %1$s: item name, %2$s: license url, %3$s: item name */ | ||
| __( 'The license key for %1$s appears to be invalid. Please <a href="%2$s">check your license key</a> to access additional accessibility features and services for %3$s.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME, | ||
| $license_url, | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| case 'invalid': | ||
| case 'site_inactive': | ||
| return sprintf( | ||
| /* translators: %s: item name */ | ||
| __( 'This license key for %s is not active for this site. Please activate it to access additional features on this website.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| case 'item_name_mismatch': | ||
| return sprintf( | ||
| /* translators: %s: the plugins item name */ | ||
| __( 'This license key does not appear to be valid for %s. Please verify you\'ve entered the correct license key.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| case 'no_activations_left': | ||
| return sprintf( | ||
| /* translators: %s: the plugins item name */ | ||
| __( 'Your %s license key has reached its site activation limit. You can upgrade your license or deactivate it on another site to use the additional features here.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
|
|
||
| default: | ||
| return sprintf( | ||
| /* translators: %s: the plugins item name */ | ||
| __( 'There was an issue validating your %s license key. Please try again or contact our support team if the problem persists.', 'accessibility-checker' ), | ||
| Connector::PRODUCT_NAME | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
pattonwebz marked this conversation as resolved.
Outdated
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.