Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
# Dependencies
/vendor
.env
.env.integration
.env.testing

# Build / Cache
/build
Expand All @@ -16,6 +18,7 @@
.pint.cache
*.log
coverage/
coverage.xml

# Artifacts
.gemini/
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ This repository is a PHP 8.5 package named `jooservices/wordpress-sdk`.
- Use typed query DTOs for common list/read filters where practical.
- Raw array escape hatches are allowed only as intentional, documented compatibility surfaces.
- Avoid hidden domain strings when enums or constants are clearer.
- Do not add story/product-review/article content template features to SDK core; those belong in `jooservices/wordpress-content-templates`.

## Delivery checklist

Expand All @@ -56,3 +57,11 @@ Before reporting completion:
2. Update README and docs for any public API change.
3. Run the relevant validation commands.
4. Report any GitHub-side or branch-flow actions that could not be verified or applied from the environment.

## Integration testing standard

- Do not run SDK integration tests against live WordPress sites.
- Use only disposable local WordPress test sites. Do not add Docker/WP Composer aliases unless the complete local-only runner, setup scripts, fixtures, and safety guards are committed in the same change.
- Integration tests must require a local WordPress URL and disposable test credentials.
- The SDK public surface should be covered by unit tests, integration tests, or explicit reasoned entries in the coverage-map script.
- Integration skips must name the exact service method, route, WordPress version, and theme/plugin reason.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@ All notable changes to `jooservices/wordpress-sdk` are tracked here.

The format follows Keep a Changelog, and this project aims to follow semantic versioning once releases are tagged from `master`.

## [Unreleased]

## [1.2.0] - 2026-05-17

### Removed

- Removed non-native content template classes, data objects, examples, and template-specific tests from SDK core.
- Removed `PostsService::createFromTemplate()` because content templates are not native WordPress REST API SDK features.

### Changed

- Kept `PostBuilder` and `ContentBuilder` as generic SDK-safe helpers for post payloads and Gutenberg-compatible block markup.
- Updated docs and testing guidance to point story, product-review, article, and custom content-template users to `jooservices/wordpress-content-templates`.

### Migration

- Install `jooservices/wordpress-content-templates` for extracted content templates:

```bash
composer require jooservices/wordpress-content-templates
```

- Generate a payload with the template package and publish it with the SDK:

```php
$post = $wordpress->posts()->create($template->toPostData());
```

## [1.1.0] - 2026-05-16

### Added
Expand All @@ -18,10 +46,13 @@ The format follows Keep a Changelog, and this project aims to follow semantic ve

- Updated README and documentation to reflect current endpoint coverage, security guidance, and deferred WordPress REST API groups.
- Changed `composer test` and `composer test:coverage` to run the unit suite; live WordPress integration checks remain available through `composer test:integration` and `composer test:all`.
- Tightened `PostsService::createFromTemplate()` to the documented `PostTemplate` contract and aligned example documentation with the PHP 8.5 package baseline.
- Clarified in the README and user guide that builders and template utilities are optional SDK helper extras layered on top of the REST API surface.

### Fixed

- Fixed `ContainerFactory` to build the SDK HTTP client through `ClientFactory` so resolving `WordPressService` from the container satisfies its typed constructor.
- Renamed the phase-based endpoint path unit test helpers to purpose-based names required by the repository standards.

