mirror of
https://github.com/mivodev/mivo.git
synced 2026-01-26 05:25:42 +07:00
Chore: Bump version to v1.1.0 and implement automated release system
This commit is contained in:
@@ -45,7 +45,7 @@ class Console {
|
||||
|
||||
private function printBanner() {
|
||||
echo "\n";
|
||||
echo self::COLOR_BOLD . " MIVO Helper " . self::COLOR_RESET . self::COLOR_GRAY . "v1.0" . self::COLOR_RESET . "\n\n";
|
||||
echo self::COLOR_BOLD . " MIVO Helper " . self::COLOR_RESET . self::COLOR_GRAY . "v1.1.0" . self::COLOR_RESET . "\n\n";
|
||||
}
|
||||
|
||||
private function commandServe($args) {
|
||||
|
||||
@@ -61,6 +61,7 @@ class Migrations {
|
||||
// 6. Quick Prints (Voucher Printing Profiles)
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS quick_prints (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
router_id INTEGER,
|
||||
session_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
server TEXT NOT NULL,
|
||||
@@ -68,6 +69,7 @@ class Migrations {
|
||||
prefix TEXT DEFAULT '',
|
||||
char_length INTEGER DEFAULT 4,
|
||||
price INTEGER DEFAULT 0,
|
||||
selling_price INTEGER DEFAULT 0,
|
||||
time_limit TEXT DEFAULT '',
|
||||
data_limit TEXT DEFAULT '',
|
||||
comment TEXT DEFAULT '',
|
||||
@@ -79,6 +81,7 @@ class Migrations {
|
||||
// 7. Voucher Templates
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS voucher_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
router_id INTEGER,
|
||||
session_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
|
||||
@@ -4,13 +4,91 @@ namespace App\Core;
|
||||
|
||||
class Router {
|
||||
protected $routes = [];
|
||||
protected $currentGroupMiddleware = [];
|
||||
protected $lastRouteKey = null;
|
||||
|
||||
protected $middlewareAliases = [
|
||||
'auth' => \App\Middleware\AuthMiddleware::class,
|
||||
'cors' => \App\Middleware\CorsMiddleware::class,
|
||||
'router.valid' => \App\Middleware\RouterCheckMiddleware::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Add a GET route
|
||||
*/
|
||||
public function get($path, $callback) {
|
||||
$this->routes['GET'][$path] = $callback;
|
||||
return $this->addRoute('GET', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a POST route
|
||||
*/
|
||||
public function post($path, $callback) {
|
||||
$this->routes['POST'][$path] = $callback;
|
||||
return $this->addRoute('POST', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add route to collection and return $this for chaining
|
||||
*/
|
||||
protected function addRoute($method, $path, $callback) {
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
$this->routes[$method][$path] = [
|
||||
'callback' => $callback,
|
||||
'middleware' => $this->currentGroupMiddleware // Inherit group middleware
|
||||
];
|
||||
|
||||
$this->lastRouteKey = ['method' => $method, 'path' => $path];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach middleware to the last defined route
|
||||
*/
|
||||
public function middleware($names) {
|
||||
if (!$this->lastRouteKey) return $this;
|
||||
|
||||
$method = $this->lastRouteKey['method'];
|
||||
$path = $this->lastRouteKey['path'];
|
||||
|
||||
$middlewares = is_array($names) ? $names : [$names];
|
||||
|
||||
// Merge with existing middleware (from groups)
|
||||
$this->routes[$method][$path]['middleware'] = array_merge(
|
||||
$this->routes[$method][$path]['middleware'],
|
||||
$middlewares
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a route group with shared attributes (middleware, prefix, etc.)
|
||||
*/
|
||||
public function group($attributes, callable $callback) {
|
||||
$previousGroupMiddleware = $this->currentGroupMiddleware;
|
||||
|
||||
if (isset($attributes['middleware'])) {
|
||||
$newMiddleware = is_array($attributes['middleware'])
|
||||
? $attributes['middleware']
|
||||
: [$attributes['middleware']];
|
||||
|
||||
$this->currentGroupMiddleware = array_merge(
|
||||
$this->currentGroupMiddleware,
|
||||
$newMiddleware
|
||||
);
|
||||
}
|
||||
|
||||
// Execute the callback with $this router instance
|
||||
$callback($this);
|
||||
|
||||
// Restore previous state
|
||||
$this->currentGroupMiddleware = $previousGroupMiddleware;
|
||||
}
|
||||
|
||||
protected function normalizePath($path) {
|
||||
return '/' . trim($path, '/');
|
||||
}
|
||||
|
||||
public function dispatch($uri, $method) {
|
||||
@@ -21,27 +99,24 @@ class Router {
|
||||
if (strpos($path, $scriptName) === 0) {
|
||||
$path = substr($path, strlen($scriptName));
|
||||
}
|
||||
$path = '/' . trim($path, '/');
|
||||
$path = $this->normalizePath($path);
|
||||
|
||||
// Global Install Check: Redirect if database is missing
|
||||
// Global Install Check
|
||||
$dbPath = ROOT . '/app/Database/database.sqlite';
|
||||
if (!file_exists($dbPath)) {
|
||||
// Whitelist /install route and assets to prevent infinite loop
|
||||
if ($path !== '/install' && strpos($path, '/assets/') !== 0) {
|
||||
header('Location: /install');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Check exact match first
|
||||
// 1. Try Exact Match
|
||||
if (isset($this->routes[$method][$path])) {
|
||||
$callback = $this->routes[$method][$path];
|
||||
return $this->invokeCallback($callback);
|
||||
return $this->runRoute($this->routes[$method][$path], []);
|
||||
}
|
||||
|
||||
// Check dynamic routes
|
||||
foreach ($this->routes[$method] as $route => $callback) {
|
||||
// Convert route syntax to regex
|
||||
// 2. Try Dynamic Routes (Regex)
|
||||
foreach ($this->routes[$method] as $route => $config) {
|
||||
// e.g. /dashboard/{session} -> #^/dashboard/([^/]+)$#
|
||||
$pattern = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '([^/]+)', $route);
|
||||
$pattern = "#^" . $pattern . "$#";
|
||||
@@ -49,13 +124,43 @@ class Router {
|
||||
if (preg_match($pattern, $path, $matches)) {
|
||||
array_shift($matches); // Remove full match
|
||||
$matches = array_map('urldecode', $matches);
|
||||
return $this->invokeCallback($callback, $matches);
|
||||
return $this->runRoute($config, $matches);
|
||||
}
|
||||
}
|
||||
|
||||
\App\Helpers\ErrorHelper::show(404);
|
||||
}
|
||||
|
||||
protected function runRoute($routeConfig, $params) {
|
||||
$callback = $routeConfig['callback'];
|
||||
$middlewares = $routeConfig['middleware'];
|
||||
|
||||
// Pipeline Runner
|
||||
$pipeline = array_reduce(
|
||||
array_reverse($middlewares),
|
||||
function ($nextStack, $middlewareName) {
|
||||
return function ($request) use ($nextStack, $middlewareName) {
|
||||
// Resolve Middleware Class
|
||||
$class = $this->middlewareAliases[$middlewareName] ?? $middlewareName;
|
||||
|
||||
if (!class_exists($class)) {
|
||||
throw new \Exception("Middleware class '$class' not found.");
|
||||
}
|
||||
|
||||
$instance = new $class();
|
||||
return $instance->handle($request, $nextStack);
|
||||
};
|
||||
},
|
||||
function ($request) use ($callback, $params) {
|
||||
// Final destination: The Controller
|
||||
return $this->invokeCallback($callback, $params);
|
||||
}
|
||||
);
|
||||
|
||||
// Start the pipeline with the current request (mock object or just null/path)
|
||||
return $pipeline($_SERVER);
|
||||
}
|
||||
|
||||
protected function invokeCallback($callback, $params = []) {
|
||||
if (is_array($callback)) {
|
||||
$controller = new $callback[0]();
|
||||
|
||||
Reference in New Issue
Block a user