New Module
For module development in Contrexx 3.1 or newer see article New Component (draft)
This article describes the development of a module for Contrexx until (and including) version 3 ServicePack 4 (3.0.4). For newer versions, please refer to New Component (draft)
This tutorial will guide you through creating a new module in just a few steps.
If you are interested in selling your module, please see Contribute.
Contents
- 1 Get ready
- 2 Determining component type
- 3 Choose a component name
- 4 Design your module
- 5 Where to write your code
- 6 Create module structure
- 7 Module activation
- 8 Backend templates
- 9 Start writing your code
Get ready
In order to successfully create a module for Contrexx, you should know about these things:
Determining component type
Contrexx consists of core components, core modules, modules and libraries. Core components are required for Contrexx to operate. Core modules are needed for Contrexx to work in a reasonable way. Modules are additional applications and libraries are code parts, that can be used outside of Contrexx. To determine to which of these component types your code belongs, see the graphic on the right.
Choose a component name
Now choose a name for your component, respecting these thoughts:
Design your module
This might be the most important step. Before you write any line of code, define for record what your module should do. Create a class diagram and an entity relationship diagram and maybe further sketches!
Where to write your code
Since your code isn't part of a standard installation of Contrexx, you best place it in the /customizing folder (see Contribute). Remember to activate customizings in global settings.
Depending on your chosen component type, your working directory will be one of these (create all non-existing folders):
- /customizing/core/{your component's name}
- /customizing/core_modules/{your component's name}
- /customizing/modules/{your component's name}
- /customizing/lib/{your company's name}/{your component's name}
You must not write any code outside your module directory! Since this is not always possible with current versions of Contrexx, there are some exceptions for this rule:
- Module activation in /core/initFrontend.php and /core/initBackend.php
- Json Adapters
- Doctrine Stuff (Entities, Yaml, Repositories, Events)
For libraries (/customizing/lib) you may start writing your code now and leave out the rest of this article. For core, core_modules and modules, please read on:
Create module structure
Now we create the basic structure for your module. The simplest way to do this is by downloading our "Demo module" This file will be updated soon and does not match the text of this article yet! and uncompress its contents into your module folder. You can of course also create the structure yourself. Here are the explained structure and sample files of the demo module:
File/Folder | Description | Purpose |
---|---|---|
Model | Model folder | See MVC |
Model/Data | Model data folder | Contains fixtures and sample data (currently unused) |
Model/Entity | Model entity folder | Contains entities |
Model/Event | Model event folder | Contains model events |
Model/Repository | Model repository folder | Contains repositories |
Model/Yaml | Model yaml folder | Contains yaml-files used to define entities and their behavior (currently Doctrine only) |
View | View folder | See MVC |
View/Media | View media folder | Contains images, videos, pdf's used by this component |
View/Script | View script folder | Contains client-side scripts such as JavaScript |
View/Script/Main.js | A sample JavaScript file | Demo file replacing some text |
View/Style | View style folder | Contains style definitions (CSS-files) |
View/Style/Main.css | A sample CSS file | Demo file making text red |
View/Template | View template folder | Contains this component's template files |
View/Template/Main.css | A sample template file | Demo template showing some text with a tooltip |
Controller | Controller folder | See MVC |
Controller/ComponentController.class.php | An example controller | Main controller for this component |
Controller/FrontendController.class.php | An example controller | Frontend controller for this component |
Controller/BackendController.class.php | An example controller | Backend controller for this component |
lang | Language folder | Contains language files (see Interface_Text) |
lang/en/backend.php | Backend language file | Default backend language file |
lang/en/frontend.php | Frontend language file | Default frontend language file |
lang/de/backend.php | Backend language file | German backend language file |
lang/de/frontend.php | Frontend language file | German frontend language file |
Testing | Testing folder | Contains test cases (currently unused) |
Module activation
In order to successfully load your module, Contrexx needs some data:
Global language data
To display the correct (display-)name for your module, copy /lang/{lang}/backend.php to /customizing/lang/{lang} and add the following entries (replace DEMO_MODULE with the name of your core component/module/core_module):
$_CORELANG['TXT_DEMO_MODULE'] = 'Demonstration';
$_CORELANG['TXT_DEMO_MODULE_DESCRIPTION'] = 'Sample code for a new module';
Activation
Add a row to the database Table DBPREFIXmodules:
id | name | distributor | description_variable | status | is_required | is_core | is_active |
---|---|---|---|---|---|---|---|
{next free ID} | {Name of your module} | {your (company's) name} | {$_CORELANG array index for description of your module} | y | {'1' for core_module, '0' otherwise} | {'1' for core, '0' otherwise} | 1 |
For {next free ID} enter the next free number that is higher than 900 (non standard IDs are defined to be higher than 900).
Modules need an existing page (frontend) in order to be activated.
Module initialization for frontend
If your module does something in frontend, copy the file /core/initFrontend.php to the customizing folder, then search for a long switch/case statement (starting somewhere after row 1055). Add your module as a case (again, replace demo with the name of your module):
case 'Demo': $component = new \Cx\Modules\Demo\Controller\ComponentController(); $componentCx = null; $componentRequest = null; $em = \Env::get('em'); $component->getPage(true, $_ARRAYLANG, $objTemplate, $em, $objDatabase, $componentCx, $componentRequest, $page_content); break;
For a core module, just change ASCMS_MODULE_PATH to ASCMS_CORE_MODULE_PATH and replace 'Modules' by 'Core_Modules' in namespace. This code should deliver all dependencies to the constructor of your controller (--> Dependency Injection). The last two parameters are objects which do not exist yet.
If you use the session, you must initialize it here! See Session handling for more information.
Module initialization for backend
If your module does something in backend, copy the file /core/initBackend.php to the customizing folder, then search for a long switch/case statement (starting somewhere after row 315). Add your module as a case:
case 'Demo': $component = new \Cx\Modules\Demo\Controller\ComponentController(); $componentCx = null; $componentRequest = null; $em = \Env::get('em'); $component->getPage(false, $_ARRAYLANG, $objTemplate, $em, $objDatabase, $componentCx, $componentRequest); break;
For a core module, just change ASCMS_MODULE_PATH to ASCMS_CORE_MODULE_PATH and replace 'Modules' by 'Core_Modules' in namespace. This code should deliver all dependencies to the constructor of your controller (--> Dependency Injection). The last two parameters are objects which do not exist yet.
You might want to check, if the user is allowed to access this module here. See Development_Permissions for more information.
In order for your module to be displayed in backend, you may add a backend navigation entry. Add a row to DBPREFIXbackend_areas:
area_id | parent_area_id | type | scope | area_name | is_active | uri | target | module_id | order_id | access_id |
---|---|---|---|---|---|---|---|---|---|---|
{next free ID} | {parent ID} | navigation | backend | {$_CORELANG array index for module name} | 1 | index.php?cmd={module name} | _self | {module ID} | {order ID} | {access ID} |
parent_area_id
Choose where your (core) module should be displayed:
parent_area_id | Area |
---|---|
1 | Content Management |
15 | Media |
8 | E-Commerce |
29 | Mail Marketing |
2 | Applications |
28 | Stats |
3 | Administration |
module_id
Enter the ID you used in DBPREFIXmodules.
order_id
The order ID tells Contrexx in which order the entries of this parent_id should be displayed. If you want to append your module to the end of the list, simply enter the next free number with the same parent_id.
access_id
Enter the next free number that is higher than 900 (non standard IDs are defined to be higher than 900). This number is the link between user permissions and your module. After you added the DBPREFIXbackend_areas entry, you may navigate to user management in backend, edit a group and find this ID there. Be sure your user is in a group which has this permission.
Protect functions
You may protect functions (of Contrexx) using DBPREFIXbackend_areas table. For each function you want to protect, add a new row to the table:
area_id | parent_area_id | type | scope | area_name | is_active | uri | target | module_id | order_id | access_id |
---|---|---|---|---|---|---|---|---|---|---|
{next free ID} | 0 | function | {backend, frontend or global} | {$_CORELANG array index for function name} | 1 | (empty) | _self | {module ID} | {order ID} | {access ID} |
These entries will be shown in group permissions too. See Development_Permissions for more info.
Workaround for customizing bug
Until Contrexx 3.0 SP4 (3.0.4), there was a bug causing your module not to be loaded. In order to work around this bug, just create an empty module folder outside the customizing. Let's say your working folder is /customizing/modules/Demo then you may create the directory /modules/Demo.
Easy activation of the demo module
The following code is not tested yet!
Here's the ready-to-use code to perform the steps described in this section for the demo module.
Insert the core language variables, perform the steps described in Module initialization for frontend and Module initialization for backend and execute the following queries in the database of your Contrexx installation:
INSERT INTO `contrexx_modules` (`id`, `name`, `distributor`, `description_variable`, `status`, `is_required`, `is_core`, `is_active`) VALUES (9000, 'Demo', 'yournamehere', 'TXT_DEMO_MODULE', 'y', 0, 0, 1); INSERT INTO `contrexx_backend_areas` (`area_id`, `parent_area_id`, `type`, `scope`, `area_name`, `is_active`, `uri`, `target`, `module_id`, `order_id`, `access_id`) VALUES (NULL, 2, 'navigation', 'backend', 'TXT_DEMO_MODULE', 1, 'index.php?cmd=Demo', '_self', 9000, 0, 0)
After this, navigate to the content manager and create a new page of type application and choose the application named 'Demo'.
Backend templates
Contrexx uses the PEAR HTML Sigma Template templating system. DO NOT USE HTML_Template_Sigma CLASS DIRECTLY use \Cx\Core\Html\Sigma instead (it's a wrapper class for HTML_Template_Sigma in order to allow template customizings).
Place your HTML templates in /customizing/modules/yourmodule/template. Assuming you have a template file named overview.html you could use the following code to include it:
$template = new \Cx\Core\Html\Sigma(ASCMS_MODULE_PATH.'/yourmodule/template/overview.html');
Start writing your code
Now you can start adding your code. Here are some links that might help you finding your way: