jinexus-framework/jinexus-module-manager

Module Manager component from JiNexus Framework

Maintainers

Package info

github.com/jinexus-framework/jinexus-module-manager

Type:component

pkg:composer/jinexus-framework/jinexus-module-manager

Transparency log

Statistics

Installs: 8

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-07-29 19:00 UTC

This package is auto-updated.

Last update: 2026-07-29 19:23:01 UTC


README

JiNexus Module Manager provides a simple modular approach for jinexus-mvc applications. It keeps an ordered registry of module namespaces and resolves any of them to a configuration array by convention — append \Module to the namespace, instantiate it, and ask it for its config.

The package intentionally ships no concrete module. Your application provides its own Vendor\Package\Module class extending AbstractModule, returning whatever that module contributes (routes, services, view paths, and so on).

Requirements

  • PHP ^8.5

Installation

Install via Composer:

composer require jinexus-framework/jinexus-module-manager

Usage

Creating a module manager

use JiNexus\ModuleManager\ModuleManager\ModuleManager;
use JiNexus\ModuleManager\ModuleManager\Factory\ModuleManagerFactory;

$manager = new ModuleManager();

// ...or via the factory (a fresh, independent instance each call).
$manager = ModuleManagerFactory::build();

Registering modules

Modules are registered as namespace strings, not class names or objects:

$manager->setModules(['Acme\Blog', 'Acme\Shop']);
$manager->getModules();             // ['Acme\Blog', 'Acme\Shop']

$manager->addModule('Acme\Wiki');   // true  — appended
$manager->addModule('Acme\Wiki');   // false — already registered

Two things about setModules() are worth knowing up front, because they differ from a conventional setter:

$manager->setModules(['Acme\Blog']);
$manager->setModules(['Acme\Shop']);
$manager->getModules();   // ['Acme\Blog', 'Acme\Shop'] — it appends, it does not replace

$manager->setModules([]); // a no-op, NOT a reset
$manager->setModules(['blog' => 'Acme\Blog']);
$manager->getModules();   // keys are discarded; the list is re-indexed

setModules() does not deduplicate — only addModule() checks for an existing entry, and it reports whether the module was actually added.

Writing a module

Extend AbstractModule and override getConfig(). The class must be named Module and sit directly under the namespace you register:

namespace Acme\Blog;

use JiNexus\ModuleManager\ModuleManager\AbstractModule;

class Module extends AbstractModule
{
    public function getConfig(): array
    {
        return [
            'name'   => 'blog',
            'routes' => ['blog' => ['route' => '/blog']],
        ];
    }
}

AbstractModule::getConfig() returns [], so a module that overrides nothing is valid and simply contributes no configuration.

Reading a module's config

$manager->getConfig('Acme\Blog');
// instantiates Acme\Blog\Module and returns its getConfig() result

The argument is the namespace above the module class — \Module is appended for you. Resolution is independent of registration: a module does not have to be added to the manager before its config can be read.

foreach ($manager->getModules() as $module) {
    $config = $manager->getConfig($module);
    // merge it into your application config however your app prefers
}

The manager returns each module's config as-is; merging, validating, and caching are left to the consuming application.

Error handling

Package-level failures throw JiNexus\ModuleManager\ModuleManagerException (a subclass of \Exception):

$manager->getConfig();     // ModuleManagerException: Module is required
$manager->getConfig('');   // ModuleManagerException: Module is required

An unsupported magic getter/setter resolved through AbstractBase::__call also throws a ModuleManagerException with a Not implemented: … message.

An unresolvable namespace also throws a ModuleManagerException:

$manager->getConfig('No\Such\Vendor');
// ModuleManagerException: Module class "No\Such\Vendor\Module" cannot be resolved

Upgrading from 1.0.0

Version 1.1.0 raises the PHP floor to ^8.5 and renames the package exception:

// 1.0
use JiNexus\ModuleManager\Exception;

// 1.1
use JiNexus\ModuleManager\ModuleManagerException;

It also adds parameter and return types across the public API, so if you implement ModuleInterface/ModuleManagerInterface or extend AbstractModule/AbstractModuleManager, your overrides need matching declarations — notably getConfig(): array. See CHANGELOG.md for the full upgrade notes.

Extending

ModuleManager is a deliberately empty subclass of AbstractModuleManager — all behavior lives on the abstract so the concrete class stays a stable extension point. Extend AbstractModuleManager when you want to change registry behavior and extend AbstractModule for your application's modules.

ModuleManagerInterface declares getModules() and getConfig() as mixed; AbstractModuleManager narrows both to array. Implementations may narrow further.

Testing

composer install
composer test            # or: ./vendor/bin/phpunit
composer test:coverage   # text coverage report
composer test:testdox    # readable, per-test output

phpunit.dist.xml is the committed configuration. Use XDEBUG_MODE=off to silence the local Xdebug notice:

XDEBUG_MODE=off ./vendor/bin/phpunit --testdox

Contributing

Please see CONDUCT.md for the code of conduct. Contributions should include tests and a CHANGELOG.md entry. See AGENTS.md for detailed build, style, and workflow conventions.

License

BSD-3-Clause. See LICENSE.md.