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
65 changes: 0 additions & 65 deletions BACKLOG.md

This file was deleted.

4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ Some WordPress host surfaces are **intentionally not targeted** by this adapter:
| `src/Exception/` | Adapter-specific exception hierarchy for hooks, settings rendering, database failures |
| `src/Filesystem/` | WpUploadsFilesystem (framework FilesystemInterface → uploads dir, via LocalFilesystem) |
| `src/Hook/` | HookRegistrar + `Contract/HookInterface` (requires an explicit, existing hook directory) |
| `src/Http/` | `Client/{HttpClient,HttpResponse}` (wp_remote_* with optional mTLS — see below), `Contract/RestControllerInterface`, `Controller/BaseController`, `Response/RestResponse`, `Routing/{Router,RouteRegistrar}`, `Inertia/{InertiaAdapter,PageContractNormalizer}`, `Middleware/AuthMiddleware` (JWT host auth), `Security/CsrfGuard` |
| `src/Http/` | `Client/{HttpClient,HttpResponse}` (wp_remote_* with optional mTLS — see below), `Contract/RestControllerInterface`, `Controller/BaseController`, `Response/RestResponse`, `Routing/{Router,RouteRegistrar}`, `Inertia/InertiaAdapter`, `Middleware/AuthMiddleware` (JWT host auth), `Security/CsrfGuard` |
| `src/Kernel/` | WpBootstrap (BootstrapInterface), WpComponentContext (HostComponentContextInterface), WpMaintenanceGate, PluginLifecycle, Loader/WpHookfileLoader |
| `src/Logging/` | ErrorLogLogger (PSR-3 → error_log) |
| `src/Logging/` | PhpErrorLogLogger (PSR-3 → error_log) |
| `src/Mail/` | WpMailer (framework MailerInterface → wp_mail), EmailSender, EmailTemplate |
| `src/Persistence/` | QueryBuilder (WP_Query/wp_posts) |
| `src/Privacy/` | PrivacyRegistrar + `Contract/PersonalDataProviderInterface` (WordPress personal-data export/erasure glue) |
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"php": "^8.2",
"ext-json": "*",
"firebase/php-jwt": "^7.0",
"middag-io/framework": "^v1.2.1",
"middag-io/framework": "^1.6",
"psr/container": "^2.0",
"psr/log": "^3.0",
"symfony/dependency-injection": "^7.0"
Expand Down
14 changes: 7 additions & 7 deletions src/Database/WpdbConnectionAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ public function supports(Capability $feature): bool
return match ($feature) {
// $wpdb has START TRANSACTION / COMMIT / ROLLBACK; only meaningful on
// InnoDB. We report true and leave engine choice to the schema layer.
Capability::TRANSACTIONS => true,
Capability::Transactions => true,
// No native unbuffered cursor; fetchAll buffers the whole result set.
Capability::STREAMING => false,
Capability::Streaming => false,
// MySQL 5.7+/8.0 supports JSON predicates; modern WP baselines do.
Capability::JSON_WHERE => true,
Capability::JsonWhere => true,
// MySQL has no RETURNING.
Capability::RETURNING => false,
Capability::Returning => false,
// INSERT ... ON DUPLICATE KEY UPDATE.
Capability::UPSERT => true,
Capability::Upsert => true,
// WordPress owns its own schema lifecycle via dbDelta(); no diffing.
Capability::SCHEMA_DIFF => false,
Capability::SchemaDiff => false,
// InnoDB supports SELECT ... FOR UPDATE / FOR SHARE.
Capability::ROW_LOCK => true,
Capability::RowLock => true,
};
}

Expand Down
9 changes: 4 additions & 5 deletions src/Http/Inertia/InertiaAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,10 @@ private static function resolveProps(array $props): array
$resolved[$key] = $value instanceof Closure ? $value() : $value;
}

// Auto-normalize PageContract to @middag-io/react v0.15+ schema
if (isset($resolved['contract']) && is_array($resolved['contract'])) {
$resolved['contract'] = PageContractNormalizer::normalize($resolved['contract']);
}

// Props (including any `contract`) pass through verbatim. The adapter
// accepts ONLY the canonical @middag-io/react PageContract and performs
// no schema migration: a legacy contract is forwarded unchanged so the
// frontend rejects it, rather than being silently rewritten here.
return $resolved;
}

Expand Down
173 changes: 0 additions & 173 deletions src/Http/Inertia/PageContractNormalizer.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,24 @@
use Stringable;

/**
* PSR-3 logger that writes to the PHP error log — the lowest common
* denominator available on every WordPress host (surfaces in `debug.log` when
* `WP_DEBUG_LOG` is on). Bind it to {@see LogSupport}
* Zero-dependency PSR-3 fallback that writes to the PHP error log — the
* lowest common denominator available on every WordPress host (surfaces in
* `debug.log` when `WP_DEBUG_LOG` is on). Bind it to {@see LogSupport}
* or the container when no richer logger (Monolog, WC_Logger) is wired.
*
* This is NOT the canonical logging path. The canonical, WooCommerce-like
* channel path is the framework `LoggerFactory::forChannel(module, channel)`
* (Monolog + rotating file handler), primed once at boot via
* {@see LogSupport::primeFromContainer()}. Host adapters extend that same
* base by choosing their `(module, channel)` destinations; this class only
* covers hosts where no factory is wired.
*
* Context values are interpolated into `{placeholders}` per PSR-3; leftover
* context is appended as JSON so no data is silently dropped.
*
* @api
*/
final class ErrorLogLogger extends AbstractLogger
final class PhpErrorLogLogger extends AbstractLogger
{
public function __construct(
private readonly string $channel = 'middag',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
* @license Apache-2.0
*/

namespace Middag\WordPress\Settings;
namespace Middag\WordPress\Settings\Enum;

use Middag\WordPress\Settings\Field;
use Middag\WordPress\Support\SanitizeSupport;

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Settings/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

namespace Middag\WordPress\Settings;

use Middag\WordPress\Settings\Enum\FieldType;

/**
* Declarative description of one admin settings field: the persisted option
* name, the control to render and how to sanitize it on save.
Expand Down
1 change: 1 addition & 0 deletions src/Settings/FieldRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Middag\WordPress\Settings;

use Middag\WordPress\Exception\SettingsRenderException;
use Middag\WordPress\Settings\Enum\FieldType;
use Middag\WordPress\Support\EscapeSupport;
use Middag\WordPress\Support\OptionSupport;

Expand Down
8 changes: 8 additions & 0 deletions src/Support/LogSupport.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Middag\WordPress\Support;

use Middag\Framework\Logging\LoggerFactory;
use Middag\WordPress\Logging\PhpErrorLogLogger;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Stringable;
Expand Down Expand Up @@ -70,6 +71,13 @@ public static function getLogger(): ?LoggerInterface
* No-op when already primed or when the container exposes no LoggerFactory
* (the `error_log()` fallback then stays active). Returns whether a logger is
* wired afterwards.
*
* This is the canonical, WooCommerce-like channel path: the `(module,
* channel)` tuple selects the on-disk destination of the framework's
* rotating file handler, and consumers/adapters pick their own tuple over
* the same base (a zero-dep `error_log` fallback such as
* {@see PhpErrorLogLogger} exists only for hosts
* where no factory is wired).
*/
public static function primeFromContainer(ContainerInterface $container, string $module = 'wordpress', string $channel = 'adapter'): bool
{
Expand Down
Loading
Loading