Fixes the configuration file
This commit is contained in:
126
app/Services/Config.php
Normal file
126
app/Services/Config.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Config as ConfigModel;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
final class Config
|
||||
{
|
||||
/** Typed public property for the content group's disclaimer field. */
|
||||
public string $contentDisclaimer = '';
|
||||
|
||||
/** Indexed config class instances keyed by their group key string. */
|
||||
private array $configClasses = [];
|
||||
|
||||
/**
|
||||
* Auto-discovers Config Field classes from app/Configs/, loads or creates
|
||||
* their database rows, and populates typed public properties with cast values.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->discoverConfigClasses();
|
||||
$this->hydrateProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans app/Configs/ for PHP files, instantiates each class,
|
||||
* and indexes them by their key property.
|
||||
*/
|
||||
private function discoverConfigClasses(): void
|
||||
{
|
||||
$files = glob(app_path('Configs/*.php')) ?: [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$className = 'App\\Configs\\'.pathinfo($file, PATHINFO_FILENAME);
|
||||
$instance = new $className;
|
||||
$this->configClasses[$instance->key] = $instance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all discovered config classes, ensures a DB row exists,
|
||||
* resolves typed field values, and assigns them to public properties.
|
||||
*/
|
||||
private function hydrateProperties(): void
|
||||
{
|
||||
try {
|
||||
$dbRecords = ConfigModel::all()->keyBy('key');
|
||||
|
||||
foreach ($this->configClasses as $key => $instance) {
|
||||
$record = $this->ensureDbRecord($key, $dbRecords);
|
||||
$jsonValue = Arr::wrap((array) ($record->json_value ?? []));
|
||||
$this->assignFieldProperties($key, $instance, $jsonValue);
|
||||
}
|
||||
} catch (QueryException) {
|
||||
// Silently skip if configs table does not yet exist during migrations.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a database record exists for the given config key,
|
||||
* creating one with an empty json_value if it does not.
|
||||
*/
|
||||
private function ensureDbRecord(string $key, Collection $dbRecords): ConfigModel
|
||||
{
|
||||
if ($dbRecords->has($key)) {
|
||||
return $dbRecords->get($key);
|
||||
}
|
||||
|
||||
return ConfigModel::firstOrCreate(
|
||||
['key' => $key],
|
||||
['json_value' => ''],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves each field value from json_value (with default fallback),
|
||||
* applies type casting, and assigns to the matching typed public property.
|
||||
*/
|
||||
private function assignFieldProperties(string $key, object $instance, array $jsonValue): void
|
||||
{
|
||||
foreach ($instance->getFieldKeys() as $fieldKey => $definition) {
|
||||
$type = Arr::get($definition, 'type', 'string');
|
||||
$rawValue = Arr::get($jsonValue, $fieldKey);
|
||||
|
||||
if ($rawValue === null || $rawValue === '') {
|
||||
$rawValue = $instance->getDefault($fieldKey);
|
||||
}
|
||||
|
||||
$castedValue = $this->castValue($rawValue, $type);
|
||||
$propertyName = Str::camel($key).Str::studly($fieldKey);
|
||||
|
||||
if (property_exists($this, $propertyName)) {
|
||||
$this->{$propertyName} = $castedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts a raw value to the PHP type defined by the config field type string.
|
||||
*/
|
||||
private function castValue(mixed $value, string $type): mixed
|
||||
{
|
||||
return match ($type) {
|
||||
'string', 'markdown' => (string) $value,
|
||||
'int', 'integer' => (int) $value,
|
||||
'bool', 'boolean' => (bool) $value,
|
||||
'float' => (float) $value,
|
||||
default => $value,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Config Field class instance for a given group key,
|
||||
* or null when no class has been discovered for that key.
|
||||
*/
|
||||
public function getConfigClassForGroup(string $group): ?object
|
||||
{
|
||||
return Arr::get($this->configClasses, $group);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user