KumbiaPHP/KumbiaPHP

View on GitHub
core/kumbia/kumbia_view.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php
/**
 * KumbiaPHP web & app Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.
 *
 * @category   View
 *
 * @copyright  Copyright (c) 2005 - 2023 KumbiaPHP Team (http://www.kumbiaphp.com)
 * @license    https://github.com/KumbiaPHP/KumbiaPHP/blob/master/LICENSE   New BSD License
 */

/**
 * Renderer de vistas.
 *
 * @category   View
 */
class KumbiaView
{
    /**
     * Contenido.
     *
     * @var string|null
     */
    protected static $_content;
    /**
     * Vista a renderizar.
     *
     * @var string
     * */
    protected static $_view;
    /**
     * Template.
     *
     * @var string|null
     */
    protected static $_template = 'default';
    /**
     * Indica el tipo de salida generada por el controlador.
     *
     * @var string
     */
    protected static $_response;
    /**
     * Indica el path al que se le añadira la constante correspondiente.
     *
     * @var string
     */
    protected static $_path;
    /**
     * Número de minutos que será cacheada la vista actual.
     *
     * type: tipo de cache (view, template)
     * time: tiempo de vida de cache
     *
     * @var array
     */
    protected static $_cache = ['type' => false, 'time' => false, 'group' => false];

    /**
     * Datos del Controlador actual.
     *
     * @var array
     */
    protected static $_controller;

    /**
     * Initialize view
     *
     * @param string $view
     * @param string $path
     * @return void
     */
    public static function init($view, $path)
    {
        self::$_view = $view;
        self::$_path = $path.'/';
        //self::$init = true;
        // TODO add defaults if init executed (workerman, ngx-php,...)
    }

    /**
     * Cambia el view y opcionalmente el template.
     *
     * @param string|null    $view     nombre del view a utilizar sin .phtml
     * @param string|null    $template opcional nombre del template a utilizar sin .phtml
     * 
     * @return void
     */
    public static function select($view, $template = '')
    {
        self::$_view = $view;

        // verifica si se indico template
        if ($template !== '') {
            self::$_template = $template;
        }
    }

    /**
     * Asigna el template para la vista.
     *
     * @param string|null $template nombre del template a utilizar sin .phtml
     * 
     * @return void
     */
    public static function template($template)
    {
        self::$_template = $template;
    }

    /**
     * Indica el tipo de Respuesta dada por el controlador
     * buscando el view con esa extension.
     * ej. View::response('xml');
     * buscara: views/controller/action.xml.phtml.
     *
     * @param string        $response
     * @param string|null   $template Opcional nombre del template sin .phtml
     * 
     * @return void
     */
    public static function response($response, $template = null)
    {
        self::$_response = $response;

        // verifica si se indico template
        if ($template !== null) {
            self::$_template = $template;
        }
    }

    /**
     * Asigna el path de la vista.
     *
     * @param string $path path de la vista sin extension .phtml
     * 
     * @return void
     */
    public static function setPath($path)
    {
        self::$_path = $path.'/';
    }

    /**
     * Obtiene el path para vista incluyendo la extension .phtml.
     *
     * @return string
     */
    public static function getPath()
    {
        if (self::$_response) {
            return self::$_path.self::$_view.'.'.self::$_response.'.phtml';
        }

        return self::$_path.self::$_view.'.phtml';
    }

    /**
     * Obtiene un atributo de KumbiaView.
     *
     * @param string $atribute nombre de atributo (template, response, path, etc)
     * 
     * @return mixed
     */
    public static function get($atribute)
    {
        return self::${"_$atribute"};
    }

    /**
     * Asigna cacheo de vistas o template.
     *
     * @param string|null  $time Tiempo de vida de cache
     * @param string        $type Tipo de cache (view, template)
     * @param string        $group Grupo de pertenencia de cache
     *
     * @return bool En producción y cache de view
     */
    public static function cache($time, $type = 'view', $group = 'kumbia.view')
    {
        if ($time === null) { //TODO borrar cache
            return self::$_cache['type'] = false;
        }
        self::$_cache['type'] = $type;
        self::$_cache['time'] = $time;
        self::$_cache['group'] = $group;
        //Si está en producción para view
        if (PRODUCTION && $type === 'view') {
            return self::getCache(); //TRUE si está cacheada
        }

        return false;
    }

    /**
     * Obtiene la cache de view.
     *
     * @return bool
     */
    protected static function getCache()
    {
        // el contenido permanece nulo si no hay nada cacheado o la cache expiro
        self::$_content = Cache::driver()->get(Router::get('route'), self::$_cache['group']);

        return self::$_content !== null;
    }

