Hallo,
OTRS ist in seiner derzeitigen Version ja bereits ein sehr mächtiges und komplexes Werkzeug geworden. Schön sind dabei die vielfältigen Konfigurationsmöglichkeiten (man wird ja mit der Optionsvielfalt unter Sysconfig förmlich erschlagen) und die Erweiterung durch eigene Module.
Dennoch empfinde ich das OTRS System an einigen Stellen etwas zu unflexibel. Erweiterungen der vorhandenen Module funktionieren meist ja nur, in dem man a) über die GmbH entsprechende Leistung einkauft oder b) selbst in den Modulen "rumschmiert".
Punkt b) ist dabei immer gefährlich, da ja doch zumeist nebst den Frontend-Modulen auch einige Backend-Module verändert werden müssen und man bei Versionsupdates des OTRS Systems die Arbeit hat, die Patches/Hacks immer wieder neu einpflegen zu müssen.
Punkt a) ist natürlich immer vorzuziehen, womal es da ja dann sicher auch einen enstprechenden Pflege- und Supportvertrag dazu gibt.
Leider ist es aber nicht immer möglich entsprechende Geldmittel locker zu machen ... bei mir hier ist das bspw. so. Also pfusche ich selber im Programmcode rum (siehe [Announce] Neuer otrs-forum.de Sammelpatch V1.4).
Da die Änderungen aber immer komplexer wurden und das Portieren dadurch nicht einfach ist, musste eine andere Lösung her. Viele OS Softwareprodukte bieten über Extensions/Plugins/Hooks und wie sie alle heißen, Schnittstellen an, mit denen man die vorhandenen Funktionen erweitern oder gar ersetzen kann.
Ich hab das mal als einen ersten Versuch für OTRS umgesetzt. Auch hier geht es natürlich erst mal nicht ohne Anpassungen des Programmcodes, aber diese beschränken sich auf 3 Dateien mit wenigen Zeilen.
Dieser Hack ermöglicht es dann, eigene Frontend- (und Backend-) Module zu programmieren die dann bspw. die HTML Ausgabe manipulieren (in dem sie zusätzliche Daten anbietet oder gar die vom OTRS Modul erzeugten anpassen bwz. verändern).
Hier mal eine grobe Beschreibung, was denn dieser Hack dann macht:
- Man programmiere ein eigenes Modul
- Dieses Modul wird über das mitgelieferte Configfile als "Hook" registriert
- In dieser Registrierung wird festgelegt, für welches Frontendmodul dieser Hook gilt und WANN er ausgeführt werden soll
- Ausführung ist Möglich: "Vor dem Ausführen des OTRS Standardmoduls" (PreRun), "Vor der Genrierung der HTML Ausgabe" (LayoutData), "Vor dem versenden von eMails" sofern das Modul dies überhaupt anbietet (MailSendData) und "Nach Ausführen des OTRS Standardmoduls" (AfterRun)
- Der Hack liest die Konfiguration ein und schaut, ob für das gerade aufgerufene Frontend-Modul ein oder mehrere Hook-Module existieren
- Ist dem so, so werden diese als Objekte erstellt und mit den selben Parametern gefüttert, wie das OTRS Standardmodul und bekommt sogar das Objekt zum Standardmodul mit übergeben um auf diesem direkt zugreifen zu können.
- Je nach Konfiguration des Hooks wird dann noch vor dem "run" des Standardmoduls eine Routine (PreRun) der Hookmodule ausgeführt
- Generiert das OTRS Standardmodul eine Ausgabe (was ja eigentlich fast immer der Fall ist) übergibt es dem Layout Objekt das Template sowie alle zu ersetzenden Daten als Parameter.
- Bevor dieses Layout Objekt dann die Daten aus dem Template ersetzt, werden wieder die gerade aktiven Hookmodule aufgerufen die dann die vom Standardmodul übergebenen Parameter verändern, löschen oder ergänzen können (LayoutData).
- Nachdem dann die Ausgabe generiert wurde werden, bevor diese dann an den Browser zu Ausgabe geschickt wird, wieder die aktiven Hookmodule nochmals aufgerufen um ggf. die Ausgabe nochmals anzupassen oder aber einfach irgendwelche Aktionen (DB bspw.) durchzuführen (AfterRun).
- Sollte eine Standardmodul eine eMail senden wollen (AgentTicketCompose bspw.) dann übergibt dieses Modul auch hier einem für den Mailversand zuständigen eMail-Objekt die Daten.
- Das eMail-Objekt nun ruft ebenfalls alle aktiven Hook-Module auf und bietet ihm die Maildaten zur Manipulation an.
Damit dieser Hack einfach und schnell verwenden werden kann, habe ich die von mir manipulierten Original OTRS Dateien mal in ein OTRS Paket gepackt. Erstellt wurde er unter OTRS Version 2.2.5 ist aber auch mit 2.2.4 getestet und sollte auch mit anderen Versionen aus der 2.2.x Reihe laufen (habe ich aber nicht getestet).
Donwload: //EDIT: Weiter geht es hier (inkl. kleinem Todo zur Erstellung solcher Module): [Announce] BETA: Modul: HookModules 0.0.2 + Mini-Handbuch
Hier für alle die den Hack in Quellcodeform sehen wollen die entsprechenden Auszüge:
Kernel/System/web/InterfaceAgent.pm.diff
Code: Select all
--- InterfaceAgent.pm.orig 2007-09-07 11:12:46.000000000 +0200
+++ InterfaceAgent.pm 2008-03-05 12:02:45.000000000 +0100
@@ -13,7 +13,7 @@
use strict;
-use vars qw($VERSION @INC);
+use vars qw($VERSION @INC %Hooks);
$VERSION = '$Revision: 1.23 $';
$VERSION =~ s/^\$.*:\W(.*)\W.+?$/$1/;
@@ -652,6 +652,7 @@
Message => 'Kernel::Modules::' . $Param{Action} .'->new',
);
}
+
# prove of concept! - create $GenericObject
my $GenericObject = ('Kernel::Modules::'.$Param{Action})->new(
%{$Self},
@@ -659,6 +660,43 @@
%UserData,
ModuleReg => $ModuleReg,
);
+
+ %Hooks = ();
+
+ if ($Self->{ConfigObject}->Get('HookModule')) {
+ my $HookModule = $Self->{ConfigObject}->Get('HookModule')->{$Param{Action}};
+ #my @HookModuleList;
+ if ($HookModule && ref($HookModule) eq 'ARRAY') {
+ foreach (@{$HookModule}) {
+ if ($Self->{MainObject}->Require('Kernel::Modules::'.$_->[0])) {
+ my $Hook = ('Kernel::Modules::'.$_->[0])->new(
+ %{$Self},
+ %Param,
+ %UserData,
+ ModuleReg => $ModuleReg,
+ ModuleObject => $GenericObject,
+ );
+ if ($_->[1]) {
+ push(@{$Hooks{'Pre'}}, $Hook);
+ }
+ if ($_->[2]) {
+ my %Hook = (Hook => $Hook, Type => $_->[2], Module => $Param{Action}
);
+ push(@{$Hooks{'Layout'}}, \%Hook);
+ }
+ if ($_->[3]) {
+ push(@{$Hooks{'MailSend'}}, $Hook);
+ }
+ if ($_->[4]) {
+ push(@{$Hooks{'After'}}, $Hook);
+ }
+ }
+ }
+ }
+ }
+ foreach (@{$Hooks{'Pre'}}) {
+ $_->PreRun();
+ }
+
# debug info
if ($Self->{Debug}) {
$Self->{LogObject}->Log(
@@ -667,7 +705,11 @@
);
}
# ->Run $Action with $GenericObject
- $Self->{LayoutObject}->Print(Output => \$GenericObject->Run());
+ my $Output = $GenericObject->Run();
+ foreach (@{$Hooks{'After'}}) {
+ $_->AfterRun(Output => $Output);
+ }
+ $Self->{LayoutObject}->Print(Output => \$Output);
# log request time
if ($Self->{ConfigObject}->Get('PerformanceLog')) {
if ((!$QueryString && $Param{Action}) || ($QueryString !~ /Action=/)) {
Code: Select all
--- Layout.pm.orig 2007-12-18 11:28:30.000000000 +0100
+++ Layout.pm 2008-03-05 13:18:25.000000000 +0100
@@ -425,6 +425,17 @@
else {
$Param{Data} = {};
}
+
+ if ($Kernel::System::Web::InterfaceAgent::Hooks{'Layout'} &&
+ @{$Kernel::System::Web::InterfaceAgent::Hooks{'Layout'}}) {
+ foreach (@{$Kernel::System::Web::InterfaceAgent::Hooks{'Layout'}}) {
+ #if ($_->{Type} == 1 || $Param{TemplateFile} =~ /^$_->{Module}.*/) {
+ $Param{Data} = $_->{Hook}->LayoutData(
+ Data => $Param{Data},
+ );
+ #}
+ }
+ }
# create %Env for this round!
my $EnvRef = {};
Code: Select all
--- Email.pm.orig 2007-11-05 14:18:11.000000000 +0100
+++ Email.pm 2008-03-06 15:21:36.000000000 +0100
@@ -164,6 +164,16 @@
sub Send {
my $Self = shift;
my %Param = @_;
+
+ if ($Kernel::System::Web::InterfaceAgent::Hooks{'MailSend'} &&
+ @{$Kernel::System::Web::InterfaceAgent::Hooks{'MailSend'}}) {
+ foreach (@{$Kernel::System::Web::InterfaceAgent::Hooks{'MailSend'}}) {
+ %Param = %{$_->MailSendData(
+ Data => \%Param
+ )};
+ }
+ }
+
# check needed stuff
foreach (qw(Body Charset)) {
if (!$Param{$_}) {
Ein erstes Hook-Modul habe ich auch bereits erstellt und werde es gleich noch veröffentlichen.
Andreas