<?php namespace Example; abstract class Setting { private string $fileName = 'NOT FOUND'; private array $settings = []; public function __construct(private string $serverName = '') { if ('' == $this->serverName) { $this->serverName = $_SERVER['SERVER_NAME'] ?? ''; } $this->load(); } public function __call(string $name, array $args) : ?string { if (! \str_starts_with($name, 'get')) { throw new \Exception('Method ' . $name . ' is not defined for ' . static::class); } $name = \lcfirst(\substr($name, 3)); return $this->settings[$name] ?? null; } public function __get(string $field) : mixed { return $this->settings[$field] ?? null; } public function __set(string $field, mixed $value) : void { $this->settings[$field] = $value; } public function addFields(array $fields) : static { $this->settings = \array_merge($this->settings, $fields); return $this; } public function empty() : bool { return empty($this->settings); } public function getFields() : array { return $this->settings; } public function getLoadedFileName() : string { return $this->fileName; } public function optional(string $key) : mixed { return $this->settings[$key] ?? false; } public function save() : bool { if (! $this->settings) { return false; } $parts = \explode('\\', static::class); $className = \array_pop($parts); if (! empty($this->serverName)) { $fileName = $this->getFileName($this->serverName . '/' . $className); } else { $fileName = $this->getFileName($className); } $parts = \explode('/', $fileName); \array_pop($parts); $dir = \implode('/', $parts); if (! \is_dir($dir)) { \mkdir($dir, recursive: true); } \file_put_contents($fileName, "<?php\nreturn " . \var_export($this->settings, true) . ';'); return true; } public function setFields(array $fields) : static { $this->settings = $fields; return $this; } private function getFileName(string $fileName) : string { if (false == \strpos($fileName, '.php')) { $fileName .= '.php'; } return PROJECT_ROOT . '/config/' . $fileName; } private function load() : void { if ($this->settings) { return; } $parts = \explode('\\', static::class); $className = \array_pop($parts); if (! empty($this->serverName)) { $this->settings = $this->loadFile($this->serverName . '/' . $className); if ($this->settings) { return; } } $this->settings = $this->loadFile($className); } private function loadFile(string $configName) : array { $fileName = $this->getFileName($configName); if (\file_exists($fileName)) { if (\function_exists('opcache_invalidate')) { \opcache_invalidate($fileName, true); } $this->fileName = $fileName; return include $fileName; } return []; } }