View.php.bak

<?php

namespace Lia\Addon;


/**
 * @todo enable fallback-namespacing when default namespace (null) is not set. So you can add view `lia:theme`, then load view `theme` and get `lia:theme`
 * @warning conflictMode has a weird interaction with null-namespace views. If you add `ns:viewname`, then try to add `viewname` a conflict will now be generated because `ns:viewname` sets null-namespace `viewname`.
 */
class View extends \Lia\Addon {


    /**
     * Views to be loaded.
     * @structure `['namespace'=>['view/name'=>$view_callable]]`
     */
    public $views = [null=>[]];


    /**
     * Args to pass to every view
     *
     */
    public array $globalArgs = [];

    /**
     * What to do when there is a new view added where one already existed
     *
     * @option throw - throw an exception
     * @option ignore - don't add the new view (use the old one)
     * @option overwrite - replace the old view with the new one
     *
     */
    public string $conflictMode = 'throw';

    public function __construct($lia=null, $name=null){
        parent::__construct($lia, $name);

        $this->props['views'] = &$this->views;

        $this->props['conflictMode'] = $this->props['conflictMode'] ?? $this->conflictMode;
        $this->conflictMode = &$this->props['conflictMode'];
        $this->props['globalArgs'] = $this->props['globalArgs'] ?? $this->globalArgs;
        $this->globalArgs = &$this->props['globalArgs'];

        $this->methods['setViewConflictMode'] = [$this, 'setConflictMode'];
        $this->methods['addViewCallable'] = [$this, 'addCallable'];
        $this->methods['addView'] = [$this, 'addViewHandler'];
        $this->methods['view'] = [$this, 'view'];
    }

    /**
     * add a callable as a view
     *
     * @param $viewName the name of the view
     * @param $callable a callable accepting 2 args: $view_name & $args
     *
     * @note The second arg passed to your callable `$args` is a key=>value array that contains args passed to the `view('view_name', $args)` call
     *
     * @example callable `function($view_name, $args)`
     *
     */
    public function addCallable($viewName, $callable, $args=[]){
        $class = '\\Lia\\Obj\\ViewCallable';
        $this->addViewHandler($class, $callable, $viewName, $args);
    }

    /**
     * Add a view handler that will be called when a view is requested
     *
     * @note null-namespace refers to `$lia->view('view-name')`
     * @note namespace refers to `$lia->view('namespace:view-name')`
     * @note Always sets null-namespace view if it's not already set. (ignores conflictMode)
     *
     */
    public function addViewHandler($class, $dir, $viewName, $args=[]){
        $vnCopy = $viewName;
        $parts = explode(':', $viewName);
        $name = $viewName = array_pop($parts);
        $namespace = array_shift($parts);

        if (isset($this->views[$namespace][$viewName])){
            $cm = $this->conflictMode;
            if ($cm=='ignore')return;
            else if ($cm!='overwrite'){
                throw new \Exception("View '$viewName' is already set.");
            }
        }

        $viewData = [
            'class'=>$class,
            'dir'=>$dir,
            'name'=>$vnCopy,
            'namespace'=>$namespace,
            'args'=>$args,
            'lia'=>$this->_lia,
        ];

        // var_dump($namespace);
        // var_dump($viewName);
        // exit;
        $this->views[$namespace][$viewName] = $viewData;
        $this->views[null][$viewName] = $this->views[null][$viewName] ?? $viewData;
    }


    /**
     * get a view object
     */
    public function view($name, $args=[]){
        $parts = explode(':', $name);
        $name = array_pop($parts);
        $namespace = array_shift($parts);

        $view_ns = $this->views[$namespace];
        $viewData = $view_ns[$name];

        // if ($viewData==null){
        //     $message="";
        //     $ext = strtolower(pathinfo($name,PATHINFO_EXTENSION));
        //     if ($ext=='php'||$ext=='html'){
        //         $message = "Do not include the file extension when calling view()";
        //     }
        //     throw new \Lia\Exception(". {$message}");
        // }
        $cn = $viewData['class'];
        $dir = $viewData['dir'];
        $name = $viewData['name'];
        $setupArgs = $viewData['args'];
        // $globalArgs = $this->lia->api('lia:globalparams.getAll');
        // $viewData['globalArgs'] = $globalArgs;
        $globalArgs = $this->globalArgs;

        // print_r(array_keys($viewData));
        if (in_array('Lia\\Obj\\IView',class_implements($cn,true))){
            // print_r(array_keys($globalArgs));
            // print_r(array_keys($setupArgs));
            // print_r(array_keys($args));
            //
            // exit;
            $allArgs = array_merge($globalArgs,$setupArgs,$args);
            $view = new $cn($name, $dir, $allArgs);
        } else {
            $viewData['given_args'] = $args;
            $view = new $cn($viewData);
        }
        return $view;
    }
}