Plugin Development with OPM Packages
In this section, you will learn how to create, install, and distribute your own plugins as OPM packages for OTOBO.
1. Structure of a .sopm file
The SOPM file (*.sopm
) contains all the metadata for your package:
<?xml version="1.0" encoding="utf-8"?>
<otobo_package version="1.0">
<Name>MyExtension</Name>
<Version>1.0.0</Version>
<Framework>10.0.x</Framework> <!-- Minimum OTOBO version -->
<Vendor>YourName Inc.</Vendor>
<URL>https://github.com/your-user/otobo-mypackage</URL>
<License>GPL-3.0</License>
<Description Lang="en">Extension for special features</Description>
<ChangeLog Version="1.0.0" Date="13.06.2025 12:00:00">Initial release</ChangeLog>
<Filelist>
<File Location="Kernel/Config/Files/XML/MyExtension.xml" Permission="644"></File>
<File Location="Kernel/System/MyExtension.pm" Permission="644"></File>
<File Location="Kernel/Modules/AgentMyPage.pm" Permission="644"></File>
<File Location="Kernel/Output/HTML/Standard/AgentMyPage.tt" Permission="644"></File>
<File Location="Kernel/Language/en_MyExtension.pm" Permission="644"></File>
</Filelist>
</otobo_package>
- Name/Version/Framework: Unique package identifier and compatible OTOBO version.
- Filelist: All files that will be copied during installation.
2. Files & Directory Structure
Create your package in its own directory, e.g., MyExtension/
:
MyExtension/
├─ MyExtension.sopm
├─ Kernel/
│ ├─ Config/Files/XML/MyExtension.xml
│ ├─ System/MyExtension.pm
│ ├─ Modules/AgentMyPage.pm
│ ├─ Output/HTML/Standard/AgentMyPage.tt
│ └─ Language/en_MyExtension.pm
└─ sql/
└─ create_tables.sql # optional, for DB migrations
- Kernel/Config/Files/XML/: Registers modules, menus, or Dynamic Fields.
- Kernel/System/: Business logic class.
- Kernel/Modules/: Frontend controller.
- Templates & Language: TT files + translation .pm files.
3. Building & Installing the Package
3.1 Creating the OPM
Use the CLI tool to build an OPM from your SOPM:
cd /path/to/MyExtension
bin/otobo.Console.pl Dev::Package::Build \
--sopm-file MyExtension.sopm \
--output /tmp/MyExtension.opm
3.2 Installation
Admin UI: Upload the package under Admin → Settings → Package Management. Console:
bin/otobo.Console.pl Admin::Package::Install /tmp/MyExtension.opm
To uninstall or upgrade:
bin/otobo.Console.pl Admin::Package::Uninstall /tmp/MyExtension.opm
bin/otobo.Console.pl Admin::Package::Upgrade /tmp/MyExtension.opm
4. Extension Points
4.1 Dynamic Fields
In Kernel/Config/Files/XML/MyExtension.xml
, you register a new Dynamic Field driver:
<Setting Name="DynamicFields::Driver###MyCustomField" Required="0" Valid="1">
<Navigation>DynamicFields::Driver</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="DriverName">MyCustomField</Item>
<Item Key="Module">Kernel::System::DynamicField::Driver::MyCustomField</Item>
</Hash></Item>
</Array>
</Value>
</Setting>
Implement the driver in Kernel/System/DynamicField/Driver/MyCustomField.pm
.
4.2 Event Handlers
Register your event handler:
<Setting Name="Event::EventHandler###MyHandler" Required="0" Valid="1">
<Navigation>Event::EventHandler</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="Module">Kernel::System::Event::Handler::MyHandler</Item>
</Hash></Item>
</Array>
</Value>
</Setting>
Implement the handler in Kernel/System/Event/Handler/MyHandler.pm
(the Run()
method).
4.3 Output Filters
<Setting Name="Output::Filter###MyFilter" Required="0" Valid="1">
<Navigation>Output::Filter</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="Module">Kernel::System::Output::Filter::MyFilter</Item>
</Hash></Item>
</Array>
</Value>
</Setting>
Filter in Kernel/System/Output/Filter/MyFilter.pm
.
5. Deployment & OTOpar
Repository Index: Create
Packages.xml
for your own repository:bashbin/otobo.Console.pl Dev::Package::RepositoryIndex \ --directory /var/www/otobo-packages
Add your repository URL under SysConfig in
Package::RepositoryList
.OTOpar: Upload your OPM to https://otopar.perl-services.de so that others can install it directly.
6. Example: MyCalendar Package
- Create the SOPM with the name
MyCalendar
. - DB script
sql/create_calendar.sql
for thecalendar_events
table. - Config XML defines a new ticket field "Appointment".
- Core module
Kernel/System/CalendarEvent.pm
with CRUD methods. - Frontend modules
Kernel/Modules/AgentCalendar.pm
, templateAgentCalendar.tt
. - Build the package and upload it to OTOpar.
7. Tips & Best Practices
- Adjust the version number in the
sopm
(SemVer). - DB migrations in
sql/
should be cleanly versioned. - Create unit tests for system and module classes.
- Documentation in the README plus POD in Perl modules.
- Translations in
Language/de_*.pm
anden_*.pm
.
With this, you have a solid foundation to develop, distribute, and maintainably use your own OTOBO plugins in client projects. Have fun