2025-11-30 15:35:04 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace StaticPHP\Config;
|
|
|
|
|
|
|
|
|
|
use StaticPHP\Exception\WrongUsageException;
|
2025-12-15 17:00:20 +08:00
|
|
|
use StaticPHP\Registry\Registry;
|
2026-02-14 17:24:49 +08:00
|
|
|
use StaticPHP\Util\FileSystem;
|
2026-01-22 16:03:01 +08:00
|
|
|
use Symfony\Component\Yaml\Yaml;
|
2025-11-30 15:35:04 +08:00
|
|
|
|
|
|
|
|
class ArtifactConfig
|
|
|
|
|
{
|
|
|
|
|
private static array $artifact_configs = [];
|
|
|
|
|
|
2025-12-18 15:43:58 +08:00
|
|
|
public static function loadFromDir(string $dir, string $registry_name): array
|
2025-11-30 15:35:04 +08:00
|
|
|
{
|
|
|
|
|
if (!is_dir($dir)) {
|
|
|
|
|
throw new WrongUsageException("Directory {$dir} does not exist, cannot load artifact config.");
|
|
|
|
|
}
|
2025-12-18 15:43:58 +08:00
|
|
|
$loaded = [];
|
2026-02-14 17:24:49 +08:00
|
|
|
$files = FileSystem::scanDirFiles($dir, false);
|
2025-11-30 15:35:04 +08:00
|
|
|
if (is_array($files)) {
|
|
|
|
|
foreach ($files as $file) {
|
2025-12-15 17:00:20 +08:00
|
|
|
self::loadFromFile($file, $registry_name);
|
2025-12-18 15:43:58 +08:00
|
|
|
$loaded[] = $file;
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (file_exists("{$dir}/artifact.json")) {
|
2025-12-15 17:00:20 +08:00
|
|
|
self::loadFromFile("{$dir}/artifact.json", $registry_name);
|
2025-12-18 15:43:58 +08:00
|
|
|
$loaded[] = "{$dir}/artifact.json";
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
2025-12-18 15:43:58 +08:00
|
|
|
return $loaded;
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load artifact configurations from a specified JSON file.
|
|
|
|
|
*/
|
2025-12-18 15:43:58 +08:00
|
|
|
public static function loadFromFile(string $file, string $registry_name): string
|
2025-11-30 15:35:04 +08:00
|
|
|
{
|
|
|
|
|
$content = file_get_contents($file);
|
|
|
|
|
if ($content === false) {
|
|
|
|
|
throw new WrongUsageException("Failed to read artifact config file: {$file}");
|
|
|
|
|
}
|
2026-04-07 17:10:33 +08:00
|
|
|
// use cache to skip redundant parsing
|
|
|
|
|
$data = ConfigCache::get($content);
|
|
|
|
|
if ($data !== null) {
|
|
|
|
|
logger()->debug("Config cache hit: {$file}");
|
|
|
|
|
} else {
|
|
|
|
|
$data = match (pathinfo($file, PATHINFO_EXTENSION)) {
|
|
|
|
|
'json' => json_decode($content, true),
|
|
|
|
|
'yml', 'yaml' => extension_loaded('yaml') ? yaml_parse($content) : Yaml::parse($content),
|
|
|
|
|
default => throw new WrongUsageException("Unsupported artifact config file format: {$file}"),
|
|
|
|
|
};
|
|
|
|
|
if (!is_array($data)) {
|
|
|
|
|
throw new WrongUsageException("Invalid JSON format in artifact config file: {$file}");
|
|
|
|
|
}
|
2026-04-07 17:11:27 +08:00
|
|
|
ConfigCache::set($content, $data);
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
|
|
|
|
ConfigValidator::validateAndLintArtifacts(basename($file), $data);
|
|
|
|
|
foreach ($data as $artifact_name => $config) {
|
|
|
|
|
self::$artifact_configs[$artifact_name] = $config;
|
2025-12-15 17:00:20 +08:00
|
|
|
Registry::_bindArtifactConfigFile($artifact_name, $registry_name, $file);
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
2025-12-18 15:43:58 +08:00
|
|
|
return $file;
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get all loaded artifact configurations.
|
|
|
|
|
*
|
|
|
|
|
* @return array<string, array> an associative array of artifact configurations
|
|
|
|
|
*/
|
|
|
|
|
public static function getAll(): array
|
|
|
|
|
{
|
|
|
|
|
return self::$artifact_configs;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 17:10:33 +08:00
|
|
|
/**
|
|
|
|
|
* Restore artifact configs from cache without re-parsing YAML files.
|
|
|
|
|
*
|
|
|
|
|
* @internal used by Registry cache layer only
|
|
|
|
|
*/
|
|
|
|
|
public static function _restoreFromCache(array $configs): void
|
|
|
|
|
{
|
|
|
|
|
self::$artifact_configs = array_merge(self::$artifact_configs, $configs);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-30 15:35:04 +08:00
|
|
|
/**
|
|
|
|
|
* Get the configuration for a specific artifact by name.
|
|
|
|
|
*
|
|
|
|
|
* @param string $artifact_name the name of the artifact
|
|
|
|
|
* @return null|array the configuration array for the specified artifact, or null if not found
|
|
|
|
|
*/
|
|
|
|
|
public static function get(string $artifact_name): ?array
|
|
|
|
|
{
|
|
|
|
|
return self::$artifact_configs[$artifact_name] ?? null;
|
|
|
|
|
}
|
2026-02-02 13:32:35 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Register an inline artifact configuration.
|
|
|
|
|
* Used when artifact is defined inline within a package configuration.
|
|
|
|
|
*
|
|
|
|
|
* @param string $artifact_name Artifact name (usually same as package name)
|
|
|
|
|
* @param array $config Artifact configuration
|
|
|
|
|
* @param string $registry_name Registry name
|
|
|
|
|
* @param string $source_info Source info for debugging
|
|
|
|
|
*/
|
|
|
|
|
public static function registerInlineArtifact(string $artifact_name, array $config, string $registry_name, string $source_info = 'inline'): void
|
|
|
|
|
{
|
|
|
|
|
self::$artifact_configs[$artifact_name] = $config;
|
|
|
|
|
Registry::_bindArtifactConfigFile($artifact_name, $registry_name, $source_info);
|
|
|
|
|
}
|
2025-11-30 15:35:04 +08:00
|
|
|
}
|