    /**
     * Obtiene el view.
     *
     * @return string path del view
     */
    protected static function getView()
    {
        $file = APP_PATH.'views/'.self::getPath();
        //Si no existe el view y es scaffold
        if (!is_file($file) && ($scaffold = self::$_controller['scaffold'] ?? null)) {
            $file = APP_PATH."views/_shared/scaffolds/$scaffold/".self::$_view.'.phtml';
        }

        return $file;
    }

    /**
     * Cachea el view o template.
     *
     * @param string $type view o template
     * 
     * @return void
     */
    protected static function saveCache($type)
    {
        // si esta en produccion y se cachea la vista
        if (PRODUCTION && self::$_cache['type'] === $type) {
            Cache::driver()->save(ob_get_contents(), self::$_cache['time'], Router::get('route'), self::$_cache['group']);
        }
    }

    /**
     * Renderiza la vista.
     *
     * @param Controller $controller
     * 
     * @return void
     */
    public static function render(Controller $controller)
    {
        if (!self::$_view && !self::$_template) {
            ob_end_flush();

            return; 
        }

        // Guarda los datos del controlador y los envia
        self::generate(self::$_controller = get_object_vars($controller));
    }

    /**
     * Genera la vista.
     *
     * @param array $controller
     * 
     * @return void
     */
    protected static function generate($controller)
    {
        // Registra la autocarga de helpers
        spl_autoload_register('kumbia_autoload_helper', true, true);
        // Mapea los atributos del controller en el scope
        extract($controller, EXTR_OVERWRITE);

        // carga la vista si tiene view y no esta cacheada
        if (self::$_view && self::$_content === null) {
            // Carga el contenido del buffer de salida
            self::$_content = ob_get_clean();
            // Renderizar vista
            ob_start();

            // carga la vista
            if (!include self::getView()) {
                throw new KumbiaException('Vista "'.self::getPath().'" no encontrada', 'no_view');
            }

            // si esta en produccion y se cachea la vista
            self::saveCache('view');

            // Verifica si hay template
            if (!self::$_template) {
                ob_end_flush();

                return;
            }

            self::$_content = ob_get_clean();
        }

        // Renderizar template
        if ($__template = self::$_template) {
            ob_start();

            // carga el template
            if (!include APP_PATH."views/_shared/templates/$__template.phtml") {
                throw new KumbiaException("Template $__template no encontrado");
            }

            // si esta en produccion y se cachea template
            self::saveCache('template');
            ob_end_flush();

            return;
        }

        echo self::$_content;
    }

    /**
     * Imprime el contenido del buffer.
     * 
     * @return void
     */
    public static function content()
    {
        if (isset($_SESSION['KUMBIA.CONTENT'])) {
            echo $_SESSION['KUMBIA.CONTENT'];
            unset($_SESSION['KUMBIA.CONTENT']);
        }
        echo self::$_content;
    }

    /**
     * Renderiza una vista parcial.
     *
     * @throw KumbiaException
     * @param  string            $partial vista a renderizar
     * @param  string            $__time  tiempo de cache
     * @param  array|string|null $params  variables para el partial
     * @param  string            $group   grupo de cache
     * @return void
     */
    public static function partial($partial, $__time = '', $params = null, $group = 'kumbia.partials')
    {
        if (PRODUCTION && $__time && !Cache::driver()->start($__time, $partial, $group)) {
            return;
        }

        //Verificando el partials en el dir app
        $__file = APP_PATH."views/_shared/partials/$partial.phtml";

        if (!is_file($__file)) {
            //Verificando el partials en el dir core
            $__file = CORE_PATH."views/partials/$partial.phtml";
        }

        if ($params) {
            if (is_string($params)) {
                $params = Util::getParams(explode(',', $params));
            }

            // carga los parametros en el scope
            extract($params, EXTR_OVERWRITE);
        }

        // carga la vista parcial
        if (!include $__file) {
            throw new KumbiaException('Vista Parcial "'.$__file.'" no encontrada', 'no_partial');
        }

        // se guarda en la cache de ser requerido
        if (PRODUCTION && $__time) {
            Cache::driver()->end();
        }
    }

    /**
     * Obtiene el valor de un atributo público o todos del controlador.
     *
     * @param string $var nombre de variable
     *
     * @return mixed valor de la variable
     */
    public static function getVar($var = '')
    {
        if (!$var) {
            return self::$_controller;
        }

        return self::$_controller[$var] ?? null;
    }
}

/**
 * Atajo para htmlspecialchars, por defecto toma el charset de la
 * aplicacion.
 *
 * @param string $string
 * @param string $charset
 *
 * @return string
 */
function h($string, $charset = APP_CHARSET)
{
    return htmlspecialchars($string, ENT_QUOTES, $charset);
}