Compare commits
107
Commits
c65fcd27c8
..
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b6da45b01 | ||
|
|
b7260b5199 | ||
|
|
1f29622914 | ||
|
|
eb882db0c8 | ||
|
|
9ba43e3f25 | ||
|
|
54e96ba4bb | ||
|
|
9027f36748 | ||
|
|
2ae9ef39f3 | ||
|
|
ee0db0307e | ||
|
|
44cbe6bbdc | ||
|
|
31728af351 | ||
|
|
4845d14ef5 | ||
|
|
aca4e732ed | ||
|
|
f475c9125f | ||
|
|
4fe7314389 | ||
|
|
1f366830bc | ||
|
|
15df7c8d96 | ||
|
|
b8dd1fd0f6 | ||
|
|
83c80bd4ab | ||
|
|
b13c07d3c4 | ||
|
|
b95747bfe0 | ||
|
|
01c5eceeb4 | ||
|
|
ee9c109ed9 | ||
|
|
7eed69725d | ||
|
|
e37035eed8 | ||
|
|
5312e5060e | ||
|
|
3c9db3ac53 | ||
|
|
2b5d19ecd5 | ||
|
|
53e862d126 | ||
|
|
b6baeef32f | ||
|
|
159da01d5c | ||
|
|
3770dd6d9b | ||
|
|
76a69e5ef8 | ||
|
|
c5a4967ae4 | ||
|
|
c0b9f3851a | ||
|
|
78e199e300 | ||
|
|
8cd5e114dd | ||
|
|
ce03bdb27d | ||
|
|
b24598b118 | ||
|
|
5019b89cc0 | ||
|
|
d030e8d30e | ||
|
|
b2672ad92f | ||
|
|
4c57770b43 | ||
|
|
8e84450f95 | ||
|
|
ece32b9bbe | ||
|
|
a5cf9d239d | ||
|
|
b9509c49ed | ||
|
|
6e433b4d06 | ||
|
|
892b3614ec | ||
|
|
a0b544eae5 | ||
|
|
20fd78ab53 | ||
|
|
f5411daaa5 | ||
|
|
7e7ec68fd7 | ||
|
|
ac9a661bc0 | ||
|
|
c8d7b69367 | ||
|
|
7f62e06ff9 | ||
|
|
674c9d5ff4 | ||
|
|
2f50532e13 | ||
|
|
b41514a491 | ||
|
|
a1a15f492c | ||
|
|
b19e7d8789 | ||
|
|
4dfdb52519 | ||
|
|
b0891885f9 | ||
|
|
b282d5479f | ||
|
|
c9f467345b | ||
|
|
0f46848d15 | ||
|
|
b2cb8d6883 | ||
|
|
e9126e7cde | ||
|
|
7169d2cae3 | ||
|
|
66b2bc0d91 | ||
|
|
c8ab2aa2cc | ||
|
|
1e302a9ea7 | ||
|
|
d0d0d4dc76 | ||
|
|
595e9c1316 | ||
|
|
45abea5301 | ||
|
|
d441f001ec | ||
|
|
19da122e05 | ||
|
|
1a0164c8ed | ||
|
|
ad9f8ec67d | ||
|
|
31c5c63952 | ||
|
|
6aef212350 | ||
|
|
c600688725 | ||
|
|
3e27b1b7af | ||
|
|
73b7b8f72a | ||
|
|
7baad428ec | ||
|
|
3d2a607768 | ||
|
|
df424ffab5 | ||
|
|
daf7250882 | ||
|
|
05cd83fd10 | ||
|
|
6b470a181d | ||
|
|
7beb161d2b | ||
|
|
701caae7eb | ||
|
|
100bdfe006 | ||
|
|
f1b79fdbc0 | ||
|
|
406f9a10a1 | ||
|
|
cc3cb6be41 | ||
|
|
59fff2a586 | ||
|
|
cd1685d2e7 | ||
|
|
b85fb7e034 | ||
|
|
a10308a8f6 | ||
|
|
9a1e5a2379 | ||
|
|
fa60ec5bb4 | ||
|
|
b294b1d627 | ||
|
|
27b5ed6015 | ||
|
|
f9b2c678f7 | ||
|
|
e294eaa7af | ||
|
|
186d640c8f |
@@ -1,6 +1,9 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Bloquear acceso a las carpetas vendor/ y src/
|
||||
RewriteRule ^(vendor|src)/.*$ - [F,L]
|
||||
|
||||
# Handle Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
require_once('config.php');
|
||||
|
||||
// Autoloader for the core classes
|
||||
spl_autoload_register(function ($className) {
|
||||
$fp = str_replace('\\', '/', $className);
|
||||
$name = basename($fp);
|
||||
$dir = dirname($fp);
|
||||
$file = ROOT_CORE . '/' . $dir . '/' . $name . '.php';
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
});
|
||||
+6
-2
@@ -1,11 +1,15 @@
|
||||
<?php
|
||||
|
||||
// Database configuration
|
||||
define('DB_TYPE', 'mysql');
|
||||
define('DB_HOST', 'localhost');
|
||||
define('DB_NAME', '');
|
||||
define('DB_USER', '');
|
||||
define('DB_PASS', '');
|
||||
|
||||
//define('SITE_URL', '');
|
||||
// Site configuration
|
||||
define('SITE_URL', '');
|
||||
|
||||
// Advanced configuration
|
||||
define('ROOT_DIR', __DIR__);
|
||||
?>
|
||||
define('ROOT_CORE', ROOT_DIR . '/src');
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
<?php
|
||||
require_once('config.php');
|
||||
|
||||
define('ROOT_CORE', ROOT_DIR.'/src');
|
||||
use Libs\Loader;
|
||||
use Libs\Router;
|
||||
|
||||
// Incluir clases
|
||||
spl_autoload_register(function ($className) {
|
||||
$fp = str_replace('\\','/',$className);
|
||||
$name = basename($fp);
|
||||
$dir = dirname($fp);
|
||||
$file = ROOT_CORE.'/'.$dir.'/'.$name.'.php';
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return;
|
||||
}
|
||||
});
|
||||
require_once('autoload.php');
|
||||
|
||||
// Incluir routers
|
||||
$routers = glob(ROOT_CORE.'/Routers/*.php');
|
||||
// Router autoload
|
||||
Loader::load(ROOT_CORE . '/Routers/');
|
||||
|
||||
foreach($routers as $file){
|
||||
require_once($file);
|
||||
}
|
||||
// Other autoloads
|
||||
Loader::load(ROOT_CORE . '/Autoloads/');
|
||||
|
||||
\Libs\Router::apply();
|
||||
?>
|
||||
// Run the routers
|
||||
Router::apply();
|
||||
|
||||
+108
-10
@@ -1,20 +1,118 @@
|
||||
* DuckBrain - PHP Microframework
|
||||
#+TITLE: Duckbrain
|
||||
#+AUTHOR: KJ
|
||||
#+OPTIONS: toc:nil
|
||||
|
||||
Este microframework PHP tiene el objetivo de presentar un framework sencillo y potente que sea válido especialmente para proyectos pequeños o simples, sin limitar demasiado, ni depender de cosas que agranden innecesariamente proyectos.
|
||||
Este conjunto de librerías (microframework, si así lo prefieres) tiene el objetivo de presentar una herramienta de trabajo sencilla y potente que sea válida especialmente para proyectos pequeños o simples, sin limitar, ni depender de cosas que agranden innecesariamente dichos proyectos.
|
||||
|
||||
Esto no es un intento de mi parte de reinventar la rueda, de hecho los primeros commits los hice con la intención de que solo fuera una prueba de concepto, pero me gustó como quedó y decidí darle continuidad hasta hacerlo usable para mi mismo.
|
||||
Tuve la idea de hacer esta herramienta luego de ver como proyectos relativamente pequeños eran hechos con frameworks demasiado grandes para la envergadura de dichos proyectos. No es bueno matar moscas a cañonazos.
|
||||
|
||||
Tuve la idea de hacer este conjunto de librerías/microframework luego de ver como proyectos relativamente pequeños eran hechos con frameworks demasiado pesados para lo que eran.
|
||||
Del mismo modo revisé algunos microframeworks y si bien me parecen una buena opción, aún me quedaba la espinita de que seguían siendo muy complejos para que un programador novato pudiera leer su código, entenderlo y modificarlo, así que intenté hacer algo más simple
|
||||
|
||||
También revisé otros microframeworks y si bien me parecen una buena opción para hacer los trabajos, aún me quedaba la espinita de que seguían siendo muy grandes para que un programador novato pudiera leerlo, entenderlo y modificarlo, así que intenté hacer algo más simple aún y de ahí salió este proyecto.
|
||||
|
||||
Lo ideal sería mantener el código sencillo, lo suficiente como para que cualquier novato que sepa POO y PHP pueda leerlo rápido, entenderlo y modificarlo a gusto. Por este motivo también he decidido desligarlo en lo posible de composer o cualquier cosa similar, ya que no pocos programadores en etapa de aprendizaje al encontrarse con frameworks más complicados o con herramientas como composer, terminan trabajando con cosas que no comprenden ni pueden arreglar por si mismos en caso de fallo, ya que son completamente dependientes de dichas herramientas.
|
||||
|
||||
El código no es perfecto, pero lo iré perfeccionando, ya que es algo que estoy usando actualmente para mis trabajos, de modo que puedo ir viendo que cosas se pueden ir mejorando.
|
||||
Lo que busco es mantener un código sencillo, lo suficiente como para que cualquier novato que sepa POO y PHP pueda leer su código rápidamente, entenderlo y modificarlo a gusto. Por este motivo también he decidido desligarlo en lo posible de composer o cualquier cosa similar, ya que no pocos programadores en etapa de aprendizaje al encontrarse con frameworks más complicados o con herramientas como composer, terminan trabajando con cosas que no comprenden ni pueden arreglar por si mismos en caso de fallo, llevándolos a la dependencia total de dichas herramientas.
|
||||
|
||||
* Uso / Documentación
|
||||
|
||||
Queda pendiente, si quieres usarlo ya mismo, puedes leer los comentarios que he colocado en el código o usar [[https://www.phpdoc.org/][phpdoc]] para generarla a partir de los bloques de comentarios.
|
||||
Actualmente existe un manual de inicio que puedes leerlo desde [[https://tools.kj2.me/duckbrain/starting-manual.html][aquí]] o desde [[https://git.kj2.me/kj/duckbrain-docs/src/branch/master/starting-manual.org][aquí]].
|
||||
|
||||
Si quieres leer el manual de inicio en su formato original (necesitas un editor/lector que soporte org-mode) puedes descargarla desde [[https://tools.kj2.me/duckbrain/starting-manual.org][aquí]].
|
||||
|
||||
Para el resto de la documentación, el código usa [[https://www.phpdoc.org/][phpdoc]], por lo que puedes tener toda la documentación API desde tu IDE o Editor de texto preferido siempre que soporte dicha característica. O si lo prefieres, puedes generarla en unbonito htm local usando la herramienta [[https://docs.phpdoc.org/3.0/packages/phpDocumentor.html][phpDocumentor]].
|
||||
|
||||
* Soporte de gestores de bases de datos
|
||||
|
||||
En la siguiente tabla se encuentra la lista de estados de los gestores de bases de datos que he probado o que planeo probar para asegurarme de que sean realmente compatibles.
|
||||
|
||||
*Entiéndase*:
|
||||
|
||||
+ *ok* como que ha sido probado y funciona.
|
||||
+ *En blanco* como que no ha sido probado aún.
|
||||
+ *error* como que fue probado, no funciona y no ha sido aún arreglado.
|
||||
+ *not supported* como no soportado por el gestor de bases de datos.
|
||||
+ *fixed* para aquello que no existe en el gestor de BD, pero la librería lo traduce a un equivalente.
|
||||
|
||||
|------------------+---------------+---------+------------|
|
||||
| method | MySQL/MariaDB | sqlite3 | postgreSQL |
|
||||
|------------------+---------------+---------+------------|
|
||||
| db | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| query | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| resetQuery | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| buildQuery | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| getInstance | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| getVars | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| className | ok | ok | pk |
|
||||
|------------------+---------------+---------+------------|
|
||||
| table | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| update | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| beginTransaction | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| rollBack | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| commit | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| add | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| save | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| delete | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| select | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| from | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| where | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereIn | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereNotIn | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereNull | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereNotNull | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereExists | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| whereNotExists | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| leftJoin | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| rightJoin | ok | fixed | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| innerJoin | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| crossJoin | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| and | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| or | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| groupBy | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| limit | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| orderBy | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| count | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| getById | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| search | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| get | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| getFirst | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| all | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
| setNull | ok | ok | ok |
|
||||
|------------------+---------------+---------+------------|
|
||||
|
||||
* Contacto
|
||||
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
* Sobre la actualización
|
||||
Previamente, el sistema usaba [[https://www.php.net/mysqli][MySQLi]] para el Modelo/ORM, como actualización, se ha cambiado para funcionar con [[https://www.php.net/pdo][PDO]].
|
||||
|
||||
* Notas de migración
|
||||
Estos son detalles importantes a tomar en cuenta a la hora de migrar del anterior ModelMySQL (MySQLi) al actual Model (PDO).
|
||||
|
||||
+ El modelo base ha cambiado de nombre de =ModelMySQL= a =Model=.
|
||||
+ El método =query= ahora devuelve un =array= en lugar de un =mysqli_result=.
|
||||
+ Se han depurado los métodos =sql_calc_found_rows= y =found_rows=.
|
||||
+ Se ha cambiado =dbname=, =dbuser= y =dbpass= a =DB_NAME=, =DB_USER= y =DB_PASS=, respectivamente.
|
||||
+ Se ha añadido la necesitad de la constante =DB_TYPE= para indicar el driver PDO a usar (ej. mysql, sqlite).
|
||||
|
||||
* Pruebas
|
||||
|
||||
En la siguiente tabla se encuentra la lista de estados de los SGBD que he probado (MySQL/MariaDB) o que planeo probar (sqlite3, postgreSQL) para asegurarme de que sean realmente compatibles.
|
||||
|
||||
*Entiéndase*:
|
||||
|
||||
+ *ok* como que ha sido probado y funciona.
|
||||
+ En blanco como que no ha sido probado aún.
|
||||
+ *error* como que fue probado, no funciona y no ha sido aún arreglado.
|
||||
+ *not supported* como no soportado por el SGBD.
|
||||
+ *fixed* para aquello que no existe, pero la librería lo traduce a un equivalente.
|
||||
|
||||
|------------------+---------------+---------------+------------|
|
||||
| method | MySQL/MariaDB | sqlite3 | postgreSQL |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| db | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| query | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| resetQuery | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| buildQuery | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| getInstance | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| getVars | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| className | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| table | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| update | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| beginTransaction | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| rollBack | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| commit | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| add | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| save | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| delete | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| select | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| from | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| where | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| where_in | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| leftJoin | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| rightJoin | ok | not supported | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| innerJoin | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| and | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| or | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| groupBy | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| limit | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| orderBy | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| count | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| getById | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| search | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| get | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| getFirst | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| all | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
| setNull | ok | ok | |
|
||||
|------------------+---------------+---------------+------------|
|
||||
+40
-35
@@ -1,58 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Database - DuckBrain
|
||||
*
|
||||
* Clase diseñada para crear y devolver una única instancia PDO (database).
|
||||
* Hace uso de las siguientes constantes:
|
||||
* DB_TYPE, DB_NAME, DB_HOST, DB_USER, DB_PASS
|
||||
*
|
||||
* Si DB_TYPE es sqlite, usará DB_NAME como el nombre del archivo sqlite.
|
||||
* Además DB_USER y DB_PASS, no será necesariop que estén definidos.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
|
||||
use Exception;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Exception;
|
||||
|
||||
class Database extends PDO {
|
||||
static private ?PDO $db = null;
|
||||
|
||||
private function __construct() {}
|
||||
/**
|
||||
* Database - DuckBrain
|
||||
*
|
||||
* Class designed to create and return a single PDO instance (database).
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class Database extends PDO
|
||||
{
|
||||
private static array $databases = [];
|
||||
|
||||
/**
|
||||
* Devuelve una instancia homogénea (singlenton) de la base de datos (PDO).
|
||||
* Private constructor to prevent direct instantiation.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a homogeneous (singleton) instance of the database (PDO).
|
||||
*
|
||||
* @return PDO
|
||||
* @throws Exception If there is an error connecting to the database.
|
||||
*/
|
||||
static public function getInstance(): PDO
|
||||
{
|
||||
if (is_null(self::$db)) {
|
||||
|
||||
if (DB_TYPE == 'sqlite') {
|
||||
$dsn = DB_TYPE .':'. DB_NAME;
|
||||
!defined('DB_USER') && define('DB_USER', '');
|
||||
!defined('DB_PASS') && define('DB_PASS', '');
|
||||
} else
|
||||
$dsn = DB_TYPE.':dbname='.DB_NAME.';host='.DB_HOST;
|
||||
public static function getInstance(
|
||||
string $type = 'mysql',
|
||||
string $host = 'localhost',
|
||||
string $name = '',
|
||||
string $user = '',
|
||||
string $pass = '',
|
||||
): PDO {
|
||||
$key = $type . '/' . $host . '/' . $name . '/' . $user;
|
||||
if (empty(static::$databases[$key])) {
|
||||
if ($type == 'sqlite') {
|
||||
$dsn = $type . ':' . $name;
|
||||
} else {
|
||||
$dsn = $type . ':dbname=' . $name . ';host=' . $host;
|
||||
}
|
||||
|
||||
try {
|
||||
self::$db = new PDO($dsn, DB_USER, DB_PASS);
|
||||
static::$databases[$key] = new PDO($dsn, $user, $pass);
|
||||
} catch (PDOException $e) {
|
||||
throw new Exception(
|
||||
'Error at connect to database: ' . $e->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
self::$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
static::$databases[$key]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
static::$databases[$key]->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
}
|
||||
return self::$db;
|
||||
return static::$databases[$key];
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Libs;
|
||||
|
||||
/**
|
||||
* Loader - DuckBrain
|
||||
*
|
||||
* Simple library to bulk load multiple php files inside a folder.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class Loader
|
||||
{
|
||||
/**
|
||||
* Loads all PHP files from a specified directory.
|
||||
* If the directory does not exist or is not a directory, no files will be loaded.
|
||||
*
|
||||
* @param string $directoryPath The path to the directory containing the PHP files to load.
|
||||
* @return void
|
||||
*/
|
||||
public static function load(string $directoryPath): void
|
||||
{
|
||||
if (is_dir($directoryPath)) {
|
||||
foreach (glob(rtrim($directoryPath, '/') . '/*.php') as $file) {
|
||||
require_once($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Middleware - DuckBrain
|
||||
*
|
||||
* Librería base para middlewares.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
|
||||
class Middleware {
|
||||
|
||||
/**
|
||||
* Llama al siguiente callback.
|
||||
*
|
||||
* @param Neuron $req
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function next(Neuron $req): mixed
|
||||
{
|
||||
$next = array_pop($req->next);
|
||||
return call_user_func_array($next, [$req]);
|
||||
}
|
||||
}
|
||||
+650
-350
File diff suppressed because it is too large
Load Diff
+30
-25
@@ -1,54 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Libs;
|
||||
|
||||
use AllowDynamicProperties;
|
||||
|
||||
/**
|
||||
* Neuron - DuckBrain
|
||||
*
|
||||
* Neuron, sirve para crear un objeto que alojará valores, pero
|
||||
* además tiene la característica especial de que al intentar
|
||||
* acceder a un atributo que no está definido devolerá nulo en
|
||||
* lugar de generar un error php notice que indica que se está
|
||||
* intentando acceder a un valor no definido.
|
||||
* Neuron, serves to create an object that will hold values.
|
||||
* In addition, it has the special characteristic that when trying
|
||||
* to access an undefined property, it will return null instead
|
||||
* of generating a notice (PHP notice) for an undefined variable or property.
|
||||
*
|
||||
* El constructor recibe un objeto o arreglo con los valores que
|
||||
* sí estarán definidos.
|
||||
* The constructor accepts an object or an array containing the
|
||||
* values that will be defined.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
use AllowDynamicProperties;
|
||||
|
||||
#[AllowDynamicProperties]
|
||||
class Neuron {
|
||||
|
||||
class Neuron
|
||||
{
|
||||
/**
|
||||
* __construct
|
||||
* Constructor
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data Data to initialize the Neuron with. Can be an array or an object.
|
||||
*/
|
||||
public function __construct(...$data)
|
||||
{
|
||||
if (count($data) === 1 &&
|
||||
if (
|
||||
count($data) === 1 &&
|
||||
isset($data[0]) &&
|
||||
(is_array($data[0]) ||
|
||||
is_object($data[0])))
|
||||
is_object($data[0]))
|
||||
) {
|
||||
$data = $data[0];
|
||||
}
|
||||
|
||||
foreach($data as $key => $value)
|
||||
foreach ($data as $key => $value) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __get
|
||||
* Magic method __get
|
||||
*
|
||||
* @param string $index
|
||||
* @return null
|
||||
* This method is called when an undefined property is accessed.
|
||||
* It returns null instead of triggering an E_NOTICE.
|
||||
*
|
||||
* @param string $index The name of the property being accessed.
|
||||
* @return null Always returns null for undefined properties.
|
||||
*/
|
||||
public function __get(string $index): null
|
||||
public function __get(string $index)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
+157
-35
@@ -1,58 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* Request - DuckBrain
|
||||
*
|
||||
* Libería complementaria de la libería Router.
|
||||
* Contiene el cuerpo básico de la petición http (POST, GET, JSON, etc).
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
|
||||
class Request extends Neuron {
|
||||
/**
|
||||
* @var Neuron $get Objeto con todos los valores de $_GET.
|
||||
*/
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Request - DuckBrain
|
||||
*
|
||||
* Complementary library to the Router library.
|
||||
* Contains the basic body of the http request (POST, GET, JSON, etc).
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class Request extends Neuron
|
||||
{
|
||||
public Neuron $get;
|
||||
/**
|
||||
* @var Neuron $post Objeto con todos los valores de $_POST.
|
||||
*/
|
||||
public Neuron $post;
|
||||
/**
|
||||
* @var Neuron $json Objeto con todos los valores json enviados.
|
||||
*/
|
||||
public Neuron $put;
|
||||
public Neuron $patch;
|
||||
public Neuron $delete;
|
||||
public Neuron $json;
|
||||
/**
|
||||
* @var mixed $params Objeto con todos los valores pseudovariables de la uri.
|
||||
*/
|
||||
public Neuron $params;
|
||||
/**
|
||||
* @var mixed $path Ruta actual tomando como raíz la instalación de DuckBrain.
|
||||
*/
|
||||
public string $path;
|
||||
public string $error;
|
||||
public string $body;
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
* @param string $path Ruta actual tomando como raíz la instalación de DuckBrain.
|
||||
*/
|
||||
public function __construct(string $path = '/')
|
||||
public function __construct()
|
||||
{
|
||||
$this->path = $path;
|
||||
$this->path = Router::currentPath();
|
||||
$this->get = new Neuron($_GET);
|
||||
$this->post = new Neuron($_POST);
|
||||
$this->put = new Neuron();
|
||||
$this->patch = new Neuron();
|
||||
$this->delete = new Neuron();
|
||||
$this->params = Router::$params ?? new Neuron();
|
||||
$this->body = file_get_contents("php://input");
|
||||
|
||||
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
|
||||
if ($contentType === "application/json")
|
||||
if ($contentType === "application/json") {
|
||||
$this->json = new Neuron(
|
||||
(object) json_decode(trim(file_get_contents("php://input")), false)
|
||||
(object) json_decode(trim($this->body), false)
|
||||
);
|
||||
else
|
||||
$this->json = new Neuron();
|
||||
} else {
|
||||
$this->json = new Neuron();
|
||||
if (
|
||||
in_array($_SERVER['REQUEST_METHOD'], ['PUT', 'PATCH', 'DELETE']) &&
|
||||
preg_match('/^[^;?\/:@&=+$,]{1,255}[=]/', $this->body, $matches)
|
||||
) {
|
||||
// With the regular expression, we verify that it is a valid
|
||||
// http query string and avoid memory errors in case
|
||||
// the body contains something larger than that.
|
||||
parse_str($this->body, $input_vars);
|
||||
$this->{strtolower($_SERVER['REQUEST_METHOD'])} = new Neuron($input_vars);
|
||||
}
|
||||
}
|
||||
|
||||
$this->params = new Neuron();
|
||||
// Run configured validations
|
||||
$this->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the configured validation.
|
||||
*
|
||||
* On failure the single error message is built with Validator::message()
|
||||
* and handed to onInvalid(), which throws by default: failures travel up
|
||||
* as exceptions instead of answering HTTP here.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception When a configured rule fails.
|
||||
*/
|
||||
public function validate(): void
|
||||
{
|
||||
$actual = match ($_SERVER['REQUEST_METHOD']) {
|
||||
'POST', 'PUT', 'PATCH', 'DELETE' => $this->{strtolower($_SERVER['REQUEST_METHOD'])},
|
||||
default => $this->get
|
||||
};
|
||||
|
||||
// Merge uploaded files ($_FILES) into the body data set so the file rules
|
||||
// (file/image/mimes and the routed min/max/required...) can validate
|
||||
// uploads through a Request. $this->post is left untouched.
|
||||
$body = empty($_FILES)
|
||||
? $actual
|
||||
: new Neuron(array_merge(get_object_vars($actual), $_FILES));
|
||||
|
||||
if (
|
||||
Validator::validateList(static::paramRules(), $this->params) &&
|
||||
Validator::validateList(static::getRules(), $this->get) &&
|
||||
Validator::validateList(static::rules(), $body)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$error = Validator::message(
|
||||
Validator::$lastFailed,
|
||||
static::messages(),
|
||||
static::attributes()
|
||||
);
|
||||
|
||||
static::onInvalid($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for the current method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for URL parameters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function paramRules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for GET parameters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Error messages in case a validation fails.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable names for the fields.
|
||||
*
|
||||
* Forwarded to Validator::message() so the :attribute marker in the error
|
||||
* text can be replaced with a friendlier name (e.g. "edad" => "la edad").
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to execute when an invalid value has been detected.
|
||||
*
|
||||
* The default implementation always throws a generic \Exception carrying
|
||||
* the single error message and HTTP 422 as its code; the framework's
|
||||
* exception boundary (Router::apply) renders the response. Override it to
|
||||
* throw a more specific exception type instead. The never return type is
|
||||
* the contract: an override that returned would let the request continue
|
||||
* with invalid data, so PHP rejects such an override at compile time.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @return never
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onInvalid(string $error): never
|
||||
{
|
||||
throw new Exception($error, 422);
|
||||
}
|
||||
}
|
||||
|
||||
+270
-156
@@ -1,57 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* Router - DuckBrain
|
||||
*
|
||||
* Librería de Enrrutador.
|
||||
* Depende de manera forzada de que la constante ROOT_DIR esté definida
|
||||
* y de manera optativa de que la constante SITE_URL lo esté también.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
|
||||
class Router {
|
||||
private static $get = [];
|
||||
private static $post = [];
|
||||
private static $put = [];
|
||||
private static $patch = [];
|
||||
private static $delete = [];
|
||||
private static $last;
|
||||
public static $notFoundCallback = 'Libs\Router::defaultNotFound';
|
||||
/**
|
||||
* Router - DuckBrain
|
||||
*
|
||||
* Router library.
|
||||
* It strictly depends on the ROOT_DIR constant being defined
|
||||
* and optionally on the SITE_URL constant being defined.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class Router
|
||||
{
|
||||
private static array $get = [];
|
||||
private static array $post = [];
|
||||
private static array $put = [];
|
||||
private static array $patch = [];
|
||||
private static array $delete = [];
|
||||
|
||||
/**
|
||||
* Función callback por defectio para cuando
|
||||
* no se encuentra configurada la ruta.
|
||||
* Stores a temporary stack of middlewares to be applied to routes defined
|
||||
* within a specific scope, typically configured by `withMiddleware()`.
|
||||
* These middlewares are active only during the execution of the scope's callback.
|
||||
*
|
||||
* @var array $withMiddlewares<callable>
|
||||
*/
|
||||
private static array $withMiddlewares = [];
|
||||
|
||||
/**
|
||||
* Stores the method and index of the last configured route, e.g., ['get', 0].
|
||||
* Used for chaining methods like middleware() or reconfigure().
|
||||
*
|
||||
* @var array $last
|
||||
*/
|
||||
private static array $last;
|
||||
|
||||
/**
|
||||
* Stores the parameters extracted from the current matching route.
|
||||
*
|
||||
* @var Neuron $params
|
||||
*/
|
||||
public static Neuron $params;
|
||||
|
||||
/**
|
||||
* The callback function to be executed when no route matches.
|
||||
*
|
||||
* @var callable $notFoundCallback
|
||||
*/
|
||||
public static $notFoundCallback = 'Libs\Router::defaultNotFound';
|
||||
|
||||
/**
|
||||
* Default callback function for when
|
||||
* the route is not found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function defaultNotFound (): void
|
||||
public static function defaultNotFound(): void
|
||||
{
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
echo '<h2 style="text-align: center;margin: 25px 0px;">Error 404 - Página no encontrada</h2>';
|
||||
echo '<h2 style="text-align: center;margin: 25px 0px;">Error 404 - Page Not Found</h2>';
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback function to be executed when the router's boundary
|
||||
* catches an exception thrown anywhere in the matched route chain.
|
||||
* It receives the exception as a named argument: the handler must
|
||||
* declare its parameter as $exception (typeable as \Throwable).
|
||||
*
|
||||
* @var callable $exceptionCallback
|
||||
*/
|
||||
public static $exceptionCallback = 'Libs\Router::defaultException';
|
||||
|
||||
/**
|
||||
* Default callback function for exception responses.
|
||||
*
|
||||
* The HTTP status comes from the exception's code only when it is an
|
||||
* integer in the 400-599 range; anything else (0, arbitrary codes, the
|
||||
* SQLSTATE string carried by PDOException) answers 500. The body is
|
||||
* negotiated from the request's Accept header: JSON when the client asks
|
||||
* for application/json, plain text otherwise. The trace is serialized
|
||||
* from getTraceAsString() because json_encode() of a Throwable yields an
|
||||
* empty object: its properties are protected.
|
||||
*
|
||||
* @param \Throwable $exception
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function defaultException(\Throwable $exception): void
|
||||
{
|
||||
$code = $exception->getCode();
|
||||
http_response_code(is_int($code) && $code >= 400 && $code <= 599 ? $code : 500);
|
||||
|
||||
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
|
||||
|
||||
if (str_contains($accept, 'application/json')) {
|
||||
header('Content-Type: application/json');
|
||||
print(json_encode([
|
||||
'error' => $exception->getMessage(),
|
||||
'exception' => get_class($exception),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'trace' => explode(PHP_EOL, $exception->getTraceAsString()),
|
||||
]));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
print($exception->getMessage() . PHP_EOL . $exception->getTraceAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*/
|
||||
private function __construct() {}
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsea para deectar las pseudovariables (ej: {variable})
|
||||
* Parses to detect pseudovariables (e.g., {variable})
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* Route with pseudovariables.
|
||||
*
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return array
|
||||
* Arreglo con 2 índices:
|
||||
* path - Contiene la ruta con las pseudovariables reeplazadas por expresiones regulares.
|
||||
* callback - Contiene el callback en formato Namespace\Clase::Método.
|
||||
* Array with 3 indices:
|
||||
* path - Contains the route with pseudovariables replaced by regular expressions.
|
||||
* callback - Contains the callback in Namespace\Class::Method format.
|
||||
* paramNames - An array of parameter names found in the path.
|
||||
*/
|
||||
private static function parse(string $path, callable $callback): array
|
||||
{
|
||||
@@ -62,72 +143,75 @@ class Router {
|
||||
$path = preg_replace(
|
||||
['/\\\{\w+\\\}/s'],
|
||||
['([^\/]+)'],
|
||||
$path);
|
||||
$path
|
||||
);
|
||||
|
||||
return [
|
||||
'path' => $path,
|
||||
'callback' => [$callback],
|
||||
'paramNames' => $paramNames
|
||||
'paramNames' => $paramNames,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Devuelve el ruta base o raiz del proyecto sobre la que trabajará el router.
|
||||
* Returns the base or root path of the project on which the router will work.
|
||||
*
|
||||
* Ej: Si la url del sistema está en "https://ejemplo.com/duckbrain"
|
||||
* entonces la ruta base sería "/duckbrain"
|
||||
* Ex: If the system URL is "https://example.com/duckbrain"
|
||||
* then the base path would be "/duckbrain"
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function basePath(): string
|
||||
{
|
||||
if (defined('SITE_URL'))
|
||||
return parse_url(SITE_URL, PHP_URL_PATH);
|
||||
if (defined('SITE_URL') && !empty(SITE_URL)) {
|
||||
return rtrim(parse_url(SITE_URL, PHP_URL_PATH), '/') . '/';
|
||||
}
|
||||
return str_replace($_SERVER['DOCUMENT_ROOT'], '/', ROOT_DIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirije a una ruta relativa interna.
|
||||
* Redirects to an internal relative path.
|
||||
*
|
||||
* @param string $path
|
||||
* La ruta relativa a la ruta base.
|
||||
* The path relative to the base path.
|
||||
*
|
||||
* Ej: Si nuesto sistema está en "https://ejemplo.com/duckbrain"
|
||||
* llamamos a Router::redirect('/docs'), entonces seremos
|
||||
* redirigidos a "https://ejemplo.com/duckbrain/docs".
|
||||
* Ex: If our system is at "https://example.com/duckbrain"
|
||||
* and we call Router::redirect('/docs'), we will be
|
||||
* redirected to "https://example.com/duckbrain/docs".
|
||||
* @return void
|
||||
*/
|
||||
public static function redirect(string $path): void
|
||||
{
|
||||
header('Location: '.static::basePath().substr($path,1));
|
||||
exit;
|
||||
header('Location: ' . static::basePath() . ltrim($path, '/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Añade un middleware a la última ruta usada.
|
||||
* Solo se puede usar un middleware a la vez.
|
||||
* Adds a middleware to the last used route.
|
||||
* Only one middleware can be added at a time.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $prioriry
|
||||
* @param int|null $priority Optional priority for the middleware execution order.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual.
|
||||
* Returns the current instance.
|
||||
*/
|
||||
public static function middleware(callable $callback, int $priority = null): static
|
||||
public static function middleware(callable $callback, ?int $priority = null): static
|
||||
{
|
||||
if (!isset(static::$last))
|
||||
if (!isset(static::$last)) {
|
||||
return new static();
|
||||
}
|
||||
|
||||
$method = static::$last[0];
|
||||
$index = static::$last[1];
|
||||
|
||||
if (isset($priority) && $priority <= 0)
|
||||
if (isset($priority) && $priority <= 0) {
|
||||
$priority = 1;
|
||||
}
|
||||
|
||||
if (is_null($priority) || $priority >= count(static::$$method[$index]['callback']))
|
||||
if (is_null($priority) || $priority >= count(static::$$method[$index]['callback'])) {
|
||||
static::$$method[$index]['callback'][] = $callback;
|
||||
else {
|
||||
} else {
|
||||
static::$$method[$index]['callback'] = array_merge(
|
||||
array_slice(static::$$method[$index]['callback'], 0, $priority),
|
||||
[$callback],
|
||||
@@ -139,7 +223,29 @@ class Router {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconfigura el callback final de la última ruta.
|
||||
* Temporarily applies a set of middlewares to routes defined within a given callback.
|
||||
* The middlewares are only active for the duration of the callback execution
|
||||
* and are reset afterwards.
|
||||
*
|
||||
* @param callable $middleware
|
||||
* @param callable $callback
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function withMiddleware(callable $middleware, callable $callback): static
|
||||
{
|
||||
$currentMiddlewares = static::$withMiddlewares;
|
||||
array_unshift(static::$withMiddlewares, $middleware);
|
||||
|
||||
$callback();
|
||||
|
||||
static::$withMiddlewares = $currentMiddlewares; // Restore withMiddleware
|
||||
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconfigures the final callback of the last route.
|
||||
*
|
||||
* @param callable $callback
|
||||
*
|
||||
@@ -147,8 +253,9 @@ class Router {
|
||||
*/
|
||||
public static function reconfigure(callable $callback): static
|
||||
{
|
||||
if (empty(static::$last))
|
||||
if (empty(static::$last)) {
|
||||
return new static();
|
||||
}
|
||||
|
||||
$method = static::$last[0];
|
||||
$index = static::$last[1];
|
||||
@@ -159,20 +266,20 @@ class Router {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configura calquier método para todas las rutas.
|
||||
* Configures any method for all routes.
|
||||
*
|
||||
* En caso de no recibir un callback, busca la ruta actual
|
||||
* solo configura la ruta como la última configurada
|
||||
* siempre y cuando la misma haya sido configurada previamente.
|
||||
* If no callback is received, it searches for the current route
|
||||
* and only sets the route as the last configured one
|
||||
* provided it has been configured previously.
|
||||
*
|
||||
* @param string $method
|
||||
* Método http.
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* @param string $method
|
||||
* HTTP method.
|
||||
* @param string $path
|
||||
* Route with pseudovariables.
|
||||
* @param callable|null $callback
|
||||
*
|
||||
* @return
|
||||
* Devuelve la instancia actual.
|
||||
* @return static
|
||||
* Returns the current instance.
|
||||
*/
|
||||
public static function configure(string $method, string $path, ?callable $callback = null): static
|
||||
{
|
||||
@@ -181,175 +288,182 @@ class Router {
|
||||
$path = preg_replace(
|
||||
['/\\\{\w+\\\}/s'],
|
||||
['([^\/]+)'],
|
||||
$path);
|
||||
$path
|
||||
);
|
||||
|
||||
foreach(static::$$method as $index => $router)
|
||||
foreach (static::$$method as $index => $router) {
|
||||
if ($router['path'] == $path) {
|
||||
static::$last = [$method, $index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new static();
|
||||
}
|
||||
|
||||
static::$$method[] = static::parse($path, $callback);
|
||||
static::$last = [$method, count(static::$$method)-1];
|
||||
static::$last = [$method, count(static::$$method) - 1];
|
||||
|
||||
foreach (static::$withMiddlewares as $middleware) {
|
||||
static::middleware($middleware);
|
||||
}
|
||||
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los routers para el método GET.
|
||||
* Defines routers for the GET method.
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* @param string $path
|
||||
* Route with pseudovariables.
|
||||
* @param callable|null $callback
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual.
|
||||
* Returns the current instance.
|
||||
*/
|
||||
public static function get(string $path, callable $callback = null): static
|
||||
public static function get(string $path, ?callable $callback = null): static
|
||||
{
|
||||
return static::configure('get', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los routers para el método POST.
|
||||
* Defines routers for the POST method.
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* @param string $path
|
||||
* Route with pseudovariables.
|
||||
* @param callable|null $callback
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual.
|
||||
* Returns the current instance.
|
||||
*/
|
||||
public static function post(string $path, callable $callback = null): static
|
||||
public static function post(string $path, ?callable $callback = null): static
|
||||
{
|
||||
return static::configure('post', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los routers para el método PUT.
|
||||
* Defines routers for the PUT method.
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* @param string $path
|
||||
* Route with pseudovariables.
|
||||
* @param callable|null $callback
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual
|
||||
* Returns the current instance
|
||||
*/
|
||||
|
||||
public static function put(string $path, callable $callback = null): static
|
||||
public static function put(string $path, ?callable $callback = null): static
|
||||
{
|
||||
return static::configure('put', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los routers para el método PATCH.
|
||||
* Defines routers for the PATCH method.
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables.
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* @param string $path
|
||||
* Route with pseudovariables.
|
||||
* @param callable|null $callback
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual
|
||||
* Returns the current instance
|
||||
*/
|
||||
public static function patch(string $path, callable $callback = null): static
|
||||
public static function patch(string $path, ?callable $callback = null): static
|
||||
{
|
||||
return static::configure('patch', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define los routers para el método DELETE.
|
||||
* Defines routers for the DELETE method.
|
||||
*
|
||||
* @param string $path
|
||||
* Ruta con pseudovariables
|
||||
* @param callable $callback
|
||||
* Callback que será llamado cuando la ruta configurada en $path coincida.
|
||||
* @param string $path
|
||||
* Route with pseudovariables
|
||||
* @param callable|null $callback
|
||||
* Callback that will be called when the route configured in $path matches.
|
||||
*
|
||||
* @return static
|
||||
* Devuelve la instancia actual
|
||||
* Returns the current instance
|
||||
*/
|
||||
public static function delete(string $path, callable $callback = null): static
|
||||
public static function delete(string $path, ?callable $callback = null): static
|
||||
{
|
||||
return static::configure('delete', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Devuelve la ruta actual tomando como raíz la ruta de instalación de DuckBrain.
|
||||
* Returns the current path, taking the DuckBrain installation path as the root.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function currentPath() : string
|
||||
public static function currentPath(): string
|
||||
{
|
||||
return preg_replace('/'.preg_quote(static::basePath(), '/').'/',
|
||||
'/', strtok($_SERVER['REQUEST_URI'], '?'), 1);
|
||||
return preg_replace(
|
||||
'/' . preg_quote(static::basePath(), '/') . '/',
|
||||
'/',
|
||||
strtok($_SERVER['REQUEST_URI'], '?'),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aplica los routers.
|
||||
* Applies the route configuration.
|
||||
*
|
||||
* Este método ha de ser llamado luego de que todos los routers hayan sido configurados.
|
||||
* This method is the framework's error boundary: any \Throwable thrown
|
||||
* while running the matched route's callback chain, while printing the
|
||||
* returned data, or while resolving the not-found callback is caught
|
||||
* here and rendered through $exceptionCallback. A failing handler is
|
||||
* deliberately left uncaught (double failure falls back to PHP itself).
|
||||
*
|
||||
* En caso que la ruta actual coincida con un router configurado, se comprueba si hay middleware; Si hay
|
||||
* middleware, se enviará el callback y los datos de la petición como un Neuron. Caso contrario, se enviarán
|
||||
* los datos directamente al callback.
|
||||
* @param string|null $path (optional) Path to use. If not defined, it detects the current path.
|
||||
*
|
||||
* Con middleware:
|
||||
* $middleware($callback, $req)
|
||||
*
|
||||
* Sin middleware:
|
||||
* $callback($req)
|
||||
*
|
||||
* $req es una instancia de Neuron que tiene los datos de la petición.
|
||||
*
|
||||
* Si no la ruta no coincide con ninguna de las rutas configuradas, ejecutará el callback $notFoundCallback
|
||||
* @return void
|
||||
*/
|
||||
public static function apply(): void
|
||||
public static function apply(?string $path = null): void
|
||||
{
|
||||
$path = static::currentPath();
|
||||
$routers = match($_SERVER['REQUEST_METHOD']) { // Según el método selecciona un arreglo de routers configurados
|
||||
'POST' => static::$post,
|
||||
'PUT' => static::$put,
|
||||
'PATCH' => static::$patch,
|
||||
'DELETE' => static::$delete,
|
||||
default => static::$get
|
||||
};
|
||||
try {
|
||||
$path = $path ?? static::currentPath();
|
||||
$routers = match ($_SERVER['REQUEST_METHOD']) { // Selects an array of routers based on the method
|
||||
'POST' => static::$post,
|
||||
'PUT' => static::$put,
|
||||
'PATCH' => static::$patch,
|
||||
'DELETE' => static::$delete,
|
||||
default => static::$get
|
||||
};
|
||||
|
||||
$req = new Request(static::currentPath());
|
||||
foreach ($routers as $router) { // Checks all routers to see if they match the current path
|
||||
if (preg_match_all('/^' . $router['path'] . '\/?$/si', $path, $matches, PREG_PATTERN_ORDER)) {
|
||||
unset($matches[0]);
|
||||
|
||||
foreach ($routers as $router) { // revisa todos los routers para ver si coinciden con la ruta actual
|
||||
if (preg_match_all('/^'.$router['path'].'\/?$/si',$path, $matches, PREG_PATTERN_ORDER)) {
|
||||
unset($matches[0]);
|
||||
|
||||
// Comprobando pseudo variables en la ruta
|
||||
if (isset($matches[1])) {
|
||||
foreach ($matches as $index => $match) {
|
||||
$paramName = $router['paramNames'][$index-1];
|
||||
$req->params->$paramName = urldecode($match[0]);
|
||||
// Checking and storing the variable parameters of the route
|
||||
if (isset($matches[1])) {
|
||||
static::$params = new Neuron();
|
||||
foreach ($matches as $index => $match) {
|
||||
$paramName = $router['paramNames'][$index - 1];
|
||||
static::$params->{$paramName} = urldecode($match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Processes the callback queue
|
||||
foreach (array_reverse($router['callback']) as $callback) {
|
||||
$data = Synapsis::resolve($callback);
|
||||
}
|
||||
|
||||
// By default, prints as JSON if something is returned
|
||||
if (isset($data)) {
|
||||
header('Content-Type: application/json');
|
||||
print(json_encode($data));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Llamar al último callback configurado
|
||||
$next = array_pop($router['callback']);
|
||||
$req->next = $router['callback'];
|
||||
$data = call_user_func_array($next, [$req]);
|
||||
|
||||
if (isset($data)) {
|
||||
header('Content-Type: application/json');
|
||||
print(json_encode($data));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Si no hay router que coincida llamamos a $notFoundCallBack
|
||||
call_user_func_array(static::$notFoundCallback, [$req]);
|
||||
// If no router matches, call $notFoundCallBack
|
||||
Synapsis::resolve(static::$notFoundCallback);
|
||||
} catch (\Throwable $exception) {
|
||||
Synapsis::resolve(static::$exceptionCallback, ['exception' => $exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Libs;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
|
||||
/**
|
||||
* Synapsis - DuckBrain
|
||||
*
|
||||
* Class responsible for dependency resolution and injection.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class Synapsis
|
||||
{
|
||||
/**
|
||||
* @var array<class-string, class-string> $bindings
|
||||
*/
|
||||
private static array $bindings = [];
|
||||
/**
|
||||
* @var array<class-string, mixed> $instances
|
||||
*/
|
||||
private static array $instances = [];
|
||||
|
||||
/**
|
||||
* Binds an interface to a class to instantiate it instead.
|
||||
*
|
||||
* @param class-string $interfaceName
|
||||
* @param class-string $className
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception If the interface or class does not exist.
|
||||
*/
|
||||
public static function bind(string $interfaceName, string $className): void
|
||||
{
|
||||
if (interface_exists($interfaceName) && class_exists($className)) {
|
||||
static::$bindings[$interfaceName] = $className;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Exception('Error at binding non existant Interface or ClassName.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds multiple interfaces to multiple classes in bulk.
|
||||
*
|
||||
* @param array<class-string, class-string> $bindings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bulkBind(array $bindings): void
|
||||
{
|
||||
foreach ($bindings as $interfaceName => $className) {
|
||||
static::bind($interfaceName, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and injects dependencies for a callable and returns its result.
|
||||
*
|
||||
* @param callable $action
|
||||
* @param array<string, mixed> $named Associative array of values injected into the callable's
|
||||
* parameters by exact name match. Consumed in resolveParameterValues().
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception If an unhandled callable type is provided.
|
||||
*/
|
||||
public static function resolve(callable $action, array $named = []): mixed
|
||||
{
|
||||
if ($action instanceof Closure) { // If it's an anonymous function
|
||||
$reflectionCallback = new ReflectionFunction($action);
|
||||
} else { // Array or string with the method
|
||||
if (is_string($action)) {
|
||||
$action = preg_split('/::/', $action);
|
||||
}
|
||||
|
||||
// Check if it's a method or just a function
|
||||
if (count($action) == 2) {
|
||||
$reflectionCallback = new ReflectionMethod($action[0], $action[1]);
|
||||
} else {
|
||||
$reflectionCallback = new ReflectionFunction($action[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the parameters
|
||||
return call_user_func_array(
|
||||
$action,
|
||||
static::resolveParameterValues($reflectionCallback->getParameters(), $named)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and injects dependencies for a class and returns its result.
|
||||
*
|
||||
* @param class-string $className
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception If a binding is missing for an interface or the class does not exist.
|
||||
*/
|
||||
public static function &resolveInstance(string $className): mixed
|
||||
{
|
||||
if (interface_exists($className)) {
|
||||
if (isset(static::$bindings[$className])) {
|
||||
$className = static::$bindings[$className];
|
||||
} else {
|
||||
throw new Exception("Missing binding for interface: {$className}");
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists($className)) {
|
||||
throw new Exception("Cannot resolve: {$className}");
|
||||
}
|
||||
|
||||
if (!isset(static::$instances[$className])) {
|
||||
// If the instance has not been resolved before, resolve it
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
$constructor = $reflectionClass->getConstructor();
|
||||
static::$instances[$className] = new $className(
|
||||
...static::resolveParameterValues($constructor?->getParameters() ?? [])
|
||||
);
|
||||
}
|
||||
|
||||
return static::$instances[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves parameter values by injecting dependencies.
|
||||
*
|
||||
* @param array<ReflectionParameter> $parameters
|
||||
* @param array<string, mixed> $named
|
||||
* Values injected into parameters whose name matches the key,
|
||||
* taking precedence over optional defaults and DI resolution.
|
||||
* Keys matching no parameter are ignored.
|
||||
*
|
||||
* @return array<mixed>
|
||||
* @throws Exception If a primitive parameter does not have a default value.
|
||||
*/
|
||||
public static function resolveParameterValues(array $parameters, array $named = []): array
|
||||
{
|
||||
$values = [];
|
||||
foreach ($parameters as $parameter) {
|
||||
if ($parameter->isVariadic()) { // Skip variatic parameters
|
||||
continue;
|
||||
}
|
||||
|
||||
if (array_key_exists($parameter->getName(), $named)) { // Named values win over defaults and DI
|
||||
$values[] = $named[$parameter->getName()];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($parameter->isOptional()) { // Always use the default value first
|
||||
$values[] = $parameter->getDefaultValue();
|
||||
continue;
|
||||
}
|
||||
|
||||
$paramType = $parameter->getType();
|
||||
if ($paramType === null) {
|
||||
// If no type is declared, and it's not optional, we cannot resolve it.
|
||||
throw new Exception(
|
||||
"Untyped parameter '{$parameter}' expect at least a default value or must be optional."
|
||||
);
|
||||
}
|
||||
|
||||
if ($paramType->isBuiltin()) {
|
||||
throw new Exception("Primitive parameter '{$parameter->getName()}' expects at least a default value.");
|
||||
}
|
||||
|
||||
$values[] = static::resolveInstance($paramType->getName());
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+75
-60
@@ -1,80 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* View - DuckBrain
|
||||
*
|
||||
* Manejador de vistas simplificado.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @licence MIT
|
||||
*/
|
||||
|
||||
namespace Libs;
|
||||
|
||||
class View extends Neuron {
|
||||
|
||||
/**
|
||||
* View - DuckBrain
|
||||
*
|
||||
* Simplified view handler.
|
||||
*
|
||||
* @author KJ
|
||||
* @website https://kj2.me
|
||||
* @license MIT
|
||||
*/
|
||||
class View extends Neuron
|
||||
{
|
||||
/**
|
||||
* Incluye el archivo.
|
||||
* Includes the file.
|
||||
*
|
||||
* @param string $viewName Ruta relativa y el nommbre sin extensión del archivo.
|
||||
* @param string $viewPath (opcional) Ruta donde se encuentra la vista.
|
||||
* @param string $extension (opcional) Extensión del archivo.
|
||||
* @param string $viewName Relative path and filename without extension.
|
||||
* @param string|null $viewPath (Optional) Path where the view file is located.
|
||||
* @param string $extension (Optional) File extension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function include(
|
||||
protected function include(
|
||||
string $viewName,
|
||||
string $viewPath = null,
|
||||
?string $viewPath = null,
|
||||
string $extension = 'php'
|
||||
): void
|
||||
{
|
||||
$view = $this;
|
||||
|
||||
if (isset($viewPath) &&
|
||||
file_exists("$viewPath$viewName.$extension")) {
|
||||
): void {
|
||||
if (
|
||||
isset($viewPath) &&
|
||||
file_exists("$viewPath$viewName.$extension")
|
||||
) {
|
||||
include("$viewPath$viewName.$extension");
|
||||
return;
|
||||
}
|
||||
|
||||
include(ROOT_CORE."/Views/$viewName.$extension");
|
||||
include(ROOT_CORE . "/Views/$viewName.$extension");
|
||||
}
|
||||
|
||||
/**
|
||||
* Función que "renderiza" las vistas
|
||||
* Function that "renders" views.
|
||||
*
|
||||
* @param string $viewName Ruta relativa y el nommbre sin extensión del archivo.
|
||||
* @param array|Neuron $params (opcional) Arreglo que podrá ser usado en la vista mediante $view ($param['index'] se usaría así: $view->index)
|
||||
* @param string $viewPath (opcional) Ruta donde se encuentra la vista. En caso de que la vista no se encuentre en esa ruta, se usará la ruta por defecto "src/Views/".
|
||||
* @param string $extension (opcional) Extensión del archivo.
|
||||
* @param string $viewName Relative path and filename without extension.
|
||||
* @param array|Neuron $params (Optional) Array that can be used in the view
|
||||
* via $view ($param['index'] would be used as: $view->index).
|
||||
* @param string|null $viewPath (Optional) Path where the view is located. If the
|
||||
* view is not found in this path, the default path "src/Views/" will be used.
|
||||
* @param string $extension (Optional) File extension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function render(
|
||||
string $viewName,
|
||||
array|Neuron $params = [],
|
||||
string $viewPath = null,
|
||||
string $extension = 'php'
|
||||
): void
|
||||
{
|
||||
?string $viewPath = null,
|
||||
string $extension = 'php'
|
||||
): void {
|
||||
$instance = new View($params);
|
||||
$instance->html($viewName, $viewPath);
|
||||
$instance->html($viewName, $viewPath, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderiza las vistas HTML
|
||||
* Renders HTML views.
|
||||
*
|
||||
* @param string $viewName Ruta relativa y el nommbre sin extensión del archivo ubicado en src/Views
|
||||
* @param string $viewPath (opcional) Ruta donde se encuentra la vista. En caso de que la vista no se encuentre en esa ruta, se usará la ruta por defecto "src/Views/".
|
||||
* @param string $extension (opcional) Extensión del archivo.
|
||||
* @param string $viewName Relative path and filename without extension located in src/Views.
|
||||
* @param string|null $viewPath (Optional) Path where the view is located. If the view is not
|
||||
* found in this path, the default path "src/Views/" will be used.
|
||||
* @param string $extension (Optional) File extension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function html(
|
||||
string $viewName,
|
||||
string $viewPath = null,
|
||||
?string $viewPath = null,
|
||||
string $extension = 'php'
|
||||
): void
|
||||
{
|
||||
): void {
|
||||
$this->include(
|
||||
$viewName,
|
||||
$viewPath,
|
||||
@@ -83,47 +83,47 @@ class View extends Neuron {
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderiza código CSS.
|
||||
* Renders CSS code.
|
||||
*
|
||||
* @param string $viewName Ruta relativa y el nommbre sin extensión del archivo ubicado en src/Views
|
||||
* @param string $viewPath (opcional) Ruta donde se encuentra la vista. En caso de que la vista no se encuentre en esa ruta, se usará la ruta por defecto "src/Views/".
|
||||
* @param string $extension (opcional) Extensión del archivo.
|
||||
* @param string $viewName Relative path and filename without extension located in src/Views.
|
||||
* @param string|null $viewPath (Optional) Path where the view is located. If the view is not
|
||||
* found in this path, the default path "src/Views/" will be used.
|
||||
* @param string $extension (Optional) File extension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function css(
|
||||
string $viewName,
|
||||
string $viewPath = null,
|
||||
?string $viewPath = null,
|
||||
string $extension = 'css'
|
||||
): void
|
||||
{
|
||||
): void {
|
||||
header("Content-type: text/css");
|
||||
$this->include($viewName, $viewPath, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderiza código Javascript.
|
||||
* Renders Javascript code.
|
||||
*
|
||||
* @param string $viewName Ruta relativa y el nommbre sin extensión del archivo ubicado en src/Views
|
||||
* @param string $viewPath (opcional) Ruta donde se encuentra la vista. En caso de que la vista no se encuentre en esa ruta, se usará la ruta por defecto "src/Views/".
|
||||
* @param string $extension (opcional) Extensión del archivo.
|
||||
* @param string $viewName Relative path and filename without extension located in src/Views.
|
||||
* @param string|null $viewPath (Optional) Path where the view is located. If the view is not
|
||||
* found in this path, the default path "src/Views/" will be used.
|
||||
* @param string $extension (Optional) File extension.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function js(
|
||||
string $viewName,
|
||||
string $viewPath = null,
|
||||
?string $viewPath = null,
|
||||
string $extension = 'js'
|
||||
): void
|
||||
{
|
||||
): void {
|
||||
header("Content-type: application/javascript");
|
||||
$this->include($viewName, $viewPath, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Imprime los datos en Json.
|
||||
* Prints data as JSON.
|
||||
*
|
||||
* @param object|array $data Objeto o array que se imprimirá a JSON.
|
||||
* @param object|array $data Object or array to be printed as JSON.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -134,9 +134,9 @@ class View extends Neuron {
|
||||
}
|
||||
|
||||
/**
|
||||
* Imprime los datos en texto plano
|
||||
* Prints data as plain text.
|
||||
*
|
||||
* @param string $txt Contenido de texto.
|
||||
* @param string $txt Text content.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -145,5 +145,20 @@ class View extends Neuron {
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
print($txt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to return the absolute URL from a relative path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function route(string $path = '/'): string
|
||||
{
|
||||
if (defined('SITE_URL') && !empty(SITE_URL)) {
|
||||
return rtrim(SITE_URL, '/') . '/' . ltrim($path, '/');
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user