From accda2f3566f1805217b4429644b5d2694114147 Mon Sep 17 00:00:00 2001 From: Artur Welp Date: Wed, 19 Aug 2026 11:30:57 -0300 Subject: [PATCH] Minor changes --- src/RR/Flash.php | 248 ++++++++++++++++++++++++++-------------- src/RR/MessageTypes.php | 19 +++ src/RR/ParamType.php | 11 ++ src/RR/Request.php | 219 ++++++++++++++++++++++++++++------- src/RR/Response.php | 170 +++++++++++++++++---------- 5 files changed, 486 insertions(+), 181 deletions(-) create mode 100644 src/RR/MessageTypes.php create mode 100644 src/RR/ParamType.php diff --git a/src/RR/Flash.php b/src/RR/Flash.php index 7c7981e..73aa924 100755 --- a/src/RR/Flash.php +++ b/src/RR/Flash.php @@ -1,51 +1,47 @@ 'error', - self::WARNING => 'warning', - self::SUCCESS => 'success', - self::INFO => 'info', - ]; - - public $oldMessages = Array(); - public $newMessages = Array(); - public $_flashes = Array(); + public $flashes = Array(); + public $nextFlashes = Array(); //SINGLETON============================================== - private function __construct(){ + private function __construct(): void + { if(session_id() == '' || !isset($_SESSION)) { session_start(); } - if( isset($_SESSION['flashes']) ){ - $this->oldMessages = $_SESSION['flashes']; + + if( isset($_SESSION[self::FLASH_SESSION_NAME]) ){ + $this->flashes = $_SESSION[self::FLASH_SESSION_NAME]; } - unset( $_SESSION[self::SESSION_NAME] ); + + // The messages are in memory. So clear the $_SESSION + $_SESSION[self::FLASH_SESSION_NAME] = Array(); } - private static function newObj(){ + private static function newObj(): Flash + { if (!isset( self::$_instance )) { self::$_instance = new Flash(); } return self::$_instance; } - public static function getInstance(){ + public static function getInstance(): Flash + { if (!isset(self::$_instance)) { return self::newObj(); } @@ -54,103 +50,189 @@ class Flash{ //======================================================= - public function merge(){ - $this->_flashes = array_merge_recursive($this->newMessages, $this->oldMessages); - } - - public function loadToSession(){ - $_SESSION[self::SESSION_NAME] = $this->newMessages; - } - - /* - * - * @ctag Flash:addMessage(); - * @ctag Flash:addMessage(Flash::FLASH_INFO, ''); - * @ctag Flash:addMessage(Flash::FLASH_SUCCESS, ''); - * @ctag Flash:addMessage(Flash::FLASH_WARNING, ''); - * @ctag Flash:addMessage(Flash::FLASH_ERROR, ''); - * - */ - public static function addMessage($type = self::defaultType, $message){ - $instance = self::getInstance(); - $instance->newMessages[$type] = $message; - $instance->loadToSession(); - } - /** + * Load the stored messages for this session to the $_SESSION varible + * to be used on the next request * - * @ctag Flash::addInfo(''); - * + * @return Flash */ - public static function addInfo($message){ + private function loadToSession(): Flash + { $instance = self::getInstance(); - $instance->newMessages[self::INFO] = $message; - $instance->loadToSession(); + $_SESSION[self::FLASH_SESSION_NAME] = array_merge_recursive($_SESSION[self::FLASH_SESSION_NAME], $instance->nextFlashes); + $instance->nextFlashes = Array(); + + return $this; } /** + * Add a message to the session with the INFO type * - * @ctag Flash::addError(''); + * @param string $message * + * @return Flash */ - public static function addError($message){ + public static function addInfo(string $message): Flash + { $instance = self::getInstance(); - $instance->newMessages[self::ERROR] = $message; + $instance->nextFlashes[MessageType::INFO->value][] = $message; $instance->loadToSession(); + + return $instance; } /** + * Add a message from a specific type on the session * - * @ctag Flash::getErrors(); + * @param MessageType $type + * @param string $message * + * @return Flash */ - public static function getErrors(){ - if(!self::hasErrors()){ + public static function addMessage(string $message, MessageType $type = MessageType::INFO): Flash + { + $instance = self::getInstance(); + $instance->nextFlashes[$type->value][] = $message; + $instance->loadToSession(); + + return $instance; + } + + /** + * Add a message to the session with the SUCCESS type + * + * @param string $message + * + * @return Flash + */ + public static function addSuccess(string $message): Flash + { + $instance = self::getInstance(); + $instance->nextFlashes[MessageType::SUCCESS->value][] = $message; + $instance->loadToSession(); + + return $instance; + } + + /** + * Add a message to the session with the WARNING type + * + * @param string $message + * + * @return Flash + */ + public static function addWarning(string $message): Flash + { + $instance = self::getInstance(); + $instance->nextFlashes[MessageType::WARNING->value][] = $message; + $instance->loadToSession(); + + return $instance; + } + + /** + * Add a message to the session with the ERROR type + * + * @param string $message + * + * @return Flash + */ + public static function addError(string $message): Flash + { + $instance = self::getInstance(); + $instance->nextFlashes[MessageType::ERROR->value][] = $message; + $instance->loadToSession(); + + return $instance; + } + + /** + * Check if there is messages from a type on the collection + * + * @param MessageType $type + * + * @return bool + */ + public static function hasMessageType(MessageType $type = MessageType::INFO): bool + { + $instance = self::getInstance(); + + if(array_key_exists($type->value, $instance->flashes)){ + return true; + } + + return false; + } + + + /** + * Return all messages from a type + * + * @param MessageType $type + */ + public static function getMessages(MessageType $type = MessageType::INFO): Array + { + if(!self::hasMessageType($type)){ return Array(); } - return self::getInstance()->_flashes[self::ERROR]; + + return self::getInstance()->flashes[$type->value]; } /** + * Return all info messages registered on the collection * - * @ctag Flash::addInfos(); - * + * @return Array */ - public static function getInfos(){ - if(!self::hasInfo()){ + public static function getInfos(): Array + { + if(!self::hasMessageType(MessageType::INFO)){ return Array(); } - return self::getInstance()->_flashes[self::INFO]; + + return self::getInstance()->flashes[MessageType::INFO->value]; } /** + * Return all success messages registered on the collection * - * @ctag Flash::addErrors(); - * + * @return Array */ - public static function hasErrors(){ - $instance = self::getInstance(); - $instance->merge(); - if( array_key_exists(self::ERROR, $instance->_flashes ) ){ - return true; - }else{ - return false; + public static function getSuccess(): Array + { + if(!self::hasMessageType(MessageType::SUCCESS)){ + return Array(); } + + return self::getInstance()->flashes[MessageType::SUCCESS->value]; } /** + * Return all warning messages registered on the collection * - * @ctag Flash::hasInfo(); - * + * @return Array */ - public static function hasInfo(){ - $instance = self::getInstance(); - $instance->merge(); - if( array_key_exists(self::INFO, $instance->_flashes ) ){ - return true; - }else{ - return false; + public static function getWarning(): Array + { + if(!self::hasMessageType(MessageType::WARNING)){ + return Array(); } + + return self::getInstance()->flashes[MessageType::WARNING->value]; + } + + /** + * Return all error messages registered on the collection + * + * @return Array + */ + public static function getError(): Array + { + if(!self::hasMessageType(MessageType::ERROR)){ + return Array(); + } + + return self::getInstance()->flashes[MessageType::ERROR->value]; } } diff --git a/src/RR/MessageTypes.php b/src/RR/MessageTypes.php new file mode 100644 index 0000000..624b7bd --- /dev/null +++ b/src/RR/MessageTypes.php @@ -0,0 +1,19 @@ + $option){ self::$key($param, $option); }*/ return $param; } - public static function requiredParamArray($parname, $type, $default = '', $options = Array() ){ - // POST has precedence. + /** + * Search a array param on the GET/POST array + * If the key is not found, we throw a `required_param_not_found` Exception + * + * @param strig $paramname + * @param ParamType $type + * @param Array $options + * + * @return mixed + * @throws \Exception + */ + public static function requiredParamArray( + string $parname, + $options = Array() + ): mixed { + if (isset($_POST[$parname])) { + $param = $_POST[$parname]; + } else if (isset($_GET[$parname])) { + $param = $_GET[$parname]; + } else { + throw new \Exception('required_param_not_found'); + } + return $param; + } + + /** + * Search a array param on the GET/POST array + * If the key is not found we return the default value + * + * If the default $value type is not the same of the $type + * Wwe throw a `default_value_type_missmatch` Exception + * + * @param strig $paramname + * @param ParamType $type + * @param mixed $default + * @param Array $options + * + * @return mixed + * @throws \Exception + */ + public static function optionalParam( + string $parname, + ParamType $type = ParamType::INT, + mixed $default = "", + $options = Array(), + ): mixed { if (isset($_POST[$parname])) { $param = $_POST[$parname]; } else if (isset($_GET[$parname])) { @@ -39,52 +98,134 @@ class Request{ return $param; } - public static function optionalParam($parname, $type, $default = '', $options = Array()){ - // POST has precedence. - if (isset($_POST[$parname])) { - $param = $_POST[$parname]; - } else if (isset($_GET[$parname])) { - $param = $_GET[$parname]; - } else { - return $default; + /** + * NOT IMPLEMENTED YET + * Search a array param on the GET/POST array + * + * @param strig $paramname + * @param Array $default + * @param Array $options + * + * @todo Implement + * + * @return Array + */ + public static function optionalParamArray( + string $parname, + Array $default = Array(), + $options = Array() + ): Array{ + // Not implemented yet + return $default; + } + + /** + * Try to detect if the request came from AJAX/FETCH/POSTMAN + * in this cases, we might want to return something else + * + * @return bool + */ + public static function detectAjaxRequest(): bool + { + if ( + isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest' + ) { + return true; } - return $param; + + if ( + isset($_SERVER['CONTENT_TYPE']) && + str_contains( + strtolower($_SERVER['CONTENT_TYPE']), + 'application/json' + ) + ) { + return true; + } + + // Detecta ferramentas conhecidas + $userAgent = strtolower($_SERVER['HTTP_USER_AGENT'] ?? ''); + + if ( + str_contains($userAgent, 'postman') || + str_contains($userAgent, 'curl') || + str_contains($userAgent, 'insomnia') || + str_contains($userAgent, 'python') || + str_contains($userAgent, 'java') + ) { + return true; + } + + // Headers comuns de navegadores modernos + if ( + isset($_SERVER['HTTP_SEC_FETCH_SITE']) || + isset($_SERVER['HTTP_SEC_FETCH_MODE']) || + isset($_SERVER['HTTP_REFERER']) + ) { + return false; + } + + return false; } - public static function optionalParamArray(){ - - } - - private static function filter($type, $paramname){ + /** + * + * @param string $paramname + * @param ParamType $type + * @param bool $cast + * + * @todo Implement casting + * @todo Review this logic, I don'r remember what it does + * + * @return mixed + private static function filter( + $paramname = "", + ParamType $type = ParamType::INT, + $cast = true + ): mixed { switch ($type){ - case 'integer': + case ParamType::INT: if(is_integer($paramname)){ return $paramname; } break; - case 'double': + case ParamType::DOUBLE: if(is_double($paramname)){ return $paramname; } break; - case 'alpha': + case ParamType::ALPHA: return $paramname; break; - case 'alphanum': + case ParamType::ALPHANUM: return $paramname; break; } } + */ - /* - * Validations + /** + * NOT IMPLEMENTED YET + * Check if the numeric value is in a number range + * + * Examples: + * From 10 to 35 = inRange($value, "10-35") + * From 45 to infinity = inRange($value, "45-") + * All numbers below 0 = inRange($value, "-0") + * + * @todo Not Implemented yet + * + * @param int|float $value + * @param string $range + * + * @return bool */ - private static function minVal(){ - + private static function inRange( + int|float $value, + string $range + ): bool { + return true; } - private static function maxVal(){ - - } - -} \ No newline at end of file +} diff --git a/src/RR/Response.php b/src/RR/Response.php index d36eb9b..a16464c 100755 --- a/src/RR/Response.php +++ b/src/RR/Response.php @@ -1,42 +1,35 @@ _headers[$key] = $value; - return $istance; + public static function header(string $key, string $value): Response + { + $instance = self::getInstance(); + $instance->_headers[$key] = $value; + return $instance; } /** + * Add content before the current content buffer * - * @ctag Response::bodyPrepend($value); + * @param string|null $body * + * @return Response */ - public static function bodyPrepend($body = null){ + public static function bodyPrepend(string|null $body = null): Response + { $instance = self::getInstance(); if (null !== $body) { $instance->_body = (string) $body . $instance->_body; @@ -71,11 +71,14 @@ class Response{ } /** + * Set or replace the body content buffer * - * @ctag Response::body($value); + * @param string|null $body * + * @return Response */ - public static function body($body = null){ + public static function body(string|null $body = ""): Response + { $instance = self::getInstance(); if (null !== $body) { $instance->_body = (string) $body; @@ -85,11 +88,14 @@ class Response{ } /** + * Add content on the end of the body buffer * - * @ctag Response::bodyAppend($value); + * @param string|null $body * + * @return Response */ - public static function bodyAppend($body = null){ + public static function bodyAppend(string|null $body = null): Response + { $instance = self::getInstance(); if (null !== $body) { $instance->_body .= (string) $body; @@ -98,14 +104,26 @@ class Response{ return $instance; } - private function sendHeaders(){ + /** + * Send the header properties to the browser + * + * @return Response + */ + private function sendHeaders(): Response + { foreach ($this->_headers as $key => $value) { header($key .': '. $value, true); } return $this; } - private function sendBody(){ + /** + * Print the body buffer to the browser + * + * @return Response + */ + private function sendBody(): Response + { if(!empty($this->_body)){ echo (string) $this->_body; } @@ -114,25 +132,15 @@ class Response{ } /** + * Formats and print a json object/array with the adequate headers * - * @ctag Response::bodySend(); + * @param mixed $object + * @param string|null $jsonPrefix * + * @return Response */ - public static function send(){ - $instance = self::getInstance(); - $instance->sendHeaders(); - $instance->sendBody(); - http_response_code($instance->_code); - return $instance; - } - - /** - * - * @ctag Response::json($object); - * @ctag Response::json($object, $prefix); - * - */ - public static function json($object, $jsonPrefix = null): Response{ + public static function json(mixed $object = Array(), string|null $jsonPrefix = null): Response + { $instance = self::getInstance(); $instance->body(''); @@ -154,45 +162,89 @@ class Response{ } /** + * Redirect the request to another URL * - * @ctag Response::redirect($url); - * @ctag Response::redirect($url, $code); - * + * @param string $url + * @param int $code */ - public static function redirect($url, $code = 303){ + public static function redirect(string $url, int $code = 303): void + { $instance = self::getInstance(); $instance->_code = $code; - if(is_ajax_request()){ - return $instance->json(['location' => $url])->send(); + if(Request::detectAjaxRequest()){ + $instance->json(['location' => $url])->send(); + die; } - ## TODO + ## TODO - Try to use the header location with the class dispatch method header("Location: $url"); die; - $instance->header('Location: ', $url)->send(); - - return $instance->send()->done(); + //$instance->header('Location: ', $url)->send(); + //$instance->send()->done(); } /** + * Try to return to the previos page (HTTP_REFERER) * - * @ctag Response::back(); + * I don't think is working, and might not make sense, return to a post endpoint with GET? * + * @param int $code + * + * @return void */ - public static function back(){ + public static function back(int $code = 303): void + { $instance = self::getInstance(); - $instance->header('Location: ', $_SERVER['HTTP_REFERER']); + $instance->_code = $code; + + if(isset($_SERVER['HTTP_REFERER'])){ + $instance->header('Location', $_SERVER['HTTP_REFERER']); + } else { + $instance->header( + 'Location', + (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] + === 'on' ? "https" : "http") . + "://" . $_SERVER['HTTP_HOST'] . + $_SERVER['REQUEST_URI'] + ); + } $instance->body(''); $instance->send(); + die; } - public function done(){ + /** + * Send all the info stored on the object + * - Send headers + * - Send body + * - Set response code + * + * @return Response + */ + public static function send(): Response + { + $instance = self::getInstance(); + http_response_code($instance->_code); + $instance->sendHeaders(); + $instance->sendBody(); + return $instance; + } + + /** + * Kill the current execution. + * + * After all the content is sent, there is no sense on keep the process + * + * @return void + */ + public function done(): void + { die; } }