fixate/pw-mvc-boilerplate

View on GitHub
core/View.php

Summary

Maintainability
B
5 hrs
Test Coverage
<?php

use fixate as f8;

class ViewException extends Exception
{
}

class View implements IView
{
    protected static $helpers = array();
    protected $layout = '';
    protected $data = array();
    protected $base_path = null;
    public $controller = null;
    protected static $allowed_view_types = ['html'];

    public static function set_allowed_view_types()
    {
        static::$allowed_view_types = func_get_args();
    }

    public function __construct(IController &$controller, $name = '')
    {
        $this->controller = $controller;
        $this->name = $name;
    }

    // Spit out the page
    public function spit()
    {
        if (!empty($this->name)) {
            echo $this->render_file($this->name);
        }
    }

    public function partial($name, $data = array())
    {
        return $this->render_file(f8\Paths::join('partials', $name), $data);
    }

    public function assets($path, $use_min = true)
    {
        $is_production = Environment::is_production();
        if ($is_production) {
            // If use MD5# manifest in use get proper path
            if (Environment::use_manifest()) {
                $path = Manifest::prod_path($path);
            }
        }

        if ($use_min) {
            $ext = f8\Paths::get_extension($path);
            // Only css and js
            if ($ext == 'js' || $ext == 'css') {
                $is_min = f8\Strings::ends_with($path, ".min.${ext}") !== false;

                // If in production change file to use .min extension
                if ($is_production && !$is_min && $use_min) {
                    $path = f8\Paths::change_extension($path, "min.{$ext}");
                }
            }
        }

        $templates = $this->controller->config->urls->templates;

        return f8\Paths::join($templates, 'assets', $path);
    }

    public function set_layout($name)
    {
        $this->layout = $name;

        return $this;
    }

    public function add_data($data)
    {
        if ($data) {
            $this->data = array_merge($this->data, $data);
        }

        return $this;
    }

    public function set_asset_uri($uri)
    {
        $this->assets_uri = $uri;

        return $this;
    }

    public function set_base_path($path)
    {
        $this->base_path = $path;

        return $this;
    }

    public function render()
    {
        if (!isset($this->layout)) {
            return '';
        }

        return $this->render_file("layouts/{$this->layout}");
    }

    public function view_exists($file)
    {
        return file_exists($this->resolve_view_path($file));
    }

    public function partial_exists($file)
    {
        return $this->view_exists(f8\Paths::join('partials', $file));
    }

    protected function resolve_view_path($file)
    {
        if (!($base_path = $this->base_path)) {
            $base_path = f8\Paths::resolve(f8\Paths::join(dirname(__FILE__), '../views'));
        }

        $extensions = array_map(function($type) {
            return ".{$type}.php";
        }, static::$allowed_view_types);

        foreach ($extensions as $ext) {
            $path = f8\Paths::join($base_path, $file);

            if (!f8\Strings::ends_with($path, $ext)) {
                $path .= $ext;
            }

            if (file_exists($path)) {
                return $path;
            }
        }

        return null;
    }

    protected function render_file($file, $_data = array(), $fallback = null)
    {
        if (!isset($this->data)) {
            $this->data = array();
        }

        $_path = $this->resolve_view_path($file);

        $view = $this;

        $config = $this->controller->config;
        $fields = $this->controller->fields;
        $input = $this->controller->input;
        $page = $this->controller->page;
        $pages = $this->controller->pages;
        $permissions = $this->controller->permissions;
        $roles = $this->controller->roles;
        $sanitizer = $this->controller->sanitizer;
        $session = $this->controller->session;
        $templates = $this->controller->templates;
        $user = $this->controller->user;
        $users = $this->controller->users;

        $env = Environment::get_instance();
        extract(array_merge($this->data, $_data));

        ob_start();
        try {
            if (!file_exists($_path)) {
                if (is_callable($fallback)) {
                    echo $fallback($this);
                } else {
                    throw new ViewException("View file {$file}.html.php does not exist.");
                }
            } else {
                include $_path;
            }
        } catch (Exception $ex) {
            return ob_get_clean().'ERROR in View: '.$ex->getMessage();
        }

        return ob_get_clean();
    }

    public function __call($method, $args)
    {
        if (property_exists(__CLASS__, $method) && is_callable($method)) {
            return call_user_func_array(array($this, $method), $args);
        } else {
            if (in_array($method, array_keys(self::$helpers))) {
                $method = self::$helpers[$method];
                if (!is_callable($method)) {
                    if (is_array($method) && count($method) >= 2) {
                        $method = $method[1];
                    }

                    throw new ViewException("Method '{$method}' not found.");
                }

                if (is_array($method)) {
                    return call_user_func_array($method, $args);
                } else {
                    return call_user_func($method, $args);
                }
            } else {
                throw new ViewException("Method '{$method}' not found.");
            }
        }
    }

    public static function add_helper($func)
    {
        if (is_array($func)) {
            $func_name = $func[1];
        } elseif (is_string($func)) {
            $func_name = $func;
        } else {
            $func_name = (string) $func;
        }

        self::$helpers[$func_name] = $func;
    }
}