Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,39 @@ Constants::EVENT_COUPON_REDEEMED // 'coupon.redeemed'

## WordPress Hooks

The plugin registers these WooCommerce and WordPress hooks:

| Hook | Handler | Purpose |
| --- | --- | --- |
| `woocommerce_after_single_product` | `hellotext_product_viewed` | Track `product.viewed` |
| `woocommerce_after_cart` | `hellotext_trigger_cart_updated` | Compare current and previous cart state |
| `woocommerce_add_to_cart` | `hellotext_trigger_cart_updated` | Compare current and previous cart state |
| `woocommerce_cart_item_removed` | `hellotext_trigger_cart_updated` | Compare current and previous cart state |
| `woocommerce_after_cart_item_quantity_update` | `hellotext_trigger_cart_updated` | Compare current and previous cart state |
| `woocommerce_applied_coupon` | `hellotext_coupon_redeemed` | Track valid `coupon.redeemed` events |
| `woocommerce_after_order_details` | `hellotext_order_placed` | Track `order.placed` and persist encrypted session metadata on the order |
| `woocommerce_order_status_changed` | `track_order_status` | Track `order.confirmed`, `order.cancelled`, and `order.delivered` |
| `woocommerce_order_refunded` | `hellotext_refund_created` | Track `refund.received` |
| `user_register` | `hellotext_user_registered` | Track customer registration/profile flow |
| `hellotext_woocommerce_cart_updated` | `hellotext_cart_updated` | Track `cart.added` and `cart.removed` |
| `update_option` | `custom_field_updated` | Recreate integration after Business ID changes |
| `admin_init` | `hellotext_settings_init` | Register plugin settings |
| `admin_head` / `wp_head` | `hellotext_script` | Inject frontend/admin scripts |

## WooCommerce Compatibility

Compatibility posture as of 2026-06-11. See [WooCommerce Compatibility and API Audit](docs/WOOCOMMERCE-AUDIT.md) for the full hook/API audit, HPOS assessment, compatibility matrix, and release recommendations.

| Area | Status | Notes |
| --- | --- | --- |
| WooCommerce order metadata | HPOS-safe code path | Uses `WC_Order` metadata CRUD for Hellotext session metadata. |
| Order status and refund events | HPOS-safe code path | Reads session metadata from the order object instead of `get_post_meta()`. |
| Product, cart, coupon events | Public hook/API usage | Uses WooCommerce hooks and objects, not order storage internals. |
| Automated tests | Mock-backed unit coverage | Event tests cover outbound payloads without real WordPress/WooCommerce. |
| Runtime verification | Required before declaration | Test with HPOS enabled and disabled in a real WooCommerce site before declaring formal compatibility in the plugin header/runtime. |

Do not add a formal HPOS compatibility declaration until the release candidate has passed runtime checks on WooCommerce with HPOS enabled and disabled.

### Actions