### Tests

Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ foreach ($posts as $post) {

| Endpoint | Service | Status |
| --- | --- | --- |
| Posts | `posts()` | CRUD + template helpers |
| Posts | `posts()` | CRUD |
| Pages | `pages()` | CRUD |
| Media | `media()` | list/get/upload/delete |
| Users | `users()` | CRUD + `me()` |
Expand All @@ -67,6 +67,17 @@ foreach ($posts as $post) {
| Widgets / sidebars | `widgets()`, `widgetTypes()`, `sidebars()` | raw widget operations |
| Site Health | `siteHealth()` | raw diagnostic test reads |

## SDK helper extras

The SDK also ships with optional developer-experience helpers under `JOOservices\WordPress\Sdk\Support`.

- `PostBuilder` helps assemble post payloads fluently before calling `posts()->create()` or `update()`.
- `ContentBuilder` helps generate Gutenberg-compatible block markup in PHP.

These helpers are not native WordPress REST API resources. They remain in the SDK because they are generic payload and Gutenberg markup helpers for normal WordPress post operations.

Content templates for stories, product reviews, articles, and template registries now live in `jooservices/wordpress-content-templates`. That package depends on this SDK and generates SDK-compatible post/page payloads; this SDK does not depend on it.

## DTO-first querying

The SDK accepts either raw query arrays or typed query DTOs for list and read operations.
Expand Down Expand Up @@ -148,6 +159,7 @@ $health = $wordpress->siteHealth()->backgroundUpdates();
```

Most of these endpoints require authenticated users with admin/editor capabilities.
Block renderer requests are sent with WordPress editor context because the REST renderer endpoint validates dynamic blocks against editor-only route context.

## Error handling

Expand Down Expand Up @@ -184,11 +196,17 @@ composer lint:all
composer test
composer test:integration
composer test:coverage
composer test:coverage:gate
composer test:coverage-map
composer quality
composer check
composer ci
```

Run `composer test:integration` only against a disposable local WordPress test site created for SDK testing. The stale Docker/WP Composer aliases from pre-release documentation are not shipped in 1.2.0 because their runner files are not present in this repository.

`composer test:coverage` now includes a Clover XML audit gate. Aggregate statement coverage must stay at or above 90%, and no coverable production file, class, or method in `src/` may remain at 0% coverage unless it has a documented exclusion reason in `tools/test-coverage-gate.php`.

## Security

Use WordPress application passwords through environment variables. Do not commit live credentials, and do not log authorization headers or raw secrets. See [SECURITY.md](./SECURITY.md).
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@
"test:all": "phpunit",
"test:unit": "phpunit --testsuite=Unit",
"test:integration": "phpunit --testsuite=Integration",
"test:coverage": "phpunit --testsuite=Unit --coverage-html=coverage --coverage-clover=coverage.xml",
"test:integration:extended": "phpunit --testsuite=ExtendedIntegration",
"test:coverage": [
"phpunit --testsuite=Unit --coverage-html=coverage --coverage-clover=coverage.xml",
"@test:coverage:gate"
],
"test:coverage:gate": "php tools/test-coverage-gate.php",
"test:coverage-map": "php tools/test-coverage-map.php",
"security": "composer audit",
"quality": [
"@lint",
Expand Down
13 changes: 13 additions & 0 deletions docs/02-user-guide/01-services-and-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ Use the facade to access typed services:
- `postTypes()`
- `statuses()`

## Helper extras

The `Support/` namespace contains optional SDK helper extras rather than native WordPress REST endpoints.

Examples:

- `PostBuilder` for fluent post payload construction
- `ContentBuilder` for Gutenberg block content generation

Story, product-review, article, and custom content templates are provided by `jooservices/wordpress-content-templates`, which depends on this SDK and passes generated payloads to `posts()->create()`.

These helpers are documented as SDK convenience layers on top of the normal REST services.

## Query DTOs

Core read and list endpoints accept either raw arrays or typed query DTOs.
Expand Down
2 changes: 2 additions & 0 deletions docs/02-user-guide/admin-editor-endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ $rendered = $wp->blockRenderer()->render('core/latest-posts', ['postsToShow' =>
$directory = $wp->blockDirectory()->search(['term' => 'gallery']);
```

Block renderer requests use WordPress editor context because dynamic server-rendered blocks validate against editor-only route context.

## Menus and navigation

```php
Expand Down
4 changes: 3 additions & 1 deletion docs/02-user-guide/posts.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Posts

`posts()` supports list, get, create, update, delete, template helpers, and post auto-pagination helpers.
`posts()` supports list, get, create, update, delete, and post auto-pagination helpers.

```php
$posts = $wp->posts()->list(['per_page' => 10, 'status' => 'publish']);
Expand All @@ -9,3 +9,5 @@ $created = $wp->posts()->create(['title' => 'Draft', 'status' => 'draft']);
```

Use `cursor()` or `each()` for large sites. Use `all()` only when loading all matching posts into memory is acceptable.

Content template helpers are not part of SDK core. Use `jooservices/wordpress-content-templates` when you want story, product review, article, or custom content templates that generate payloads for `posts()->create()`.
4 changes: 4 additions & 0 deletions docs/03-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ This section collects complete workflows built from the public SDK services.
- [Media Upload Workflow](./media-upload-workflow.md)
- [Headless Export Workflow](./headless-export-workflow.md)
- [Custom Post Type Workflow](./custom-post-type-workflow.md)

Repository PHP examples:

- Content template examples live in `jooservices/wordpress-content-templates`.
2 changes: 2 additions & 0 deletions docs/04-development/02-ci-cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ The workflow uses Composer scripts instead of duplicating raw tool invocations:
- `composer test:coverage`
- `composer security`

`composer test:coverage` is the coverage gate entrypoint. It must keep aggregate statement coverage at or above 90% and reject any coverable production file, class, or method in `src/` that still has 0% coverage in the Clover XML report.

Branch workflow follows the JOOservices `develop` and `master` model. Any missing branch-protection or remote branch setup must be verified directly in GitHub.
1 change: 1 addition & 0 deletions docs/04-development/03-ai-guidance.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Key rules:
- keep test filenames matched to test class names
- name tests and shared helpers for source class, domain, or precise behavior, not phases or buckets such as `P1`, `P2`, `Phase1`, `Phase2`, `Sprint`, `Milestone`, `Temporary`, `Temp`, `Misc`, `Bucket`, `NewEndpoints`, `OldEndpoints`, `Legacy`, or `WIP`
- validate before reporting completion
- aggregate 90% coverage is not enough; run `composer test:coverage` so the Clover XML gate can reject any coverable `src/` file, class, or method that is still at 0% coverage
6 changes: 6 additions & 0 deletions docs/04-development/ai-contributor-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ Test filenames must match their test class names, and test classes should descri
Do not use phase, planning, temporary, or vague bucket names in code, tests, helpers, docs, or examples: `P1`, `P2`, `Phase1`, `Phase2`, `Sprint`, `Milestone`, `Temporary`, `Temp`, `Misc`, `Bucket`, `NewEndpoints`, `OldEndpoints`, `Legacy`, or `WIP`. Shared test helpers should use purpose-based names such as `RecordsServiceRequests` or `NullHttpClient`.

If requirements are unclear, conflicting, missing, or cannot be verified from repository truth, stop and ask.

Integration tests must never target a live WordPress site. Use only disposable local WordPress test sites, and do not restore Docker/WP Composer aliases without committing the complete local-only runner, setup scripts, fixtures, and safety guards in the same change. Public SDK classes and concrete service methods should be mapped by unit tests, integration tests, or an explicit reason in `tools/test-coverage-map.php`.

Aggregate coverage alone is insufficient. Contributors must run `composer test:coverage`, which now audits `coverage.xml` and fails when overall statement coverage drops below 90% or any coverable production file, class, or method in `src/` is still at 0% coverage. Exclusions in `tools/test-coverage-gate.php` need a concrete reason.

Integration skips must be precise and documented: name the service method, exact missing route, WordPress version, and active theme or plugin requirement. Do not use vague skip reasons.
60 changes: 59 additions & 1 deletion docs/04-development/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,64 @@ composer test:unit
composer test:integration
composer test:all
composer test:coverage
composer test:coverage:gate
composer test:coverage-map
```

`composer test` and `composer test:coverage` run the unit suite so normal validation does not depend on a live WordPress server. Use `composer test:integration` or `composer test:all` when `WORDPRESS_URL`, `WORDPRESS_USER`, and `WORDPRESS_APP_PASSWORD` point at a reachable test site.
`composer test` and `composer test:coverage` run the unit suite so normal validation does not depend on WordPress. `composer test:integration` runs the integration suite and must only be used with a disposable local WordPress test site.

`composer test:coverage` now runs a Clover XML coverage gate after PHPUnit writes `coverage.xml`. Aggregate statement coverage must stay at or above 90%. The gate also fails when any coverable production file, class, or method under `src/` is left at 0% coverage. Do not rely on the aggregate percentage alone.

## Unit Tests

Unit tests cover DTO hydration and serialization, query DTO output, endpoint path builders, auth middleware, response decoding, exception redaction, pagination helpers, service request construction, and generic builder support. They must use fake clients or deterministic local values and must not make network calls.

## Integration Tests

Integration tests must run only against a disposable local WordPress environment created for SDK testing.

```bash
composer test:integration
```

The 1.2.0 release does not ship Docker/WP Composer aliases because the Docker runner files are not present in this repository. Do not add `composer test:wordpress`, `composer test:wordpress:extended`, or Docker aliases back without committing the complete local-only runner, setup scripts, fixtures, and safety guards in the same change.

Template-specific integration tests live in `jooservices/wordpress-content-templates`. SDK integration tests stay focused on native WordPress REST API endpoints, generic post payload creation, media uploads, and Gutenberg content builder behavior.

The local test site uses disposable credentials only. Do not commit real WordPress credentials.

## Safety Guard

Do not run SDK integration tests against production, staging, or personal WordPress sites. Until a complete Docker/WP runner is restored, contributors should treat the integration suite as manually provisioned and keep normal release validation on unit tests, coverage, coverage-map, static analysis, and security audit.

## Coverage Map

`composer test:coverage-map` reflects over `src/**/*.php` and verifies that production classes are mapped to unit coverage and concrete services are mapped to integration coverage. Pure interfaces are excluded. Abstract helpers, traits, and grouped tests require an explicit reason in `tools/test-coverage-map.php`.

## Coverage Gate

`composer test:coverage:gate` reads PHPUnit's Clover XML output from `coverage.xml`. It is deterministic and CI-safe because it does not parse HTML. The gate fails when any of these conditions are true:

- overall statement coverage is below 90%
- a coverable production file in `src/` has 0 covered statements
- a coverable production class in `src/` has 0 covered statements or 0 covered methods
- a coverable production method in `src/` has 0 execution count

If a production file, class, or method is truly non-coverable by project convention, add a documented exclusion reason in `tools/test-coverage-gate.php`. Do not exclude code only because it is inconvenient to test. Run the coverage gate before calling coverage work complete.

## Skip and Version-Gate Policy

Integration tests must check `/wp-json` route availability before skipping feature-dependent endpoints. Skip messages must include the service method, exact route, WordPress version, and active theme. Prefer Docker setup fixes over skips.

Acceptable reasons include:

- route missing in the tested WordPress version
- feature requires a block theme
- feature requires an optional plugin
- WordPress did not generate a revision for the test resource

## Troubleshooting

- Missing WordPress environment values: set `WORDPRESS_URL`, `WORDPRESS_USER`, and `WORDPRESS_APP_PASSWORD` for a disposable local test site only.
- WordPress server is unreachable: start the local test site and verify `/wp-json/` is reachable.
- Integration failures after resource creation: clean up the disposable local test site before rerunning.
3 changes: 1 addition & 2 deletions docs/guides/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ The following table outlines the current capabilities of the SDK services.
The SDK includes powerful tools for generating content:

- **ContentBuilder**: Fluent API for creating Gutenberg-compatible block content programmatically.
- **Templates**: Type-safe Post Templates (Stories, Product Reviews) for standardized content creation.

- **Content templates**: Available in `jooservices/wordpress-content-templates`, outside SDK core.
Loading