Skip to content

Internally extending the OTOBO core system

In this article, you will learn how to customize OTOBO directly in the core – via XML configuration, Perl modules, and templates. We will show you step-by-step how to integrate your own “HelloWorld” module into the system.


All customizations are located below your OTOBO clone in the Kernel/ directory:

Kernel/
├─ Config/Files/ # XML registrations
│ └─ XML/
├─ System/ # Business logic modules (Core)
├─ Modules/ # Frontend controllers (Agent/Customer)
├─ Output/HTML/Standard/ # Template Toolkit (TT) templates
└─ Language/ # Translations

New modules and routes are registered via XML. Create a file HelloWorld.xml in Kernel/Config/Files/XML/:

<?xml version="1.0" encoding="UTF-8"?>
<otobo_config version="2.0" init="Application">
<!-- 1. Register frontend module -->
<Setting Name="Frontend::Module###AgentHelloWorld" Required="1" Valid="1">
<Navigation>Frontend::Agent::ModuleRegistration</Navigation>
<Value>
<Item ValueType="FrontendRegistration">
<Hash>
<Item Key="Group"><Array><Item>users</Item></Array></Item>
<Item Key="Description" Translatable="1">HelloWorld module</Item>
<Item Key="Title" Translatable="1">HelloWorld</Item>
<Item Key="NavBarName">HelloWorld</Item>
</Hash>
</Item>
</Value>
</Setting>
</otobo_config>

Create your logic in Kernel/System/HelloWorld.pm:

package Kernel::System::HelloWorld;
use strict;
use warnings;
our @ObjectDependencies = ();
sub new {
my ($Type, %Param) = @_;
return bless {}, $Type;
}
sub GetHelloWorldText {
my ($Self, %Param) = @_;
return $Self->_FormatText(String => 'Hello World');
}
sub _FormatText {
my ($Self, %Param) = @_;
return uc $Param{String};
}
1;

In Kernel/Modules/AgentHelloWorld.pm, you integrate your logic into the Agent frontend:

package Kernel::Modules::AgentHelloWorld;
use strict;
use warnings;
sub new { bless {}, shift }
sub Run {
my ($Self, %Param) = @_;
my $HelloObj = $Kernel::OM->Get('Kernel::System::HelloWorld');
my $LayoutObj = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
my %Data;
$Data{Text} = $HelloObj->GetHelloWorldText();
return
$LayoutObj->Header(Title => 'HelloWorld')
. $LayoutObj->NavigationBar()
. $LayoutObj->Output(
TemplateFile => 'AgentHelloWorld',
Data => \%Data,
)
. $LayoutObj->Footer();
}
1;

Create the following template in Kernel/Output/HTML/Standard/AgentHelloWorld.tt:

[% Data.Text %]
<p>This is your self-created HelloWorld module!</p>

  1. Reload:

    Terminal window
    bin/otobo.Console.pl Maint::Config::Rebuild
  2. Clear cache:

    Terminal window
    bin/otobo.Console.pl Maint::Cache::Delete
  3. Open browser: Agent interface → Menu → “HelloWorld”


  • Declare ObjectDependencies cleanly (e.g., DB, Layout).
  • Don’t forget POD documentation in Perl modules.
  • Maintain translations under Kernel/Language/en_*.pm.
  • Set up unit tests with Mojolicious (optional).
  • After every change, perform a Config rebuild & Clear cache.

With this, you have a solid template for implementing further core extensions in OTOBO. Have fun developing!

Custom OTOBO module & plugin development

Need custom features or legacy package upgrades? Softoft builds maintainable, upgrade-safe Perl and frontend extensions.

Frequently asked questions

What is the recommended directory structure for custom OTOBO core extensions?

The recommended directory structure for OTOBO core customizations places all custom files under the Kernel/ directory within your OTOBO installation. This structure helps maintain organization and separates custom code from the core system. Specifically, Kernel/Config/Files/XML/ is where XML files are placed to register new modules and routes, defining how OTOBO recognizes and integrates your extensions. Business logic and core functionalities are implemented in Perl modules located in Kernel/System/, ensuring that the underlying operations are robust and reusable. Frontend controllers, which manage the interaction between the business logic and the user interface, reside in Kernel/Modules/ for both agent and customer interfaces. Presentation layers, utilizing Template Toolkit (TT), are stored in Kernel/Output/HTML/Standard/. Lastly, Kernel/Language/ is designated for translation files, allowing your extension to support multiple languages. This clear separation of concerns aids in development, maintenance, and future upgrades.