#### `hellotext_create_profile`
Expand Down
98 changes: 73 additions & 25 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,35 @@ The project uses [Pest](https://pestphp.com/) for testing.
./vendor/bin/paratest
```

The Composer aliases used by CI and maintainers are:

```bash
composer install
composer test
composer format:check
composer build
```

`composer build` installs production dependencies with `--no-dev --optimize-autoloader`. Do not use the build output for local development without reinstalling dev dependencies afterward.

### Verified Local Flow

Last verified: 2026-06-11

| Command | Result | Notes |
| --- | --- | --- |
| `composer install` | Passed | Requires PHP 8.2+ and Composer 2. The local system Composer emitted PHP deprecation notices under PHP 8.4; dependencies still installed correctly. |
| `composer test` | Passed | Pest suite runs against WordPress/WooCommerce mocks, not a real WordPress install. |
| `composer format:check` | Passed | PHP CS Fixer warned when run under PHP 8.4 because the Composer platform is PHP 8.2.12. CI runs the style check on PHP 8.2. |
| `composer build` | Passed | Runs `composer install --no-dev --optimize-autoloader` and removes dev tooling from `vendor/`. Run `composer install` again afterward before continuing local development. |

Setup assumptions:

- PHP 8.2 or newer is available locally.
- Composer can install from the checked-in `composer.lock`.
- Tests do not require a real WordPress, WooCommerce, database, or Hellotext API connection.
- Outbound HTTP in tests is mocked through WordPress HTTP function stubs.

### Writing Tests

#### Unit Tests
Expand Down Expand Up @@ -312,14 +341,22 @@ add_action('all', function($hook) {

### Pre-Release Checklist

- [ ] Run all tests: `./vendor/bin/pest`
- [ ] Check for PHP errors/warnings
- [ ] Test on fresh WordPress installation
- [ ] Test with WooCommerce latest version
- [ ] Verify settings page functionality
- [ ] Test event tracking in Hellotext dashboard
- [ ] Update documentation if API changed
- [ ] Update changelog.txt
- [ ] Confirm the version in `hellotext.php` matches the release tag.
- [ ] Update `changelog.txt` with user-facing changes, compatibility notes, and any known limitations.
- [ ] Review open dependency PRs and confirm there are no urgent security/runtime updates pending.
- [ ] Run `composer install` from a clean checkout.
- [ ] Run `composer test` and confirm all tests pass.
- [ ] Run `composer format:check` and confirm no style diff is reported.
- [ ] Run `composer build` and confirm production dependencies install with `--no-dev --optimize-autoloader`.
- [ ] Inspect the production `vendor/` tree enough to confirm dev-only packages such as Pest, Mockery, stubs, PHPUnit, and PHP CS Fixer are not included in the release build.
- [ ] Verify `.distignore` excludes development files from the release zip: `.github/`, `tests/`, `composer.json`, `composer.lock`, `DEVELOPMENT.md`, and `API.md`.
- [ ] Smoke test the plugin zip in a clean WordPress/WooCommerce site.
- [ ] Confirm settings save correctly: Business ID, access token, webchat ID, placement, and behavior.
- [ ] Confirm script/webchat injection renders on the storefront when configured.
- [ ] Smoke test tracking for product view, cart add/remove, coupon redemption, checkout/order placement, order status change, refund, user registration, plugin activation, and plugin deactivation.
- [ ] Smoke test order and refund flows with WooCommerce HPOS enabled and disabled.
- [ ] Record WooCommerce API/HPOS compatibility notes in the release description if anything changed.
- [ ] Run `composer install` again after build validation to restore dev dependencies before more local work.

### Creating a Release

Expand All @@ -329,31 +366,42 @@ git tag -a v1.3.0 -m "Release version 1.3.0"
git push origin v1.3.0
```

2. **Build release package:**
```bash
# Remove dev dependencies
composer install --no-dev

# Create zip
cd ..
zip -r hellotext-wordpress-1.3.0.zip hellotext-wordpress \
-x "hellotext-wordpress/.git/*" \
-x "hellotext-wordpress/tests/*" \
-x "hellotext-wordpress/node_modules/*"
```
2. **Let GitHub Actions build the release package:**
- Tags matching `v*` trigger `.github/workflows/release.yml`.
- The workflow installs PHP 8.2 dependencies with `composer install --no-dev --optimize-autoloader`.
- The workflow creates `release/hellotext-wordpress.zip` and uploads it to the GitHub release.

3. **Create GitHub release:**
- Go to Releases → Draft new release
- Select the tag
- Upload the zip file
- Add release notes from changelog
3. **Verify the generated release:**
- Download the release zip from GitHub.
- Confirm files excluded by `.distignore` are not included: `.github/`, `tests/`, `composer.json`, `composer.lock`, `DEVELOPMENT.md`, and `API.md`.
- Confirm runtime files are included: `hellotext.php`, `src/`, `vendor/`, `README.md`, and `changelog.txt` if present.
- Install the zip in a clean WordPress/WooCommerce site.
- Confirm the release asset installs and activates without PHP warnings in `debug.log`.

### Post-Release

1. Reinstall dev dependencies: `composer install`
2. Announce release to team
3. Monitor error logs for issues

### Dependency Update Triage

Use this checklist before merging dependency-only PRs:

- Confirm the diff is limited to dependency metadata or the expected workflow file.
- Confirm GitHub reports the PR as mergeable.
- Confirm required CI checks pass.
- Prefer merging patch/minor test stub updates independently from runtime code changes.
- For GitHub Action major updates, inspect the action release notes before merging.

Dependency PRs reviewed during this maintenance pass:

- Keep dependency-only lockfile refreshes separate from runtime compatibility changes.
- Prefer one broad lock refresh over multiple older overlapping Dependabot PRs when it carries newer compatible versions and CI passes.
- For GitHub Action major updates, inspect the action release notes and verify the generated zip on the next tagged release because release publishing only runs on tags.

See also [WooCommerce Compatibility and API Audit](docs/WOOCOMMERCE-AUDIT.md) for hook, HPOS, and release compatibility notes.

## Contributing

### Workflow
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,30 @@ For developers looking to integrate, extend, or contribute to this plugin:

- **[API Documentation](API.md)** - Complete API reference for classes, methods, and hooks
- **[Development Guide](DEVELOPMENT.md)** - Setup, testing, and contribution guidelines
### Requirements
- **[WooCommerce API Audit](docs/WOOCOMMERCE-AUDIT.md)** - Hook, HPOS, and compatibility audit notes

## Requirements

- PHP 8.2 or higher
- WordPress 5.0 or higher
- WooCommerce 5.0 or higher

## Compatibility Matrix

| Layer | Declared support | Tested in CI | Notes |
| --- | --- | --- | --- |
| PHP | 8.2+ | 8.2, 8.3, 8.4, 8.5 | Composer platform is pinned to PHP 8.2.12. |
| WordPress | 5.0+ | Unit tests only, no WordPress runtime | Tests use WordPress stubs/mocks; runtime smoke testing is required before release. |
| WooCommerce | 5.0+ | Unit tests only, no WooCommerce runtime | Tests use WooCommerce stubs/mocks; HPOS and block-theme behavior require manual smoke testing. |
| WooCommerce stubs | Not a runtime dependency | Locked through Composer dev dependencies | Used for development/test confidence only. |
| Release package | GitHub tag workflow | Tag workflow only runs on `v*` tags | Verify the generated zip contents before publishing. |

## Compatibility Notes

- Order session metadata uses WooCommerce order CRUD methods instead of direct post meta APIs.
- Before each release, test event tracking with WooCommerce HPOS enabled and disabled.
- Formal WooCommerce HPOS compatibility declaration is deferred until manual runtime smoke testing passes.

## Support

Need help?
Expand Down
86 changes: 86 additions & 0 deletions docs/WOOCOMMERCE-AUDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# WooCommerce Compatibility and API Audit

Last reviewed: 2026-06-11

This audit covers the WooCommerce and WordPress integration points used by the Hellotext WooCommerce plugin. It is intentionally maintenance-focused: it documents current hooks, validates order access against current WooCommerce HPOS guidance, and records practical release risks without changing Hellotext API contracts.

## References

- WooCommerce APIs overview: <https://developer.woocommerce.com/docs/apis/>
- WooCommerce block hooks reference: <https://developer.woocommerce.com/docs/block-development/reference/hooks/>
- WooCommerce HPOS extension recipe book: <https://developer.woocommerce.com/docs/features/high-performance-order-storage/recipe-book>
- WooCommerce Code Reference: <https://woocommerce.github.io/code-reference/>
- WordPress Plugin Handbook hooks and activation/deactivation APIs: <https://developer.wordpress.org/plugins/>

## Summary

The plugin uses current WooCommerce PHP hooks and CRUD object access for the customer activity it tracks. Order and refund handling are HPOS-safe in code after the order session metadata changes because order reads/writes use `wc_get_order()`, `$order->get_meta()`, `$order->update_meta_data()`, and `$order->save()` rather than direct post meta functions.

Do not declare HPOS compatibility yet. Add the declaration only after a manual runtime smoke test passes with WooCommerce HPOS enabled and disabled in a real WordPress/WooCommerce install.

## Hook and API Matrix

| Area | Hook/API | Handler | Current status | Notes |
| --- | --- | --- | --- | --- |
| Product views | `woocommerce_after_single_product` | `hellotext_product_viewed()` | Appropriate for classic product templates | This is a classic template hook. Confirm behavior with block themes before claiming full block-theme coverage. |
| Cart updates | `woocommerce_add_to_cart` | `hellotext_trigger_cart_updated()` | Appropriate | Mutation hook is still a valid WooCommerce cart hook. Tests cover event creation with mocks. |
| Cart removals | `woocommerce_cart_item_removed` | `hellotext_trigger_cart_updated()` | Appropriate | Tests cover `cart.removed` payloads. |
| Cart quantity changes | `woocommerce_after_cart_item_quantity_update` | `hellotext_trigger_cart_updated()` | Appropriate | Tests cover quantity increases and no-op unchanged carts. |
| Cart page diff check | `woocommerce_after_cart` | `hellotext_trigger_cart_updated()` | Works for classic cart template | This hook does not cover all Cart block render paths. Future block-specific coverage should be evaluated. |
| Coupon redemption | `woocommerce_applied_coupon` | `hellotext_coupon_redeemed()` | Appropriate | Handler validates the coupon before sending `coupon.redeemed`; tests cover valid and invalid coupons. |
| Order placement | `woocommerce_after_order_details` | `hellotext_order_placed()` | Works, but has duplicate-risk | This template hook can fire on thank-you/order details and My Account view-order screens. Evaluate `woocommerce_thankyou` for classic checkout and `woocommerce_store_api_checkout_order_processed` for Checkout block support. |
| Order status changes | `woocommerce_order_status_changed` | `track_order_status()` | Appropriate | Handler maps `processing`, `cancelled`, and `completed` to Hellotext events. Uses WooCommerce order object/meta access. |
| Refunds | `woocommerce_order_refunded` | `hellotext_refund_created()` | Appropriate | Handler loads orders/refunds with WooCommerce APIs and reads session meta with `$order->get_meta()`. |
| User registration | `user_register` | `hellotext_user_registered()` | Appropriate WordPress hook | Tests cover profile creation flow with mocked HTTP. |
| Profile creation | `hellotext_create_profile` | Closure in `CreateProfile.php` | Internal plugin hook | Used by event flows to associate logged-in users/sessions. |
| Plugin deactivation | `register_deactivation_hook()` and `hellotext_remove_integration` | `hellotext_deactivate()` and closure in `AppRemoved.php` | Appropriate WordPress APIs | Tests cover DELETE request shape for integration cleanup. |
| Plugin uninstall | `register_uninstall_hook()` | `uninstall()` | Appropriate WordPress API | Cleans Hellotext options and WooCommerce API keys. |
| Settings | WordPress Settings API | `src/Misc/Settings.php` | Appropriate | Stores Business ID, access token, and webchat options using WordPress options. |
| Webchat injection | WordPress script/footer hooks | `src/Misc/Scripts.php` | Appropriate WordPress APIs | Verify rendered script manually in a real WordPress page during release smoke testing. |
| WooCommerce API keys | Direct `$wpdb` against `{$prefix}woocommerce_api_keys` | `src/Events/AppInstalled.php`, `hellotext.php` uninstall | Acceptable exception | WooCommerce API keys are not order data and are not part of HPOS order storage. No WooCommerce CRUD replacement is required for this table access. |

## HPOS Assessment

WooCommerce HPOS changes where order data is stored. The HPOS recipe book recommends avoiding direct WordPress post/postmeta APIs for order data and using WooCommerce CRUD APIs instead.

The plugin's order-related runtime paths are compatible with that guidance:

- `src/Adapters/OrderAdapter.php` loads numeric orders with `wc_get_order()`.
- `src/Events/OrderPlaced.php` stores the Hellotext session with `$order->update_meta_data(Constants::META_SESSION, ...)` and `$order->save()`.
- `src/Events/OrderStatus.php` reads the stored session with `$order->get_meta(Constants::META_SESSION, true)`.
- `src/Events/RefundReceived.php` loads the order with `wc_get_order($order_id)` and reads session metadata with `$order->get_meta(Constants::META_SESSION, true)`.
- The plugin does not query `shop_order` posts or use direct post meta functions for order session metadata.

The test suite uses WordPress/WooCommerce mocks, so it validates code behavior and request shape but not a real HPOS datastore. Because of that, the formal declaration is deferred.

## Deferred HPOS Declaration

After a real WooCommerce smoke test passes with HPOS enabled and disabled, add this to the main plugin file:

```php
add_action('before_woocommerce_init', function () {
if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
}
});
```

Do not add this declaration until manual runtime testing confirms product view, cart, coupon, checkout, status transition, refund, settings, deactivation, and webchat behavior in a real store.

## Compatibility Matrix

| Layer | Declared | CI-tested | Stub-tested | Assumed or manual-only |
| --- | --- | --- | --- | --- |
| PHP | README requires PHP 8.2+; Composer platform is PHP 8.2.12 | GitHub Actions runs Pest on PHP 8.2, 8.3, 8.4, and 8.5; format check on PHP 8.2 in CI | Not applicable | Local contributor machines may run newer PHP; PHP CS Fixer warns when run outside project platform. |
| WordPress | README requires WordPress 5.0+ | No full WordPress runtime in CI | `php-stubs/wordpress-stubs` is locked to 6.9.x after dependency refresh | Runtime compatibility with each supported WordPress version is manual-only. |
| WooCommerce | README requires WooCommerce 5.0+ | No full WooCommerce runtime in CI | `php-stubs/woocommerce-stubs` is locked to 10.x after dependency refresh | HPOS, Cart/Checkout blocks, and block themes require manual smoke testing. |
| Hellotext API | Existing plugin endpoints and payload contracts | HTTP calls are intercepted in tests | Not applicable | Real API authentication and dashboard ingestion require staging/production smoke testing. |
| Release package | `.github/workflows/release.yml` builds tag-triggered zip | Release workflow runs only on `v*` tags | Not applicable | Zip contents and installability must be checked after each tagged release. |

## Recommendations

1. Keep the HPOS declaration deferred until manual smoke testing passes with HPOS on and off.
2. Evaluate replacing `woocommerce_after_order_details` with a checkout-completion hook such as `woocommerce_thankyou` for classic checkout, while separately evaluating Checkout block coverage through Store API hooks.
3. Document classic-template limitations for `woocommerce_after_single_product`, `woocommerce_after_cart`, and any block-theme gaps in release notes until runtime coverage is confirmed.
4. Consider migrating cart diff state from `$_SESSION` to WooCommerce session storage (`WC()->session`) in a future compatibility-focused PR.
5. Continue using WooCommerce CRUD methods for all future order/refund metadata reads and writes.