From a61a136fc606e89b2e9b2b124c3c94fed90c1cb2 Mon Sep 17 00:00:00 2001 From: "Bruno O. Notario" Date: Sun, 15 Aug 2021 20:25:00 -0300 Subject: [PATCH] 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 --- system/engine/controller.php | 32 +++-- system/engine/exception.php | 4 + system/engine/interfaces/action.php | 11 +- system/engine/log.php | 178 ++++++++++++++++++++++++++-- system/engine/response.php | 7 +- system/engine/traits/action.php | 10 +- system/login/interfaces/login.php | 43 +++++++ 7 files changed, 262 insertions(+), 23 deletions(-) diff --git a/system/engine/controller.php b/system/engine/controller.php index 53469b5..91eb9d2 100644 --- a/system/engine/controller.php +++ b/system/engine/controller.php @@ -57,47 +57,58 @@ abstract class Controller { protected $layout; /** + * The template path * * @var string */ protected $template; /** + * The childrens parts of the controller * * @var array */ protected $children = array(); /** + * The variables of controller * * @var array */ protected $data = array(); /** + * The twig aditional funcions created by your! * * @var array */ protected $twig = array(); /** + * The errors array * * @var array */ protected $error = array(); /** + * The rendered output * * @var string */ protected $output; /** + * Allowed template types * * @var string[] */ public $templateTypes = ["tpl", "twig", "mustache", "smarty", "phtml"]; + /** + * The original route of childrens + * @var string + */ public $routeOrig; /** @@ -116,9 +127,9 @@ abstract class Controller { */ global $engine; - $registry = $engine->registry; + $registry =& $engine->registry; } - $this->registry = $registry; + $this->registry =& $registry; } /** @@ -153,18 +164,22 @@ abstract class Controller { } /** + * 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) { - header('Status: ' . $status); - header('Location: ' . str_replace('&', '&', $url)); - exit(); + final protected function redirect($url, int $status = 302) { + $this->registry->response->redirect($url, $status); } /** + * Get and load the childrens controller classes + * * @final * @param string $child * @param array $args @@ -199,8 +214,9 @@ abstract class Controller { return $controller->output; } else { - trigger_error('Error: Could not load controller ' . $child . '!'); - exit(); + throw new Exception("Could not load controller " . $child . '!', 1); + + //exit(); } } diff --git a/system/engine/exception.php b/system/engine/exception.php index 8afb3fd..268e4a2 100644 --- a/system/engine/exception.php +++ b/system/engine/exception.php @@ -13,6 +13,10 @@ namespace Phacil\Framework; class Exception extends \Exception { + /** + * Save the exceptions in the exceptions log file + * @return void + */ public function __destruct() { $log = new \Phacil\Framework\Log("exception.log"); diff --git a/system/engine/interfaces/action.php b/system/engine/interfaces/action.php index 10a13f6..280db7f 100644 --- a/system/engine/interfaces/action.php +++ b/system/engine/interfaces/action.php @@ -20,15 +20,18 @@ interface Action { /** * Return the controller file path * - * @return string */ + * @since 1.0.0 + * @return string + */ public function getFile(); /** * Return the class of controller * - * @deprecated 2.0.0 This method return only legacy class. user getClassAlt instead. + * @deprecated 2.0.0 This method return only legacy class. Use getClassAlt instead. * @see \Phacil\Framework\Interfaces\Action::getClassAlt() * + * @since 1.0.0 * @return string */ public function getClass(); @@ -41,7 +44,9 @@ interface Action { public function setClass($class); /** - * Get all classes for the new 2.0 framework version + * Get all possible classes for controller in the new 2.0 framework version + * + * @since 2.0.0 * * @return array */ diff --git a/system/engine/log.php b/system/engine/log.php index acd1f22..9304101 100644 --- a/system/engine/log.php +++ b/system/engine/log.php @@ -8,34 +8,194 @@ namespace Phacil\Framework; -/** @package Phacil\Framework */ +/** + * The principal log class for this framework + * + * @param string $filename (optional) The name of log file. The path is automatic defined in the DIR_LOGS constant in config file. Isn't not possible to change the path. The default name is error.log. + * @package Phacil\Framework + */ final class Log { /** + * Storage the object of log file * * @var resource|false */ + private $fileobj; + + /** + * Storage the filename + * + * @var string + */ private $filename; - + + /** + * Storage the path + * + * @var string + */ + private $filepath; + /** - * @param string $filename + * @param string $filename (optional) The name of log file. The path is automatic defined in the DIR_LOGS constant in config file. Isn't not possible to change the path. The default name is error.log. * @return void */ public function __construct($filename = "error.log") { - $this->filename = fopen(DIR_LOGS . $filename, 'a+'); + $this->filename = $filename; + $this->filepath = DIR_LOGS . $filename; + if(!is_dir(DIR_LOGS)){ + $old = umask(0); + mkdir(DIR_LOGS, 0764, true); + umask($old); + } + if(!is_writable(DIR_LOGS)){ + trigger_error('The '.DIR_LOGS.' folder must to be writeable!', E_USER_ERROR); + } + $this->fileobj = fopen($this->filepath, 'a+'); return; } - + /** + * Write the error message in the log file + * * @param string $message - * @return void + * @return int|false + * @since 1.0.0 */ public function write($message) { - fwrite($this->filename, date('Y-m-d G:i:s') . ' - ' . print_r($message, true)." | ".$_SERVER['REQUEST_URI'] . PHP_EOL); + return fwrite($this->fileobj, date('Y-m-d G:i:s') . ' - ' . print_r($message, true)." | ".$_SERVER['REQUEST_URI'] . PHP_EOL); } - /** @return void */ + /** + * Remove object from memory + * + * @since 1.0.0 + * @return void + */ public function __destruct() { - fclose($this->filename); + fclose($this->fileobj); + } + + /** + * Return the log file name + * + * @since 2.0.0 + * @return string + */ + public function getFileName() + { + return $this->filename; + } + + /** + * Return the log file path + * + * @since 2.0.0 + * @return string + */ + public function getFilePath() + { + return $this->filepath; + } + + /** + * Return last lines of log archive + * + * @param string|null $filepath (optional) Path of file. Default is the log file. + * @param int $lines (optional) Lines to be readed. Default value is 10. + * @param bool $adaptive (optional) Default value is true. + * @return false|string + * @since 2.0.0 + */ + public function tail($filepath = null, int $lines = 10, bool $adaptive = true) + { + + // Open file + $f = @fopen(($filepath ?: $this->filepath), "rb"); + if ($f === false) return false; + + // Sets buffer size + if (!$adaptive) + $buffer = 4096; + else + $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096)); + + // Jump to last character + fseek($f, -1, SEEK_END); + + // Read it and adjust line number if necessary + // (Otherwise the result would be wrong if file doesn't end with a blank line) + if (fread($f, 1) != "\n") $lines -= 1; + + // Start reading + $output = ''; + $chunk = ''; + + // While we would like more + while (ftell($f) > 0 && $lines >= 0) { + + // Figure out how far back we should jump + $seek = min(ftell($f), $buffer); + + // Do the jump (backwards, relative to where we are) + fseek($f, -$seek, SEEK_CUR); + + // Read a chunk and prepend it to our output + $output = ($chunk = fread($f, $seek)) . $output; + + // Jump back to where we started reading + fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR); + + // Decrease our line counter + $lines -= substr_count($chunk, "\n"); + } + + // While we have too many lines + // (Because of buffer size we might have read too many) + while ($lines++ < 0) { + + // Find first newline and remove all text before that + $output = substr($output, strpos($output, "\n") + 1); + } + + // Close file and return + fclose($f); + return trim($output); + } + + /** + * Return first lines of log archive + * + * @param string|null $filepath (optional) Path of file. Default is the log file. + * @param int $lines (optional) Lines to be readed. Default value is 10. + * @param bool $adaptive (optional) Default value is true. + * @return false|string + * @since 2.0.0 + */ + public function head($filepath = null, int $lines = 10, bool $adaptive = true) + { + + // Open file + $f = @fopen(($filepath ?: $this->filepath), "rb"); + if ($f === false) return false; + + // Sets buffer size + /* if (!$adaptive) + $buffer = 4096; + else + $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096)); */ + + // Start reading + $output = ''; + while (($line = fgets($f)) !== false) { + if (feof($f)) break; + if ($lines-- == 0) break; + $output .= $line . ""; + } + + // Close file and return + fclose($f); + return trim($output); } } diff --git a/system/engine/response.php b/system/engine/response.php index a8114f4..cf96810 100644 --- a/system/engine/response.php +++ b/system/engine/response.php @@ -47,10 +47,15 @@ final class Response { } /** + * Send redirect HTTP header to specified URL + * * @param string $url + * @param int $status * @return never */ - public function redirect($url) { + public function redirect($url, int $status = 302) + { + header('Status: ' . $status); header('Location: ' . $url); exit; } diff --git a/system/engine/traits/action.php b/system/engine/traits/action.php index d7d1af7..e174689 100644 --- a/system/engine/traits/action.php +++ b/system/engine/traits/action.php @@ -18,32 +18,38 @@ namespace Phacil\Framework\Traits; trait Action { /** + * Storage the file to be loaded * * @var string */ protected $file; /** + * Storage the class to be loaded * * @var string */ protected $class; /** + * Storage the method to be called * * @var string */ protected $method; /** + * Storage the method args * * @var array */ protected $args = array(); /** + * Storage the all possible controller classes * - * @var (string[]|string|null)[] + * @since 2.0.0 + * @var (string[]|string|array|null)[] */ private $classAlt = []; @@ -53,7 +59,7 @@ trait Action { } /** - * @deprecated 2.0.0 This method return only legacy class. user getClassAlt instead. + * @deprecated 2.0.0 This method return only legacy class. Use getClassAlt instead. * @inheritdoc */ public function getClass() { return $this->class; diff --git a/system/login/interfaces/login.php b/system/login/interfaces/login.php index c6a3681..eed01ab 100644 --- a/system/login/interfaces/login.php +++ b/system/login/interfaces/login.php @@ -8,17 +8,60 @@ namespace Phacil\Framework\Login\Interfaces; +use Phacil\Framework\Registry; + +/** + * Login interface + * + * @since 2.0.0 + * @package Phacil\Framework\Login\Interfaces + */ interface Login { + /** + * @param string $authorizedUsers + * @param Registry|null $registry + * @return void + */ public function __construct($authorizedUsers, \Phacil\Framework\Registry $registry = null); + /** + * Restrict Access To Page: Grant or deny access to this page + * + * @param string $strUsers + * @param string $strGroups + * @param string $UserName + * @param string $UserGroup + * @return bool + */ public function isAuthorized($strUsers, $strGroups, $UserName, $UserGroup); + /** + * Check if is logged on MM_Username session and, if isn't, go to $restrictGoTo URL + * + * @param string $restrictGoTo URL that send the user for login + * @return void + */ public function check($restrictGoTo); + /** + * Check is logged + * + * @return bool + */ public function isLogged(); + /** + * Destroy the login session + * + * @return void + */ public function logout(); + /** + * Return the login Username + * + * @return string + */ public function getUserName(); } \ No newline at end of file