Skip to main content

Creating a custom module

The Jadu Control Center is extensible in that you can develop your own modules and have them accessed through the Control Center using the granular, role-based access privileges.

You can also use the Jadu Pulsar user interface library to ensure your custom modules have consistent user experiences with Jadu Central.

Structure

A custom module should follow the MVC architecture. It is recommended that you create your module within a bundle that is registered with the application.

A module is comprised of:

  • Model: Entities, Data Mappers and related database tables
  • View: Twig templates
  • Controller: Class linking the Model with the View and any other service classes
  • Database entries: To register the module and position it in the menu

Creating a module

Before you start, it is a good idea to plan out what you need in your module and identify any required database tables, their mapped entities as well as the pages that you want to appear in the Control Center.

Model

What's required here will vary a lot depending on the purpose of your module.

Start by adding database migrations to create the required database table(s).

Create an Entity class for each database table that needs to be represented in your application's logic as well as a Data Mapper for each to handle moving those entities in and out of the database table.

Make sure to define your Data Mapper(s) as services in your bundles services.yml:

Custom\Module\DataMapper\ThingMapper:
arguments:
- '@Jadu\Continuum\Context\JaduSiteContext'

View

Create your twig template(s) and place them in your bundle in Resources/views.

To use the standard Jadu Central UI, your template should extend base.html.twig and import a number of helpers, as in the example below:

{% extends '@assets/base.html.twig' %}

{% import '@pulsarBundle/views/pulsar/v2/helpers/html.html.twig' as html %}
{% import '@pulsarBundle/views/pulsar/v2/helpers/form.html.twig' as form %}
{% import '@pulsarBundle/views/pulsar/v2/helpers/flash.html.twig' as flash %}
{% import '@pulsarBundle/views/pulsar/v2/helpers/tabs.html.twig' as tabs %}
{% import _self as macros %}

{% block tabs_content %}
<!-- Page content goes here... -->
{% endblock tabs_content %}

Controller

Create your Controller class and have any logic needed carried out through a call to the __invoke() method.

Inject any required dependencies where possible. In the example below we pass the Data Mapper to the constructor.

namespace CustomBundle\Controller;

use Custom\Module\DataMapper\ThingMapper;
use Jadu\ControlCentre\Response\Renderer;

class CustomController
{
private Renderer $renderer;

private ThingMapper $mapper;

public function __construct(Renderer $renderer, ThingMapper $mapper)
{
$this->renderer = $renderer;
$this->mapper = $mapper;
}

public function __invoke()
{
return $this->renderer->render('@Custom/template.html.twig', [ ]);
}
}

Register the controller in the services.yml config file:

custombundle.controller.custompage:
class: CustomBundle\Controller\CustomController
arguments:
- '@jadu_cc.request.response_renderer'
- '@Custom\Module\DataMapper\ThingMapper'

Finally, map the URL path to your controller the routes.yml config for your bundle:

custom_page:
path: /custom/page
methods: GET
defaults:
_controller: custombundle.controller.custompage

Database entries

For your module and its pages to be accessible from the menu and to allow Jadu Central administrator privileges to be set against it, you must add records to JaduModules and JaduModulePages database tables.

Create a migration to add the Custom module to JaduModules:


namespace DoctrineMigrations;

use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version20210527123456 extends AbstractMigration
{
public function up(Schema $schema)
{
$sql = <<<SQL
INSERT INTO JaduModules (
id, name, module_url, displayOrder
) VALUES (
7, 'Custom', '/custom', 6
)
SQL;

$this->addSql($sql);
}

public function down(Schema $schema)
{
$this->addSql("DELETE FROM JaduModules WHERE id=7");
}
}
note

The module ID 7 is reserved for the custom module and is the only ID number that should be used. Use of any other ID numbers may result in collisions with current or future modules.

Then add subsequent migrations for your pages:


namespace DoctrineMigrations;

use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;

class Version20210527123457 extends AbstractMigration
{
public function up(Schema $schema)
{
$sql = <<<SQL
INSERT INTO JaduModulePages (
`module_id`, `page_url`, `name`, `parent_id`, `workflow`,
`adminAccessOnly`, `position`, `pageGroup`, `isTab`
) VALUES (
7, '/custom/things', 'Things', -1, 1,
0, 0, 0, 0
);
SQL;

$this->addSql($sql);
}

public function down(Schema $schema)
{
$this->addSql("DELETE FROM JaduModulePages WHERE module_id=7 AND page_url='/custom/things'");
}
}

Once the above records are added, your module and its pages will be available to grant permissions to through the same Utilities > Admin Privileges interface as all other pages in Jadu Central.

Further information

The Jadu Central Advanced Developer Training course provides further examples for creating your own modules.