Skip to content

Releases: luminovang/framework

3.8.4

03 Jun 18:20

Choose a tag to compare

Full Changelog: 3.8.3...3.8.4

3.8.3

02 Jun 19:45

Choose a tag to compare

Full Changelog: 3.8.2...3.8.3

3.8.2

16 May 14:12

Choose a tag to compare

Full Changelog: 3.6.6...3.8.2

3.8.1

09 May 07:17

Choose a tag to compare

Full Changelog: 3.7.9...3.8.1

3.7.9

27 Apr 17:59

Choose a tag to compare

Full Changelog: 3.7.8...3.7.9

3.7.8

13 Apr 16:20

Choose a tag to compare

Full Changelog: 3.6.6...3.7.8

3.7.2

22 Mar 17:35

Choose a tag to compare

Full Changelog: 3.7.0...3.7.2

Changes

3.7.0

12 Dec 12:48

Choose a tag to compare

Full Changelog: 3.6.8...3.7.0

Fixes

Fixed incorrect mixing of PHP 8.1 standards with PHP 8.0, which caused runtime errors.


New Features


PHP Layout Composition

Improved the PHP layout composition class and introduced new helper features.
The layout object is now automatically available inside PHP template files when App\Config\Template->enableDefaultTemplateLayout is enabled.

Dynamic Template Placeholders

Placeholders defined within a layout section are now resolved automatically when extending or rendering the layout with options:

<?php $this->layout->begin('title'); ?>
<h1>{{ placeholder }}</h1>
<?php $this->layout->end('title'); ?>

Smarty Template Extension

Improved the Smarty extension to provide simpler access to functions and classes, giving it behavior in Luminova closer to Twig.

Object Method Access

You can now call object methods directly without assigning the object to a Smarty variable first:

{{ $self.app->doFoo()->getBar() }}

Smarty & Twig Template Extension

Improved both extensions with a single configuration point for managing custom extensions and modifiers.
Template caching is now handled by Luminova for consistent behavior and integration with the static URL cache system.


Routing System

Optimized the routing system. All HTTP method helpers are now static.
Dependency Injection in routing has been improved to honor default parameter values when a dependency cannot be resolved.

Added the Router::isPrefix(...) helper for checking URI prefixes.

Static HTTP Helpers:

  • get — HTTP GET
  • post — HTTP POST
  • put — HTTP PUT
  • patch — HTTP PATCH
  • delete — HTTP DELETE
  • head — HTTP HEAD
  • options — HTTP OPTIONS
  • any — Any valid HTTP method
  • middleware — Before-middleware handler
  • after — After-middleware handler
  • guard — CLI middleware handler
  • capture — Custom HTTP methods
  • command — CLI command
  • group — CLI command grouping
  • bind — HTTP URI group binding
  • onError — HTTP error handler

HTTP Message Stream

Optimized the message stream class, added a new buffer method, and moved the class namespace from
Luminova\Utility\Storage\Stream to Luminova\Http\Message\Stream.


Global Import Function

The global import() function now supports promise resolving:

use function \Luminova\Funcs\import;

import('view:template', promise: true)
  ->then(fn(string $html) => print($html))
  ->catch(fn(Throwable $e) => echo $e->getMessage());

3.6.8

22 Nov 15:23

Choose a tag to compare

Full Changelog: 3.6.6...3.6.8

Version 3.6.8 brings a major cleanup across Luminova’s core. Many parts were renamed, optimized, or fixed, and several new helper classes were added, including Password, String, and the improved error-handling system. The template view engine and the core exception layer also received substantial tuning.

Default HTTP error templates now support grouped pages using 4xx.php and 5xx.php, replacing the old 404.php and 500.php pattern.


Fixes

Routing System

Fixed an issue where routes defined with HTTP HEAD method were incorrectly returning 404 errors.


New Features

HTTP Controller Methods

HTTP controller routable methods can now return Psr\Http\Message\ResponseInterface, Luminova\Interface\ViewResponseInterface, or the traditional int.

Example

Using Luminova\Template\Response class.

use Luminova\Attributes\Route;
use Luminova\Http\Message\Response;
use Psr\Http\Message\ResponseInterface;

#[Route('/api/hello', methods: ['GET'])]
public function hello(): ViewResponseInterface
{
  return new Response('Hello world', 200);
}

Routing System

Added a new pattern method to define and manage custom URI segment placeholders.
This allows you to create reusable patterns for route parameters, improving maintainability and reducing repetition of patterns.

// In App\Application::onCreate()
Router::pattern('slug', '[a-z0-9-]+');  

// In App\Controllers
#[Luminova\Attributes\Route('/blog/(:slug)', methods: ['GET'])]
public function blog(string $slug): int 
{
  // Handle blog route using the slug value
}

Note:
Once defined, the slug pattern can be reused across multiple routes, ensuring consistent validation.


Password Helper

