|
|
|
<?php
|
|
|
|
/*
|
|
|
|
* Copyright © 2021 ExacTI Technology Solutions. All rights reserved.
|
|
|
|
* GPLv3 General License.
|
|
|
|
* https://exacti.com.br
|
|
|
|
* Phacil PHP Framework - https://github.com/exacti/phacil-framework
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Phacil\Framework;
|
|
|
|
|
|
|
|
use Phacil\Framework\Config;
|
|
|
|
use Phacil\Framework\Registry;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extend this class to create interation with your module controller to Phacil engine controller.
|
|
|
|
*
|
|
|
|
* Use as:
|
|
|
|
* <code>
|
|
|
|
* <?php
|
|
|
|
* namespace YourPrefix\Path\Controller;
|
|
|
|
* class YouClass extends \Phacil\Framework\Controller {
|
|
|
|
* public function index() {
|
|
|
|
* #Your code
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* </code>
|
|
|
|
*
|
|
|
|
* You can use the __construct function on call the \Phacil\Framework\Register object inside parent.
|
|
|
|
*
|
|
|
|
* <code>
|
|
|
|
* public funcion __construct(\Phacil\Framework\Registry $registry){ parent::__construct($registry); YOUR_CODE; }
|
|
|
|
* </code>
|
|
|
|
*
|
|
|
|
* @abstract
|
|
|
|
* @package Phacil\Framework
|
|
|
|
* @since 0.1.0
|
|
|
|
* @api
|
|
|
|
*/
|
|
|
|
abstract class Controller implements \Phacil\Framework\Interfaces\Controller {
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var Registry
|
|
|
|
*/
|
|
|
|
protected $registry;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var int
|
|
|
|
*/
|
|
|
|
protected $id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var mixed
|
|
|
|
*/
|
|
|
|
protected $layout;
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The template path
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $template;
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The childrens parts of the controller
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $children = array();
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The variables of controller
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $data = array();
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The twig aditional funcions created by your!
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $twig = array();
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The errors array
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $error = array();
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* The rendered output
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $output;
|
|
|
|
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
/**
|
|
|
|
* The original route of childrens
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $routeOrig;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The output content type
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $contentType = 'text/html; charset=utf-8';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements constructor.
|
|
|
|
*
|
|
|
|
* If you use this, don't forget the parent::__construct($registry);
|
|
|
|
*
|
|
|
|
* @param \Phacil\Framework\Registry $registry
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function __construct(\Phacil\Framework\Registry $registry = null) {
|
|
|
|
if (!$registry) {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var \Phacil\Framework\Registry
|
|
|
|
*/
|
|
|
|
$registry = \Phacil\Framework\Registry::getInstance();
|
|
|
|
}
|
|
|
|
$this->registry = &$registry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return void */
|
|
|
|
private function __getRegistryClass(){
|
|
|
|
$this->registry = \Phacil\Framework\startEngineExacTI::getRegistry();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* {@inheritdoc}
|
|
|
|
*/
|
|
|
|
static public function getInstance() {
|
|
|
|
$class = get_called_class();
|
|
|
|
return \Phacil\Framework\Registry::getAutoInstance((new $class()));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @return object
|
|
|
|
* @final
|
|
|
|
*/
|
|
|
|
final public function __get($key) {
|
|
|
|
if (!$this->registry) {
|
|
|
|
$this->__getRegistryClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->registry->get($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @return object
|
|
|
|
* @final
|
|
|
|
* @todo Not yet...
|
|
|
|
*/
|
|
|
|
/* final public function __call($key, array $arguments) {
|
|
|
|
if (!$this->registry) {
|
|
|
|
$this->__getRegistryClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->registry->get($key);
|
|
|
|
} */
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param string $key
|
|
|
|
* @param object $value
|
|
|
|
* @return void
|
|
|
|
* @final
|
|
|
|
*/
|
|
|
|
final public function __set($key, $value) {
|
|
|
|
if(!$this->registry) {
|
|
|
|
$this->__getRegistryClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->registry->set($key, $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $route
|
|
|
|
* @param array $args
|
|
|
|
* @return \Phacil\Framework\Interfaces\Action
|
|
|
|
* @final
|
|
|
|
*/
|
|
|
|
final protected function forward($route, array $args = array()) {
|
|
|
|
return new Action($route, $args);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* Send redirect HTTP header to specified URL
|
|
|
|
*
|
|
|
|
* Use the \Phacil\Framework\Response::redirect() registered object.
|
|
|
|
*
|
|
|
|
* @param string $url
|
|
|
|
* @param int $status
|
|
|
|
* @return never
|
|
|
|
* @final
|
|
|
|
*/
|
|
|
|
final protected function redirect($url, $status = 302) {
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
$this->registry->response->redirect($url, $status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
* Get and load the childrens controller classes
|
|
|
|
*
|
|
|
|
* @final
|
|
|
|
* @param string $child
|
|
|
|
* @param array $args
|
|
|
|
* @return object
|
|
|
|
*/
|
|
|
|
final protected function getChild($child, array $args = array()) {
|
|
|
|
$action = new Action($child, $args);
|
|
|
|
$file = $action->getFile();
|
|
|
|
$class = $action->getClass();
|
|
|
|
$classAlt = $action->getClassAlt();
|
|
|
|
$method = $action->getMethod();
|
|
|
|
|
|
|
|
if ($file && file_exists($file)) {
|
|
|
|
require_once($file);
|
|
|
|
|
|
|
|
foreach($classAlt as $classController){
|
|
|
|
try {
|
|
|
|
if(class_exists($classController)){
|
|
|
|
$this->registry->routeOrig = $child;
|
|
|
|
$controller = $this->registry->injectionClass($classController);
|
|
|
|
//$controller = new $classController($this->registry);
|
|
|
|
if (is_callable([$controller, $method])) {
|
|
|
|
call_user_func_array(array($controller, $method), $args);
|
|
|
|
} else {
|
|
|
|
throw new \Phacil\Framework\Exception("Error Processing Request", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (\Phacil\Framework\Exception\Throwable $th) {
|
|
|
|
throw $th;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->registry->routeOrig = null;
|
|
|
|
|
|
|
|
return $controller->output;
|
|
|
|
|
|
|
|
} elseif (!$file && isset($classAlt['class']) && !empty($classAlt['class']) && class_exists($classAlt['class'])) {
|
|
|
|
try {
|
|
|
|
$this->registry->routeOrig = $child;
|
|
|
|
$controller = $this->registry->injectionClass($classAlt['class']);
|
|
|
|
if (is_callable(array($controller, $method))) {
|
|
|
|
call_user_func_array(array($controller, $method), $args);
|
|
|
|
} else {
|
|
|
|
throw new \Phacil\Framework\Exception("Error Processing Request", 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->registry->routeOrig = null;
|
|
|
|
|
|
|
|
return $controller->output;
|
|
|
|
} catch (\Phacil\Framework\Exception\Throwable $th) {
|
|
|
|
throw ($th);
|
|
|
|
}
|
|
|
|
} else {
|
Controller child exception, Log, Response and Login
Action PHPDoc improvements, Controller child exception, Log new functions (getpath, getfilename, head and tail), log class check dir and creates if not exists, Response redirect improvement, Controller redirect function use the response redirect class, login interface documentation, login doc
3 years ago
|
|
|
throw new Exception("Could not load controller " . $child . '!', 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Render template
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
* @throws TypeError
|
|
|
|
* @throws Exception
|
|
|
|
* @final
|
|
|
|
*/
|
|
|
|
protected function render() {
|
|
|
|
|
|
|
|
foreach ($this->children as $key => $child) {
|
|
|
|
$this->data[(is_string($key) ? $key : basename($child))] = $this->getChild($child);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var \Phacil\Framework\Render
|
|
|
|
*/
|
|
|
|
$tpl = $this->registry->getInstance(\Phacil\Framework\Render::class);
|
|
|
|
|
|
|
|
$pegRout = explode("/", ($this->registry->routeOrig)?: \Phacil\Framework\startEngineExacTI::getRoute());
|
|
|
|
|
|
|
|
if($this->template === NULL) {
|
|
|
|
$thema = ($this->config->get("config_template") != NULL) ? $this->config->get("config_template") : "default";
|
|
|
|
|
|
|
|
$noCaseFunction = function ($str) {
|
|
|
|
return \Phacil\Framework\Registry::case_insensitive_pattern($str);
|
|
|
|
};
|
|
|
|
|
|
|
|
//Just template not set manual
|
|
|
|
$routePatterned = array_map($noCaseFunction, $pegRout);
|
|
|
|
$routeWithoutLastPatterned = $routePatterned;
|
|
|
|
$lastRoutePatterned = array_pop($routeWithoutLastPatterned);
|
|
|
|
//$routeWithoutFirstPatterned = $routePatterned;
|
|
|
|
//$firstRoutePatterned = array_shift($routeWithoutFirstPatterned);
|
|
|
|
|
|
|
|
$structure = [];
|
|
|
|
|
|
|
|
if ($thema != "default")
|
|
|
|
$structure[self::TEMPLATE_AREA_THEME][] = $thema . '/' . implode("/", $routePatterned);
|
|
|
|
|
|
|
|
$structure[self::TEMPLATE_AREA_THEME][] = 'default/' . implode("/", $routePatterned);
|
|
|
|
|
|
|
|
$positions = 2;
|
|
|
|
|
|
|
|
for ($i=1; $i <= $positions; $i++) {
|
|
|
|
if(count($routePatterned) <= ($i)) break;
|
|
|
|
|
|
|
|
$mount = $routePatterned;
|
|
|
|
array_splice($mount, $i, 0, 'View');
|
|
|
|
$structure[self::TEMPLATE_AREA_MODULAR][] = implode("/", $mount);
|
|
|
|
|
|
|
|
if(($i+1) < count($routePatterned))
|
|
|
|
$structure[self::TEMPLATE_AREA_MODULAR][] = implode("/", array_slice($mount, 0, -1)). "_" .end($mount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count($routePatterned) > 2) {
|
|
|
|
//Old compatibility
|
|
|
|
if($thema != "default")
|
|
|
|
$structure[self::TEMPLATE_AREA_THEME][] = $thema . '/' . implode("/", $routeWithoutLastPatterned) . '_' . $lastRoutePatterned ;
|
|
|
|
|
|
|
|
$structure[self::TEMPLATE_AREA_THEME][] = 'default/' . implode("/", $routeWithoutLastPatterned) . '_' . $lastRoutePatterned;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if theme exists
|
|
|
|
$findThemeFile = (function(array $structure, $pathArea) use ($tpl) {
|
|
|
|
foreach ($structure as $themefile) {
|
|
|
|
$types = [
|
|
|
|
'modular' => $pathArea . $themefile,
|
|
|
|
];
|
|
|
|
$files['modular'] = null;
|
|
|
|
foreach ($types as $type => $globs) {
|
|
|
|
foreach ($tpl->getTemplateTypes() as $extensionTemplate) {
|
|
|
|
$files[$type] = glob($globs . "." . $extensionTemplate, GLOB_BRACE);
|
|
|
|
if (count($files[$type]) > 0) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (empty($files['modular'])) continue;
|
|
|
|
if (!empty($files['modular'])) {
|
|
|
|
foreach ($files['modular'] as $modular) {
|
|
|
|
$this->template = str_replace($pathArea, "", $modular);
|
|
|
|
return $templatePath = $pathArea;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!empty($this->template)) break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$templatePath = $findThemeFile($structure[self::TEMPLATE_AREA_THEME], Config::DIR_TEMPLATE()) ?: $findThemeFile($structure[self::TEMPLATE_AREA_MODULAR], Config::DIR_APP_MODULAR());
|
|
|
|
} else {
|
|
|
|
if(file_exists(Config::DIR_APP_MODULAR(). $pegRout[0] ."/View/" .$this->template)){
|
|
|
|
$templatePath = Config::DIR_APP_MODULAR(). $pegRout[0] ."/View/";
|
|
|
|
} else {
|
|
|
|
$filesSeted = glob(
|
|
|
|
Config::DIR_APP_MODULAR() .
|
|
|
|
\Phacil\Framework\Registry::case_insensitive_pattern($pegRout[0])
|
|
|
|
. "/View/" . $this->template,
|
|
|
|
GLOB_BRACE
|
|
|
|
);
|
|
|
|
|
|
|
|
if (count($filesSeted) > 0) {
|
|
|
|
$templatePath = str_replace($this->template, "", $filesSeted[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(file_exists(Config::DIR_TEMPLATE() .$this->template)){
|
|
|
|
$templatePath = Config::DIR_TEMPLATE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(empty($this->template)) {
|
|
|
|
throw new Exception('Error: template not seted!');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_readable($templatePath . $this->template)) {
|
|
|
|
|
|
|
|
$templateFileInfo = pathinfo($templatePath .$this->template);
|
|
|
|
$templateType = $templateFileInfo['extension'];
|
|
|
|
|
|
|
|
$tpl->setTemplate($templateType, $templatePath, $this->template, $this->data, $this->twig);
|
|
|
|
|
|
|
|
$this->registry->response->addHeader('Content-Type', $this->contentType);
|
|
|
|
|
|
|
|
$this->output = $tpl->render();
|
|
|
|
|
|
|
|
unset($tpl);
|
|
|
|
|
|
|
|
return $this->output;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
throw new Exception('Error: Could not load template ' . $templatePath . $this->template . '!');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param bool $commonChildren (optional) Whether to include the common children (common/header and common/footer)
|
|
|
|
* @return \Phacil\Framework\Response
|
|
|
|
* @throws Exception
|
|
|
|
* @since 1.1.0
|
|
|
|
*/
|
|
|
|
protected function out ($commonChildren = true) {
|
|
|
|
if($commonChildren === true){
|
|
|
|
$this->children = array_merge(
|
|
|
|
self::DEFAULT_CHILDREN,
|
|
|
|
$this->children
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->response->setOutput($this->render());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add child to render
|
|
|
|
*
|
|
|
|
* @param string $route Route for render child
|
|
|
|
* @param string $name (Optional) Name for use as variable in template. If empty, the last word of route path will be used as the name.
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
protected function addChild($route, $name = null) {
|
|
|
|
if(!empty($name) && is_string($name)){
|
|
|
|
$this->children[$name] = $route;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
$this->children[] = $route;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|