You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You can also use `agent-browser` CLI if available with WP Docker environments for a more interactive testing experience, with credentials:
42
+
43
+
```
44
+
Username: admin
45
+
Password: password
46
+
```
47
+
41
48
## Code Quality
42
49
43
50
-**PHP standard**: Themeisle ruleset (WordPress-based) via `phpcs.xml`. Text domain: `woocommerce-product-addon`.
44
-
-**PHPStan**: Level 6 with a large baseline file (`phpstan-baseline.neon`). Scans `inc/`, `classes/`, `backend/`, `templates/`, and the main plugin file.
45
-
-**Min PHP**: 7.2 (composer platform config). CI runs PHPStan on PHP 7.4.
51
+
-**PHPStan**: Level 8 with a large baseline file (`phpstan-baseline.neon`). Scans `inc/`, `classes/`, `backend/`, `templates/`, and the main plugin file.
52
+
-**Min PHP**: 7.4
46
53
47
54
## Architecture
48
55
56
+
You can read more about it on `./ARCHITECTURE.md`, but here’s a high-level overview of the main components and their relationships.
57
+
49
58
### Entry Point & Bootstrap
50
59
51
60
`woocommerce-product-addon.php` — defines constants, loads Composer autoload, manually `require_once`s all class/include files (no PSR-4 autoloading for plugin code), then hooks `PPOM()` on `woocommerce_init`.
@@ -116,14 +125,49 @@ Declares WooCommerce Custom Order Tables compatibility via `FeaturesUtil::declar
116
125
117
126
## WooCommerce Security + Workflow
118
127
119
-
- Treat all input as untrusted (POST/AJAX/cart session/order meta).
120
-
- For state-changing actions, require both capability checks and nonce verification.
121
-
- Never trust frontend option pricing; recompute server-side in cart/checkout.
122
-
- Validate product/variation context with Woo objects before processing.
123
-
- Sanitize on input (type-aware) and escape on output (context-aware).
124
-
- Use `$wpdb->prepare()` (plus `$wpdb->esc_like()` for LIKE queries); never concatenate user input.
125
-
- For uploads, enforce extension/mime/size rules and block executable files.
126
-
- Prefer WooCommerce CRUD/order APIs (HPOS-safe) over direct post/meta SQL.
127
-
- Keep pricing hooks idempotent, especially in `woocommerce_before_calculate_totals`.
128
+
### Trust Boundaries
129
+
130
+
- Treat product page fields, AJAX/REST payloads, cart item data, restored sessions, order item meta, and admin imports/settings as untrusted input.
131
+
- Never trust browser-sent prices, fee amounts, labels, field IDs, variation IDs, conditional flags, upload metadata, or Pro gating flags. Recompute from saved PPOM/WooCommerce configuration on the server.
132
+
- Validate submitted field names/options against the field schema attached to the current product/meta group before storing or pricing anything.
133
+
- Resolve product and variation IDs to real WooCommerce objects and confirm the variation belongs to the parent product before processing.
134
+
135
+
### Authorization + Request Integrity
136
+
137
+
- For every state-changing admin, AJAX, or REST action, require both a capability check and nonce verification. For REST routes, always implement a strict `permission_callback`.
138
+
- Never use `is_admin()` as an authorization check.
139
+
- Scope privileged actions to the narrowest capability that fits the action: field-group CRUD, settings changes, file deletion, import/export, license actions, and diagnostic tools should not share a blanket permission model.
140
+
141
+
### Data Handling Rules
142
+
143
+
- Sanitize on input with type-appropriate functions, validate against business rules, and escape on output with the correct context-aware `esc_*()` function.
144
+
- Use `$wpdb->prepare()` for every query containing dynamic input, and pair `LIKE` clauses with `$wpdb->esc_like()`. Never concatenate request data into SQL.
145
+
- Prefer WooCommerce CRUD APIs and order/item meta APIs over direct post/meta SQL so behavior stays HPOS-safe.
146
+
- Do not persist raw `$_POST` or `$_REQUEST` payloads into cart item data, session data, or order meta. Store only the normalized values the plugin actually needs.
147
+
- Do not expose addon values, upload URLs, or order item metadata in logs, notices, REST responses, emails, or templates unless the current user/context is explicitly allowed to see them.
148
+
149
+
### Pricing + Cart Integrity
150
+
151
+
- Keep all pricing logic server-authoritative and idempotent. Hooks like `woocommerce_before_calculate_totals` may run multiple times per request.
152
+
- Recalculate addon totals from canonical field definitions during validation, cart restore, and checkout instead of trusting values carried forward from the browser or session.
153
+
- Guard against double-charging when cart items are restored from session, when quantities change, or when multiple pricing hooks run in sequence.
154
+
- When pricing depends on product type, variation, quantity, tax mode, currency, or coupon state, use current WooCommerce objects/state at calculation time instead of stale cart snapshots.
155
+
156
+
### Upload Safety
157
+
158
+
- Enforce an allowlist for extensions, MIME types, and size limits; reject executable/scriptable files, double extensions, and unexpected archive types.
159
+
- Generate filenames and paths server-side, keep uploads inside the dedicated PPOM upload directory, and never trust client-provided path, MIME, or filename values.
160
+
- Re-check authorization and attachment ownership before serving, deleting, or attaching uploaded files to cart/order data.
0 commit comments