Package.php

<?php

namespace Lia;

class Package {

    /** example: package */
    public string $name;
    /** example: vendor:package */
    public string $fqn;

    /**
     * The root dir for the package
     */
    public ?string $dir = null;

    /**
     * Liaison object
     */
    public \Lia $lia;

    /** array of addons */
    public array $addons = [];

    /** Configurations for the package */
    protected array $config = [];

    /**
     * @param $liaison a lia object
     * @param $fqn a string like `vendor:package_name`
     * @param $dir the root dir of this package
     */
    public function __construct(\Lia $liaison, string $fqn, ?string $dir=null){
        $this->lia = $liaison;
        $this->dir = $dir ?? $this->dir;
        $this->fqn = $fqn ?? $this->fqn;
        $this->lia->addPackage($this, $this->fqn);
        //$this->lia->fqn_packages[$this->fqn] = $this;
        $pos = strpos($this->fqn, ':');
        if ($pos!==false)$pos +=1;
        $short_name = substr($this->fqn, $pos);
        $this->name = $short_name;
        //$this->lia->packages[$short_name] = $this;

        if ($dir != null){
            $config = $dir.'/config.json';
            if (is_file($config)){
                $props = json_decode(file_get_contents($config), true);
                $this->config = $props;
            }
        }


        $this->bootstrap();
    }

    /**
     * `require()` the bootstrap.php file in the package's root dir, if it exists.
     *
     * It's called after the Package class has been initialized, with name, dir, lia, and fqn set. Addons are not yet loaded.  
     * If you use addons, call '$this->load_addons()' in your bootstrap.php file
     * @NOTE subclass `\Lia\Package` or `\Lia\Package\Server` and implement a custom 'bootstrap()' method.
     */
    protected function bootstrap(){
        if (file_exists($this->dir.'/bootstrap.php')){
            require($this->dir.'/bootstrap.php');
        }
    }

    /**
     * foreach $addon, $addon->init_lia
     */
    public function init_lia(){
        foreach ($this->addons as $name=>$a){
            // echo "\n- $name: init_lia";
            $a->init_lia($this);
        }
    }


    public 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'];
            // if (!class_exists($className,true))continue;
            $addon = new $className($this);
        }
    }

    public function ready(){
        foreach ($this->addons as $a){
            $a->onPackageReady($this);
        }
    }

    /** 
     * Return the absolute path to a directory inside your package
     */
    public function dir(string $sub_dir): string{
        return $this->dir.'/'.$sub_dir.'/';
    }



    /**
     * Get a config's value or `null` if it is not set
     *
     * @param string $key the config's key
     * @return mixed the config's value or null
     */
    public function config(string $key): mixed {
        return $this->config[$key] ?? null;
    }

    /**
     * Set the config's value to a primitive value or array. Arrays should NOT contain objects, only that which can be expressed in JSON.
     *
     * @param $key string a config name
     * @param int|string|bool|float|array $value a primitive value or array
     */
    public function setConfig(string $key, int|string|bool|float|array $value): void {
        $this->config[$key] = $value;
    }
}