Quellen / Sources

How are new frontend modules, like the 'HelloWorld' example, registered in OTOBO?

New frontend modules in OTOBO are registered through XML configuration files, typically located in the Kernel/Config/Files/XML/ directory. For instance, the HelloWorld.xml file demonstrates how to register a module named AgentHelloWorld. Within this XML, an otobo_config element contains a Setting with a Name attribute like Frontend::Module###AgentHelloWorld.

Key elements within this setting define the module's behavior and appearance:

  • Navigation: Specifies the category for the setting, often Frontend::Agent::ModuleRegistration for agent interface modules.
  • ValueType: Indicates the type of value being set, such as FrontendRegistration.
  • Hash items: Define properties like Group (e.g., users to control access), Description (a translatable short description), Title (the translatable name displayed in the navigation), and NavBarName (the name shown in the navigation bar). These configurations ensure the module is correctly recognized and displayed within the OTOBO agent interface.

Quellen / Sources

What are the distinct roles of the core module, frontend module, and templates in an OTOBO custom extension?

In an OTOBO custom extension, each component plays a specific and crucial role:

  • Core Module (e.g., Kernel/System/HelloWorld.pm): This module handles the business logic and core functionalities. It encapsulates the underlying operations, data processing, and system routines, making it reusable and independent of the user interface. It's designed to perform tasks like retrieving or manipulating data, as seen with GetHelloWorldText in the example.

  • Frontend Module (e.g., Kernel/Modules/AgentHelloWorld.pm): Acting as a controller, this module orchestrates the interaction between the core logic and the presentation layer. It retrieves data from core modules (e.g., Kernel::System::HelloWorld), prepares it, and then passes it to the layout and template for rendering. It manages the flow of control and integrates various system components like Kernel::Output::HTML::Layout.

  • Templates (e.g., Kernel/Output/HTML/Standard/AgentHelloWorld.tt): These files are responsible for rendering the user interface using Template Toolkit (TT). They display the data provided by the frontend module in a structured and visually appealing manner. Templates focus solely on presentation, separating it from the application's logic.

This separation of concerns promotes modularity, maintainability, and easier development.

Quellen / Sources

What post-development steps are necessary to activate and view a new OTOBO core extension?

After developing the XML configuration, Perl modules, and templates for a new OTOBO core extension, two crucial console commands must be executed to activate and make the extension visible within the system. First, you need to rebuild the system's configuration by running bin/otobo.Console.pl Maint::Config::Rebuild. This command ensures that OTOBO recognizes the new XML settings you've added, such as module registrations and routes.

Second, it is essential to clear the OTOBO cache. This is achieved by executing bin/otobo.Console.pl Maint::Cache::Delete. Clearing the cache forces the system to load the newly registered modules and templates, preventing issues where old cached data might prevent your changes from appearing. Once these commands are successfully run, your extension can typically be accessed through the OTOBO agent interface, often appearing as a new menu entry or link, as demonstrated by the 'HelloWorld' example.

Quellen / Sources

What are some important best practices to follow when developing OTOBO core extensions?

Adhering to best practices when developing OTOBO core extensions is vital for ensuring maintainability, stability, and future compatibility. Key practices include:

  • Declare ObjectDependencies cleanly: Always specify required objects (e.g., DB, Layout, Logger) in your Perl modules using @ObjectDependencies. This ensures proper dependency injection and makes your code more robust and testable.
  • Include POD Documentation: Add Plain Old Documentation (POD) within your Perl modules. This provides clear, in-code explanations of your module's purpose, methods, and parameters, which is invaluable for other developers and for future reference.
  • Maintain Translations: For internationalization, ensure your module supports multiple languages by maintaining translation files under Kernel/Language/ (e.g., en_*.pm). This makes your extension accessible to a wider user base.
  • Set up Unit Tests: While optional, implementing unit tests, potentially with Mojolicious, is highly recommended. Unit tests help verify the correctness of your code, prevent regressions, and ensure changes don't break existing functionality.
  • Configuration Rebuild & Cache Clear: After any changes to your XML configuration, Perl modules, or templates, consistently perform bin/otobo.Console.pl Maint::Config::Rebuild and bin/otobo.Console.pl Maint::Cache::Delete. This ensures the system recognizes and applies your updates.

Following these practices will lead to higher quality and more sustainable OTOBO extensions.

Quellen / Sources