fix: keep usage logger alive when chart settings meta is not an array - #1360
fix: keep usage logger alive when chart settings meta is not an array#1360lucadobrescu wants to merge 2 commits into
Conversation
A published chart whose visualizer-settings meta resolves to a string crashed Visualizer_Module_Setup::getUsage() with a PHP 8 TypeError at the unchecked array_key_exists() call, aborting the whole Themeisle SDK usage collection request. Guard the settings read, harden the sibling pro-permissions meta read the same way, and drop the dangling visualizer_logger_data registration in Visualizer_Module_Admin, which points to a method that class never had and fatals the same filter once the first crash is fixed. Fixes #1359 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Hardens usage telemetry against malformed chart metadata so collection continues for healthy charts.
Changes:
- Guards settings and permissions metadata before access.
- Removes an invalid Admin logger callback.
- Adds PHPUnit and E2E regression coverage.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
classes/Visualizer/Module/Setup.php |
Adds metadata type guards. |
classes/Visualizer/Module/Admin.php |
Removes invalid logger registration. |
tests/test-usage-logger.php |
Adds unit regression tests. |
tests/e2e/specs/usage-logger.spec.js |
Adds end-to-end logger coverage. |
tests/e2e/config/mu-plugins/plant-chart-settings.php |
Exposes a protected E2E logger endpoint. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ( Visualizer_Module::is_pro() ) { | ||
| $permissions = get_post_meta( $chart_id, Visualizer_Pro::CF_PERMISSIONS, true ); | ||
| if ( empty( $permissions ) ) { | ||
| if ( ! is_array( $permissions ) || empty( $permissions['permissions'] ) ) { |
There was a problem hiding this comment.
Confirmed and fixed in a4de841 — the scenario reproduces exactly as described (TypeError at the count() call). Guarded the per-key value with is_array() and added a regression test that forces the pro branch via the visualizer_is_pro filter with a stubbed Visualizer_Pro class.
| /** | ||
| * WordPress dependencies | ||
| */ | ||
| const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); | ||
|
|
||
| /** | ||
| * Regression tests for https://github.com/Codeinwp/visualizer/issues/1359 | ||
| * | ||
| * A published chart whose `visualizer-settings` meta is a string (instead of | ||
| * the sanitized settings array) crashed `Visualizer_Module_Setup::getUsage()` | ||
| * with a PHP 8 TypeError, aborting the whole SDK usage collection request. | ||
| * The logger must tolerate such charts and still report the others. | ||
| */ | ||
| test.describe( 'Usage logger', () => { | ||
| let corruptedId; | ||
| let manualId; | ||
|
|
||
| test.beforeAll( async ( { requestUtils } ) => { |
There was a problem hiding this comment.
Fixed in a4de841 — the spec now calls deleteAllCharts() in beforeAll like the other chart-counting specs.
Copilot review follow-ups: a string where an array-valued permission is expected (e.g. permissions.edit-specific) still crashed the usage logger via count() on PHP 8 — guard it and cover the pro branch through the visualizer_is_pro filter with a stubbed Visualizer_Pro. Also clear leftover charts before the e2e usage assertions, matching the other chart-counting specs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| if ( Visualizer_Module::is_pro() ) { | ||
| $permissions = get_post_meta( $chart_id, Visualizer_Pro::CF_PERMISSIONS, true ); | ||
| if ( empty( $permissions ) ) { | ||
| if ( ! is_array( $permissions ) || empty( $permissions['permissions'] ) ) { |
Scheduled usage telemetry died with
TypeError: array_key_exists(): Argument #2 ($array) must be of type array, string givenwhenever a site had one published chart whosevisualizer-settingspost meta is a string instead of the sanitized settings array — one bad chart record aborted the whole SDK usage collection request (three production sites hit this on PHP 8.2/8.3). The logger now tolerates malformed chart meta and still reports every healthy chart.What changed
Visualizer_Module_Setup::getUsage()— themanual_configcounter reads the settings meta through anis_array()guard. Before → a string (or a chart with no settings meta at all, whereget_post_meta()returns'') threw an uncaught TypeError on PHP 8; after → the chart is skipped for that statistic and collection completes.Visualizer_Module_Setup::getUsage()(pro path) — thepermissionsmeta read had the same shape ($permissions['permissions']on an unvalidated meta value), so it gets the sameis_array()guard.Visualizer_Module_Admin— removed itsvisualizer_logger_dataregistration: it points to agetLoggerDatamethod that class does not have, so once the first crash is fixed the filter fatals again with "class Visualizer_Module_Admin does not have a method getLoggerData". The working callback inVisualizer_Module_Setupis unchanged.Note
How the affected sites acquired string-valued settings meta is unknown (the issue's telemetry couldn't tell). The fix deliberately hardens the reader instead of chasing the writer: the logger must never let one bad record kill the whole collection request.
Usage collection flow
flowchart LR A[SDK cron:<br/>visualizer_logger_data] --> B[Setup::getUsage<br/>loops published charts] B --> C{Changed:<br/>settings meta<br/>is an array?}:::changed C -- Yes --> D[Count manual_config] C -- No --> E[Skip statistic,<br/>keep looping] D --> F[Usage payload returned] E --> F A -.-> G[New: dangling Admin<br/>callback removed]:::added classDef added fill:#1a7f37,color:#fff,stroke:#116329,stroke-width:3px classDef changed fill:#9a6700,color:#fff,stroke:#5c3d00,stroke-width:3px,stroke-dasharray:6 3QA
Create any chart (WP Admin → Visualizer → Add New Chart, complete the wizard) and corrupt its settings meta with WP-CLI, replacing
<chart_id>with the chart's post ID:Trigger the logger on PHP 8.2+:
Expect: a usage array is printed (
types,sources,manual_config, …) with no TypeError. On 4.0.7 the same command dies with thearray_key_exists()TypeError from the crash report.Fixes #1359