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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- fix(ui): add keyboard-resizable drawers with Escape handling and focus restoration.
- fix: harden packaging, privacy, lifecycle, snapshot recovery, dump and toolbar security, and accelerate value hydration.
- refactor: simplify strict value hydration, collector cleanup reporting, sensitive-key lookup, and toolbar message validation without changing public contracts.
- test: enforce complete PHP line, method, and mutation coverage with exact HTML rendering assertions.
5 changes: 4 additions & 1 deletion src/Capture/CapturePolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ public function isSensitiveKey(string $key): bool
*/
public function redact(#[SensitiveParameter] array $value): array
{
return SensitiveDataRedactor::redact($value, $this->sensitiveKeys);
return SensitiveDataRedactor::redact(
$value,
$this->sensitiveKeys,
);
}

/**
Expand Down
40 changes: 5 additions & 35 deletions src/Collector/CollectorCoordinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ public function __construct(iterable $collectors)
/**
* Captures every collector into one versioned request snapshot.
*
* Usage example:
*
* ```php
* $snapshot = $coordinator->capture($summary);
* ```
*
* @param RequestSummary $summary Captured request metadata.
*
* @return DebugSnapshot Captured request envelope.
Expand All @@ -78,18 +72,16 @@ public function capture(RequestSummary $summary): DebugSnapshot
}
}

return new DebugSnapshot($summary, $panels, $failures);
return new DebugSnapshot(
$summary,
$panels,
$failures,
);
}

/**
* Returns the collector registered under the given stable ID.
*
* Usage example:
*
* ```php
* $collector = $coordinator->collector('app.orders');
* ```
*
* @param string $id Collector ID.
*
* @return CollectorInterface|null Registered collector, or `null` when the ID is unknown.
Expand All @@ -102,12 +94,6 @@ public function collector(string $id): CollectorInterface|null
/**
* Returns whether a collector is registered under the given stable ID.
*
* Usage example:
*
* ```php
* $registered = $coordinator->hasCollector('app.orders');
* ```
*
* @param string $id Collector ID.
*
* @return bool Whether the collector is registered.
Expand Down Expand Up @@ -157,20 +143,10 @@ public function run(callable $operation, callable|null $cleanupFailureHandler =
/**
* Stops every collector once and propagates the first shutdown error after cleanup completes.
*
* Usage example:
*
* ```php
* $coordinator->shutdown();
* ```
*
* @throws Throwable When a collector cannot shut down.
*/
public function shutdown(): void
{
if (!$this->started && $this->startedCollectors === []) {
return;
}

$this->started = false;

$failure = null;
Expand All @@ -193,12 +169,6 @@ public function shutdown(): void
/**
* Starts every registered collector once and rolls back affected collectors when startup fails.
*
* Usage example:
*
* ```php
* $coordinator->startup();
* ```
*
* @throws Throwable When a collector cannot start.
*/
public function startup(): void
Expand Down
24 changes: 0 additions & 24 deletions src/Collector/CollectorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,48 +14,24 @@ interface CollectorInterface
/**
* Captures the current request data as a typed snapshot.
*
* Usage example:
*
* ```php
* $snapshot = $collector->capture();
* ```
*
* @return PanelSnapshot|null Captured payload or `null` when the collector has no data.
*/
public function capture(): PanelSnapshot|null;

/**
* Returns the stable ID used as the persisted panel key.
*
* Usage example:
*
* ```php
* $id = $collector->id();
* ```
*
* @return string Stable collector ID.
*/
public function id(): string;

/**
* Stops collection and clears request-scoped state idempotently.
*
* Usage example:
*
* ```php
* $collector->shutdown();
* ```
*/
public function shutdown(): void;

/**
* Starts collection for the current request.
*
* Usage example:
*
* ```php
* $collector->startup();
* ```
*/
public function startup(): void;
}
4 changes: 1 addition & 3 deletions src/Data/FilterEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function addCondition(string $attribute, mixed $rawValue, bool $partial =
return;
}

if (preg_match('/^\s*([<>])\s*(-?(?:\d+(?:\.\d+)?|\.\d+))\s*$/D', $value, $matches) === 1) {
if (preg_match('/^\s*([<>])\s*(-?(?:\d+(?:\.\d+)?|\.\d+))\s*$/', $value, $matches) === 1) {
$this->conditions[] = [
'attribute' => $attribute,
'operator' => $matches[1],
Expand Down Expand Up @@ -126,8 +126,6 @@ private function matches(array|object $row): bool
return false;
}

$candidate = (float) $candidate;

$matched = match ($operator) {
'>' => $candidate > $expected,
'<' => $candidate < $expected,
Expand Down
13 changes: 7 additions & 6 deletions src/Data/PageSize.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ final class PageSize
/**
* Selector options in display order; the literal `all` disables pagination.
*/
public const array OPTIONS = ['10', '25', '50', '100', 'all'];
public const array OPTIONS = [
'10',
'25',
'50',
'100',
'all',
];

/**
* Returns the `per-page` selector state, canonicalizing `all` and falling back to the default.
Expand Down Expand Up @@ -72,11 +78,6 @@ public static function resolve(string|null $raw, int $default = self::DEFAULT):
/**
* Renders the inline page-size selector shown in the grid summary header.
*
* Usage example:
* ```php
* $html = \PHPForge\Debug\Data\PageSize::selectorHtml('50');
* ```
*
* @param string $current Currently selected raw value (one of {@see OPTIONS} for a highlighted option).
*/
public static function selectorHtml(string $current): string
Expand Down
9 changes: 0 additions & 9 deletions src/Helper/Avatar.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@

/**
* Derives stable, deterministic avatar colours from arbitrary identifying strings.
*
* Two debug-panel renderers (mail and queue) display a colored circle next to each item; both used to compute the hue
* with the same `abs(crc32(strtolower(...))) % 360` formula. This helper centralises that derivation so the colour
* stays consistent across renderers.
*/
final class Avatar
{
Expand All @@ -25,11 +21,6 @@ final class Avatar
/**
* Returns a stable hue (`0..359`) for the given seed, or {@see self::DEFAULT_HUE} when the seed is empty.
*
* Usage example:
* ```php
* $hue = \PHPForge\Debug\Helper\Avatar::hueFor('Alice');
* ```
*
* @param string $seed Identifying value used to derive the hue.
*
* @return int Hue in the `0..359` range.
Expand Down
14 changes: 0 additions & 14 deletions src/Helper/CellMore.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@

/**
* Wraps long grid-cell content in a collapsible clamp with an expand/collapse pill toggle.
*
* The body collapses to a few lines through a CSS max-height clamp — the markup is never truncated server side, so
* any cell payload (plain text, highlighted SQL, trace lists) stays intact. The `debug.min.js` `cell-more` delegation
* flips the `is-open` state and swaps the toggle label.
*/
final class CellMore
{
Expand All @@ -37,11 +33,6 @@ final class CellMore
* The decision reads the raw source rather than the rendered markup, so highlighting or trace lists never tip a
* short value over the threshold.
*
* Usage example:
* ```php
* \PHPForge\Debug\Helper\CellMore::clamp($highlightedSql, $row->query);
* ```
*
* @param string $content Rendered cell HTML.
* @param string $source Raw payload the content was rendered from.
*
Expand All @@ -55,11 +46,6 @@ public static function clamp(string $content, string $source): string
/**
* Wraps the rendered cell content in the collapsible clamp container.
*
* Usage example:
* ```php
* \PHPForge\Debug\Helper\CellMore::wrap($renderedCellHtml);
* ```
*
* @param string $content Rendered cell HTML to clamp; emitted verbatim inside the body container.
*
* @return string Collapsible cell markup.
Expand Down
51 changes: 0 additions & 51 deletions src/Helper/Coerce.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,12 @@

/**
* Narrows arbitrary mixed payloads into the typed scalars debug-panel renderers expect.
*
* Framework callbacks, logger entries, request parameters, and renderer rows remain mixed even though persisted
* snapshots use strict JSON DTOs. This helper is limited to those external runtime boundaries; snapshot hydration is
* handled by {@see \PHPForge\Debug\Storage\Payload} without scalar coercion.
*/
final class Coerce
{
/**
* Returns a numeric value as a float or the supplied default.
*
* Usage example:
* ```php
* $duration = \PHPForge\Debug\Helper\Coerce::float($payload['duration'] ?? null, 0.0);
* ```
*
* @param mixed $value Value to narrow.
* @param float $default Value returned for non-numeric input.
*
Expand All @@ -41,11 +32,6 @@ public static function float(mixed $value, float $default = 0.0): float
/**
* Returns the value as a float when it is numeric, `null` otherwise.
*
* Usage example:
* ```php
* $duration = \PHPForge\Debug\Helper\Coerce::floatOrNull($payload['duration'] ?? null);
* ```
*
* @param mixed $value Value to narrow.
*
* @return float|null Numeric value or `null`.
Expand All @@ -58,11 +44,6 @@ public static function floatOrNull(mixed $value): float|null
/**
* Returns a numeric value as an int or the supplied default.
*
* Usage example:
* ```php
* $count = \PHPForge\Debug\Helper\Coerce::int($payload['count'] ?? null);
* ```
*
* @param mixed $value Value to narrow.
* @param int $default Value returned for non-numeric input.
*
Expand All @@ -76,11 +57,6 @@ public static function int(mixed $value, int $default = 0): int
/**
* Returns the value as an int when it is an integer or numeric, `null` otherwise.
*
* Usage example:
* ```php
* $statusCode = \PHPForge\Debug\Helper\Coerce::intOrNull($payload['statusCode'] ?? null);
* ```
*
* @param mixed $value Value to narrow.
*
* @return int|null Numeric value or `null`.
Expand All @@ -93,11 +69,6 @@ public static function intOrNull(mixed $value): int|null
/**
* Returns a string value or the supplied default.
*
* Usage example:
* ```php
* $category = \PHPForge\Debug\Helper\Coerce::string($payload['category'] ?? null, 'application');
* ```
*
* @param mixed $value Value to narrow.
* @param string $default Value returned for non-string input.
*
Expand All @@ -114,11 +85,6 @@ public static function string(mixed $value, string $default = ''): string
* Narrows a mixed/`array<array-key, mixed>` snapshot down to the `array<string, mixed>` shape downstream view-model
* normalizers expect.
*
* Usage example:
* ```php
* $data = \PHPForge\Debug\Helper\Coerce::stringKeyedArray(['name' => 'debug', 0 => 'ignored']);
* ```
*
* @param array<array-key, mixed> $data Source array with arbitrary keys.
*
* @return array<string, mixed> Entries whose key was already a string, in original order.
Expand All @@ -139,11 +105,6 @@ public static function stringKeyedArray(array $data): array
/**
* Returns only the string entries of a raw list, preserving order.
*
* Usage example:
* ```php
* $categories = \PHPForge\Debug\Helper\Coerce::stringList(['application', 42, 'database']);
* ```
*
* @param mixed $values Raw list, typically a user-configured category list.
*
* @return list<string> String entries in original order, possibly empty.
Expand All @@ -168,11 +129,6 @@ public static function stringList(mixed $values): array
/**
* Returns the value as a string when it is scalar or {@see Stringable}, `null` otherwise.
*
* Usage example:
* ```php
* $label = \PHPForge\Debug\Helper\Coerce::stringOrNull($payload['label'] ?? null);
* ```
*
* @param mixed $value Value to narrow.
*
* @return string|null String representation or `null`.
Expand All @@ -190,13 +146,6 @@ public static function stringOrNull(mixed $value): string|null
* Narrows a raw trace value (as captured by Yii's logger) into the `list<array<string, mixed>>` shape every panel
* renderer consumes.
*
* Each frame keeps only its string-keyed entries; non-array frames are dropped.
*
* Usage example:
* ```php
* $frames = \PHPForge\Debug\Helper\Coerce::traceFrames($payload['trace'] ?? null);
* ```
*
* @param mixed $value Raw trace payload.
*
* @return list<array<string, mixed>> Trace frames normalized to string-keyed maps.
Expand Down
Loading
Loading