A new Password helper has been added to handle all password-related operations in one place.

Now:

use Luminova\Security\Password;

$hash = Password::hash('pass');
Password::verify('pass', $hash);

// Additional utilities:
Password::rehash('pass', $hash);
Password::strength('pass');
Password::isCompromised('pass');

// and more...

Before:

Crypter::password('pass');
Crypter::isPassword('pass', 'hash');

Proxy Helper

A dedicated Proxy helper is now available for checking and validating HTTP/SOCKS proxies.

Now:

use Luminova\Utility\Proxy;

$proxy = '';
Proxy::validate($proxy);
Proxy::ping($proxy);

// and more...

String Helper

A new Str helper provides object-based string manipulation features.

Now:

use Luminova\Utility\String\Str;

$str = Str::of('peter');

echo $str->length();         // 5
echo $str->toUpperCase()
         ->trim();           // PETER

// and more...

Backend Session Class

The Session class now supports role-based access control, with methods for finer-grained permission management:

  • roles(array $roles)
    Assign user roles to the session.

  • getRoles(): array
    Retrieve all roles currently stored in the session.

  • guard(array $roles, int $mode = Session::GUARD_ANY, ?callable $onDenied = null): bool
    Validate roles against access rules. Returns true if access is denied (fail-fast pattern), false if access is granted.

  • toSessionId(string $id, string $algo = 'sha256')
    Convert a string into a valid PHP session ID.

    Example:

    Convert a system identifier into a valid PHP session ID for persistent CLI logins.

    use Luminova\Command\Terminal;
    use Luminova\Sessions\Session;
    
    $sid = Session::toSessionId(Terminal::getSystemId());

    Supported Guard Modes:

    • Session::GUARD_ANY (default): Access granted if at least one role matches.
    • Session::GUARD_ALL: Access granted only if all roles match.
    • Session::GUARD_EXACT: Access granted only if all and only the specified roles match.
    • Session::GUARD_NONE: Access granted only if none of the roles are present.

Example:

if ($session->guard(['admin', 'moderator'], Session::GUARD_ALL)) {
    throw new AccessDenied('Insufficient privileges.');
}

PHP Route Attribute

A new $aliases property has been added to the Route attribute to define multiple alternative URI patterns for the same controller method.

Before (using multiple attributes)

Previously, to map several URIs to the same method, you had to repeat the Route attribute:

// /app/Controllers/Http/ExampleController.php

use Luminova\Attributes\Route;

#[Route('/', methods: ['GET'])]
#[Route('/home', methods: ['GET'])]
#[Route('/default', methods: ['GET'])]
#[Route('/dashboard', methods: ['GET'])]
public function home(): int 
{
  return $this->view('index');
}

Now (using aliases)

You can achieve the same result with a single attribute, improving readability and reducing duplication:

// /app/Controllers/Http/ExampleController.php

use Luminova\Attributes\Route;

#[Route('/', methods: ['GET'], aliases: [
  '/home',
  '/default'
  '/dashboard'
])]
public function home(): int 
{
  return $this->view('index');
}

PHP Prefix Attribute

The Prefix attribute now supports a new $exclude property that allows you to specify URI prefixes to exclude from controller matching. This removes the need for complex negative-lookahead patterns.

Before (manual regex exclusions)

// /app/Controllers/Http/MainController.php

use Luminova\Attributes\Prefix;

#[Prefix(pattern: '/(?!api(?:/|$)|admin(?:/|$)).*')]
class MainController extends Controller
{
}

Now (using the built-in exclude list)

// /app/Controllers/Http/MainController.php

use Luminova\Attributes\Prefix;

#[Prefix(pattern: '/(:base)', exclude: [
    'api',
    'admin'
])]
class MainController extends Controller
{
}

Full Changes documentation.

3.6.7

05 Aug 11:17

Choose a tag to compare

Full Changelog: 3.6.6...3.6.7

New Features

Core Application Class

Introduced a new static method: onShutdown().
This method acts as a hook that runs when the application terminates due to a fatal error or explicit shutdown. It allows the application to inspect the error and choose to:

  • Return false to suppress default framework handling.
  • Return true to let the framework handle the error normally.

Example:

// /app/Application.php
namespace App;

use Luminova\Core\CoreApplication;

class Application extends CoreApplication
{
    public static function onShutdown(array $error): bool 
    {
        return true;
        // Or handle shutdown and return false
    }
}

This gives developers more control over graceful shutdowns in critical situations.


Optimizations

Global Helper Functions

Improved performance and flexibility of global functions.

  • import() now supports resolving virtual paths using predefined URI-style schemes. This simplifies file inclusion across common system directories.

Examples:

import('app:Config/settings.php');
import('view:layouts/header.php');
import('package:brick/math/src/BigNumber.php');

This update enhances code readability and keeps file paths consistent across modules.
You can still pass a full file path if preferred. The scheme prefix is entirely optional.

Full Changes