feat: manifest checks, Divi compatibility from manifests, reference fingerprints
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Release;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* The expected fingerprints of the mirrors (fingerprints.json, shipped with the plugin) and their reference sources
|
||||
* (tests/Fixtures/divi/reference/<id>.txt, development only – not in the plugin package). Written by
|
||||
* wp lit-mcp divi-check --update-reference.
|
||||
*/
|
||||
final class DiviReference
|
||||
{
|
||||
public const FILE = __DIR__ . '/fingerprints.json';
|
||||
|
||||
/** @return array<string, string> Mirror ID => sha256; [] when the file is missing or broken. */
|
||||
public static function expected(?string $file = null): array
|
||||
{
|
||||
$file ??= self::FILE;
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local plugin file.
|
||||
$raw = is_file($file) && is_readable($file) ? file_get_contents($file) : false;
|
||||
$data = is_string($raw) ? json_decode($raw, true) : null;
|
||||
if (! is_array($data)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$expected = [];
|
||||
foreach ($data as $id => $hash) {
|
||||
if (is_string($id) && is_string($hash)) {
|
||||
$expected[$id] = $hash;
|
||||
}
|
||||
}
|
||||
ksort($expected);
|
||||
|
||||
return $expected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $hashes Mirror ID => sha256.
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function writeExpected(array $hashes, ?string $file = null): void
|
||||
{
|
||||
ksort($hashes);
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode -- pure PHP, no WordPress.
|
||||
$json = json_encode($hashes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- dev fixture.
|
||||
if (! is_string($json) || file_put_contents($file ?? self::FILE, $json . "\n") === false) {
|
||||
throw new RuntimeException('fingerprints.json not written');
|
||||
}
|
||||
}
|
||||
|
||||
/** tests/Fixtures/divi/reference of a development checkout; null in an installed plugin. */
|
||||
public static function sourceDir(): ?string
|
||||
{
|
||||
$dir = dirname(__DIR__, 4) . '/tests/Fixtures/divi/reference';
|
||||
|
||||
return is_dir($dir) ? $dir : null;
|
||||
}
|
||||
|
||||
public static function readSource(string $id, string $dir): ?string
|
||||
{
|
||||
$file = $dir . '/' . $id . '.txt';
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local dev fixture.
|
||||
$source = is_file($file) ? file_get_contents($file) : false;
|
||||
|
||||
return is_string($source) ? $source : null;
|
||||
}
|
||||
|
||||
/** @throws RuntimeException */
|
||||
public static function writeSource(string $id, string $source, string $dir): void
|
||||
{
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- dev fixture.
|
||||
if (file_put_contents($dir . '/' . $id . '.txt', $source . "\n") === false) {
|
||||
throw new RuntimeException(sprintf('reference source %s not written', $id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fingerprints of every mirror in the installed Divi.
|
||||
*
|
||||
* @return array<string, SourceFingerprint>
|
||||
* @throws RuntimeException When a mirrored function cannot be read.
|
||||
*/
|
||||
public static function current(string $themeDir): array
|
||||
{
|
||||
$prints = [];
|
||||
foreach (DiviAdapters::mirrors() as $mirror) {
|
||||
$file = $themeDir . '/' . $mirror->file;
|
||||
$prints[$mirror->id] = SourceFingerprint::of($file, $mirror->function, $mirror->class);
|
||||
}
|
||||
|
||||
return $prints;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user