<?php
namespace Lia;
/**
* Liaison App
*
*/
class App implements AppInterface {
/** Namespace */
protected string $namespace;
/**
* Root dir of the app
*/
public string $dir;
/**
* Liaison instance this app is in
*/
public \Lia $lia;
/** Addons in this app */
public array $addons = [];
/**
* The app's configs, usually in a config.json file in the app's root dir, unless overridden.
*/
public array $config = [];
/**
* @param $lia
* @param $fqn a string like `vendor:package_name`
* @param $dir the root dir of this package
*/
public function __construct(\Lia $lia, string $dir){
$this->lia = $lia;
$this->dir = $dir;
$config_file=$dir.'/config.json';
if (!file_exists($config_file)){
throw new \Exception("Config file 'config.json' MUST exist in the root of your app's dir '$dir'\n");
}
try {
$this->config = json_decode(file_get_contents($config_file),true, 512, JSON_THROW_ON_ERROR);
} catch (\Exception $e){
$lia->throw($e, "JSON file '$config_file' failed to `json_decode()`");
}
if (!isset($this->config['namespace']) && !isset($this->namespace)){
throw new \Exception("You MUST set 'namespace' to a string value in your 'config.json' at the root of your app's dir '$dir' OR set `protected string \$namespace = 'your_namespace';` in your subclass.");
}
$this->namespace = $this->config['namespace'];
$lia->addApp($this);
if (isset($this->config['addon_dir'])){
$this->load_addons($this->config['addon_dir']);
} else {
$this->load_addons();
}
}
public function getLia(): \Lia {
return $this->lia;
}
public function getNamespace(): string {
return $this->namespace;
}
/**
* Get the absolute path to a directory or file within the app
*/
public function getPath(string $relative_path = ""): string {
return str_replace('//','/',$this->dir.'/'.$relative_path);
}
/**
*
* @throws if $config_name is not set
*/
public function getConfig(string $config_name): mixed {
if (!isset($this->config[$config_name])){
$ns = $this->getNamespace();
$class = get_class($this);
throw new \Exception("Config '$config_name' is not set on app '$ns' (class '$class')");
}
return $this->config[$config_name];
}
/**
* Check if the named config is set for your app
*/
public function hasConfig(string $config_name): bool {
return isset($this->config[$config_name]);
}
/**
* Load THIS app's addons from the addon dir.
*
* @param $sub_dir directory where addons are stored defaults to 'addon'. config 'addon_dir' can be used.
*/
protected function load_addons($sub_dir = 'addon'){
$dir = $this->dir.'/'.$sub_dir;
$classes = \Lia\Utility\ClassFinder::classesFromDir($dir);
if (count($classes)==0)return;
$addons = [];
foreach ($classes as $info){
// if (!in_array('Lia\\iCore\\Compo',$info['interfaces']))continue;
$className = $info['class'];
$addons[] = $addon = new $className($this);
$this->addAddon($addon);
}
foreach ($this->addons as $addon){
$addon->onAddonsLoaded($this, $addons);
}
}
public function addAddon(\Lia\AddonInterface $addon){
$this->addons[$addon->getName()] = $addon;
}
/**
* Get an addon by its name
*/
public function getAddon(string $addon_name): \Lia\AddonInterface{
if (!isset($this->addons[$addon_name])){
throw new \Exception("Addon '$addon_name' does not exist on this app (namespace:'".$this->getNamespace()."', class:".get_class($this).")");
}
return $this->addons[$addon_name];
}
/**
* Get the sub-directory.
*
* @return $sub_dir appended to $this->dir
*/
public function dir(string $sub_dir): string {
return $this->dir.'/'.$sub_dir.'/';
}
/** called before an HTTP request or CLI input is processed */
public function onLiaisonReady(\Lia $lia){
foreach ($this->config['addons']??[] as $addon_name => $value){
$addon = $this->lia->addon($addon_name);
$addon->onEnabledByApp($this, $value);
}
}
/** called after input is processed */
public function onFinish(\Lia $lia){}
/** Called when `$lia->terminate()` is called, which will `exit` after the `onTerminate()` event. */
public function onTerminate(\Lia $lia){}
/** called by $lia->deliver() after onReady() event */
public function onStartRequest(\Lia\Http\Request $request, \Lia\Http\Response $response){}
/** called by $lia->execute() after onReady() event */
public function onCliReady(\Lia\CliExecution $cli){}
}