|null $icons Plugin icons for WordPress admin * @param array|null $sections Content sections for plugin info modal */ public function __construct( public bool $updateAvailable, public ?string $version = null, public ?string $slug = null, public ?string $plugin = null, public ?string $downloadUrl = null, public ?\DateTimeImmutable $lastUpdated = null, public ?string $tested = null, public ?string $requires = null, public ?string $requiresPhp = null, public ?string $changelog = null, public ?string $packageHash = null, public ?string $name = null, public ?string $homepage = null, public ?array $icons = null, public ?array $sections = null, ) { } public static function fromArray(array $data): self { if (!isset($data['update_available']) || !is_bool($data['update_available'])) { throw new \InvalidArgumentException('Invalid response: missing or invalid update_available'); } $lastUpdated = null; if (isset($data['last_updated']) && $data['last_updated'] !== null) { try { $lastUpdated = new \DateTimeImmutable($data['last_updated']); } catch (\Exception $e) { throw new \InvalidArgumentException( 'Invalid response: invalid date format for last_updated', 0, $e ); } } $icons = null; if (isset($data['icons']) && is_array($data['icons'])) { $icons = $data['icons']; } $sections = null; if (isset($data['sections']) && is_array($data['sections'])) { $sections = $data['sections']; } return new self( updateAvailable: $data['update_available'], version: isset($data['version']) && is_string($data['version']) ? $data['version'] : null, slug: isset($data['slug']) && is_string($data['slug']) ? $data['slug'] : null, plugin: isset($data['plugin']) && is_string($data['plugin']) ? $data['plugin'] : null, downloadUrl: isset($data['download_url']) && is_string($data['download_url']) ? $data['download_url'] : ( isset($data['package']) && is_string($data['package']) ? $data['package'] : null ), lastUpdated: $lastUpdated, tested: isset($data['tested']) && is_string($data['tested']) ? $data['tested'] : null, requires: isset($data['requires']) && is_string($data['requires']) ? $data['requires'] : null, requiresPhp: isset($data['requires_php']) && is_string($data['requires_php']) ? $data['requires_php'] : null, changelog: isset($data['changelog']) && is_string($data['changelog']) ? $data['changelog'] : null, packageHash: isset($data['package_hash']) && is_string($data['package_hash']) ? $data['package_hash'] : null, name: isset($data['name']) && is_string($data['name']) ? $data['name'] : null, homepage: isset($data['homepage']) && is_string($data['homepage']) ? $data['homepage'] : null, icons: $icons, sections: $sections, ); } /** * Check if the package hash is valid against the expected format. */ public function hasValidPackageHash(): bool { if ($this->packageHash === null) { return false; } // Package hash format: "sha256:hexstring" return preg_match('/^sha256:[a-f0-9]{64}$/i', $this->packageHash) === 1; } }