Skip to content

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
<?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:

bash
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:

bash
bin/otobo.Console.pl Admin::Package::Install /tmp/MyExtension.opm

To uninstall or upgrade:

bash
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:

xml
<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:

xml
<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

xml
<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:

    bash
    bin/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

  1. Create the SOPM with the name MyCalendar.
  2. DB script sql/create_calendar.sql for the calendar_events table.
  3. Config XML defines a new ticket field "Appointment".
  4. Core module Kernel/System/CalendarEvent.pm with CRUD methods.
  5. Frontend modules Kernel/Modules/AgentCalendar.pm, template AgentCalendar.tt.
  6. 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 and en_*.pm.

With this, you have a solid foundation to develop, distribute, and maintainably use your own OTOBO plugins in client projects. Have fun