Az OTRS modulrétegek erejének használata

Hitelesítés és felhasználókezelés
Ügyintézői hitelesítő modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
Hitelesítés szinkronizációs modul
Kódpélda
Beállítási példa
Használati eset példák
Kiadási elérhetőség
Ellenjavaslatok és figyelmeztetések
Ügyfél hitelesítő modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
Beállítások
Ügyfél-felhasználó beállítások modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
Várólista beállítások modul
Kódpélda
Beállítási példa
Használati eset példák
Kiadási elérhetőség
Szolgáltatás beállítások modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
SLA beállítások modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
Egyéb alapfüggvények
Naplózás modul
Kódpélda: Kernel::System::Log::CustomFile
Beállítási példa
Használati eset példák
Ellenjavaslatok és figyelmeztetések
Kimenetszűrő
FilterElementPost
FilterContent
FilterText
Kódpélda
Beállítási példa
Használati esetek
Ellenjavaslatok és figyelmeztetések
Bevált gyakorlatok
Kiadási elérhetőség
Statisztikák modul
Dinamikus statisztikák
Statikus statisztikák
Jegyszám előállító modulok
Kódpélda
Beállítási példa
Használati esetek
Ellenjavaslatok és figyelmeztetések
Kiadási elérhetőség
Jegyesemény modul
Kódpélda
Beállítási példa
Használati esetek
Ellenjavaslatok és figyelmeztetések
Kiadási elérhetőség
Előtétprogram modulok
Vezérlőpult modul
Ellenjavaslatok és figyelmeztetések
Kiadási elérhetőség
Értesítési modul
Kódpélda
Beállítási példa
Használati eset példa
Kiadási elérhetőség
Jegymenü modul
Kódpélda
Beállítási példa
Használati eset példa
Ellenjavaslatok és figyelmeztetések
Kiadási elérhetőség
Általános felület modulok
Hálózati átvitel
Átviteli háttérprogram
Leképezés
Leképező háttérprogram
Meghívó
Meghívó háttérprogram
Művelet
Műveleti háttérprogram
Démon és ütemező
OTRS démon
OTRS démonmodulok
OTRS ütemező
OTRS ütemező feladatkezelők
OTRS ütemező feladatelvégzők
Dinamikus mezők
Áttekintés
Dinamikus mezők keretrendszer
Dinamikus mező háttérprogram modulok
Dinamikus mezők adminisztrátori moduljai
Dinamikus mezők alapmoduljai
Dinamikus mezők adatbázistáblái
Dinamikus mezők beállítófájljai
Dinamikus mező kölcsönhatása az előtétprogram modulokkal
Hogyan lehet kiterjeszteni a dinamikus mezőket
Egy új dinamikus mező típus létrehozása (a jegy vagy bejegyzés objektumokhoz)
Egy új dinamikus mező típus létrehozása (egyéb objektumokhoz)
Egy új csomag létrehozása a dinamikus mezők használatához
A háttérprogram és az illesztőprogramok funkcionalitásainak kiterjesztése
Egyéb kiterjesztések
Egy új dinamikus mező létrehozása
Dinamikus mező jelszó fájlok
Egy dinamikus mező funkcionalitás kiterjesztés létrehozása
Dinamikus mező Foo kiterjesztés fájlok
E-mail kezelés
Jegy levelezési modul

Az OTRS nagyszámú úgynevezett „modulréteggel” rendelkezik, amely nagyon egyszerűvé teszi a rendszer kibővítését a meglévő kód foltozása nélkül. Egy példa erre a számelőállító mechanizmus a jegyeknél. Ez egy csatlakoztatható modulokkal rendelkező „modulréteg”, és ha szeretné, hozzáadhatja a saját egyéni számelőállító moduljait is. Nézzük meg részletesen a különböző rétegeket!

Hitelesítés és felhasználókezelés

Ügyintézői hitelesítő modul

Számos ügyintézői hitelesítő modul létezik (DB, LDAP és HTTPBasicAuth), amelyek az OTRS keretrendszerrel érkeznek. Lehetőség van saját hitelesítő modulok fejlesztésére is. Az ügyintézői hitelesítő modulok a Kernel/System/Auth/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. Ezt követően egy egyszerű ügyintézői hitelesítő modul példája található. Mentse el a Kernel/System/Auth/Simple.pm helyre. Mindössze három függvényre van szüksége: new(), GetOption() és Auth(). Adja vissza az uid-t, és ezután a hitelesítés rendben van.

Kódpélda

A felületosztály neve Kernel::System::Auth. A példa ügyintézői hitelesítés hívható Kernel::System::Auth::CustomAuth néven. Lent találhat egy példát.

# --
# Kernel/System/Auth/CustomAuth.pm - provides the CustomAuth authentication
# based on Martin Edenhofer's Kernel::System::Auth::DB
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# ID: CustomAuth.pm,v 1.1 2010/05/10 15:30:34 fk Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Auth::CustomAuth;

use strict;
use warnings;

use Authen::CustomAuth;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(LogObject ConfigObject DBObject)) {
        $Self->{$_} = $Param{$_} || die "No $_!";
    }

    # Debug 0=off 1=on
    $Self->{Debug} = 0;

    # get config
    $Self->{Die} = $Self->{ConfigObject}->Get( 'AuthModule::CustomAuth::Die' . $Param{Count} );

    # get user table
    $Self->{CustomAuthHost} = $Self->{ConfigObject}->Get( 'AuthModule::CustomAuth::Host' . $Param{Count} )
        || die "Need AuthModule::CustomAuth::Host$Param{Count}.";
    $Self->{CustomAuthSecret}
        = $Self->{ConfigObject}->Get( 'AuthModule::CustomAuth::Password' . $Param{Count} )
        || die "Need AuthModule::CustomAuth::Password$Param{Count}.";

    return $Self;
}

sub GetOption {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{What} ) {
        $Self->{LogObject}->Log( Priority => 'error', Message => "Need What!" );
        return;
    }

    # module options
    my %Option = ( PreAuth => 0, );

    # return option
    return $Option{ $Param{What} };
}

sub Auth {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{User} ) {
        $Self->{LogObject}->Log( Priority => 'error', Message => "Need User!" );
        return;
    }

    # get params
    my $User       = $Param{User}      || '';
    my $Pw         = $Param{Pw}        || '';
    my $RemoteAddr = $ENV{REMOTE_ADDR} || 'Got no REMOTE_ADDR env!';
    my $UserID     = '';
    my $GetPw      = '';

    # just in case for debug!
    if ( $Self->{Debug} > 0 ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: '$User' tried to authenticate with Pw: '$Pw' ($RemoteAddr)",
        );
    }

    # just a note
    if ( !$User ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "No User given!!! (REMOTE_ADDR: $RemoteAddr)",
        );
        return;
    }

    # just a note
    if ( !$Pw ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User authentication without Pw!!! (REMOTE_ADDR: $RemoteAddr)",
        );
        return;
    }

    # Create a RADIUS object
    my $CustomAuth = Authen::CustomAuth->new(
        Host   => $Self->{CustomAuthHost},
        Secret => $Self->{CustomAuthecret},
    );
    if ( !$CustomAuth ) {
        if ( $Self->{Die} ) {
            die "Can't connect to $Self->{CustomAuthHost}: $@";
        }
        else {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Can't connect to $Self->{CustomAuthHost}: $@",
            );
            return;
        }
    }
    my $AuthResult = $CustomAuth->check_pwd( $User, $Pw );

    # login note
    if ( defined($AuthResult) && $AuthResult == 1 ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User authentication ok (REMOTE_ADDR: $RemoteAddr).",
        );
        return $User;
    }

    # just a note
    else {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User authentication with wrong Pw!!! (REMOTE_ADDR: $RemoteAddr)"
        );
        return;
    }
}

1;

        

Beállítási példa

Szükség van az egyéni ügyintézői hitelesítés modul bekapcsolására. Ezt a lenti Perl beállítás használatával lehet megtenni. Nem ajánlott az XML beállítás használata, mert kizárhatja magát a rendszerbeállításokon keresztül.

            $Self->{'AuthModule'} = 'Kernel::System::Auth::CustomAuth';
        

Használati eset példa

Egy hitelesítési megvalósítás hasznos példája lehet egy SOAP háttérprogram.

Kiadási elérhetőség

NévKiadás
DB1.0
HTTPBasicAuth1.2
LDAP1.0
RADIUS1.3

Hitelesítés szinkronizációs modul

Létezik egy LDAP hitelesítés szinkronizációs modul, amely az OTRS keretrendszerrel érkezik. Lehetőség van saját hitelesítés modulok fejlesztésére is. A hitelesítés szinkronizációs modulok a Kernel/System/Auth/Sync/*.pm alatt találhatók. A beállításaikkal kapcsolatban további információkért nézze meg az adminisztrációs kézikönyvet. A következőkben egy hitelesítés szinkronizációs modul példája található. Mentse el a Kernel/System/Auth/Sync/CustomAuthSync.pm fájlba. Mindössze két függvényre van szüksége: new() és Sync(). Adjon vissza 1-et, és ezután a szinkronizáció rendben van.

Kódpélda

A felületosztály neve Kernel::System::Auth. A példa ügyintézői hitelesítés hívható Kernel::System::Auth::Sync::CustomAuthSync néven. Lent találhat egy példát.

# --
# Kernel/System/Auth/Sync/CustomAuthSync.pm - provides the CustomAuthSync
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: CustomAuthSync.pm,v 1.9 2010/03/25 14:42:45 martin Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Auth::Sync::CustomAuthSync;

use strict;
use warnings;
use Net::LDAP;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(LogObject ConfigObject DBObject UserObject GroupObject EncodeObject)) {
        $Self->{$_} = $Param{$_} || die "No $_!";
    }

    # Debug 0=off 1=on
    $Self->{Debug} = 0;

...

    return $Self;
}

sub Sync {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(User)) {
        if ( !$Param{$_} ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }
...
    return 1;
}

        

Beállítási példa

Be kell kapcsolnia az egyéni szinkronizációs modult. Ezt a lenti Perl beállítás használatával lehet megtenni. Nem ajánlott az XML beállítás használata, mert az lehetővé teheti, hogy kizárja magát a rendszerbeállításokon keresztül.

            $Self->{'AuthSyncModule'} = 'Kernel::System::Auth::Sync::LDAP';
        

Használati eset példák

Hasznos szinkronizációs megvalósítás lehet egy SOAP vagy egy RADIUS háttérprogram.

Kiadási elérhetőség

NévKiadás
LDAP2.4

Ellenjavaslatok és figyelmeztetések

Ne feledje, hogy a szinkronizáció a Kernel::System::Auth hitelesítési osztály része volt a 2.4-es keretrendszer előtt.

Ügyfél hitelesítő modul

Számos ügyfél hitelesítő modul létezik (DB, LDAP és HTTPBasicAuth), amelyek az OTRS keretrendszerrel érkeznek. Lehetőség van saját hitelesítő modulok fejlesztésére is. Az ügyfél hitelesítő modulok a Kernel/System/CustomerAuth/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. Ezt követően egy egyszerű ügyfél hitelesítő modul példája található. Mentse el a Kernel/System/CustomerAuth/Simple.pm helyre. Mindössze három függvényre van szüksége: new(), GetOption() és Auth(). Adja vissza az uid-t, és ezután a hitelesítés rendben van.

Kódpélda

A felületosztály neve Kernel::System::CustomerAuth. A példa ügyfél hitelesítés hívható Kernel::System::CustomerAuth::CustomAuth néven. Lent találhat egy példát.

# --
# Kernel/System/CustomerAuth/CustomAuth.pm - provides the custom Authentication
# based on Martin Edenhofer's Kernel::System::Auth::DB
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: CustomAuth.pm,v 1.11 2009/09/22 15:16:05 mb Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::CustomerAuth::CustomAuth;

use strict;
use warnings;

use Authen::CustomAuth;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(LogObject ConfigObject DBObject)) {
        $Self->{$_} = $Param{$_} || die "No $_!";
    }

    # Debug 0=off 1=on
    $Self->{Debug} = 0;

    # get config
    $Self->{Die}
        = $Self->{ConfigObject}->Get( 'Customer::AuthModule::CustomAuth::Die' . $Param{Count} );

    # get user table
    $Self->{CustomAuthHost}
        = $Self->{ConfigObject}->Get( 'Customer::AuthModule::CustomAuth::Host' . $Param{Count} )
        || die "Need Customer::AuthModule::CustomAuth::Host$Param{Count} in Kernel/Config.pm";
    $Self->{CustomAuthSecret}
        = $Self->{ConfigObject}->Get( 'Customer::AuthModule::CustomAuth::Password' . $Param{Count} )
        || die "Need Customer::AuthModule::CustomAuth::Password$Param{Count} in Kernel/Config.pm";

    return $Self;
}

sub GetOption {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{What} ) {
        $Self->{LogObject}->Log( Priority => 'error', Message => "Need What!" );
        return;
    }

    # module options
    my %Option = ( PreAuth => 0, );

    # return option
    return $Option{ $Param{What} };
}

sub Auth {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{User} ) {
        $Self->{LogObject}->Log( Priority => 'error', Message => "Need User!" );
        return;
    }

    # get params
    my $User       = $Param{User}      || '';
    my $Pw         = $Param{Pw}        || '';
    my $RemoteAddr = $ENV{REMOTE_ADDR} || 'Got no REMOTE_ADDR env!';
    my $UserID     = '';
    my $GetPw      = '';

    # just in case for debug!
    if ( $Self->{Debug} > 0 ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: '$User' tried to authentificate with Pw: '$Pw' ($RemoteAddr)",
        );
    }

    # just a note
    if ( !$User ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "No User given!!! (REMOTE_ADDR: $RemoteAddr)",
        );
        return;
    }

    # just a note
    if ( !$Pw ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User Authentication without Pw!!! (REMOTE_ADDR: $RemoteAddr)",
        );
        return;
    }

    # Create a custom object
    my $CustomAuth = Authen::CustomAuth->new(
        Host   => $Self->{CustomAuthHost},
        Secret => $Self->{CustomAuthSecret},
    );
    if ( !$CustomAuth ) {
        if ( $Self->{Die} ) {
            die "Can't connect to $Self->{CustomAuthHost}: $@";
        }
        else {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Can't connect to $Self->{CustomAuthHost}: $@",
            );
            return;
        }
    }
    my $AuthResult = $CustomAuth->check_pwd( $User, $Pw );

    # login note
    if ( defined($AuthResult) && $AuthResult == 1 ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User Authentication ok (REMOTE_ADDR: $RemoteAddr).",
        );
        return $User;
    }

    # just a note
    else {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message  => "User: $User Authentication with wrong Pw!!! (REMOTE_ADDR: $RemoteAddr)"
        );
        return;
    }
}

1;

        

Beállítási példa

Szükség van az egyéni ügyfél hitelesítő modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="AuthModule" Required="1" Valid="1">
    <Description Lang="en">Module to authenticate customers.</Description>
    <Description Lang="hu">Egy modul az ügyfelek hitelesítéséhez.</Description>
    <Group>Framework</Group>
    <SubGroup>Frontend::CustomerAuthAuth</SubGroup>
    <Setting>
        <Option Location="Kernel/System/CustomerAuth/*.pm" SelectedID="Kernel::System::CustomerAuth::CustomAuth"></Option>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos hitelesítés megvalósítás lehet egy SOAP háttérprogram.

Kiadási elérhetőség

NévKiadás
DB1.0
HTTPBasicAuth1.2
LDAP1.0
RADIUS1.3

Beállítások

Ügyfél-felhasználó beállítások modul

Létezik egy DB ügyfél-felhasználó beállítások modul, amely az OTRS keretrendszerrel érkezik. Lehetőség van saját ügyfél-felhasználó beállítási modulok fejlesztésére is. Az ügyfél-felhasználó beállítási modulok a Kernel/System/CustomerUser/Preferences/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. A következőkben egy ügyfél-felhasználó beállítások modul példája található. Mentse el a Kernel/System/CustomerUser/Preferences/Custom.pm helyre. Mindössze négy függvényre van szüksége: new(), SearchPreferences(), SetPreferences() és GetPreferences().

Kódpélda

A felületosztály neve Kernel::System::CustomerUser. A példa ügyfél-felhasználó beállítások hívhatók Kernel::System::CustomerUser::Preferences::Custom néven. Lent találhat egy példát.

# --
# Kernel/System/CustomerUser/Preferences/Custom.pm - some customer user functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: Custom.pm,v 1.20 2009/10/07 20:41:50 martin Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::CustomerUser::Preferences::Custom;

use strict;
use warnings;

use vars qw(@ISA $VERSION);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for my $Object (qw(DBObject ConfigObject LogObject)) {
        $Self->{$Object} = $Param{$Object} || die "Got no $Object!";
    }

    # preferences table data
    $Self->{PreferencesTable} = $Self->{ConfigObject}->Get('CustomerPreferences')->{Params}->{Table}
        || 'customer_preferences';
    $Self->{PreferencesTableKey}
        = $Self->{ConfigObject}->Get('CustomerPreferences')->{Params}->{TableKey}
        || 'preferences_key';
    $Self->{PreferencesTableValue}
        = $Self->{ConfigObject}->Get('CustomerPreferences')->{Params}->{TableValue}
        || 'preferences_value';
    $Self->{PreferencesTableUserID}
        = $Self->{ConfigObject}->Get('CustomerPreferences')->{Params}->{TableUserID}
        || 'user_id';

    return $Self;
}

sub SetPreferences {
    my ( $Self, %Param ) = @_;

    my $UserID = $Param{UserID} || return;
    my $Key    = $Param{Key}    || return;
    my $Value = defined( $Param{Value} ) ? $Param{Value} : '';

    # delete old data
    return if !$Self->{DBObject}->Do(
        SQL => "DELETE FROM $Self->{PreferencesTable} WHERE "
            . " $Self->{PreferencesTableUserID} = ? AND $Self->{PreferencesTableKey} = ?",
        Bind => [ \$UserID, \$Key ],
    );

    $Value .= 'Custom';

    # insert new data
    return if !$Self->{DBObject}->Do(
        SQL => "INSERT INTO $Self->{PreferencesTable} ($Self->{PreferencesTableUserID}, "
            . " $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue}) "
            . " VALUES (?, ?, ?)",
        Bind => [ \$UserID, \$Key, \$Value ],
    );

    return 1;
}

sub GetPreferences {
    my ( $Self, %Param ) = @_;

    my $UserID = $Param{UserID} || return;
    my %Data;

    # get preferences

    return if !$Self->{DBObject}->Prepare(
        SQL => "SELECT $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue} "
            . " FROM $Self->{PreferencesTable} WHERE $Self->{PreferencesTableUserID} = ?",
        Bind => [ \$UserID ],
    );
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $Data{ $Row[0] } = $Row[1];
    }

    # return data
    return %Data;
}

sub SearchPreferences {
    my ( $Self, %Param ) = @_;

    my %UserID;
    my $Key   = $Param{Key}   || '';
    my $Value = $Param{Value} || '';

    # get preferences
    my $SQL = "SELECT $Self->{PreferencesTableUserID}, $Self->{PreferencesTableValue} "
        . " FROM "
        . " $Self->{PreferencesTable} "
        . " WHERE "
        . " $Self->{PreferencesTableKey} = '"
        . $Self->{DBObject}->Quote($Key) . "'" . " AND "
        . " LOWER($Self->{PreferencesTableValue}) LIKE LOWER('"
        . $Self->{DBObject}->Quote( $Value, 'Like' ) . "')";

    return if !$Self->{DBObject}->Prepare( SQL => $SQL );
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $UserID{ $Row[0] } = $Row[1];
    }

    # return data
    return %UserID;
}

1;

        

Beállítási példa

Szükség van az egyéni ügyfél-felhasználó beállítások modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="CustomerPreferences" Required="1" Valid="1">
    <Description Lang="en">Parameters for the customer preference table.</Description>
    <Description Lang="hu">Paraméterek az ügyfél beállításainak táblájához.</Description>
    <Group>Framework</Group>
    <SubGroup>Frontend::Customer::Preferences</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::System::CustomerUser::Preferences::Custom</Item>
            <Item  Key="Params">
                <Hash>
                    <Item Key="Table">customer_preferences</Item>
                    <Item Key="TableKey">preferences_key</Item>
                    <Item Key="TableValue">preferences_value</Item>
                    <Item Key="TableUserID">user_id</Item>
                </Hash>
            </Item>
        </Hash>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos beállítások megvalósítás lehet egy SOAP vagy egy LDAP háttérprogram.

Kiadási elérhetőség

NévKiadás
DB2.3

Várólista beállítások modul

Létezik egy DB várólista beállítások modul, amely az OTRS keretrendszerrel érkezik. Lehetőség van saját várólista beállítási modulok fejlesztésére is. A várólista beállítási modulok a Kernel/System/Queue/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. A következőkben egy várólista beállítások modul példája található. Mentse el a Kernel/System/Queue/PreferencesCustom.pm helyre. Mindössze három függvényre van szüksége: new(), QueuePreferencesSet() és QueuePreferencesGet(). Adjon vissza 1-et, és ezután a szinkronizáció rendben van.

Kódpélda

A felületosztály neve Kernel::System::Queue. A példa várólista beállítások hívhatók Kernel::System::Queue::PreferencesCustom néven. Lent találhat egy példát.

# --
# Kernel/System/Queue/PreferencesCustom.pm - some user functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: PreferencesCustom.pm,v 1.5 2009/02/16 11:47:34 tr Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Queue::PreferencesCustom;

use strict;
use warnings;

use vars qw(@ISA $VERSION);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(DBObject ConfigObject LogObject)) {
        $Self->{$_} = $Param{$_} || die "Got no $_!";
    }

    # preferences table data
    $Self->{PreferencesTable}        = 'queue_preferences';
    $Self->{PreferencesTableKey}     = 'preferences_key';
    $Self->{PreferencesTableValue}   = 'preferences_value';
    $Self->{PreferencesTableQueueID} = 'queue_id';

    return $Self;
}

sub QueuePreferencesSet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(QueueID Key Value)) {
        if ( !defined( $Param{$_} ) ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # delete old data
    return if !$Self->{DBObject}->Do(
        SQL => "DELETE FROM $Self->{PreferencesTable} WHERE "
            . "$Self->{PreferencesTableQueueID} = ? AND $Self->{PreferencesTableKey} = ?",
        Bind => [ \$Param{QueueID}, \$Param{Key} ],
    );

    $Self->{PreferencesTableValue} .= 'PreferencesCustom';

    # insert new data
    return $Self->{DBObject}->Do(
        SQL => "INSERT INTO $Self->{PreferencesTable} ($Self->{PreferencesTableQueueID}, "
            . " $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue}) "
            . " VALUES (?, ?, ?)",
        Bind => [ \$Param{QueueID}, \$Param{Key}, \$Param{Value} ],
    );
}

sub QueuePreferencesGet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(QueueID)) {
        if ( !$Param{$_} ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # check if queue preferences are available
    if ( !$Self->{ConfigObject}->Get('QueuePreferences') ) {
        return;
    }

    # get preferences
    return if !$Self->{DBObject}->Prepare(
        SQL => "SELECT $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue} "
            . " FROM $Self->{PreferencesTable} WHERE $Self->{PreferencesTableQueueID} = ?",
        Bind => [ \$Param{QueueID} ],
    );
    my %Data;
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $Data{ $Row[0] } = $Row[1];
    }

    # return data
    return %Data;
}

1;

        

Beállítási példa

Szükség van az egyéni várólista beállítások modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="Queue::PreferencesModule" Required="1" Valid="1">
    <Description Lang="en">Default queue preferences module.</Description>
    <Description Lang="hu">Alapértelmezett várólista beállítások modul.</Description>
    <Group>Ticket</Group>
    <SubGroup>Frontend::Queue::Preferences</SubGroup>
    <Setting>
        <String Regex="">Kernel::System::Queue::PreferencesCustom</String>
    </Setting>
</ConfigItem>
        

Használati eset példák

Hasznos beállítások megvalósítás lehet egy SOAP vagy egy RADIUS háttérprogram.

Kiadási elérhetőség

NévKiadás
PreferencesDB2.3

Szolgáltatás beállítások modul

Létezik egy DB szolgáltatás beállítások modul, amely az OTRS keretrendszerrel érkezik. Lehetőség van saját szolgáltatás beállítási modulok fejlesztésére is. A szolgáltatás beállítási modulok a Kernel/System/Service/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. A következőkben egy szolgáltatás beállítások modul példája található. Mentse el a Kernel/System/Service/PreferencesCustom.pm helyre. Mindössze három függvényre van szüksége: new(), ServicePreferencesSet() és ServicePreferencesGet(). Adjon vissza 1-et, és ezután a szinkronizáció rendben van.

Kódpélda

A felületosztály neve Kernel::System::Service. A példa szolgáltatás beállítások hívhatók Kernel::System::Service::PreferencesCustom néven. Lent találhat egy példát.

# --
# Kernel/System/Service/PreferencesCustom - some user functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: PreferencesCustom.pm,v 1.2 2009/02/16 11:47:34 tr Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Service::PreferencesCustom;

use strict;
use warnings;

use vars qw(@ISA $VERSION);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(DBObject ConfigObject LogObject)) {
        $Self->{$_} = $Param{$_} || die "Got no $_!";
    }

    # preferences table data
    $Self->{PreferencesTable}          = 'service_preferences';
    $Self->{PreferencesTableKey}       = 'preferences_key';
    $Self->{PreferencesTableValue}     = 'preferences_value';
    $Self->{PreferencesTableServiceID} = 'service_id';

    return $Self;
}

sub ServicePreferencesSet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(ServiceID Key Value)) {
        if ( !defined( $Param{$_} ) ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # delete old data
    return if !$Self->{DBObject}->Do(
        SQL => "DELETE FROM $Self->{PreferencesTable} WHERE "
            . "$Self->{PreferencesTableServiceID} = ? AND $Self->{PreferencesTableKey} = ?",
        Bind => [ \$Param{ServiceID}, \$Param{Key} ],
    );

$Self->{PreferencesTableValue} .= 'PreferencesCustom';

    # insert new data
    return $Self->{DBObject}->Do(
        SQL => "INSERT INTO $Self->{PreferencesTable} ($Self->{PreferencesTableServiceID}, "
            . " $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue}) "
            . " VALUES (?, ?, ?)",
        Bind => [ \$Param{ServiceID}, \$Param{Key}, \$Param{Value} ],
    );
}

sub ServicePreferencesGet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(ServiceID)) {
        if ( !$Param{$_} ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # check if service preferences are available
    if ( !$Self->{ConfigObject}->Get('ServicePreferences') ) {
        return;
    }

    # get preferences
    return if !$Self->{DBObject}->Prepare(
        SQL => "SELECT $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue} "
            . " FROM $Self->{PreferencesTable} WHERE $Self->{PreferencesTableServiceID} = ?",
        Bind => [ \$Param{ServiceID} ],
    );
    my %Data;
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $Data{ $Row[0] } = $Row[1];
    }

    # return data
    return %Data;
}

1;

        

Beállítási példa

Szükség van az egyéni szolgáltatás beállítások modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="Service::PreferencesModule" Required="1" Valid="1">
    <Description Lang="en">Default service preferences module.</Description>
    <Description Lang="hu">Alapértelmezett szolgáltatás beállítások modul.</Description>
    <Group>Ticket</Group>
    <SubGroup>Frontend::Service::Preferences</SubGroup>
    <Setting>
        <String Regex="">Kernel::System::Service::PreferencesCustom</String>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos beállítások megvalósítás lehet egy SOAP vagy egy RADIUS háttérprogram.

Kiadási elérhetőség

NévKiadás
PreferencesDB2.4

SLA beállítások modul

Létezik egy DB SLA beállítások modul, amely az OTRS keretrendszerrel érkezik. Lehetőség van saját SLA beállítási modulok fejlesztésére is. Az SLA beállítási modulok a Kernel/System/SLA/*.pm alatt találhatók. Ezek beállításáról további információkért nézze meg az adminisztrátori kézikönyvet. A következőkben egy SLA beállítások modul példája található. Mentse el a Kernel/System/SLA/PreferencesCustom.pm helyre. Mindössze három függvényre van szüksége: new(), SLAPreferencesSet() és SLAPreferencesGet(). Győződjön meg arról, hogy a függvény 1-et adjon vissza.

Kódpélda

A felületosztály neve Kernel::System::SLA. A példa SLA beállítások hívhatók Kernel::System::SLA::PreferencesCustom néven. Lent találhat egy példát.

# --
# Kernel/System/SLA/PreferencesCustom.pm - some user functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::SLA::PreferencesCustom;

use strict;
use warnings;

use vars qw(@ISA);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for (qw(DBObject ConfigObject LogObject)) {
        $Self->{$_} = $Param{$_} || die "Got no $_!";
    }

    # preferences table data
    $Self->{PreferencesTable}      = 'sla_preferences';
    $Self->{PreferencesTableKey}   = 'preferences_key';
    $Self->{PreferencesTableValue} = 'preferences_value';
    $Self->{PreferencesTableSLAID} = 'sla_id';

    return $Self;
}

sub SLAPreferencesSet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(SLAID Key Value)) {
        if ( !defined( $Param{$_} ) ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # delete old data
    return if !$Self->{DBObject}->Do(
        SQL => "DELETE FROM $Self->{PreferencesTable} WHERE "
            . "$Self->{PreferencesTableSLAID} = ? AND $Self->{PreferencesTableKey} = ?",
        Bind => [ \$Param{SLAID}, \$Param{Key} ],
    );

$Self->{PreferencesTableValue} .= 'PreferencesCustom';

    # insert new data
    return $Self->{DBObject}->Do(
        SQL => "INSERT INTO $Self->{PreferencesTable} ($Self->{PreferencesTableSLAID}, "
            . " $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue}) "
            . " VALUES (?, ?, ?)",
        Bind => [ \$Param{SLAID}, \$Param{Key}, \$Param{Value} ],
    );
}

sub SLAPreferencesGet {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for (qw(SLAID)) {
        if ( !$Param{$_} ) {
            $Self->{LogObject}->Log( Priority => 'error', Message => "Need $_!" );
            return;
        }
    }

    # check if SLA preferences are available
    if ( !$Self->{ConfigObject}->Get('SLAPreferences') ) {
        return;
    }

    # get preferences
    return if !$Self->{DBObject}->Prepare(
        SQL => "SELECT $Self->{PreferencesTableKey}, $Self->{PreferencesTableValue} "
            . " FROM $Self->{PreferencesTable} WHERE $Self->{PreferencesTableSLAID} = ?",
        Bind => [ \$Param{SLAID} ],
    );
    my %Data;
    while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
        $Data{ $Row[0] } = $Row[1];
    }

    # return data
    return %Data;
}

1;

        

Beállítási példa

Szükség van az egyéni SLA beállítások modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="SLA::PreferencesModule" Required="1" Valid="1">
    <Description Translatable="1">Default SLA preferences module.</Description>
    <Group>Ticket</Group>
    <SubGroup>Frontend::SLA::Preferences</SubGroup>
    <Setting>
        <String Regex="">Kernel::System::SLA::PreferencesCustom</String>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos beállítások megvalósítás lehet további értékek tárolása az SLA-khoz.

Kiadási elérhetőség

NévKiadás
PreferencesDB2.4

Egyéb alapfüggvények

Naplózás modul

Létezik egy globális naplózó felület az OTRS-hez, amely a saját naplózó háttérprogramok létrehozásának lehetőségét biztosítja.

Egy saját naplózó háttérprogram írása olyan egyszerű, mint újra megvalósítani a Kernel::System::Log::Log() metódust.

Kódpélda: Kernel::System::Log::CustomFile

Ebben a kis példában írni fogunk egy kicsi fájl naplózó háttérprogramot, amely hasonlóan működik mint a Kernel::System::Log::File, de egy szöveget fűz minden naplóbejegyzés elé.

# --
# Kernel/System/Log/CustomFile.pm - file log backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Log::CustomFile;

use strict;
use warnings;

umask "002";

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # get needed objects
    for (qw(ConfigObject EncodeObject)) {
        if ( $Param{$_} ) {
            $Self->{$_} = $Param{$_};
        }
        else {
            die "Got no $_!";
        }
    }

    # get logfile location
    $Self->{LogFile} = '/var/log/CustomFile.log';

    # set custom prefix
    $Self->{CustomPrefix} = 'CustomFileExample';

    # Fixed bug# 2265 - For IIS we need to create a own error log file.
    # Bind stderr to log file, because IIS do print stderr to web page.
    if ( $ENV{SERVER_SOFTWARE} && $ENV{SERVER_SOFTWARE} =~ /^microsoft\-iis/i ) {
        if ( !open STDERR, '>>', $Self->{LogFile} . '.error' ) {
            print STDERR "ERROR: Can't write $Self->{LogFile}.error: $!";
        }
    }

    return $Self;
}

sub Log {
    my ( $Self, %Param ) = @_;

    my $FH;

    # open logfile
    if ( !open $FH, '>>', $Self->{LogFile} ) {

        # print error screen
        print STDERR "\n";
        print STDERR " >> Can't write $Self->{LogFile}: $! <<\n";
        print STDERR "\n";
        return;
    }

    # write log file
    $Self->{EncodeObject}->SetIO($FH);
    print $FH '[' . localtime() . ']';
    if ( lc $Param{Priority} eq 'debug' ) {
        print $FH "[Debug][$Param{Module}][$Param{Line}] $Self->{CustomPrefix} $Param{Message}\n";
    }
    elsif ( lc $Param{Priority} eq 'info' ) {
        print $FH "[Info][$Param{Module}]  $Self->{CustomPrefix} $Param{Message}\n";
    }
    elsif ( lc $Param{Priority} eq 'notice' ) {
        print $FH "[Notice][$Param{Module}] $Self->{CustomPrefix} $Param{Message}\n";
    }
    elsif ( lc $Param{Priority} eq 'error' ) {
        print $FH "[Error][$Param{Module}][$Param{Line}] $Self->{CustomPrefix} $Param{Message}\n";
    }
    else {

        # print error messages to STDERR
        print STDERR
            "[Error][$Param{Module}] $Self->{CustomPrefix} Priority: '$Param{Priority}' not defined! Message: $Param{Message}\n";

        # and of course to logfile
        print $FH
            "[Error][$Param{Module}] $Self->{CustomPrefix} Priority: '$Param{Priority}' not defined! Message: $Param{Message}\n";
    }

    # close file handle
    close $FH;
    return 1;
}

1;
        

Beállítási példa

Az egyéni naplózómodul bekapcsolásához az adminisztrátor beállíthatja kézzel a meglévő LogModule konfigurációs elemet a Kernel::System::Log::CustomFile osztályhoz. Ennek automatikus megvalósításához megadhat egy XML beállítófájlt, amely felülbírálja az alapértelmezett beállítást.

<ConfigItem Name="LogModule" Required="1" Valid="1">
    <Description Translatable="1">Set Kernel::System::Log::CustomFile as default logging backend.</Description>
    <Group>Framework</Group>
    <SubGroup>Core::Log</SubGroup>
    <Setting>
        <Option Location="Kernel/System/Log/*.pm" SelectedID="Kernel::System::Log::CustomFile"></Option>
    </Setting>
</ConfigItem>
        

Használati eset példák

Hasznos naplózó háttérprogram lehet egy webszolgáltatásba vagy egy titkosított fájlba történő naplózás.

Ellenjavaslatok és figyelmeztetések

Ne feledje, hogy a Kernel::System::Log a Log() metóduson kívül egyéb metódusokkal is rendelkezik, amelyeket nem lehet újra megvalósítani, például az osztott memóriaszakaszokkal történő munkához tartozó kód és a naplóadatok gyorsítótárazása.

Kimenetszűrő

A kimenetszűrők lehetővé teszik a HTML módosítását röptében. A bevált gyakorlat a kimenetszűrők használata a .tt fájlok közvetlen módosítása helyett. Három jó ok létezik erre. Amikor ugyanazt az átdolgozást kell alkalmazni számos előtétprogram modulon, akkor az átdolgozást csak egyszer kell megvalósítani. A második előnye, hogy amikor az OTRS-t frissítik, akkor megvan az esély arra, hogy a szűrőt nem kell frissíteni, ha a hozzá tartozó minta nem változott. Amikor két kiterjesztés ugyanazt a fájlt módosítja, akkor ütközés lép fel a második csomag telepítése során. Ez az ütközés feloldható két kimenetszűrő használatával, amelyek ugyanazt az előtétprogram modult módosítják.

Három különböző fajta kimenetszűrő létezik. Ezek a HTML tartalom előállításának különböző szakaszaiban aktívak.

FilterElementPost

Ezek a szűrők lehetővé teszik egy sablon kimenetének módosítást, miután az megjelenítésre került.

A tartalom lefordításához futtathatja közvetlenül a $LayoutObject->Translate() függvényt. Ha egyéb sablonszolgáltatásokra van szüksége, akkor egyszerűen határozzon meg egy kis sablonfájlt a kimenetszűrőhöz, és használja azt a tartalom megjelenítéséhez, mielőtt beültetné azt a fő adatokba. Néhány esetben hasznos lehet a jQuery DOM műveletek használata is a képernyőn lévő tartalom sorrendjének megváltoztatásához vagy cseréjéhez a reguláris kifejezések használata helyett. Ebben az esetben láthatatlan tartalomként kellene beültetnie az új kódot valahova az oldalba (például a Hidden osztállyal), majd ezután áthelyezni a jQuery használatával a megfelelő helyre a DOM-ban, és megjeleníteni azt.

Az utó-kimenetszűrők használatának megkönnyítéséhez létezik egy mechanizmus is a HTML megjegyzéshorgok lekéréséhez bizonyos sablonoknál vagy blokkoknál. Hozzáadhatja a modulbeállító XML-be a következőhöz hasonlóan:

<ConfigItem
Name="Frontend::Template::GenerateBlockHooks###100-OTRSBusiness-ContactWithData"
Required="1" Valid="1">
    <Description Translatable="1">Generate HTML comment hooks for
the specified blocks so that filters can use them.</Description>
    <Group>OTRSBusiness</Group>
    <SubGroup>Core</SubGroup>
    <Setting>
        <Hash>
            <Item Key="AgentTicketZoom">
                <Array>
                    <Item>CustomerTable</Item>
                </Array>
            </Item>
        </Hash>
    </Setting>
</ConfigItem>
            

Ez azt fogja okozni, hogy az AgentTicketZoom.tt fájlban lévő CustomerTable blokk át lesz alakítva a HTML megjegyzésekben minden alkalommal, amikor megjelenítésre kerül:

<!--HookStartCustomerTable-->
... blokk kimenet ...
<!--HookEndCustomerTable-->
            

Ezzel a mechanizmussal minden csomag csak azokat a blokkhorgokat kérheti, amelyekre szüksége van, és következetesen kerülnek megjelenítésre. Ezek a HTML megjegyzések használhatók ezután a kimenetszűrőben az egyszerű reguláris kifejezés illesztéshez.

FilterContent

Ez a fajta szűrő lehetővé teszi a teljes HTML kimenet feldolgozását a kérésnél közvetlenül azelőtt, hogy kiküldésre kerül a böngészőnek. Ez globális átalakításokhoz használható.

FilterText

Ez a fajta kimenetszűrő egy bővítmény a Kernel::Output::HTML::Layout::Ascii2HTML() metódushoz, és csak akkor aktív, amikor a LinkFeature paraméter 1-re van állítva. Így a FilterText kimenetszűrők jelenleg csak az egyszerű szöveges bejegyzések törzsének megjelenítésénél aktívak. Az egyszerű szöveges bejegyzéseket a bejövő nem HTML levelek állítják elő, illetve amikor az OTRS úgy van beállítva, hogy ne használja a Rich Text szolgáltatást az előtétprogramon.

Kódpélda

Lásd a TemplateModule csomagot.

Beállítási példa

Lásd a TemplateModule csomagot.

Használati esetek
További jegyattribútumok megjelenítése az AgentTicketZoom képernyőn

Ez egy FilterElementPost kimenetszűrővel valósítható meg.

A szolgáltatásválasztás megjelenítése többszintű menüként

Használjon egy FilterElementPost szűrőt ehhez a szolgáltatáshoz. A választható szolgáltatások listája a feldolgozott sablonkimenetből dolgozható fel. A többszintű választás a szolgáltatáslistából építhető fel, és szúrható be a sablontartalomba. Egy FilterElementPost kimenetszűrőt kell használni ehhez.

Hivatkozások létrehozása az egyszerű szöveges bejegyzés törzseiben

Egy biotechnológiai vállalat IPI00217472 formátumú génneveket használ az egyszerű szöveges bejegyzésekben. Egy FilterText kimenetszűrő használható a szekvencia-adatbázisra mutató hivatkozások létrehozásához a génneveknél, például http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-e+[IPI-acc:IPI00217472]+-vn+2 formában.

Az aktív tartalom megtiltása

Van egy olyan tűzfalszabály, amely megtiltja az összes aktív tartalmat. Azért, hogy elkerüljük a tűzfal visszautasítását, az <applet> HTML-címke kiszűrhető egy FilterContent kimenetszűrővel.

Ellenjavaslatok és figyelmeztetések

Minden FilterElementPost kimenetszűrő felépítésre és futtatásra kerül minden olyan beállított sablonnál, amely szükséges az aktuális kéréshez. Így a kimenetszűrő alacsony teljesítménye vagy a szűrők nagy száma komolyan csökkentheti a teljesítményt.

Bevált gyakorlatok

A rugalmasság növelésének érdekében az érintett sablonok listáját be kell állítani a rendszerbeállításokban.

Kiadási elérhetőség

A kimenetszűrők az OTRS 2.4-es verziójától érhetők el. A FilterElementPre típus eldobásra került az OTRS 5-tel.

Statisztikák modul

A belső statisztikamoduloknak két különböző típusa létezik - dinamikus és statikus. Ez a szakasz azt írja le, hogy az ilyen statisztikamodulok hogyan fejleszthetők.

Dinamikus statisztikák

A statikus statisztikamodulokkal ellentétben a dinamikus statisztikák beállíthatók az OTRS webes felületén keresztül. Ebben a szakaszban egy egyszerű statisztikamodul kerül fejlesztésre. Minden egyes dinamikus statisztikamodulnak meg kell valósítania ezeket a szubrutinokat:

  • new

  • GetObjectName

  • GetObjectAttributes

  • ExportWrapper

  • ImportWrapper

Továbbá a modulnak meg kell valósítania vagy a GetStatElement, vagy a GetStatTable rutint. És ha az eredménytábla fejlécsorát is meg kell változtatni, akkor egy úgynevezett GetHeaderLine szubrutint is fejleszteni kell.

Kódpélda

Ebben a szakaszban egy minta statisztikamodul lesz megjelenítve, és minden szubrutin elmagyarázásra kerül.

# --
# Kernel/System/Stats/Dynamic/DynamicStatsTemplate.pm - all advice functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Stats::Dynamic::DynamicStatsTemplate;

use strict;
use warnings;

use Kernel::System::Queue;
use Kernel::System::State;
use Kernel::System::Ticket;
                

Ez egy gyakori sabloncsomag, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva. Ezután a szükséges modulok használatának megadása következik a use kulcsszóval.

sub new {
    my ( $Type, %Param ) = @_;

    # új kivonat lefoglalása az objektumhoz
    my $Self = {};
    bless( $Self, $Type );

    # a szükséges objektumok ellenőrzése
    for my $Object (
        qw(DBObject ConfigObject LogObject UserObject TimeObject MainObject EncodeObject)
        )
    {
        $Self->{$Object} = $Param{$Object} || die "Nincs $Object!";
    }

    # a létrehozott szükséges objektumok
    $Self->{QueueObject}    = Kernel::System::Queue->new( %{$Self} );
    $Self->{TicketObject}   = Kernel::System::Ticket->new( %{$Self} );
    $Self->{StateObject}    = Kernel::System::State->new( %{$Self} );

    return $Self;
}
                

A new a statisztikamodul konstruktora. Ez hozza létre az osztály új példányát. A kódolási irányelveknek megfelelően az ebben a modulban szükséges más osztályok objektumait is a new konstruktorban kell létrehozni. A 27-29. sorban van létrehozva a statisztikák modul objektuma. A 31-37. sorban azt ellenőrzik, hogy az ebben a kódban szükséges objektumok - vagy más objektumok létrehozásánál, vagy ebben a modulban - át vannak-e adva. Ezután a többi objektum kerül létrehozásra.

sub GetObjectName {
    my ( $Self, %Param ) = @_;

    return 'Minta statisztikák';
}
                

A GetObjectName visszaad egy nevet a statisztikák modulhoz. Ez az a címke, amely a lenyíló menüben jelenik meg a beállításokban, valamint a meglévő statisztikák listájában (az „objektum” oszlopban).

sub GetObjectAttributes {
    my ( $Self, %Param ) = @_;

    # állapotlista lekérése
    my %StateList = $Self->{StateObject}->StateList(
        UserID => 1,
    );

    # várólisták listájának lekérése
    my %QueueList = $Self->{QueueObject}->GetAllQueues();

    # a jelenlegi idő lekérése a 3830. hiba javításához
    my $TimeStamp = $Self->{TimeObject}->CurrentTimestamp();
    my ($Date) = split /\s+/, $TimeStamp;
    my $Today = sprintf "%s 23:59:59", $Date;

    my @ObjectAttributes = (
        {
            Name             => 'Állapot',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'StateIDs',
            Block            => 'MultiSelectField',
            Values           => \%StateList,
        },
        {
            Name             => 'Létrehozva várólistában',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'CreatedQueueIDs',
            Block            => 'MultiSelectField',
            Translation      => 0,
            Values           => \%QueueList,
        },
        {
            Name             => 'Létrehozás ideje',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'CreateTime',
            TimePeriodFormat => 'DateInputFormat',    # 'DateInputFormatLong',
            Block            => 'Time',
            TimeStop         => $Today,
            Values           => {
                TimeStart => 'TicketCreateTimeNewerDate',
                TimeStop  => 'TicketCreateTimeOlderDate',
            },
        },
    );

    return @ObjectAttributes;
}
                

Ebben a minta statisztikák modulban három olyan attribútumot szeretnénk szolgáltatni, amelyből a felhasználó választhat: a várólisták listáját, az állapotok listáját és egy idő legördülőt. A legördülőben megjelenített értékek lekéréséhez szükséges néhány művelet. Ebben az esetben a StateList és a GetAllQueues kerül meghívásra.

Ezután az attribútumok listája kerül létrehozásra. Minden egyes attribútum egy kivonathivatkozáson keresztül van meghatározva. Ezeket a kulcsokat használhatja:

  • Name

    A címke a webes felületen.

  • UseAsXvalue

    Ez az attribútum használható az X-tengelyen.

  • UseAsValueSeries

    Ez az attribútum használható az Y-tengelyen.

  • UseAsRestriction

    Ez az attribútum használható a korlátozásokhoz.

  • Element

    A HTML mező neve.

  • Block

    A blokknév a sablonfájlban (például <OTRS_HOME>/Kernel/Output/HTML/Standard/AgentStatsEditXaxis.tt).

  • Values

    Az attribútumban megjelenített értékek.

Tipp: Ha telepíti ezt a mintát, és beállít egy statisztikát néhány várólistával (mondjuk „A várólista” és „B várólista”), akkor ezek a várólisták az egyetlenek, amelyek láthatóak lesznek a felhasználónak, amikor elindítja a statisztikát. Néha egy dinamikus legördülő vagy többválasztós mező szükséges. Ebben az esetben beállíthatja a SelectedValues kulcsot az attribútum meghatározásában:

        {
            Name             => 'Létrehozva várólistában',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'CreatedQueueIDs',
            Block            => 'MultiSelectField',
            Translation      => 0,
            Values           => \%QueueList,
            SelectedValues   => [ @SelectedQueues ],
        },
                

sub GetStatElement {
    my ( $Self, %Param ) = @_;

    # jegyek keresése
    return $Self->{TicketObject}->TicketSearch(
        UserID     => 1,
        Result     => 'COUNT',
        Permission => 'ro',
        Limit      => 100_000_000,
        %Param,
    );
}
                

A GetStatElement kerül meghívásra minden egyes cellánál az eredménytáblában. Így annak számszerű értéknek kell lennie. Ebben a mintában egy egyszerű jegykeresést hajt végre. A %Param kivonat tartalmaz információkat a „jelenlegi” X-értékről és Y-értékről, valamint bármely korlátozásról. Így egy olyan cellánál, amelynek össze kell számolnia a „nyitott” állapotban lévő létrehozott jegyeket a „Misc” várólistánál, az átadott paraméter kivonat valahogy így néz ki:

    'CreatedQueueIDs' => [
        '4'
    ],
    'StateIDs' => [
        '2'
    ]
                

Ha a „cellánkénti” számítást el kellene kerülni, akkor a GetStatTable egy alternatíva. A GetStatTable visszaadja a sorok listáját, amely ezentúl egy tömbhivatkozások tömbje. Ez ugyanahhoz az eredményhez vezet mint a GetStatElement használata.

sub GetStatTable {
    my ( $Self, %Param ) = @_;

    my @StatData;

    for my $StateName ( keys %{ $Param{TableStructure} } ) {
        my @Row;
        for my $Params ( @{ $Param{TableStructure}->{$StateName} } ) {
            my $Tickets = $Self->{TicketObject}->TicketSearch(
                UserID     => 1,
                Result     => 'COUNT',
                Permission => 'ro',
                Limit      => 100_000_000,
                %{$Params},
            );

            push @Row, $Tickets;
        }

        push @StatData, [ $StateName, @Row ];
    }

    return @StatData;
}
                

A GetStatTable az összes olyan információt lekéri a statisztikák lekérdezéssel kapcsolatban, amelyek szükségesek. Az átadott paraméterek információkat tartalmaznak az attribútumokról (Restrictions, olyan attribútumok, amelyek az X/Y-tengelynél vannak használva) és a táblaszerkezetről. A táblaszerkezet egy olyan kivonathivatkozás, ahol a kulcsok az Y-tengely értékei, és azok értékei kivonathivatkozások a GetStatElement szubrutinokhoz használt paraméterekkel.

    'Restrictions' => {},
    'TableStructure' => {
        'closed successful' => [
            {
                'CreatedQueueIDs' => [
                    '3'
                ],
                'StateIDs' => [
                    '2'
                ]
            },
        ],
        'closed unsuccessful' => [
            {
                'CreatedQueueIDs' => [
                    '3'
                ],
                'StateIDs' => [
                    '3'
                ]
            },
        ],
    },
    'ValueSeries' => [
        {
            'Block' => 'MultiSelectField',
            'Element' => 'StateIDs',
            'Name' => 'Állapot',
            'SelectedValues' => [
                '5',
                '3',
                '2',
                '1',
                '4'
            ],
            'Translation' => 1,
            'Values' => {
                '1' => 'new',
                '10' => 'closed with workaround',
                '2' => 'closed successful',
                '3' => 'closed unsuccessful',
                '4' => 'open',
                '5' => 'removed',
                '6' => 'pending reminder',
                '7' => 'pending auto close+',
                '8' => 'pending auto close-',
                '9' => 'merged'
            }
        }
    ],
    'XValue' => {
        'Block' => 'MultiSelectField',
        'Element' => 'CreatedQueueIDs',
        'Name' => 'Létrehozva várólistában',
        'SelectedValues' => [
            '3',
            '4',
            '1',
            '2'
        ],
        'Translation' => 0,
        'Values' => {
            '1' => 'Postmaster',
            '2' => 'Raw',
            '3' => 'Junk',
            '4' => 'Misc'
        }
    }
                

Néha a táblázat fejléceit meg kell változtatni. Ebben az esetben egy GetHeaderLine nevű szubrutint kell megvalósítani. Ennek a szubrutinnak egy tömbhivatkozást kell visszaadnia az oszlopfejlécekkel mint elemekkel. Ez információkat kap az átadott X-értékekkel kapcsolatban.

sub GetHeaderLine {
    my ( $Self, %Param ) = @_;

    my @HeaderLine = ('');
    for my $SelectedXValue ( @{ $Param{XValue}->{SelectedValues} } ) {
        push @HeaderLine, $Param{XValue}->{Values}->{$SelectedXValue};
    }

    return \@HeaderLine;
}
                

sub ExportWrapper {
    my ( $Self, %Param ) = @_;

    # azonosítók átalakítása a használt helyesíráshoz
    for my $Use (qw(UseAsValueSeries UseAsRestriction UseAsXvalue)) {
        ELEMENT:
        for my $Element ( @{ $Param{$Use} } ) {
            next ELEMENT if !$Element || !$Element->{SelectedValues};
            my $ElementName = $Element->{Element};
            my $Values      = $Element->{SelectedValues};

            if ( $ElementName eq 'QueueIDs' || $ElementName eq 'CreatedQueueIDs' ) {
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;
                    $ID->{Content} = $Self->{QueueObject}->QueueLookup( QueueID => $ID->{Content} );
                }
            }
            elsif ( $ElementName eq 'StateIDs' || $ElementName eq 'CreatedStateIDs' ) {
                my %StateList = $Self->{StateObject}->StateList( UserID => 1 );
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;
                    $ID->{Content} = $StateList{ $ID->{Content} };
                }
            }
        }
    }
    return \%Param;
}
                

A beállított statisztikák exportálhatók XML-formátumba. De ahogy a várólistáknál, ahol ugyanazok a várólistanevek rendelkezhetnek különböző azonosítókkal a különböző OTRS példányoknál, különösen fájdalmas lehet az azonosítók exportálása (a statisztikák ekkor rossz számokat számítanának ki). Ezért egy exportálási átalakítót kell írni, hogy az azonosítók helyett neveket használjon. Ezt a statisztikák modul minden egyes „dimenziójánál” el kell végezni (X-tengely, Y-tengely és korlátozások).

Az ImportWrapper fordítva működik - átalakítja a nevet az azonosítóra abban a példányban, ahova a beállítások importálásra kerülnek.

Ez egy minta exportálás:

<?xml version="1.0" encoding="utf-8"?>

<otrs_stats>
<Cache>0</Cache>
<Description>Minta statisztikák modul</Description>
<File></File>
<Format>CSV</Format>
<Format>Print</Format>
<Object>DeveloperManualSample</Object>
<ObjectModule>Kernel::System::Stats::Dynamic::DynamicStatsTemplate</ObjectModule>
<ObjectName>Sample Statistics</ObjectName>
<Permission>stats</Permission>
<StatType>dynamic</StatType>
<SumCol>0</SumCol>
<SumRow>0</SumRow>
<Title>Sample 1</Title>
<UseAsValueSeries Element="StateIDs" Fixed="1">
<SelectedValues>removed</SelectedValues>
<SelectedValues>closed unsuccessful</SelectedValues>
<SelectedValues>closed successful</SelectedValues>
<SelectedValues>new</SelectedValues>
<SelectedValues>open</SelectedValues>
</UseAsValueSeries>
<UseAsXvalue Element="CreatedQueueIDs" Fixed="1">
<SelectedValues>Junk</SelectedValues>
<SelectedValues>Misc</SelectedValues>
<SelectedValues>Postmaster</SelectedValues>
<SelectedValues>Raw</SelectedValues>
</UseAsXvalue>
<Valid>1</Valid>
</otrs_stats>
                

Most, hogy az összes szubrutin elmagyarázásra került, itt a teljes minta statisztikák modul.

# --
# Kernel/System/Stats/Dynamic/DynamicStatsTemplate.pm - all advice functions
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Stats::Dynamic::DynamicStatsTemplate;

use strict;
use warnings;

use Kernel::System::Queue;
use Kernel::System::State;
use Kernel::System::Ticket;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # check needed objects
    for my $Object (
        qw(DBObject ConfigObject LogObject UserObject TimeObject MainObject EncodeObject)
        )
    {
        $Self->{$Object} = $Param{$Object} || die "Got no $Object!";
    }

    # created needed objects
    $Self->{QueueObject}    = Kernel::System::Queue->new( %{$Self} );
    $Self->{TicketObject}   = Kernel::System::Ticket->new( %{$Self} );
    $Self->{StateObject}    = Kernel::System::State->new( %{$Self} );

    return $Self;
}

sub GetObjectName {
    my ( $Self, %Param ) = @_;

    return 'Sample Statistics';
}

sub GetObjectAttributes {
    my ( $Self, %Param ) = @_;

    # get state list
    my %StateList = $Self->{StateObject}->StateList(
        UserID => 1,
    );

    # get queue list
    my %QueueList = $Self->{QueueObject}->GetAllQueues();

    # get current time to fix bug#3830
    my $TimeStamp = $Self->{TimeObject}->CurrentTimestamp();
    my ($Date) = split /\s+/, $TimeStamp;
    my $Today = sprintf "%s 23:59:59", $Date;

    my @ObjectAttributes = (
        {
            Name             => 'State',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'StateIDs',
            Block            => 'MultiSelectField',
            Values           => \%StateList,
        },
        {
            Name             => 'Created in Queue',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'CreatedQueueIDs',
            Block            => 'MultiSelectField',
            Translation      => 0,
            Values           => \%QueueList,
        },
        {
            Name             => 'Create Time',
            UseAsXvalue      => 1,
            UseAsValueSeries => 1,
            UseAsRestriction => 1,
            Element          => 'CreateTime',
            TimePeriodFormat => 'DateInputFormat',    # 'DateInputFormatLong',
            Block            => 'Time',
            TimeStop         => $Today,
            Values           => {
                TimeStart => 'TicketCreateTimeNewerDate',
                TimeStop  => 'TicketCreateTimeOlderDate',
            },
        },
    );

    return @ObjectAttributes;
}

sub GetStatElement {
    my ( $Self, %Param ) = @_;

    # search tickets
    return $Self->{TicketObject}->TicketSearch(
        UserID     => 1,
        Result     => 'COUNT',
        Permission => 'ro',
        Limit      => 100_000_000,
        %Param,
    );
}

sub ExportWrapper {
    my ( $Self, %Param ) = @_;

    # wrap ids to used spelling
    for my $Use (qw(UseAsValueSeries UseAsRestriction UseAsXvalue)) {
        ELEMENT:
        for my $Element ( @{ $Param{$Use} } ) {
            next ELEMENT if !$Element || !$Element->{SelectedValues};
            my $ElementName = $Element->{Element};
            my $Values      = $Element->{SelectedValues};

            if ( $ElementName eq 'QueueIDs' || $ElementName eq 'CreatedQueueIDs' ) {
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;
                    $ID->{Content} = $Self->{QueueObject}->QueueLookup( QueueID => $ID->{Content} );
                }
            }
            elsif ( $ElementName eq 'StateIDs' || $ElementName eq 'CreatedStateIDs' ) {
                my %StateList = $Self->{StateObject}->StateList( UserID => 1 );
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;
                    $ID->{Content} = $StateList{ $ID->{Content} };
                }
            }
        }
    }
    return \%Param;
}

sub ImportWrapper {
    my ( $Self, %Param ) = @_;

    # wrap used spelling to ids
    for my $Use (qw(UseAsValueSeries UseAsRestriction UseAsXvalue)) {
        ELEMENT:
        for my $Element ( @{ $Param{$Use} } ) {
            next ELEMENT if !$Element || !$Element->{SelectedValues};
            my $ElementName = $Element->{Element};
            my $Values      = $Element->{SelectedValues};

            if ( $ElementName eq 'QueueIDs' || $ElementName eq 'CreatedQueueIDs' ) {
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;
                    if ( $Self->{QueueObject}->QueueLookup( Queue => $ID->{Content} ) ) {
                        $ID->{Content}
                            = $Self->{QueueObject}->QueueLookup( Queue => $ID->{Content} );
                    }
                    else {
                        $Self->{LogObject}->Log(
                            Priority => 'error',
                            Message  => "Import: Can' find the queue $ID->{Content}!"
                        );
                        $ID = undef;
                    }
                }
            }
            elsif ( $ElementName eq 'StateIDs' || $ElementName eq 'CreatedStateIDs' ) {
                ID:
                for my $ID ( @{$Values} ) {
                    next ID if !$ID;

                    my %State = $Self->{StateObject}->StateGet(
                        Name  => $ID->{Content},
                        Cache => 1,
                    );
                    if ( $State{ID} ) {
                        $ID->{Content} = $State{ID};
                    }
                    else {
                        $Self->{LogObject}->Log(
                            Priority => 'error',
                            Message  => "Import: Can' find state $ID->{Content}!"
                        );
                        $ID = undef;
                    }
                }
            }
        }
    }
    return \%Param;
}

1;
                

Beállítási példa

<?xml version="1.0" encoding="utf-8" ?>
<otrs_config version="1.0" init="Config">
    <ConfigItem Name="Stats::DynamicObjectRegistration###DynamicStatsTemplate" Required="0" Valid="1">
        <Description Lang="en">Here you can decide if the common stats module may generate stats about the number of default tickets a requester created.</Description>
        <Group>Framework</Group>
        <SubGroup>Core::Stats</SubGroup>
        <Setting>
            <Hash>
                <Item Key="Module">Kernel::System::Stats::Dynamic::DynamicStatsTemplate</Item>
            </Hash>
        </Setting>
    </ConfigItem>
</otrs_config>
                

Használati eset példák

Használati esetek.

Ellenjavaslatok és figyelmeztetések

Ha nagyon sok cellája van az eredménytáblázatban és a GetStatElement meglehetősen összetett, akkor a kérés eltarthat egy ideig.

Kiadási elérhetőség

A dinamikus statisztikamodulok az OTRS 2.0 óta érhetők el.

Statikus statisztikák

A következő bekezdések a statikus statisztikákat írják le. A statikus statisztikákat nagyon könnyű létrehozni, mivel ezeknek a moduloknak csak három szubrutint kell megvalósítaniuk.

  • new

  • Param

  • Run

Kódpélda

A következő bekezdések a statikus statisztikákban szükséges szubrutinokat mutatják be.

sub new {
    my ( $Type, %Param ) = @_;

    # új kivonat lefoglalása az objektumhoz
    my $Self = {%Param};
    bless( $Self, $Type );

    # az összes szükséges objektum ellenőrzése
    for my $Needed (
        qw(DBObject ConfigObject LogObject
        TimeObject MainObject EncodeObject)
        )
    {
        $Self->{$Needed} = $Param{$Needed} || die "Nincs $Needed";
    }

    # a szükséges objektumok létrehozása
    $Self->{TypeObject}   = Kernel::System::Type->new( %{$Self} );
    $Self->{TicketObject} = Kernel::System::Ticket->new( %{$Self} );
    $Self->{QueueObject}  = Kernel::System::Queue->new( %{$Self} );

    return $Self;
}
                

A new hozza létre a statikus statisztikák osztályának egy új példányát. Először létrehoz egy új objektumot, és azután ellenőrzi a szükséges objektumokat.

sub Param {
    my $Self = shift;

    my %Queues = $Self->{QueueObject}->GetAllQueues();
    my %Types  = $Self->{TypeObject}->TypeList(
        Valid => 1,
    );

    my @Params = (
        {
            Frontend  => 'Type',
            Name      => 'TypeIDs',
            Multiple  => 1,
            Size      => 3,
            Data      => \%Types,
        },
        {
            Frontend  => 'Queue',
            Name      => 'QueueIDs',
            Multiple  => 1,
            Size      => 3,
            Data      => \%Queues,
        },
    );

    return @Params;
}
                

A Param metódus biztosítja az összes olyan paraméter és attribútum listáját, amelyek kiválaszthatók egy statikus statisztika létrehozásához. Megkap néhány átadott paramétert: az értékeket egy kérésben szolgáltatott statisztikák attribútumaihoz, a statisztikák formátumát és az objektum nevét (a modul nevét).

A paramétereknek és az attribútumoknak kivonathivatkozásoknak kell lenniük ezekkel a kulcs-érték párokkal:

  • Frontend

    A címke a webes felületen.

  • Name

    A HTML mező neve.

  • Data

    Az attribútumban megjelenített értékek.

Egyéb paraméterek is használhatók a LayoutObject BuildSelection metódusánál, ahogy az a Size és Multiple paraméterekkel történik ebben a minta modulban.

sub Run {
    my ( $Self, %Param ) = @_;

    # a szükséges dolgok ellenőrzése
    for my $Needed (qw(TypeIDs QueueIDs)) {
        if ( !$Param{$Needed} ) {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Szükséges: $Needed!",
            );
            return;
        }
    }

    # a jelentés címének beállítása
    my $Title = 'Jegyek várólistánként';

    # táblázat címsorok
    my @HeadData = (
        'Jegyszám',
        'Várólista',
        'Típus',
    );

    my @Data;
    my @TicketIDs = $Self->{TicketObject}->TicketSearch(
        UserID     => 1,
        Result     => 'ARRAY',
        Permission => 'ro',
        %Param,
    );

    for my $TicketID ( @TicketIDs ) {
        my %Ticket = $Self->{TicketObject}->TicketGet(
            UserID => 1,
            TicketID => $TicketID,
        );
        push @Data, [ $Ticket{TicketNumber}, $Ticket{Queue}, $Ticket{Type} ];
    }

    return ( [$Title], [@HeadData], @Data );
}
                

Tulajdonképpen a Run metódus állítja elő a táblázat adatait a statisztikákhoz. Megkapja az ennél a statisztikánál átadott attribútumokat. Ebben a mintában a %Param paraméterben egy TypeIDs kulcs és egy QueueIDs kulcs létezik (lásd a Param metódusban lévő attribútumokat), és ezek értékei tömbhivatkozások. A visszaadott adatok három részből állnak: két tömbhivatkozásból és egy tömbből. Az első tömbhivatkozásban a statisztika címe van eltárolva, a második tömbhivatkozás tartalmazza a táblázatban lévő oszlopok címsorait. És ezután a táblázattörzs adatai következnek.

# --
# Kernel/System/Stats/Static/StaticStatsTemplate.pm
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Stats::Static::StaticStatsTemplate;

use strict;
use warnings;

use Kernel::System::Type;
use Kernel::System::Ticket;
use Kernel::System::Queue;

=head1 NAME

StaticStatsTemplate.pm - the module that creates the stats about tickets in a queue

=head1 SYNOPSIS

All functions

=head1 PUBLIC INTERFACE

=over 4

=cut

=item new()

create an object

    use Kernel::Config;
    use Kernel::System::Encode;
    use Kernel::System::Log;
    use Kernel::System::Main;
    use Kernel::System::Time;
    use Kernel::System::DB;
    use Kernel::System::Stats::Static::StaticStatsTemplate;

    my $ConfigObject = Kernel::Config->new();
    my $EncodeObject = Kernel::System::Encode->new(
        ConfigObject => $ConfigObject,
    );
    my $LogObject    = Kernel::System::Log->new(
        ConfigObject => $ConfigObject,
    );
    my $MainObject = Kernel::System::Main->new(
        ConfigObject => $ConfigObject,
        LogObject    => $LogObject,
    );
    my $TimeObject = Kernel::System::Time->new(
        ConfigObject => $ConfigObject,
        LogObject    => $LogObject,
    );
    my $DBObject = Kernel::System::DB->new(
        ConfigObject => $ConfigObject,
        LogObject    => $LogObject,
        MainObject   => $MainObject,
    );
    my $StatsObject = Kernel::System::Stats::Static::StaticStatsTemplate->new(
        ConfigObject => $ConfigObject,
        LogObject    => $LogObject,
        MainObject   => $MainObject,
        TimeObject   => $TimeObject,
        DBObject     => $DBObject,
        EncodeObject => $EncodeObject,
    );

=cut

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {%Param};
    bless( $Self, $Type );

    # check all needed objects
    for my $Needed (
        qw(DBObject ConfigObject LogObject
        TimeObject MainObject EncodeObject)
        )
    {
        $Self->{$Needed} = $Param{$Needed} || die "Got no $Needed";
    }

    # create needed objects
    $Self->{TypeObject}   = Kernel::System::Type->new( %{$Self} );
    $Self->{TicketObject} = Kernel::System::Ticket->new( %{$Self} );
    $Self->{QueueObject}  = Kernel::System::Queue->new( %{$Self} );

    return $Self;
}

=item Param()

Get all parameters a user can specify.

    my @Params = $StatsObject->Param();

=cut

sub Param {
    my $Self = shift;

    my %Queues = $Self->{QueueObject}->GetAllQueues();
    my %Types  = $Self->{TypeObject}->TypeList(
        Valid => 1,
    );

    my @Params = (
        {
            Frontend  => 'Type',
            Name      => 'TypeIDs',
            Multiple  => 1,
            Size      => 3,
            Data      => \%Types,
        },
        {
            Frontend  => 'Queue',
            Name      => 'QueueIDs',
            Multiple  => 1,
            Size      => 3,
            Data      => \%Queues,
        },
    );

    return @Params;
}

=item Run()

generate the statistic.

    my $StatsInfo = $StatsObject->Run(
        TypeIDs  => [
            1, 2, 4
        ],
        QueueIDs => [
            3, 4, 6
        ],
    );

=cut

sub Run {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    for my $Needed (qw(TypeIDs QueueIDs)) {
        if ( !$Param{$Needed} ) {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Need $Needed!",
            );
            return;
        }
    }

    # set report title
    my $Title = 'Tickets per Queue';

    # table headlines
    my @HeadData = (
        'Ticket Number',
        'Queue',
        'Type',
    );

    my @Data;
    my @TicketIDs = $Self->{TicketObject}->TicketSearch(
        UserID     => 1,
        Result     => 'ARRAY',
        Permission => 'ro',
        %Param,
    );

    for my $TicketID ( @TicketIDs ) {
        my %Ticket = $Self->{TicketObject}->TicketGet(
            UserID => 1,
            TicketID => $TicketID,
        );
        push @Data, [ $Ticket{TicketNumber}, $Ticket{Queue}, $Ticket{Type} ];
    }

    return ( [$Title], [@HeadData], @Data );
}

1;
                

Beállítási példa

Nincs szükség beállításokra. Közvetlenül telepítés után a modul elérhető egy statisztika létrehozásához ennél a modulnál.

Használati eset példák

Használati esetek.

Ellenjavaslatok és figyelmeztetések

Ellenjavaslatok és figyelmeztetések a statikus statisztikáknál.

Kiadási elérhetőség

A statikus statisztikamodulok az OTRS 1.3 óta érhetők el.

Régi statikus statisztikák használata

A szabványos 1.3-as és 2.0-ás OTRS verziók már megkönnyítették a statisztikák előállítását. Az OTRS 1.3-as és 2.0-ás verzióinak különféle statisztikái, amelyek különlegesen lettek kifejlesztve, hogy kielégítsék az ügyfelek követelményeit, használhatók az újabb verziókban is.

A fájlokat pusztán csak át kell helyezni a Kernel/System/Stats/ útvonalról a Kernel/System/Stats/Static/ könyvtárba. Továbbá a megfelelő parancsfájl csomagnevét ::Static névre kell módosítani.

A következő példa azt mutatja be, hogy hogyan kell az első útvonalat módosítani.

    package Kernel::System::Stats::AccountedTime;
                

    package Kernel::System::Stats::Static::AccountedTime;
                

Jegyszám előállító modulok

A jegyszám előállítókat elkülönülő azonosítók létrehozásához használják az új jegyekhez, amelyeket jegyszámnak neveznek. Bármilyen metódus lehetséges a számok karakterláncainak létrehozásához, de a józan ész határain belül kell maradnia az eredményül kapott szöveg hosszával kapcsolatban (irányelv: 5-10).

Egy jegyszám létrehozásakor győződjön meg arról, hogy az eredmény megkapta-e a SystemID rendszerbeállítási változót előtagként annak érdekében, hogy engedélyezze a jegyszámok felismerését a bejövő e-mail válaszoknál. Egy jegyszám előállító modulnak a következő két függvényre van szüksége: TicketCreateNumber() és GetTNByString().

A TicketCreateNumber() metódus paraméterek nélkül kerül meghívásra, és az új jegyszámot adja vissza.

A GetTNByString() metódus egy olyan szöveg paraméterrel kerül meghívásra, amely a feldolgozandó szöveget tartalmazza a jegyszámnál, és visszaadja a jegyszámot, ha megtalálta.

Kódpélda

Nézze meg a Kernel/System/Ticket/Number/UserRandom.pm fájlt a TemplateModule csomagban.

Beállítási példa

Nézze meg a Kernel/Config/Files/TicketNumberGenerator.xml fájlt a TemplateModule csomagban.

Használati esetek
A jegyszámoknak egy bizonyos sémát kell követniük.

Akkor kell majd egy új jegyszám előállítót létrehoznia, ha az alapértelmezett modulok nem biztosítják azt a jegyszám sémát, amelyet használni szeretne.

Ellenjavaslatok és figyelmeztetések

Ragaszkodnia kell a meglévő jegyszám előállítókban használt GetTNByString() kódjához, hogy megelőzze a jegyszám feldolgozással kapcsolatos problémákat. A TicketCreateNumber() metódusban lévő hurok felismeréséhez használt rutint is érintetlenül kell hagynia a kettőzött jegyszámok megelőzéséhez.

Kiadási elérhetőség

A jegyszám előállítók az OTRS 1.1 óta lettek elérhetők az OTRS-ben.

Jegyesemény modul

A jegyesemény modulok közvetlenül azután futnak le, amikor egy jegyművelet megtörténik. Megegyezés szerint ezek a modulok a Kernel/System/Ticket/Event könyvtárban találhatók. Egy jegyesemény modulnak mindössze két függvényre van szüksége: new() és Run(). A Run() metódus legalább az Event, a UserID és a Data paramétereket fogadja. A Data a jegy adatait tartalmazó kivonathivatkozás, és a bejegyzésre vonatkozó események esetében a bejegyzés adatait is tartalmazza.

Kódpélda

Nézze meg a Kernel/System/Ticket/Event/EventModulePostTemplate.pm fájlt a TemplateModule csomagban.

Beállítási példa

Nézze meg a Kernel/Config/Files/EventModulePostTemplate.xml fájlt a TemplateModule csomagban.

Használati esetek
Egy jegyet fel kell oldani egy áthelyezés művelet után.

Ez a szabványos funkció a Kernel::System::Ticket::Event::ForceUnlock jegyesemény modullal lett megvalósítva. Amikor erre a funkcióra nincs szükség, akkor az kikapcsolható a Ticket::EventModulePost###910-ForceUnlockOnMove rendszerbeállítási bejegyzés beállításának törlésével.

További tisztítóművelet végrehajtása egy jegy törlésekor.

Egy személyre szabott OTRS tarthat nem szabványos adatokat további adatbázistáblákban. Amikor egy jegyet törölnek, akkor ezeket a további adatokat is törölni kell. Ez a funkcionalitás elérhető egy olyan jegyesemény modullal, amely a TicketDelete eseményekre figyel.

Az új jegyeket közzé kell tenni a Twitteren.

Egy TicketCreate eseményre figyelő jegyesemény modul képes üzeneteket kiküldeni a Twitterre.

Ellenjavaslatok és figyelmeztetések

Nincsenek ismert ellenjavaslatok.

Kiadási elérhetőség

A jegyesemények az OTRS 2.0 óta lettek elérhetők az OTRS-ben.

Az OTRS 6.0 verziójában elérhető jegyesemények:

  • TicketCreate

  • TicketDelete

  • TicketTitleUpdate

  • TicketUnlockTimeoutUpdate

  • TicketQueueUpdate

  • TicketTypeUpdate

  • TicketServiceUpdate

  • TicketSLAUpdate

  • TicketCustomerUpdate

  • TicketPendingTimeUpdate

  • TicketLockUpdate

  • TicketArchiveFlagUpdate

  • TicketStateUpdate

  • TicketOwnerUpdate

  • TicketResponsibleUpdate

  • TicketPriorityUpdate

  • HistoryAdd

  • HistoryDelete

  • TicketAccountTime

  • TicketMerge

  • TicketSubscribe

  • TicketUnsubscribe

  • TicketFlagSet

  • TicketFlagDelete

  • EscalationResponseTimeNotifyBefore

  • EscalationUpdateTimeNotifyBefore

  • EscalationSolutionTimeNotifyBefore

  • EscalationResponseTimeStart

  • EscalationUpdateTimeStart

  • EscalationSolutionTimeStart

  • EscalationResponseTimeStop

  • EscalationUpdateTimeStop

  • EscalationSolutionTimeStop

  • NotificationNewTicket

  • NotificationFollowUp

  • NotificationLockTimeout

  • NotificationOwnerUpdate

  • NotificationResponsibleUpdate

  • NotificationAddNote

  • NotificationMove

  • NotificationPendingReminder

  • NotificationEscalation

  • NotificationEscalationNotifyBefore

  • NotificationServiceUpdate

Az OTRS 6.0 verziójában elérhető bejegyzésesemények:

  • ArticleCreate

  • ArticleUpdate

  • ArticleSend

  • ArticleBounce

  • ArticleAgentNotification

  • ArticleCustomerNotification

  • ArticleAutoResponse

  • ArticleFlagSet

  • ArticleFlagDelete

  • ArticleAgentNotification

  • ArticleCustomerNotification

Előtétprogram modulok

Vezérlőpult modul

Vezérlőpult modul statisztikák megjelenítéséhez vonaldiagram formájában.

3.1. ábra - Vezérlőpult felületi elem

Vezérlőpult felületi elem


# --
# Kernel/Output/HTML/DashboardTicketStatsGeneric.pm - message of the day
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::Output::HTML::DashboardTicketStatsGeneric;

use strict;
use warnings;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {%Param};
    bless( $Self, $Type );

    # get needed objects
    for (
        qw(Config Name ConfigObject LogObject DBObject LayoutObject ParamObject TicketObject UserID)
        )
    {
        die "Got no $_!" if !$Self->{$_};
    }

    return $Self;
}

sub Preferences {
    my ( $Self, %Param ) = @_;

    return;
}

sub Config {
    my ( $Self, %Param ) = @_;

    my $Key = $Self->{LayoutObject}->{UserLanguage} . '-' . $Self->{Name};
    return (
        %{ $Self->{Config} },
        CacheKey => 'TicketStats' . '-' . $Self->{UserID} . '-' . $Key,
    );

}

sub Run {
    my ( $Self, %Param ) = @_;

    my %Axis = (
        '7Day' => {
            0 => { Day => 'Sun', Created => 0, Closed => 0, },
            1 => { Day => 'Mon', Created => 0, Closed => 0, },
            2 => { Day => 'Tue', Created => 0, Closed => 0, },
            3 => { Day => 'Wed', Created => 0, Closed => 0, },
            4 => { Day => 'Thu', Created => 0, Closed => 0, },
            5 => { Day => 'Fri', Created => 0, Closed => 0, },
            6 => { Day => 'Sat', Created => 0, Closed => 0, },
        },
    );

    my @Data;
    my $Max = 1;
    for my $Key ( 0 .. 6 ) {

        my $TimeNow = $Self->{TimeObject}->SystemTime();
        if ($Key) {
            $TimeNow = $TimeNow - ( 60 * 60 * 24 * $Key );
        }
        my ( $Sec, $Min, $Hour, $Day, $Month, $Year, $WeekDay )
            = $Self->{TimeObject}->SystemTime2Date(
            SystemTime => $TimeNow,
            );

        $Data[$Key]->{Day} = $Self->{LayoutObject}->{LanguageObject}->Get(
            $Axis{'7Day'}->{$WeekDay}->{Day}
        );

        my $CountCreated = $Self->{TicketObject}->TicketSearch(

            # cache search result 20 min
            CacheTTL => 60 * 20,

            # tickets with create time after ... (ticket newer than this date) (optional)
            TicketCreateTimeNewerDate => "$Year-$Month-$Day 00:00:00",

            # tickets with created time before ... (ticket older than this date) (optional)
            TicketCreateTimeOlderDate => "$Year-$Month-$Day 23:59:59",

            CustomerID => $Param{Data}->{UserCustomerID},
            Result     => 'COUNT',

            # search with user permissions
            Permission => $Self->{Config}->{Permission} || 'ro',
            UserID => $Self->{UserID},
        );
        $Data[$Key]->{Created} = $CountCreated;
        if ( $CountCreated > $Max ) {
            $Max = $CountCreated;
        }

        my $CountClosed = $Self->{TicketObject}->TicketSearch(

            # cache search result 20 min
            CacheTTL => 60 * 20,

            # tickets with create time after ... (ticket newer than this date) (optional)
            TicketCloseTimeNewerDate => "$Year-$Month-$Day 00:00:00",

            # tickets with created time before ... (ticket older than this date) (optional)
            TicketCloseTimeOlderDate => "$Year-$Month-$Day 23:59:59",

            CustomerID => $Param{Data}->{UserCustomerID},
            Result     => 'COUNT',

            # search with user permissions
            Permission => $Self->{Config}->{Permission} || 'ro',
            UserID => $Self->{UserID},
        );
        $Data[$Key]->{Closed} = $CountClosed;
        if ( $CountClosed > $Max ) {
            $Max = $CountClosed;
        }
    }

    @Data = reverse @Data;
    my $Source = $Self->{LayoutObject}->JSONEncode(
        Data => \@Data,
    );

    my $Content = $Self->{LayoutObject}->Output(
        TemplateFile => 'AgentDashboardTicketStats',
        Data         => {
            %{ $Self->{Config} },
            Key    => int rand 99999,
            Max    => $Max,
            Source => $Source,
        },
    );

    return $Content;
}

1;
            

Ezen modul használatához adja hozzá a következőket a Kernel/Config.pm fájlhoz, és indítsa újra a webkiszolgálóját (ha a mod_perl modult használja).

<ConfigItem Name="DashboardBackend###0250-TicketStats" Required="0" Valid="1">
    <Description Lang="en">Parameters for the dashboard backend. "Group" are used to restricted access to the plugin (e. g. Group: admin;group1;group2;). "Default" means if the plugin is enabled per default or if the user needs to enable it manually. "CacheTTL" means the cache time in minutes for the plugin.</Description>
    <Description Lang="hu">Paraméterek a vezérlőpult háttérprogramhoz. A „Csoport” használható a hozzáférés korlátozásához a bővítményre (például Csoport: admin;csoport1;csoport2;). Az „Alapértelmezett” azt jelenti, hogy a bővítmény alapértelmezetten engedélyezve van, vagy hogy a felhasználónak kézzel kell engedélyeznie azt. A „CacheTTL” a bővítmény gyorsítótár lejárati időtartamát jelenti percben.</Description>
    <Group>Ticket</Group>
    <SubGroup>Frontend::Agent::Dashboard</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::Output::HTML::DashboardTicketStatsGeneric</Item>
            <Item Key="Title">7 Day Stats</Item>
            <Item Key="Created">1</Item>
            <Item Key="Closed">1</Item>
            <Item Key="Permission">rw</Item>
            <Item Key="Block">ContentSmall</Item>
            <Item Key="Group"></Item>
            <Item Key="Default">1</Item>
            <Item Key="CacheTTL">45</Item>
        </Hash>
    </Setting>
</ConfigItem>
            

Ellenjavaslatok és figyelmeztetések

A napok vagy az önálló sorok túlzott száma teljesítmény-csökkenéshez vezethet.

Kiadási elérhetőség

A 2.4.0-ás verziótól.

Értesítési modul

Az értesítési modulokat egy értesítés megjelenítéséhez használják a fő navigáció alatt. Megírhatja és regisztrálhatja a saját értesítési modulját. Jelenleg 5 jegymenü van az OTRS keretrendszerben.

  • AgentOnline

  • AgentTicketEscalation

  • CharsetCheck

  • CustomerOnline

  • UIDCheck

Kódpélda

Az értesítési modulok a Kernel/Output/HTML/TicketNotification*.pm alatt találhatók. Ezt követően egy értesítőmodul példája található. Mentse el a Kernel/Output/HTML/TicketNotificationCustom.pm fájlba. Mindössze két függvényre van szüksége: new() és Run().

# --
# Kernel/Output/HTML/NotificationCustom.pm
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::Output::HTML::NotificationCustom;

use strict;
use warnings;

use Kernel::System::Custom;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # get needed objects
    for my $Object (qw(ConfigObject LogObject DBObject LayoutObject TimeObject UserID)) {
        $Self->{$Object} = $Param{$Object} || die "Got no $Object!";
    }
    $Self->{CustomObject} = Kernel::System::Custom->new(%Param);
    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;

    # get session info
    my %CustomParam      = ();
    my @Customs    = $Self->{CustomObject}->GetAllCustomIDs();
    my $IdleMinutes = $Param{Config}->{IdleMinutes} || 60 * 2;
    for (@Customs) {
        my %Data = $Self->{CustomObject}->GetCustomIDData( CustomID => $_, );
        if (
            $Self->{UserID} ne $Data{UserID}
            && $Data{UserType} eq 'User'
            && $Data{UserLastRequest}
            && $Data{UserLastRequest} + ( $IdleMinutes * 60 ) > $Self->{TimeObject}->SystemTime()
            && $Data{UserFirstname}
            && $Data{UserLastname}
            )
        {
            $CustomParam{ $Data{UserID} } = "$Data{UserFirstname} $Data{UserLastname}";
            if ( $Param{Config}->{ShowEmail} ) {
                $CustomParam{ $Data{UserID} } .= " ($Data{UserEmail})";
            }
        }
    }
    for ( sort { $CustomParam{$a} cmp $CustomParam{$b} } keys %CustomParam ) {
        if ( $Param{Message} ) {
            $Param{Message} .= ', ';
        }
        $Param{Message} .= "$CustomParam{$_}";
    }
    if ( $Param{Message} ) {
        return $Self->{LayoutObject}->Notify( Info => 'Custom Message: %s", "' . $Param{Message} );
    }
    else {
        return '';
    }
}

1;

        

Beállítási példa

Szükség van az egyéni értesítési modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni. Lehetnek további paraméterek is a beállítás kivonatában az értesítési moduljánál.

<ConfigItem Name="Frontend::NotifyModule###3-Custom" Required="0" Valid="0">
    <Description Lang="en">Module to show custom message in the agent interface.</Description>
    <Description Lang="hu">Egy modul egyéni üzenet megjelenítéséhez az ügyintézői felületen.</Description>
    <Group>Framework</Group>
    <SubGroup>Frontend::Agent::ModuleNotify</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::Output::HTML::NotificationCustom</Item>
            <Item Key="Key1">1</Item>
            <Item Key="Key2">2</Item>
        </Hash>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos jegymenü megvalósítás lehet egy hivatkozás egy külső eszközre, ha a paraméterek (például FreeTextField) be lettek állítva.

Kiadási elérhetőség

NévKiadás
NotificationAgentOnline2.0
NotificationAgentTicketEscalation2.0
NotificationCharsetCheck1.2
NotificationCustomerOnline2.0
NotificationUIDCheck1.2

Jegymenü modul

A jegymenü modulokat egy további hivatkozás megjelenítéséhez használják a jegy fölött lévő menüben. Megírhatja és regisztrálhatja a saját jegymenü moduljait. Négy jegymenü létezik (Általános, Zárolás, Felelős és Jegymegfigyelő), amely az OTRS keretrendszerrel érkezik. További információkért nézzen bele az OTRS adminisztrációs kézikönyvébe.

Kódpélda

A jegymenü modulok a Kernel/Output/HTML/TicketMenu*.pm fájlokban találhatók. A következőkben egy jegymenü modul példája található. Mentse el a Kernel/Output/HTML/TicketMenuCustom.pm helyre. Mindössze két függvényre van szüksége: new() és Run().

# --
# Kernel/Output/HTML/TicketMenuCustom.pm
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# Id: TicketMenuCustom.pm,v 1.17 2010/04/12 21:34:06 martin Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::Output::HTML::TicketMenuCustom;

use strict;
use warnings;

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless( $Self, $Type );

    # get needed objects
    for my $Object (qw(ConfigObject LogObject DBObject LayoutObject UserID TicketObject)) {
        $Self->{$Object} = $Param{$Object} || die "Got no $Object!";
    }

    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;

    # check needed stuff
    if ( !$Param{Ticket} ) {
        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => 'Need Ticket!'
        );
        return;
    }

    # check if frontend module registered, if not, do not show action
    if ( $Param{Config}->{Action} ) {
        my $Module = $Self->{ConfigObject}->Get('Frontend::Module')->{ $Param{Config}->{Action} };
        return if !$Module;
    }

    # check permission
    my $AccessOk = $Self->{TicketObject}->Permission(
        Type     => 'rw',
        TicketID => $Param{Ticket}->{TicketID},
        UserID   => $Self->{UserID},
        LogNo    => 1,
    );
    return if !$AccessOk;

    # check permission
    if ( $Self->{TicketObject}->CustomIsTicketCustom( TicketID => $Param{Ticket}->{TicketID} ) ) {
        my $AccessOk = $Self->{TicketObject}->OwnerCheck(
            TicketID => $Param{Ticket}->{TicketID},
            OwnerID  => $Self->{UserID},
        );
        return if !$AccessOk;
    }

    # check acl
    return
        if defined $Param{ACL}->{ $Param{Config}->{Action} }
            && !$Param{ACL}->{ $Param{Config}->{Action} };

    # if ticket is customized
    if ( $Param{Ticket}->{Custom} eq 'lock' ) {

        # if it is locked for somebody else
        return if $Param{Ticket}->{OwnerID} ne $Self->{UserID};

        # show custom action
        return {
            %{ $Param{Config} },
            %{ $Param{Ticket} },
            %Param,
            Name        => 'Custom',
            Description => 'Custom to give it back to the queue!',
            Link        => 'Action=AgentTicketCustom;Subaction=Custom;TicketID=$QData{"TicketID"}',
        };
    }

    # if ticket is customized
    return {
        %{ $Param{Config} },
        %{ $Param{Ticket} },
        %Param,
        Name        => 'Custom',
        Description => 'Custom it to work on it!',
        Link        => 'Action=AgentTicketCustom;Subaction=Custom;TicketID=$QData{"TicketID"}',
    };
}

1;

        

Beállítási példa

Szükség van az egyéni jegymenü modul bekapcsolására. Ezt a lenti XML beállítás használatával lehet megtenni. Lehetnek további paraméterek is a beállítás kivonatában a jegymenü moduljánál.

<ConfigItem Name="Ticket::Frontend::MenuModule###110-Custom" Required="0" Valid="1">
    <Description Lang="en">Module to show custom link in menu.</Description>
    <Description Lang="hu">Egy modul egyéni hivatkozás megjelenítéséhez a menüben.</Description>
    <Group>Ticket</Group>
    <SubGroup>Frontend::Agent::Ticket::MenuModule</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::Output::HTML::TicketMenuCustom</Item>
            <Item Key="Name">Custom</Item>
            <Item Key="Action">AgentTicketCustom</Item>
        </Hash>
    </Setting>
</ConfigItem>
        

Használati eset példa

Hasznos jegymenü megvalósítás lehet egy hivatkozás egy külső eszközre, ha a paraméterek (például FreeTextField) be lettek állítva.

Ellenjavaslatok és figyelmeztetések

A jegymenü egy olyan URL-re irányít, amely kezelhető. Ha ezt a kérést az OTRS keretrendszeren keresztül szeretné kezelni, akkor meg kell írnia a saját előtétprogram modulját.

Kiadási elérhetőség

NévKiadás
TicketMenuGeneric2.0
TicketMenuLock2.0
TicketMenuResponsible2.1
TicketMenuTicketWatcher2.4

Általános felület modulok

Hálózati átvitel

A hálózati átvitelt használják az információk küldésének és fogadásának módszereként az OTRS és egy távoli rendszer között. Az általános felület beállításai lehetővé teszik egy webszolgáltatásnak, hogy különböző hálózati átviteli modulokat használjon a szolgáltatónál és a kérelmezőnél, de a leggyakoribb forgatókönyv az, hogy ugyanazt az átviteli modult használják mindkettőnél.

OTRS mint szolgáltató:

Az OTRS arra használja a hálózati átviteli modulokat, hogy lekérje az adatokat a távoli rendszertől, valamint lekérje a végrehajtandó műveleteket. A művelet végrehajtása után az OTRS ismét azokat használja a válasz visszaküldéséhez a távoli rendszernek.

OTRS mint kérelmező:

Az OTRS arra használja a hálózati átviteli modulokat, hogy kérelmeket küldjön a távoli rendszernek egy távoli művelet végrehajtásához a szükséges adatok mellett. Az OTRS várakozik a távoli rendszer válaszára, és visszaküldi azt a kérelmező modulnak.

Mindkét irányban a hálózati átviteli modulok foglalkoznak a távoli rendszer formátumában lévő adatokkal. Nem ajánlott semmilyen adatátalakítás végrehajtása sem ezekben a modulokban, mivel a leképező réteg felelős a kommunikáció során szükséges bármilyen adatátalakítás végrehajtásáért. Egy kivétel erre az olyan adatátalakítás, amely kifejezetten az átvitelnél szükséges, például XML vagy JSON és Perl átalakítások.

Átviteli háttérprogram

Ezután be fogjuk mutatni, hogy hogyan kell egy új átviteli háttérprogramot kifejleszteni. Minden egyes átviteli háttérprogramnak meg kell valósítania ezeket a szubrutinokat:

  • new

  • ProviderProcessRequest

  • ProviderGenerateResponse

  • RequesterPerformRequest

Meg kell valósítanunk ezen metódusok mindegyikét azért, hogy képesek legyünk mindkét irányban helyesen kommunikálni egy távoli rendszerrel. Az összes átviteli háttérprogramot az átviteli modul kezeli (Kernel/GenericInterface/Transport.pm).

Jelenleg az általános felület megvalósítja a HTTP SOAP és a HTTP REST átviteleket. Ha a tervezett webszolgáltatás használhat HTTP SOAP vagy HTTP SOAP átviteleket, akkor nincs szükség egy új hálózati átviteli modul létrehozására, hanem ahelyett azt ajánljuk, hogy vessen egy pillantást a HTTP SOAP vagy HTTP REST konfigurációira a beállításaik ellenőrzéséhez, valamint hogy hogyan hangolhatók a távoli rendszernek megfelelően.

Kódpélda

Abban az esetben, ha a biztosított hálózati átvitelek nem illeszkednek a webszolgáltatás igényeire, akkor ebben a szakaszban egy minta hálózati átviteli modul van bemutatva, és minden egyes szubrutin elmagyarázásra kerül. Normális esetben az átviteli modulok CPAN modulokat használnak háttérprogramokként. Például a HTTP SOAP átviteli modulok a SOAP::Lite modult használják háttérprogramként.

Ennél a példánál egy egyéni csomagot használnak az adatok visszaadásához anélkül, hogy valódi hálózati kérést intéznének egy távoli rendszerhez, ehelyett ez az egyéni modul működik visszacsatolási felületként.

# --
# Kernel/GenericInterface/Transport/HTTP/Test.pm - GenericInterface network transport interface for testing
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::GenericInterface::Transport::HTTP::Test;

use strict;
use warnings;

use HTTP::Request::Common;
use LWP::UserAgent;
use LWP::Protocol;

# prevent 'Used once' warning for Kernel::OM
use Kernel::System::ObjectManager;

our $ObjectManagerDisabled = 1;
                

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva. Az átvitelek nem példányosíthatók az objektumkezelővel.

sub new {
    my ( $Type, %Param ) = @_;

    my $Self = {};
    bless( $Self, $Type );

    for my $Needed (qw( DebuggerObject TransportConfig)) {
        $Self->{$Needed} = $Param{$Needed} || return {
            Success      => 0,
            ErrorMessage => "Nincs $Needed!"
        };
    }

    return $Self;
}

                

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint az objektumkezelő által nem kezelt más osztályoknak csak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

sub ProviderProcessRequest {
    my ( $Self, %Param ) = @_;

    if ( $Self->{TransportConfig}->{Config}->{Fail} ) {

        return {
            Success      => 0,
            ErrorMessage => "HTTP állapotkód: 500",
            Data         => {},
        };
    }

    my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');

    my %Result;
    for my $ParamName ( $ParamObject->GetParamNames() ) {
        $Result{$ParamName} = $ParamObject->GetParam( Param => $ParamName );
    }

    # különleges kezelés az üres POST kérésnél
    if ( scalar keys %Result == 1 && exists $Result{POSTDATA} && !$Result{POSTDATA} ) {
        %Result = ();
    }

    if ( !%Result ) {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Nem található kért adat.',
        );
    }

    return {
        Success   => 1,
        Data      => \%Result,
        Operation => 'test_operation',
    };
}
                

A ProviderProcessRequest függvény megkapja a kérést a távoli kiszolgálótól (ebben az esetben ugyanaz az OTRS), és kibontja az adatokat és a műveletet a kérésből a végrehajtáshoz. Ennél a példánál a művelet mindig a test_operation.

Annak a módja, ahogy ez a függvény feldolgozza a kérést az adatok és a művelet nevének lekéréséhez, az teljes egészében a megvalósítandó protokolltól és azon külső moduloktól függ, amelyekhez használják azokat.

sub ProviderGenerateResponse {
    my ( $Self, %Param ) = @_;

    if ( $Self->{TransportConfig}->{Config}->{Fail} ) {

        return {
            Success      => 0,
            ErrorMessage => 'A tesztválasz előállítása sikertelen.',
        };
    }

    my $Response;

    if ( !$Param{Success} ) {
        $Response
            = HTTP::Response->new( 500 => ( $Param{ErrorMessage} || 'Internal Server Error' ) );
        $Response->protocol('HTTP/1.0');
        $Response->content_type("text/plain; charset=UTF-8");
        $Response->date(time);
    }
    else {

        # egy kérésszöveg előállítása az adatokból
        my $Request
            = HTTP::Request::Common::POST( 'http://testhost.local/', Content => $Param{Data} );

        $Response = HTTP::Response->new( 200 => "OK" );
        $Response->protocol('HTTP/1.0');
        $Response->content_type("text/plain; charset=UTF-8");
        $Response->add_content_utf8( $Request->content() );
        $Response->date(time);
    }

    $Self->{DebuggerObject}->Debug(
        Summary => 'HTTP-válasz küldése',
        Data    => $Response->as_string(),
    );

    # a válasz elküldése a kliensnek most
    print STDOUT $Response->as_string();

    return {
        Success => 1,
    };
}
                

Ez a függvény visszaküldi a választ a távoli rendszernek a kért művelethez.

Ennél a bizonyos példánál minden esetben egy szabványos sikeres HTTP-választ adunk vissza (200) vagy nem (500) a szükséges adatok mellett.

sub RequesterPerformRequest {
    my ( $Self, %Param ) = @_;

    if ( $Self->{TransportConfig}->{Config}->{Fail} ) {

        return {
            Success      => 0,
            ErrorMessage => "HTTP állapotkód: 500",
            Data         => {},
        };
    }

    # egyéni protokollkezelő használata a valódi hálózati kérések kiküldésének elkerüléséhez
    LWP::Protocol::implementor(
        testhttp => 'Kernel::GenericInterface::Transport::HTTP::Test::CustomHTTPProtocol'
    );
    my $UserAgent = LWP::UserAgent->new();
    my $Response = $UserAgent->post( 'testhttp://localhost.local/', Content => $Param{Data} );

    return {
        Success => 1,
        Data    => {
            ResponseContent => $Response->content(),
        },
    };
}
                

Ez az egyetlen olyan függvény, amelyet az OTRS mint kérelmező használ. Elküldi a kérést a távoli rendszernek, és várakozik annak válaszára.

Ennél a példánál egy egyéni protokollkezelőt használunk a valódi hálózatra történő kérésküldés elkerüléséhez. Ez az egyéni protokoll az alábbiakban van megadva.

package Kernel::GenericInterface::Transport::HTTP::Test::CustomHTTPProtocol;

use base qw(LWP::Protocol);

sub new {
    my $Class = shift;

    return $Class->SUPER::new(@_);
}

sub request {    ## nem kritikus
    my $Self = shift;

    my ( $Request, $Proxy, $Arg, $Size, $Timeout ) = @_;

    my $Response = HTTP::Response->new( 200 => "OK" );
    $Response->protocol('HTTP/1.0');
    $Response->content_type("text/plain; charset=UTF-8");
    $Response->add_content_utf8( $Request->content() );
    $Response->date(time);

    #print $Request->as_string();
    #print $Response->as_string();

    return $Response;
}

                

Ez a kód ahhoz az egyéni protokollhoz van, amelyet használunk. Ez a megközelítés csak gyakorlásnál vagy olyan tesztelési környezeteknél hasznos, ahol a távoli rendszerek nem érhetők el.

Egy új modul kifejlesztéséhez nem ajánljuk ezen megközelítés használatát, egy valódi protokollt kell megvalósítani.

Beállítási példa

Szükség van ezen hálózati átviteli modul regisztrálására, hogy elérhető legyen az OTRS grafikus felhasználói felületén. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="GenericInterface::Transport::Module###HTTP::Test" Required="0" Valid="1">
    <Description Translatable="1">GenericInterface module registration for the transport layer.</Description>
    <Group>GenericInterface</Group>
    <SubGroup>GenericInterface::Transport::ModuleRegistration</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Name">Test</Item>
            <Item Key="Protocol">HTTP</Item>
            <Item Key="ConfigDialog">AdminGenericInterfaceTransportHTTPTest</Item>
        </Hash>
    </Setting>
</ConfigItem>
                

Leképezés

A leképezést adatok átalakításához használják az OTRS és a távoli rendszer között, illetve fordítva. Ezek az adatok kulcs => érték párokként vannak ábrázolva. Leképező modulok fejleszthetők ki nem csak az értékek, hanem a kulcsok átalakításához is.

Például:

ErrőlErre
Prio => WarningPriorityID => 3

A leképező réteg nem feltétlenül szükséges, egy webszolgáltatás teljesen kihagyhatja azt a webszolgáltatás beállításaitól, valamint a meghívók és műveletek megvalósításának módjától függően. De ha egy kis átalakítás szükséges, akkor erősen ajánlott egy meglévő leképezőmodul használata, vagy egy új létrehozása.

A leképező modulok egynél több alkalommal is meghívhatók egy normál kommunikáció közben. Vessen egy pillantást a következő példákra.

OTRS mint szolgáltató példa:

  1. A távoli rendszer elküldi a kérést az adatokkal a távoli rendszer formátumában

  2. Az adatok leképezésre kerülnek a távoli rendszer formátumáról az OTRS formátumára

  3. Az OTRS végrehajtja a műveletet, és visszaadja a választ az OTRS formátumában

  4. Az adatok leképezésre kerülnek az OTRS formátumáról a távoli rendszer formátumára

  5. A válasz a távoli rendszer formátumában lévő adatokkal elküldésre kerül a távoli rendszernek

OTRS mint kérelmező példa:

  1. Az OTRS előkészíti a kérést a távoli rendszerhez az OTRS formátumában lévő adatokkal

  2. Az adatok leképezésre kerülnek az OTRS formátumáról a távoli rendszer formátumára

  3. A kérés elküldésre kerül a távoli rendszernek, amely végrehajtja a műveletet, és visszaküldi a választ az OTRS-nek a távoli rendszer formátumában lévő adatokkal

  4. Az adatok (ismét) leképezésre kerülnek a távoli rendszer formátumáról az OTRS formátumára

  5. Az OTRS feldolgozza a választ

Leképező háttérprogram

Az általános felület biztosít egy Simple nevű leképezőmodult. Ezzel a modullal a legtöbb adatátalakítás (beleértve a kulcs és érték leképezést) elvégezhető, és szabályokat is meghatároz az alapértelmezett leképezések kezeléséhez mind a kulcsoknál, mind az értékeknél.

Ezért erősen valószínű, hogy nem lesz szüksége egy egyéni leképezőmodul kifejlesztésére. A folytatás előtt nézze meg a Simple leképezőmodult (Kernel/GenericInterface/Mapping/Simple.pm) és annak internetes dokumentációját.

Ha a Simple leképezőmodul nem felel meg az igényeinek, akkor meg fogjuk mutatni, hogy hogyan lehet kifejleszteni egy új leképező háttérprogramot. Minden egyes leképező háttérprogramnak meg kell valósítania ezeket a szubrutinokat:

  • new

  • Map

Meg kell valósítanunk ezen metódusok mindegyikét azért, hogy képesek legyünk az adatok leképezésére a kommunikációban, amelyet vagy a kérelmező, vagy a szolgáltató kezel. Az összes leképező háttérprogramot a leképezőmodul kezeli (Kernel/GenericInterface/Mapping.pm).

Kódpélda

Ebben a szakaszban egy minta leképezőmodul lesz megjelenítve, és minden szubrutin elmagyarázásra kerül.

# --
# Kernel/GenericInterface/Mapping/Test.pm - GenericInterface test data mapping backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::GenericInterface::Mapping::Test;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(IsHashRefWithData IsStringWithData);

our $ObjectManagerDisabled = 1;
                

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva.

Felveszünk egy VariableCheck modult is bizonyos ellenőrzések végrehajtásához néhány változón. A leképezések nem példányosíthatók az objektumkezelővel.

sub new {
    my ( $Type, %Param ) = @_;

    # új kivonat lefoglalása az objektumhoz
    my $Self = {};
    bless( $Self, $Type );

    # a szükséges paraméterek ellenőrzése
    for my $Needed (qw(DebuggerObject MappingConfig)) {
        if ( !$Param{$Needed} ) {

            return {
                Success      => 0,
                ErrorMessage => "Nincs $Needed!"
            };
        }
        $Self->{$Needed} = $Param{$Needed};
    }

    # leképezési beállítás ellenőrzése
    if ( !IsHashRefWithData( $Param{MappingConfig} ) ) {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Nincs MappingConfig objektum kivonathivatkozásként tartalommal!',
        );
    }

    # beállítás ellenőrzése - ha van leképezési beállításunk, akkor annak
    # nem üres kivonathivatkozásnak kell lennie
    if (
        defined $Param{MappingConfig}->{Config}
        && !IsHashRefWithData( $Param{MappingConfig}->{Config} )
        )
    {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Van MappingConfig adatokkal, de az adat nem kivonathivatkozás tartalommal!',
        );
    }

    return $Self;
}
                

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint az objektumkezelő által nem kezelt más osztályoknak csak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

sub Map {
    my ( $Self, %Param ) = @_;

    # adatok ellenőrzése - csak meghatározatlant vagy kivonathivatkozást fogad el
    if ( defined $Param{Data} && ref $Param{Data} ne 'HASH' ) {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Van adat, de az nem kivonathivatkozás a leképezésteszt háttérprogramban!'
        );
    }

    # visszatérés, ha az adat üres
    if ( !defined $Param{Data} || !%{ $Param{Data} } ) {

        return {
            Success => 1,
            Data    => {},
        };
    }

    # ha nincs beállítás, akkor az azt jelenti, hogy egyszerűen visszaadjuk a bemeneti adatot
    if (
        !defined $Self->{MappingConfig}->{Config}
        || !defined $Self->{MappingConfig}->{Config}->{TestOption}
        )
    {

        return {
            Success => 1,
            Data    => $Param{Data},
        };
    }

    # a TestOption formátum ellenőrzése
    if ( !IsStringWithData( $Self->{MappingConfig}->{Config}->{TestOption} ) ) {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Nincs TestOption szövegként értékkel!',
        );
    }

    # adatok feldolgozása a beállítások szerint
    my $ReturnData = {};
    if ( $Self->{MappingConfig}->{Config}->{TestOption} eq 'ToUpper' ) {
        $ReturnData = $Self->_ToUpper( Data => $Param{Data} );
    }
    elsif ( $Self->{MappingConfig}->{Config}->{TestOption} eq 'ToLower' ) {
        $ReturnData = $Self->_ToLower( Data => $Param{Data} );
    }
    elsif ( $Self->{MappingConfig}->{Config}->{TestOption} eq 'Empty' ) {
        $ReturnData = $Self->_Empty( Data => $Param{Data} );
    }
    else {
        $ReturnData = $Param{Data};
    }

    # az eredmény visszaadása
    return {
        Success => 1,
        Data    => $ReturnData,
    };
}
                

A Map függvény az egyes leképezőmodulok fő része. Fogadja a leképezési beállításokat (szabályokat) és az eredeti formátumban lévő adatokat (vagy az OTRS vagy a távoli rendszer formátumában lévőket), és átalakítja azokat egy új formátumra még akkor is, ha az adatok szerkezete megváltozhat a leképezési folyamat során.

Ebben a bizonyos példában három szabály van az értékek leképezéséhez. Ezek a szabályok a leképezési beállítások TestOption kulcsában vannak beállítva, és a következők: ToUpper, ToLower és Empty.

  • ToUpper: nagybetűsre alakít át minden egyes adatértéket.

  • ToLower: kisbetűsre alakít át minden egyes adatértéket.

  • Empty: egy üres szövegre alakít át minden egyes adatértéket.

Ebben a példában nem lettek adatkulcs átalakítások megvalósítva.

sub _ToUpper {
    my ( $Self, %Param ) = @_;

    my $ReturnData = {};
    for my $Key ( sort keys %{ $Param{Data} } ) {
        $ReturnData->{$Key} = uc $Param{Data}->{$Key};
    }

    return $ReturnData;
}

sub _ToLower {
    my ( $Self, %Param ) = @_;

    my $ReturnData = {};
    for my $Key ( sort keys %{ $Param{Data} } ) {
        $ReturnData->{$Key} = lc $Param{Data}->{$Key};
    }

    return $ReturnData;
}

sub _Empty {
    my ( $Self, %Param ) = @_;

    my $ReturnData = {};
    for my $Key ( sort keys %{ $Param{Data} } ) {
        $ReturnData->{$Key} = '';
    }

    return $ReturnData;
}

                

Ezek azok a segédfüggvények, amelyek ténylegesen végrehajtják a szövegátalakításokat.

Beállítási példa

Szükség van ezen leképezőmodul regisztrálására, hogy elérhető legyen az OTRS grafikus felhasználói felületén. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="GenericInterface::Mapping::Module###Test" Required="0" Valid="1">
    <Description Translatable="1">GenericInterface module registration for the mapping layer.</Description>
    <Group>GenericInterface</Group>
    <SubGroup>GenericInterface::Mapping::ModuleRegistration</SubGroup>
    <Setting>
        <Hash>
            <Item Key="ConfigDialog"></Item>
        </Hash>
    </Setting>
</ConfigItem>
                

Meghívó

A meghívót arra használják, hogy egy kérést hozzon létre az OTRS-ből egy távoli rendszerhez. Az általános ügyintéző ezen része felelős a szükséges feladatok végrehajtásáért az OTRS oldalán, illetve a szükséges adatok begyűjtéséért a kérés felépítésének érdekében.

Meghívó háttérprogram

Ezután be fogjuk mutatni, hogy hogyan kell egy új meghívót kifejleszteni. Minden egyes meghívónak meg kell valósítania ezeket a szubrutinokat:

  • new

  • PrepareRequest

  • HandleResponse

Meg kell valósítanunk ezen metódusok mindegyikét azért, hogy képesek legyünk végrehajtani egy kérést a kéréskezelő használatával (Kernel/GenericInterface/Requester.pm).

Kódpélda

Ebben a szakaszban egy minta meghívómodul lesz megjelenítve, és minden szubrutin elmagyarázásra kerül.

# --
# Kernel/GenericInterface/Invoker/Test.pm - GenericInterface test data Invoker backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::GenericInterface::Invoker::Test::Test;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(IsString IsStringWithData);

# prevent 'Used once' warning for Kernel::OM
use Kernel::System::ObjectManager;

our $ObjectManagerDisabled = 1;
                

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva. A meghívók nem példányosíthatók az objektumkezelővel.

sub new {
    my ( $Type, %Param ) = @_;

    # új kivonat lefoglalása az objektumhoz
    my $Self = {};
    bless( $Self, $Type );

    # a szükséges paraméterek ellenőrzése
    if ( !$Param{DebuggerObject} ) {
        return {
            Success      => 0,
            ErrorMessage => "Nem sikerült lekérni a hibakezelő objektumot!"
        };
    }

    $Self->{DebuggerObject} = $Param{DebuggerObject};

    return $Self;
}
                

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint az objektumkezelő által nem kezelt más osztályoknak csak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

sub PrepareRequest {
    my ( $Self, %Param ) = @_;

    # szükségünk van egy jegyszámra
    if ( !IsStringWithData( $Param{Data}->{TicketNumber} ) ) {
        return $Self->{DebuggerObject}->Error( Summary => 'Nem kaptunk jegyszámot' );
    }

    my %ReturnData;

    $ReturnData{TicketNumber} = $Param{Data}->{TicketNumber};

    # a művelet ellenőrzése
    if ( IsStringWithData( $Param{Data}->{Action} ) ) {
        $ReturnData{Action} = $Param{Data}->{Action} . 'Test';
    }

    # a rendszeridő kérésének ellenőrzése
    if ( IsStringWithData( $Param{Data}->{GetSystemTime} ) && $Param{Data}->{GetSystemTime} ) {
        $ReturnData{SystemTime} = $Kernel::OM->Get('Kernel::System::Time')->SystemTime();
    }

    return {
        Success => 1,
        Data    => \%ReturnData,
    };
}
                

A PrepareRequest függvényt használják a kérésbe küldendő összes szükséges adat kezeléséhez és összegyűjtéséhez. Itt fogadhatunk adatokat a kéréskezelőtől, használhatjuk azokat, kiterjeszthetjük azokat, új adatokat állíthatunk elő, és ezután átvihetjük az eredményeket a leképező réteghez.

Ennél a példánál azt várjuk, hogy kapunk egy jegyszámot. Ha nem, akkor az Error() hibakeresési metódust használjuk, amely létrehoz egy bejegyzést a hibakeresési naplóban, és visszaad egy szerkezetet is a Success paraméterrel 0-ként, és egy hibaüzenetet az átadott Summary értékként.

Ez a példa hozzáfűzi a „Test” szót is az Action paraméterhez, és ha a GetSystemTime kérve volt, akkor ki fogja tölteni a SystemTime paramétert az aktuális rendszeridővel. A kód ezen része azért van, hogy előkészítse az elküldendő adatokat. Egy valódi meghívónál itt kell elvégezni néhány hívást az alapmodulokhoz (Kernel/System/*.pm).

Ha a kérést a PrepareRequest függvény bármely része közben le kell állítani a hibakeresési naplóba való bejegyzés előállítása és hibajelzése nélkül, akkor a következő kód használható:

# a kérelmező kommunikációjának leállítása
return {
    Success           => 1,
    StopCommunication => 1,
};
                

Ennek használatával a kérelmező meg foga érteni, hogy a kérést nem szabad folytatni (nem kerül elküldésre a leképező réteghez, és nem kerül elküldésre a hálózati átvitelhez sem). A kérelmező nem fog hibát küldeni a hibakeresési naplóba, hanem csak csendben le fog állni.

sub HandleResponse {
    my ( $Self, %Param ) = @_;

    # ha hiba volt a válaszban, akkor továbbítja
    if ( !$Param{ResponseSuccess} ) {
        if ( !IsStringWithData( $Param{ResponseErrorMessage} ) ) {

            return $Self->{DebuggerObject}->Error(
                Summary => 'Hiba volt a válaszban, de nincs válasz hibaüzenet!',
            );
        }

        return {
            Success      => 0,
            ErrorMessage => $Param{ResponseErrorMessage},
        };
    }

    # szükségünk van egy jegyszámra
    if ( !IsStringWithData( $Param{Data}->{TicketNumber} ) ) {

        return $Self->{DebuggerObject}->Error( Summary => 'Nem kaptunk jegyszámot!' );
    }

    # a jegyszám előkészítése
    my %ReturnData = (
        TicketNumber => $Param{Data}->{TicketNumber},
    );

    # a művelet ellenőrzése
    if ( IsStringWithData( $Param{Data}->{Action} ) ) {
        if ( $Param{Data}->{Action} !~ m{ \A ( .*? ) Test \z }xms ) {

            return $Self->{DebuggerObject}->Error(
                Summary => 'Kaptunk műveletet, nem az nem megfelelő formátumú!',
            );
        }
        $ReturnData{Action} = $1;
    }

    return {
        Success => 1,
        Data    => \%ReturnData,
    };
}
                

A HandleResponse függvényt használják az előző kérésből származó adatok fogadásához és feldolgozásához, amelyet a távoli rendszernek készítettek. Ezeket az adatokat már átadta a leképező réteg, hogy átalakítsa azokat a távoli rendszer formátumáról az OTRS formátumára (ha szükséges).

Ennél a bizonyos példánál ismét ellenőrzi a jegyszámot, és azt is ellenőrzi, hogy a művelet a „Test” szóval végződik-e (amint az a PrepareRequest függvényben történt).

Megjegyzés

Ez a meghívó csak tesztelésekhez van, egy valódi meghívó ellenőrizni fogja, hogy a válasz a távoli rendszer által leírt formátumban volt-e, és végrehajthat néhány műveletet, mint például: egy másik meghívó meghívása, egy hívás végrehajtása egy alapmodulhoz, az adatbázis frissítése, hiba küldése, stb.

Beállítási példa

Szükség van ezen meghívómodul regisztrálására, hogy elérhető legyen az OTRS grafikus felhasználói felületén. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="GenericInterface::Invoker::Module###Test::Test" Required="0" Valid="1">
    <Description Translatable="1">GenericInterface module registration for the invoker layer.</Description>
    <Group>GenericInterface</Group>
    <SubGroup>GenericInterface::Invoker::ModuleRegistration</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Name">Test</Item>
            <Item Key="Controller">Test</Item>
            <Item Key="ConfigDialog">AdminGenericInterfaceInvokerDefault</Item>
        </Hash>
    </Setting>
</ConfigItem>
                

Művelet

A műveletet egy tevékenység végrehajtásához használják az OTRS-en belül. Ezt a tevékenységet a távoli rendszer kéri, és tartalmazhat különleges paramétereket azért, hogy helyesen végrehajtsa a tevékenységet. A tevékenység végrehajtása után az OTRS elküld egy meghatározott megerősítést a távoli rendszernek.

Műveleti háttérprogram

Ezután be fogjuk mutatni, hogy hogyan kell egy új műveletet kifejleszteni. Minden egyes műveletnek meg kell valósítania ezeket a szubrutinokat:

  • new

  • Run

Meg kell valósítanunk ezen metódusok mindegyikét azért, hogy képesek legyünk végrehajtani a szolgáltató által kezelt műveletet (Kernel/GenericInterface/Provider.pm).

Kódpélda

Ebben a szakaszban egy minta műveletmodul lesz megjelenítve, és minden szubrutin elmagyarázásra kerül.

# --
# Kernel/GenericInterface/Operation/Test/Test.pm - GenericInterface test operation backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::GenericInterface::Operation::Test::Test;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(IsHashRefWithData);

our $ObjectManagerDisabled = 1;
                

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva.

Felveszünk egy VariableCheck modult is bizonyos ellenőrzések végrehajtásához néhány változón. A műveletek nem példányosíthatók az objektumkezelővel.

sub new {
    my ( $Type, %Param ) = @_;

    my $Self = {};
    bless( $Self, $Type );

    # a szükséges objektumok ellenőrzése
    for my $Needed (qw(DebuggerObject)) {
        if ( !$Param{$Needed} ) {
            return {
                Success      => 0,
                ErrorMessage => "Nincs $Needed!"
            };
        }

        $Self->{$Needed} = $Param{$Needed};
    }

    return $Self;
}
                

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint az objektumkezelő által nem kezelt más osztályoknak csak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

sub Run {
    my ( $Self, %Param ) = @_;

    # adatok ellenőrzése - csak meghatározatlant vagy kivonathivatkozást fogad el
    if ( defined $Param{Data} && ref $Param{Data} ne 'HASH' ) {

        return $Self->{DebuggerObject}->Error(
            Summary => 'Van adat, de az nem kivonathivatkozás a műveletteszt háttérprogramban!'
        );
    }

    if ( defined $Param{Data} && $Param{Data}->{TestError} ) {

        return {
            Success      => 0,
            ErrorMessage => "Hibaüzenet a következő hibakódhoz: $Param{Data}->{TestError}",
            Data         => {
                ErrorData => $Param{Data}->{ErrorData},
            },
        };
    }

    # adatok másolása
    my $ReturnData;

    if ( ref $Param{Data} eq 'HASH' ) {
        $ReturnData = \%{ $Param{Data} };
    }
    else {
        $ReturnData = undef;
    }

    # az eredmény visszaadása
    return {
        Success => 1,
        Data    => $ReturnData,
    };
}
                

A Run függvény az egyes műveletek fő része. Fogadja az összes belsőleg leképezett adatot a távoli rendszertől, amelyre a szolgáltatónak szüksége van a művelet végrehajtásához, végrehajtja a műveletet, és visszaadja az eredményt a szolgáltatónak a külső leképezéshez, valamint visszaszállítja a távoli rendszerhez.

Ez a bizonyos példa ugyanúgy adja vissza az adatokat, ahogy azok a távoli rendszertől jönnek, hacsak a TestError paraméter át nincs adva. Ebben az esetben egy hibát ad vissza.

Beállítási példa

Szükség van ezen műveletmodul regisztrálására, hogy elérhető legyen az OTRS grafikus felhasználói felületén. Ezt a lenti XML beállítás használatával lehet megtenni.

<ConfigItem Name="GenericInterface::Operation::Module###Test::Test" Required="0" Valid="1">
    <Description Translatable="1">GenericInterface module registration for the operation layer.</Description>
    <Group>GenericInterface</Group>
    <SubGroup>GenericInterface::Operation::ModuleRegistration</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Name">Test</Item>
            <Item Key="Controller">Test</Item>
            <Item Key="ConfigDialog">AdminGenericInterfaceOperationDefault</Item>
        </Hash>
    </Setting>
</ConfigItem>
                

Egységteszt példa

Az általános felület műveleteinek egységtesztjei nem különböznek más egységtesztektől, de fontolóra kell venni a helyi tesztelést, viszont egy távoli kapcsolatot is szimulálni kell. Egy jó bevált gyakorlat mindkettőt különválasztva tesztelni, mivel az eredmények némileg különbözők lehetnek.

Ha többet szeretne megtudni az egységtesztekről, akkor vessen egy pillantást az egységteszt fejezetre.

A következő csak a kezdési pont egy egységteszthez:

# --
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

## no critic (Modules::RequireExplicitPackage)
use strict;
use warnings;
use utf8;

use vars (qw($Self));

use Kernel::GenericInterface::Debugger;
use Kernel::GenericInterface::Operation::Test::Test;

use Kernel::System::VariableCheck qw(:all);

# Skip SSL certificate verification (RestoreDatabase must not be used in this test).
$Kernel::OM->ObjectParamAdd(
    'Kernel::System::UnitTest::Helper' => {
        SkipSSLVerify => 1,
    },
);
my $Helper = $Kernel::OM->Get('Kernel::System::UnitTest::Helper');

# get a random number
my $RandomID = $Helper->GetRandomNumber();

# create a new user for current test
my $UserLogin = $Helper->TestUserCreate(
    Groups => ['users'],
);
my $Password = $UserLogin;

my $UserID = $Kernel::OM->Get('Kernel::System::User')->UserLookup(
    UserLogin => $UserLogin,
);

# set web-service name
my $WebserviceName = '-Test-' . $RandomID;

# create web-service object
my $WebserviceObject = $Kernel::OM->Get('Kernel::System::GenericInterface::Webservice');
$Self->Is(
    'Kernel::System::GenericInterface::Webservice',
    ref $WebserviceObject,
    "Create web service object",
);

my $WebserviceID = $WebserviceObject->WebserviceAdd(
    Name   => $WebserviceName,
    Config => {
        Debugger => {
            DebugThreshold => 'debug',
        },
        Provider => {
            Transport => {
                Type => '',
            },
        },
    },
    ValidID => 1,
    UserID  => 1,
);
$Self->True(
    $WebserviceID,
    "Added Web Service",
);

# get remote host with some precautions for certain unit test systems
my $Host = $Helper->GetTestHTTPHostname();

my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

# prepare web-service config
my $RemoteSystem =
    $ConfigObject->Get('HttpType')
    . '://'
    . $Host
    . '/'
    . $ConfigObject->Get('ScriptAlias')
    . '/nph-genericinterface.pl/WebserviceID/'
    . $WebserviceID;

my $WebserviceConfig = {
    Description =>
        'Test for Ticket Connector using SOAP transport backend.',
    Debugger => {
        DebugThreshold => 'debug',
        TestMode       => 1,
    },
    Provider => {
        Transport => {
            Type   => 'HTTP::SOAP',
            Config => {
                MaxLength => 10000000,
                NameSpace => 'http://otrs.org/SoapTestInterface/',
                Endpoint  => $RemoteSystem,
            },
        },
        Operation => {
            Test => {
                Type => 'Test::Test',
            },
        },
    },
    Requester => {
        Transport => {
            Type   => 'HTTP::SOAP',
            Config => {
                NameSpace => 'http://otrs.org/SoapTestInterface/',
                Encoding  => 'UTF-8',
                Endpoint  => $RemoteSystem,
            },
        },
        Invoker => {
            Test => {
                Type => 'Test::TestSimple'
                ,    # requester needs to be Test::TestSimple in order to simulate a request to a remote system
            },
        },
    },
};

# update web-service with real config
# the update is needed because we are using
# the WebserviceID for the Endpoint in config
my $WebserviceUpdate = $WebserviceObject->WebserviceUpdate(
    ID      => $WebserviceID,
    Name    => $WebserviceName,
    Config  => $WebserviceConfig,
    ValidID => 1,
    UserID  => $UserID,
);
$Self->True(
    $WebserviceUpdate,
    "Updated Web Service $WebserviceID - $WebserviceName",
);

# debugger object
my $DebuggerObject = Kernel::GenericInterface::Debugger->new(
    DebuggerConfig => {
        DebugThreshold => 'debug',
        TestMode       => 1,
    },
    WebserviceID      => $WebserviceID,
    CommunicationType => 'Provider',
);
$Self->Is(
    ref $DebuggerObject,
    'Kernel::GenericInterface::Debugger',
    'DebuggerObject instantiate correctly',
);

# define test cases
my @Tests = (
    {
        Name           => 'Test case name',
        SuccessRequest => 1,                  # 1 or 0
        RequestData    => {

            # ... add test data
        },
        ExpectedReturnLocalData => {
            Data => {

                # ... add expected local results
            },
            Success => 1,                     # 1 or 0
        },
        ExpectedReturnRemoteData => {
            Data => {

                # ... add expected remote results
            },
            Success => 1,                     # 1 or 0
        },
        Operation => 'Test',
    },

    # ... add more test cases
);

TEST:
for my $Test (@Tests) {

    # create local object
    my $LocalObject = "Kernel::GenericInterface::Operation::Test::$Test->{Operation}"->new(
        DebuggerObject => $DebuggerObject,
        WebserviceID   => $WebserviceID,
    );

    $Self->Is(
        "Kernel::GenericInterface::Operation::Test::$Test->{Operation}",
        ref $LocalObject,
        "$Test->{Name} - Create local object",
    );

    my %Auth = (
        UserLogin => $UserLogin,
        Password  => $Password,
    );
    if ( IsHashRefWithData( $Test->{Auth} ) ) {
        %Auth = %{ $Test->{Auth} };
    }

    # start requester with our web-service
    my $LocalResult = $LocalObject->Run(
        WebserviceID => $WebserviceID,
        Invoker      => $Test->{Operation},
        Data         => {
            %Auth,
            %{ $Test->{RequestData} },
        },
    );

    # check result
    $Self->Is(
        'HASH',
        ref $LocalResult,
        "$Test->{Name} - Local result structure is valid",
    );

    # create requester object
    my $RequesterObject = $Kernel::OM->Get('Kernel::GenericInterface::Requester');
    $Self->Is(
        'Kernel::GenericInterface::Requester',
        ref $RequesterObject,
        "$Test->{Name} - Create requester object",
    );

    # start requester with our web-service
    my $RequesterResult = $RequesterObject->Run(
        WebserviceID => $WebserviceID,
        Invoker      => $Test->{Operation},
        Data         => {
            %Auth,
            %{ $Test->{RequestData} },
        },
    );

    # check result
    $Self->Is(
        'HASH',
        ref $RequesterResult,
        "$Test->{Name} - Requester result structure is valid",
    );

    $Self->Is(
        $RequesterResult->{Success},
        $Test->{SuccessRequest},
        "$Test->{Name} - Requester successful result",
    );

    # ... add tests for the results
}

# delete web service
my $WebserviceDelete = $WebserviceObject->WebserviceDelete(
    ID     => $WebserviceID,
    UserID => $UserID,
);
$Self->True(
    $WebserviceDelete,
    "Deleted Web Service $WebserviceID",
);

# also delete any other added data during the this test, since RestoreDatabase must not be used.

1;
                

WSDL-kiterjesztés példa

WSDL files contain the definitions of the web services and its operations for SOAP messages, in case we will extend development/webservices/GenericTickeConnectorSOAP.wsdl in some places:

Port típusa:

    <wsdl:portType name="GenericTicketConnector_PortType">
        <!-- ... -->
        <wsdl:operation name="Test">
            <wsdl:input message="tns:TestRequest"/>
            <wsdl:output message="tns:TestResponse"/>
        </wsdl:operation>
    <!-- ... -->
                

Kötés:

    <wsdl:binding name="GenericTicketConnector_Binding" type="tns:GenericTicketConnector_PortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <!-- ... -->
        <wsdl:operation name="Test">
            <soap:operation soapAction="http://www.otrs.org/TicketConnector/Test"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
        <!-- ... -->
    </wsdl:binding>
                

Típus:

    <wsdl:types>
        <xsd:schema targetNamespace="http://www.otrs.org/TicketConnector/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <!-- ... -->
            <xsd:element name="Test">
                <xsd:complexType>
                    <xsd:sequence>
                            <xsd:element minOccurs="0" name="Param1" type="xsd:string"/>
                            <xsd:element minOccurs="0" name="Param2" type="xsd:positiveInteger"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="TestResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element maxOccurs="unbounded" minOccurs="1" name="Attribute1" type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        <!-- ... -->
        </xsd:schema>
    </wsdl:types>
                

Üzenet:

    <!-- ... -->
    <wsdl:message name="TestRequest">
        <wsdl:part element="tns:Test" name="parameters"/>
    </wsdl:message>
    <wsdl:message name="TestResponse">
        <wsdl:part element="tns:TestResponse" name="parameters"/>
    </wsdl:message>
    <!-- ... -->
                

WADL-kiterjesztés példa

WADL files contain the definitions of the web services and its operations for REST interface, add a new resource to development/webservices/GenericTickeConnectorREST.wadl.

  <resources base="http://localhost/otrs/nph-genericinterface.pl/Webservice/GenericTicketConnectorREST">
    <!-- ... -->
    <resource path="Test" id="Test">
      <doc xml:lang="en" title="Test"/>
        <param name="Param1" type="xs:string" required="false" default="" style="query" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
        <param name="Param2" type="xs:string" required="false" default="" style="query" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
        <method name="GET" id="GET_Test">
          <doc xml:lang="en" title="GET_Test"/>
          <request/>
          <response status="200">
            <representation mediaType="application/json; charset=UTF-8"/>
          </response>
        </method>
      </resource>
    </resource>
    <!-- ... -->
  </resources>
                

Webszolgáltatás SOAP-kiterjesztés példa

Web services can be imported into OTRS by a YAML with a predefined structure in this case we will extend development/webservices/GenericTickeConnectorSOAP.yml for a SOAP web service.

Provider:
  Operation:
    # ...
    Test:
      Description: Ez csak egy teszt
      MappingInbound: {}
      MappingOutbound: {}
      Type: Test::Test
                

Webszolgáltatás REST-kiterjesztés példa

Web services can be imported into OTRS by a YAML with a predefined structure in this case we will extend development/webservices/GenericTickeConnectorREST.yml for a REST web service.

Provider:
  Operation:
    # ...
    Test:
      Description: Ez csak egy teszt
      MappingInbound: {}
      MappingOutbound: {}
      Type: Test::Test
  # ...
  Transport:
    Config:
      # ...
      RouteOperationMapping:
        # ..
        Test:
          RequestMethod:
          - GET
          Route: /Test
                

Démon és ütemező

OTRS démon

Az OTRS démon egy elkülönített folyamat, amely segít az OTRS-nek bizonyos műveleteket aszinkron módon és a webszolgáltatás folyamattól leválasztva végrehajtani, de ugyanazt az adatbázist megosztva.

OTRS démonmodulok

A bin/otrs.Daemon.pl OTRS démon fő célja, hogy meghívja (démonizálja) a rendszerbeállításokban lévő összes regisztrált démonmodult.

Minden egyes démonmodulnak meg kell valósítania egy közös API-t annak érdekében, hogy az OTRS démon helyesen tudja meghívni, és félig állandó folyamat legyen a rendszeren. Az állandó folyamat megnövelheti a méretét és memóriahasználatát az idő múlásával, és normális esetben nem válaszolnak a beállításokban lévő változásokra. Ezért kell a démonmoduloknak megvalósítaniuk egy eldobási mechanizmust, hogy leállíthatók és újra meghívhatók legyenek időről időre, felszabadítva a rendszer erőforrásait és újraolvasva a beállításokat.

Egy démonmodul lehet mindenre jó megoldás bizonyos feladat végrehajtásánál, de lehet olyan eset is, amikor egy megoldás különböző démonmodulokat igényel az összetettsége miatt. Pontosan ez az eset az OTRS ütemező démonjával, amely fel van osztva számos démonmodulra, beleértve a feladatkezeléshez és a feladatvégrehajtáshoz szükséges néhány démonmodult.

Nem szükséges mindig új démonmodult létrehozni bizonyos feladatok végrehajtásához. Általában az OTRS ütemező démon elboldogul ezek jelentős részével – akár ha egy olyan OTRS függvényről van szó, amelyet rendszeresen végre kell hajtani (CRON-szerűen), vagy ha egy OTRS esemény aktiválta azt – az OTRS ütemezőnek képesnek kell lenni kezelnie mindenféle beállítás nélkül, vagy egy új ütemező feladatelvégző modul hozzáadásával.

Új démonmodul létrehozása

Az összes démonmodulnak regisztrálva kell lennie a rendszerbeállításokban azért, hogy a fő OTRS démon meg tudja hívni azokat.

Démonmodul regisztrációs kódpélda

<Setting Name="DaemonModules###TestDaemon" Required="1" Valid="1">
    <Description Translatable="1">The daemon registration for the scheduler generic agent task manager.</Description>
    <Navigation>Daemon::ModuleRegistration</Navigation>
    <Value>
        <Hash>
            <Item Key="Module">Kernel::System::Daemon::DaemonModules::TestDaemon</Item>
        </Hash>
    </Value>
</Setting>
                    

Démonmodul kódpélda

A következő kód egy olyan démonmodult valósít meg, amely megjeleníti a rendszeridőt 2 másodpercenként.

# --
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Daemon::DaemonModules::TestDaemon;

use strict;
use warnings;
use utf8;

use Kernel::System::VariableCheck qw(:all);

use parent qw(Kernel::System::Daemon::BaseDaemon);

our @ObjectDependencies = (
    'Kernel::Config',
    'Kernel::System::Cache',
    'Kernel::System::DB',
);
                    

This is common header that can be found in most OTRS modules. The class/package name is declared via the package keyword.

Ebben az esetben a BaseDaemon osztályból származtatunk le, és az objektumkezelő függőségei be vannak állítva.

sub new {
    my ( $Type, %Param ) = @_;

    # Új kivonat lefoglalása az objektumhoz.
    my $Self = {};
    bless $Self, $Type;

    # Objektumok lekérése a konstruktorban a teljesítmény megtartásáért.
    $Self->{ConfigObject} = $Kernel::OM->Get('Kernel::Config');
    $Self->{CacheObject}  = $Kernel::OM->Get('Kernel::System::Cache');
    $Self->{DBObject}     = $Kernel::OM->Get('Kernel::System::DB');

    # Letiltás a memóriagyorsítótárban, hogy fürtözhető legyen.
    $Self->{CacheObject}->Configure(
        CacheInMemory  => 0,
        CacheInBackend => 1,
    );

    $Self->{SleepPost} = 2;          # 2 másodperc alvás minden hurok után
    $Self->{Discard}   = 60 * 60;    # eldobás minden órában

    $Self->{DiscardCount} = $Self->{Discard} / $Self->{SleepPost};

    $Self->{Debug}      = $Param{Debug};
    $Self->{DaemonName} = 'Daemon: TestDaemon';

    return $Self;
}
                    

A new konstruktor hozza létre az osztály új példányát. Néhány felhasznált objektum is itt lesz létrehozva. Erősen ajánlott a memóriába történő gyorsítótárazás letiltása a démonmodulokban, különösen akkor, ha az OTRS fürtözött környezetben fut.

Azért, hogy ez a démonmodul minden második másodpercben végrehajtható legyen, egy alvási idő meghatározása szükséges annak megfelelően, egyébként azonnal végrehajtásra kerül, amint lehetséges.

A démonmodul frissítése időről időre azért szükséges, hogy meghatározható legyen, mikor kell eldobni.

A következő függvényeknél (PreRun, Run és PostRun) ha azok hamis értékkel térnek vissza, akkor a fő OTRS démon el fogja dobni az objektumot, és egy újat hoz létre, amint lehetséges.

sub PreRun {
    my ( $Self, %Param ) = @_;

    # Annak ellenőrzése, hogy az adatbázis elérhető-e.
    return 1 if $Self->{DBObject}->Ping();

    sleep 10;

    return;
}
                    

A PreRun metódus a fő démonmodul metódusa előtt kerül végrehajtásra, és a célja néhány teszt elvégzése a valódi műfelet előtt. Ebben az esetben az adatbázis ellenőrzése készen van (mindig javasolt), egyébként 10 másodpercet alszik. Ez azért szükséges, hogy megvárja az adatbázis-kapcsolat ismételt felépítését.

sub Run {
    my ( $Self, %Param ) = @_;

    print "Jelenlegi idő: " . localtime . "\n";

    return 1;
}
                    

A Run metódus az, ahol a fő démonmodul kódja található. Ebben az esetben csak az aktuális időt írja ki.

sub PostRun {
    my ( $Self, %Param ) = @_;
    sleep $Self->{SleepPost};
    $Self->{DiscardCount}--;

    if ( $Self->{Debug} ) {
        print "  $Self->{DaemonName} eldobásainak száma: $Self->{DiscardCount}\n";
    }

    return if $Self->{DiscardCount} <= 0;

    return 1;
}
                    

A PostRun metódus használható az alvások végrehajtásához (annak megakadályozásához, hogy a démonmodul túl gyakran legyen végrehajtva), valamint az objektum biztonságos eldobásának kezeléséhez is. Egyéb műveletek is elvégezhetők itt, mint például ellenőrzés vagy tisztítás.

sub Summary {
    my ( $Self, %Param ) = @_;

    my %Summary = (
        Header => 'Tesztdémon összegzés:',
        Column => [
            {
                Name        => 'SomeColumn',
                DisplayName => 'Valamilyen oszlop',
                Size        => 15,
            },
            {
                Name        => 'AnotherColumn',
                DisplayName => 'Egy másik oszlop',
                Size        => 15,
            },
            # ...
        ],
        Data => [
            {
                SomeColumn    => '1. valamilyen adat',
                AnotherColumn => '1. másik adat',
            },
            {
                SomeColumn    => '2. valamilyen adat',
                AnotherColumn => '2. másik adat',
            },
            # ...
        ],
        NoDataMesssage => '',
    );

    return \%Summary;
}
                    

A Summary metódust a Maint::Daemon::Summary konzolparancs hívja meg, és Header, Column, Data és NoDataMessages kulcsokat kell visszaadnia. A Column és a Data kulcsoknak tömböknek vagy kivonatoknak kell lenniük. Arra használható, hogy hasznos információkat jelenítsen meg arról, amit a démonmodul éppen csinál, vagy ami eddig történt. Ez a metódus elhagyható.

1;
                    

Fájl vége.

OTRS ütemező

Az OTRS ütemező a démonmodulok és a feladatelvégzők együttese, amelyek együtt futnak azért, hogy az összes szükséges OTRS feladatot aszinkron módon végrehajtsák a webkiszolgáló folyamatából.

OTRS ütemező feladatkezelők

A SchedulerCronTaskManager kiolvassa a regisztrált cron-feladatokat az OTRS rendszerbeállításaiból, és meghatározza a helyes időt a végrehajtandó feladat létrehozásához.

A SchedulerFutureTaskManager ellenőrzi azokat a feladatokat, amelyek úgy vannak beállítva, hogy csak egy alkalommal fussanak a jövőben, és beállítja, hogy a feladat időben kerüljön végrehajtásra. Például amikor egy általános felület meghívónak nem sikerül elérnie a távoli kiszolgálót, akkor ütemezni tudja magát, hogy 5 perccel később újra fusson.

A SchedulerGenericAgentTaskManager folyamatosan olvassa a GenericAgent feladatot, amely rendszeres időközönkénti futáshoz van beállítva, és annak megfelelően állítja be azok végrehajtását.

Amikor ezek a feladatkezelők nem elegendőek, akkor egy új démonmodul hozható létre. Egy feladat regisztrálásához a Run() metódusuk egy bizonyos pontján meg kell hívni a TaskAdd() függvényt a chedulerDB objektumból, és amint regisztrálva lett, akkor a SchedulerTaskWorker végrehajtja a következő szabad időszeletben.

OTRS ütemező feladatelvégzők

A SchedulerTaskWorker az aszinkron végrehajtó használatával végrehajtja az előző feladatkezelő által tervezett összes feladatot, és még azokat is, amelyek közvetlenül a kódból jönnek.

Annak érdekében, hogy az összes feladatot végrehajtsa, a SchedulerTaskWorker meghív egy háttérprogram-modult (feladatelvégzőt) az adott feladat végrehajtásához. Az elvégző modult a feladat típusa határozza meg. Ha új feladattípus kerül hozzáadásra, akkor az új feladatelvégzőt is igényel.

Új ütemező feladatelvégző létrehozása

A Kernel/System/Daemon/DaemonModules/SchedulerTaskWorker mappa alatt elhelyezett összes fájl lehet potenciális feladatelvégző, és azok nem igényelnek semmilyen regisztrációt a rendszerbeállításokban.

Ütemező feladatelvégző kódpélda

# --
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::Daemon::DaemonModules::SchedulerTaskWorker::TestWorker;

use strict;
use warnings;

use parent qw(Kernel::System::Daemon::DaemonModules::BaseTaskWorker);

our @ObjectDependencies = (
    'Kernel::System::Log',
);
                        

This is common header that can be found in most OTRS modules. The class/package name is declared via the package keyword.

Ebben az esetben a BaseTaskWorker osztályból származtatunk le, és az objektumkezelő függőségei be vannak állítva.

sub new {
    my ( $Type, %Param ) = @_;

    my $Self = {};
    bless( $Self, $Type );

    $Self->{Debug}      = $Param{Debug};
    $Self->{WorkerName} = 'Worker: Test';

    return $Self;
}
                        

A new konstruktor hozza létre az osztály új példányát.

sub Run {
    my ( $Self, %Param ) = @_;

    # Feladatparaméterek ellenőrzése.
    my $CheckResult = $Self->_CheckTaskParams(
        %Param,
        NeededDataAttributes => [ 'NeededAtrribute1', 'NeededAtrribute2' ],
        DataParamsRef        => 'HASH', # vagy 'ARRAT'
    );

    # Végrehajtás leállítása, ha hiba található a paraméterekben.
    return if !$CheckResult;

    my $Success;
    my $ErrorMessage;

    if ( $Self->{Debug} ) {
        print "    $Self->{WorkerName} végrehajtja a feladatot: $Param{TaskName}\n";
    }

    do {

        # A szabványos hiba lokalizálása.
        local *STDERR;

        # A szabványos hiba átirányítása egy változóba.
        open STDERR, ">>", \$ErrorMessage;

        $Success = $Kernel::OM->Get('Kernel::System::MyPackage')->Run(
            Param1 => 'someparam',
        );
    };

    if ( !$Success ) {

        $ErrorMessage ||= "$Param{TaskName} végrehajtása sikertelen egy hibaüzenettel!";

        $Self->_HandleError(
            TaskName     => $Param{TaskName},
            TaskType     => 'Test',
            LogMessage   => "Hiba történt a(z) $Param{TaskName} végrehajtásakor: $ErrorMessage",
            ErrorMessage => "$ErrorMessage",
        );
    }

    return $Success;
}
                        

A Run a fő metódus. Egy _CheckTaskParams() hívás az alaposztályból megspórol néhány kódsort. A feladat végrehajtása a szabványos hibakimenet megszerzése közben nagyon jó gyakorlat, mivel az OTRS ütemező normális esetben felügyelet nélkül fut, és az összes hiba egy változóba történő mentése lehetővé fogja tenni a későbbi feldolgozást. A _HandleError() közös felületet biztosít a hibaüzenetek e-mailben történő küldéséhez a rendszerbeállításokban megadott címzetteknek.

1;
                        

Fájl vége.

Dinamikus mezők

Áttekintés

A dinamikus mezők olyan egyéni mezők, amelyek hozzáadhatók egy képernyőhöz, hogy javítsák és információkat adjanak hozzá egy objektumhoz (például egy jegyhez vagy egy bejegyzéshez).

A dinamikus mezők a jegy és a bejegyzés szabad mezőinek (TikcetFreeText, TicketFreeKey, TicketFreeTime, ArticleFreeText, ArticleFreeKey és ArticleFreeTime) evolúciója az OTRS régebbi verzióiból.

Az OTRS 3.1-es verziójától a régi szabad mezőket lecserélték az új dinamikus mezőkre. A korábbi verziókról történő frissítéskor a jobb visszafelé kompatibilitáshoz és az adatmegőrzéshez egy költöztető parancsfájlt fejlesztettek ki a meglévő szabad mezők dinamikus mezőkre való átalakításához, és azok értékeinek áthelyezéséhez az adatbázisban lévő ticket és article táblákból az új dinamikus mezők tábláiba.

Megjegyzés

Minden szabad mezőket használó egyéni fejlesztést át kell írni az új dinamikus mezők kódszerkezetére, különben többé nem fognak működni. Emiatt nagyon fontos tudni azt, hogy az OTRS 3.0-nak csak a frissített telepítései rendelkeznek a dinamikus mezőkre átalakított régi szabad mezőkkel, az OTRS új vagy tiszta telepítéseinek nincsenek „eredetileg” meghatározott dinamikus mezői, és az egyéni fejlesztés által szükséges összes dinamikus mezőt hozzá kell adni.

A jegyenkénti vagy bejegyzésenkénti mezők számának korlátozása eltávolításra került. Ez azt jelenti, hogy egy jegy vagy egy bejegyzés annyi mezővel rendelkezhet, amennyi szükséges. És mostantól lehetséges a dinamikus mezők keretrendszerének használata egyéb objektumoknál is ahelyett, hogy csak a jegynél vagy a bejegyzésnél lenne használható.

Az új dinamikus mezők ugyanazokat az adattípusokat tudják eltárolni mint a szabad mezők (szöveg és dátum/idő), és ugyanúgy határozhatók meg mint azok (egysoros beviteli mező, legördülő és dátum/idő), de a dinamikus mezők túlmennek ezen, ugyanis egy új egész szám adattípus került hozzáadásra, valamint új lehetőségek is az olyan mezők meghatározásához, mint például többsoros beviteli mezők, jelölőnégyzetek, többválasztós mezők és (idő nélküli) dátum mezők. Minden egyes mezőtípus saját adattípust határoz meg.

A moduláris tervezésének köszönhetően az egyes dinamikus mezőtípusok egy keretrendszerhez tartozó bővítményként láthatók, és ez a bővítmény lehet egy szabványos OTRS csomag is a dinamikus mezők elérhető típusainak kiterjesztéséhez, vagy akár a jelenlegi dinamikus mező további függvényekkel való kiterjesztéséhez.

Dinamikus mezők keretrendszer

Az új dinamikus mezők létrehozása előtt szükséges megérteni azok keretrendszerét, és hogy az OTRS képernyők hogyan lépnek kölcsönhatásba azokkal, valamint a mögöttes API-t.

A következő kép a dinamikus mezők keretrendszer szerkezetét mutatja be.

3.2. ábra - Dinamikus mezők szerkezete

Dinamikus mezők szerkezete


Dinamikus mező háttérprogram modulok
Dinamikus mező (háttérprogram)

Az előtétprogram modulokban normális esetben a BackendObject nevű objektum a közvetítő az előtétprogram modulok és az egyes konkrét dinamikus mező megvalósítás vagy illesztőprogram között. Ez határoz meg egy általános közbenső API-t az összes dinamikus mező illesztőprogramhoz, és az egyes illesztőprogramok felelőssége a közbenső API megvalósítása a mező sajátos szükségleteihez.

A dinamikus mező háttérprogram az összes illesztőprogram fő vezérlője. Ebben a modulban minden egyes függvény felelős a szükséges paraméterek ellenőrzéséért, és ugyanazon függvény meghívásáért az adott illesztőprogramban a kapott dinamikus mező beállítási paraméter szerint.

Ez a modul felelős bizonyos függvények meghívásáért is minden egyes objektumtípus delegáltnál (úgymint jegy vagy bejegyzés). Például egy előzmény bejegyzés hozzáadásához vagy egy esemény elsütéséhez.

Ez a modul az $OTRS_HOME/Kernel/System/DynamicField/Backend.pm fájlban található.

Dinamikus mező illesztőprogramok

Egy dinamikus mező illesztőprogram a dinamikus mező megvalósítása. Minden egyes illesztőprogramnak meg kell valósítania a háttérprogramban meghatározott összes kötelező függvényt (van néhány olyan függvény, amely egy viselkedéstől függ, és nem szükséges megvalósítani azokat, ha a dinamikus mező nem rendelkezik azzal a bizonyos viselkedéssel).

Egy illesztőprogram felelős annak ismeretéért, hogy hogyan kérje le a saját értékét vagy értékeit egy webkérésből vagy egy profilból (mint például egy keresési profilból). Szükséges tudnia a HTML kódot is a szerkesztő vagy megjelenítő képernyőkön lévő mező megjelenítéséhez, vagy hogy hogyan lépjen kölcsönhatásba a statisztikák modullal, többek között a függvényekkel.

Ezek a modulok az $OTRS_HOME/Kernel/System/DynamicField/Driver/*.pm fájlokban találhatók.

Létezik néhány alap illesztőprogram, úgymint Base.pm, BaseText.pm, BaseSelect.pm és BaseDateTime.pm, amely gyakori függvényeket valósít meg bizonyos illesztőprogramokhoz (például a TextArea.pm illesztőprogram a BaseText.pm fájlt használja, amely a Base.pm fájlt használja, ekkor a TextArea csak azon függvények megvalósítását igényli, amelyek hiányoznak a Base.pm és BateText.pm fájlokból, vagy azokat, amelyek különleges esetek).

A következő az illesztőprogramok öröklődési fája:

  • Base.pm

    • BaseText.pm

      • Text.pm

      • TextArea.pm

    • BaseSelect.pm

      • Dropdown.pm

      • Multiselect.pm

    • BaseDateTime.pm

      • DateTime.pm

      • Date.pm

    • Checkbox.pm

Objektumtípus delegált

Egy objektumtípus delegált felelős bizonyos függvények végrehajtásáért a dinamikus mezőhöz kapcsolt objektumon. Ezeket a függvényeket a háttérprogram objektum aktiválja, amint szükség van rájuk.

Ezek a modulok az $OTRS_HOME/Kernel/System/DynamicField/ObjectType/*.pm fájlokban találhatók.

Dinamikus mezők adminisztrátori moduljai

A dinamikus mezők kezeléséhez (hozzáadás, szerkesztés és felsorolás) már egy csomó modul van kifejlesztve. Van egy bizonyos fő modul (AdminDynamicField.pm), amely megjeleníti a meghatározott dinamikus mezők listáját, és más modulokon belülről hívják meg új dinamikus mezők létrehozásához vagy a meglévők módosításához.

Normális esetben egy dinamikus mező illesztőprogramnak saját adminisztrátori modulra van szüksége (adminisztrátori párbeszédablak) a tulajdonságai meghatározásához. Ez a párbeszédablak esetleg eltérhet a többi illesztőprogramtól. De ez nem kötelező, az illesztőprogramok megoszthatják az adminisztrátori párbeszédablakokat, ha szükséges információkat biztosíthatnak az összes olyan illesztőprogramhoz, amelyek hozzájuk vannak kapcsolva, nem számít, hogy eltérő típusból származnak. Ami kötelező, hogy minden egyes illesztőprogramnak hozzákapcsolva kell lennie egy adminisztrátori párbeszédablakhoz (például a szöveg és a szövegterület illesztőprogramok megosztják az AdminDynamicFieldText.pm adminisztrátori párbeszédablakot, és a dátum és a dátum/idő illesztőprogramok megosztják az AdminDynamicFieldDateTime.pm adminisztrátori párbeszédablakot).

Az adminisztrátori párbeszédablakok a normál OTRS adminisztrátori modulszabályokat és szerkezetet követik. De a szabványosításhoz az összes beállítás közös részének az összes dinamikus mezőnél ugyanolyan megjelenésűnek kell lennie az összes adminisztrátori párbeszédablaknál.

Ezek a modulok az $OTRS_HOME/Kernel/Modules/*.pm fájlokban találhatók.

Megjegyzés

Minden adminisztrátori párbeszédablaknak szüksége van a neki megfelelő HTML sablonfájlra (.tt).

Dinamikus mezők alapmoduljai

Ezek a modulok olvassák és írják a dinamikus mezők információit az adatbázistáblákban.

DynamicField.pm alapmodul

Ez a modul felelős a dinamikus mező meghatározások kezeléséért. Ez biztosítja az alap API-t a hozzáadáshoz, megváltoztatáshoz, törléshez, felsoroláshoz és a dinamikus mezők lekéréséhez. Ez a modul az $OTRS_HOME/Kernel/System/DynamicField.pm fájlban található.

DynamicFieldValue.pm alapmodul

Ez a modul felelős a dinamikus mező értékeinek olvasásáért és írásáért az űrlapon és az adatbázisban. Ezt a modult erősen használják az illesztőprogramok, és az $OTRS_HOME/Kernel/System/DynamicFieldValue.pm fájlban található.

Dinamikus mezők adatbázistáblái

Két tábla van az adatbázisban a dinamikus mező információinak tárolásához:

dynamic_field: a DynamicField.pm alapmodul használja, és a dinamikus mező meghatározásokat tárolja.

dynamic_field_value: a DynamicFieldValue.pm alapmodul használja a dinamikus mező értékeinek mentéséhez minden egyes dinamikus mező és minden egyes objektumtípus példánynál.

Dinamikus mezők beállítófájljai

A háttérprogram modulnak szüksége van egy módra megtudni azt, hogy mely illesztőprogramok léteznek, mivel az illesztőprogramok mennyisége egyszerűen kiterjeszthető. Ezek kezelésének legegyszerűbb módja a rendszerbeállítás használata, ahol a dinamikus mező illesztőprogramok és az objektumtípus illesztőprogramok információi eltárolhatók és kiterjeszthetők.

A fő adminisztrátori modulnak is szükséges tudnia ezeket az információkat az elérhető dinamikus mező illesztőprogramokról a hozzájuk kapcsolt adminisztrátori párbeszédablakok használatához, a dinamikus mezők létrehozásához vagy módosításához.

Az előtétprogram moduloknak szükségük van a rendszerbeállítások olvasására megtudni azt, hogy mely dinamikus mezők vannak bekapcsolva az egyes képernyőknél, és melyek kötelezőek. Például a Ticket::Frontend::AgentTicketPhone###DynamicField tárolja az aktív, kötelező és inaktív dinamikus mezőket az új telefonos jegy képernyőnél.

Dinamikus mező kölcsönhatása az előtétprogram modulokkal

Ismerve azt, hogy az előtétprogram modulok hogyan lépnek kölcsönhatásba a dinamikus mezőkkel, nem feltétlenül szükséges a dinamikus mezők kiterjesztése a jegy vagy bejegyzés objektumokhoz, mivel már elő van készítve az összes olyan képernyő, amely dinamikus mezőket tud használni. De egyéni fejlesztések esetén vagy a dinamikus mezők más objektumokhoz történő kiterjesztéséhez nagyon hasznos tudni, hogy a dinamikus mezők keretrendszere hogyan érhető el egy előtétprogram modulból.

A következő kép egy egyszerű példáját mutatja be annak, hogy a dinamikus mezők hogyan lépnek kölcsönhatásba az OTRS keretrendszer többi részével.

3.3. ábra - Dinamikus mezők kölcsönhatása

Dinamikus mezők kölcsönhatása


Az első lépés, hogy az előtétprogram modul beolvassa a beállított dinamikus mezőket. Például az AgentTicketNote modulnak be kell olvasnia a Ticket::Frontend::AgentTicketNote###DynamicField beállítást. Ez a beállítás használható szűrőparaméterként a DynamicFieldListGet() dinamikus mező alapmodul függvénynél. A képernyő tárolhatja ennek a függvénynek az eredményeit, hogy meglegyen az aktivált dinamikus mezők listája ennél a bizonyos képernyőnél.

Ezután a képernyőnek meg kell próbálnia lekérni az értékeket a webkérésből. Erre a célra használhatja az EditFieldValueGet() háttérprogram-objektum függvényt, és használhatja ezeket az értékeket az ACL-ek aktiválásához. A háttérprogram-objektum minden egyes illesztőprogramot használni fog a különleges műveletek végrehajtásához az összes függvénynél.

A folytatáshoz a képernyőnek le kell kérnie a HTML-t minden egyes mezőhöz annak megjelenítéséhez. Az EditFieldRender() háttérprogram-objektum függvény használható ezen művelet és az ACL-ek korlátozásának végrehajtásához, valamint a webkérésből származó értékek átadhatók ennek a függvénynek azért, hogy jobb eredményeket kapjon. Egy elküldés esetén a képernyő használhatja az EditFieldValueValidate() háttérprogram-objektum függvényt is a kötelező mezők ellenőrzéséhez.

Megjegyzés

A többi képernyő használhatja a DisplayFieldRender() függvényt az EditFieldRender() helyett, ha a képernyő csak a mezőértéket jeleníti meg, és ilyen esetben nincs szükség értékellenőrzésre.

A dinamikus mező értékének tárolásához szükséges az objektumazonosító lekérése. Ennél a példánál ha a dinamikus mező hozzá van kapcsolva egy jegy objektumhoz, akkor a képernyőnek már rendelkeznie kell a jegyazonosítóval, egyébként ha a mező hozzá van kapcsolva egy bejegyzés objektumhoz azért, hogy beállítsa a mező értékét, akkor először a bejegyzés létrehozása szükséges. A háttérprogram-objektumból a ValueSet() függvény használható a dinamikus mező értékének beállításához.

Összefoglalva, az előtétprogram moduloknak nem szükséges tudniuk, hogy az egyes dinamikus mezők hogyan működnek belsőleg azért, hogy lekérjék vagy beállítsák az értékeiket vagy megjelenítsék azokat. Egyszerűen csak meg kell hívnia a háttérprogram-objektum modult, és általános módon kell használnia a mezőket.

Hogyan lehet kiterjeszteni a dinamikus mezőket

Számos módszer létezik a dinamikus mezők kiterjesztésére. A következő szakaszok meg fogják próbálni a leggyakoribb forgatókönyveket bemutatni.

Egy új dinamikus mező típus létrehozása (a jegy vagy bejegyzés objektumokhoz)

Egy új dinamikus mező típus létrehozásához a következők szükségesek:

  • Hozzon létre egy dinamikus mező illesztőprogramot

    Ez az új mező fő modulja.

  • Hozzon létre vagy használjon egy meglévő adminisztrátori párbeszédablakot

    Egy kezelőfelület megszerzéséhez, és a konfigurációs beállításainak megadásához.

  • Hozzon létre egy beállítófájlt

    Az új mező regisztrálásához a háttérprogramban (vagy a keretrendszerben lévő új adminisztrátori párbeszédablakokban, ha szükséges), valamint hogy képes legyen példányokat vagy azt létrehozni.

Egy új dinamikus mező típus létrehozása (egyéb objektumokhoz)

Egy új dinamikus mező típus létrehozásához más objektumoknál a következők szükségesek:

  • Hozzon létre egy dinamikus mező illesztőprogramot

    Ez az új mező fő modulja.

  • Hozzon létre egy objektumtípus delegáltat

    Ez akkor is szükséges, ha a „másik objektum” nem igényel semmilyen különleges adatkezelést a függvényeiben (például egy érték beállítása után). Az összes objektumtípus delegáltnak meg kell valósítania azokat a függvényeket, amelyeket a háttérprogram igényel.

    Vessen egy pillantást a jelenlegi objektumtípus delegáltakra ugyanazon függvények megvalósításához még akkor is, ha azok csak egy sikeres értéket adnak vissza a „másik objektumnál”.

  • Hozzon létre vagy használjon egy meglévő adminisztrátori párbeszédablakot

    Egy kezelőfelület megszerzéséhez, és a konfigurációs beállításainak megadásához.

  • Valósítsa meg a dinamikus mezőket az előtétprogram modulokban

    Hogy képes legyen használni a dinamikus mezőket.

  • Hozzon létre egy beállítófájlt

    Az új mező regisztrálásához a háttérprogramban (vagy a keretrendszerben lévő új adminisztrátori párbeszédablakokban, ha szükséges), valamint hogy képes legyen példányokat vagy azt létrehozni. És végezze el a szükséges beállításokat az új képernyőkön történő megjelenítéshez, elrejtéshez vagy a dinamikus mezők kötelezőként való megjelenítéséhez.

Egy új csomag létrehozása a dinamikus mezők használatához

Egy csomag létrehozásához a meglévő dinamikus mezők használata érdekében a következők szükségesek:

  • Valósítsa meg a dinamikus mezőket az előtétprogram modulokban

    Hogy képes legyen használni a dinamikus mezőket.

  • Hozzon létre egy beállítófájlt

    Hogy lehetőséget adjon a végfelhasználónak az új képernyőkön történő megjelenítéshez, elrejtéshez vagy a dinamikus mezők kötelezőként való megjelenítéséhez.

A háttérprogram és az illesztőprogramok funkcionalitásainak kiterjesztése

Lehetséges lehet, hogy a háttérprogram objektum nem rendelkezik egy szükséges függvénnyel az egyéni fejlesztésekhez, vagy az is előfordulhat, hogy megvan ugyan a szükséges függvénye, de a visszatérési formátum nem felel meg az egyéni fejlesztés szükségleteinek, vagy hogy egy új viselkedés az új vagy a régi függvények végrehajtását igényli.

A legegyszerűbb mód ennek elvégzéséhez a jelenlegi mezőfájlok kiterjesztése. Ehhez egy olyan új háttérprogram kiterjesztésfájlt szükséges létrehozni, amely meghatározza az új függvényeket, és olyan illesztőprogram kiterjesztéseket is létre kell hozni, amelyek megvalósítják ezeket az új függvényeket minden egyes mezőnél. Ezeknek az új illesztőprogramoknak csak az új függvényeket kell majd megvalósítaniuk, mivel az eredeti illesztőprogramok törődnek a szabványos függvényekkel. Ezen új fájlok egyikének sincs szüksége konstruktorra, mivel ezek egy alapként lesznek betöltve a háttérprogram objektumhoz és az illesztőprogramokhoz.

Az egyetlen korlátozás, hogy a függvényeket eltérően kell elnevezni a háttérprogramnál és az illesztőprogramnál lévőknél, különben felül fognak íródni a jelenlegi objektumokkal.

Tegye az új háttérprogram kiterjesztést a DynamicField könyvtárba (például /$OTRS_HOME/Kernel/System/DynamicField/NewPackageBackend.pm és az illesztőprogramjait a /$OTRS_HOME/Kernel/System/DynamicField/Driver/NewPackage*.pm fájlokba).

Az új viselkedéseknek csak egy kis beállítás szükséges a kiterjesztések beállítófájljában.

Az új háttérprogram függvények létrehozásához a következők szükségesek:

  • Hozzon létre egy új háttérprogram kiterjesztés modult

    Csak az új függvények meghatározásához.

  • Hozza létre a dinamikus mezők illesztőprogram kiterjesztéseit

    Csak az új függvények megvalósításához.

  • Valósítsa meg az új dinamikus mezők függvényeit az előtétprogram modulokban

    Hogy képes legyen használni az új dinamikus mezők függvényeit.

  • Hozzon létre egy beállítófájlt

    Az új háttérprogram és az illesztőprogramok kiterjesztéseinek és viselkedéseinek regisztrálásához.

Egyéb kiterjesztések

Egyéb kiterjesztések lehetnek a fenti példák kombinációi.

Egy új dinamikus mező létrehozása

A folyamat bemutatásához egy új „jelszó” dinamikus mező lesz létrehozva. Ez az új dinamikus mező típus egy új jelszómezőt fog megjeleníteni a jegy és a bejegyzés objektumokhoz. Mivel nagyon hasonló egy szöveg dinamikus mezőhöz, ezért a Base és a BaseText illesztőprogramokat fogjuk használni alapként ezen új mező felépítéséhez.

Megjegyzés

Az új jelszómező megvalósítása csak oktatási célokra van, nem biztosít semmilyen biztonsági szintet, és nem ajánlott termelési rendszereknél.

A dinamikus mező létrehozásához négy fájlt fogunk létrehozni: egy beállítófájlt (XML) a modulok regisztrálásához, egy adminisztrátori párbeszédablak modult (Perl) a mezőlehetőségek beállításához, egy sablonmodult az adminisztrátori párbeszédablakhoz és egy dinamikus mező illesztőprogramot (Perl).

Fájlszerkezet:

$HOME (például /opt/otrs/)
|
...
|--/Kernel/
|   |--/Config/
|   |   |--/Files/
|   |   |   |DynamicFieldPassword.xml
...
|   |--/Modules/
|   |   |AdminDynamicFieldPassword.pm
...
|   |--/Output/
|   |   |--/HTML/
|   |   |   |--/Standard/
|   |   |   |   |AdminDynamicFieldPassword.tt
...
|   |--/System/
|   |   |--/DynamicField/
|   |   |   |--/Driver/
|   |   |   |   |Password.pm
...
        
Dinamikus mező jelszó fájlok
Dinamikus mező beállítófájl példa

A beállítófájlokat használják a dinamikus mező típusok (illesztőprogram) és az objektumtípus illesztőprogramok regisztrálásához a BackendObject számára. Ezek szabványos regisztrációkat is tárolnak az adminisztrátori modulokhoz a keretrendszerben.

Kódpélda:

Ebben a szakaszban a jelszó dinamikus mezőhöz egy beállítófájl van megjelenítve és elmagyarázva.

<?xml version="1.0" encoding="utf-8"?>
<otrs_config version="1.0" init="Application">
            

Ez a normál fejléc egy beállítófájlhoz.

    <ConfigItem Name="DynamicFields::Driver###Password" Required="0" Valid="1">
        <Description Translatable="1">Dinamikus mező háttérprogram regisztráció.</Description>
        <Group>DynamicFieldPassword</Group>
        <SubGroup>DynamicFields::Backend::Registration</SubGroup>
        <Setting>
            <Hash>
                <Item Key="DisplayName" Translatable="1">Jelszó</Item>
                <Item Key="Module">Kernel::System::DynamicField::Driver::Password</Item>
                <Item Key="ConfigDialog">AdminDynamicFieldPassword</Item>
            </Hash>
        </Setting>
    </ConfigItem>
            

Ez a beállítás regisztrálja a jelszó dinamikus mező illesztőprogramot a háttérprogram modulhoz, így az felvehető az elérhető dinamikus mezők típusainak listájába. A saját adminisztrátori párbeszédablakát is meghatározza a ConfigDialog kulcsban. Ezt a kulcsot a fő dinamikus mező adminisztrátori modul használja ennek az új dinamikus mező típusának a kezeléséhez.

    <ConfigItem Name="Frontend::Module###AdminDynamicFieldPassword" Required="0" Valid="1">
        <Description Translatable="1">Előtétprogram-modul regisztráció az ügyintézői felülethez.</Description>
        <Group>DynamicFieldPassword</Group>
        <SubGroup>Frontend::Admin::ModuleRegistration</SubGroup>
        <Setting>
            <FrontendModuleReg>
                <Group>admin</Group>
                <Description>Admin</Description>
                <Title Translatable="1">Dinamikus mezők szöveg háttérprogram grafikus felület</Title>
                <Loader>
                    <JavaScript>Core.Agent.Admin.DynamicField.js</JavaScript>
                </Loader>
            </FrontendModuleReg>
        </Setting>
    </ConfigItem>
            

Ez egy szabványos modulregisztráció a jelszó adminisztrátori párbeszédablakhoz az adminisztrátori felületen.

</otrs_config>
            

Egy beállítófájl szabványos lezárása.

Dinamikus mező adminisztrátori párbeszédablak példa

Az adminisztrátori párbeszédablakok szabványos adminisztrátori modulok a dinamikus mezők kezeléséhez (hozzáadás vagy szerkesztés).

Kódpélda:

Ebben a szakaszban a jelszó dinamikus mezőhöz egy adminisztrátori párbeszédablak van megjelenítve és elmagyarázva.

# --
# Kernel/Modules/AdminDynamicFieldPassword.pm - provides a dynamic fields password config view for admins
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::Modules::AdminDynamicFieldPassword;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(:all);
use Kernel::System::Valid;
use Kernel::System::CheckItem;
use Kernel::System::DynamicField;
            

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva.

sub new {
    my ( $Type, %Param ) = @_;

    my $Self = {%Param};
    bless( $Self, $Type );

    for (qw(ParamObject LayoutObject LogObject ConfigObject)) {
        if ( !$Self->{$_} ) {
            $Self->{LayoutObject}->FatalError( Message => "Nincs $_!" );
        }
    }

    # további objektumok létrehozása
    $Self->{ValidObject} = Kernel::System::Valid->new( %{$Self} );

    $Self->{DynamicFieldObject} = Kernel::System::DynamicField->new( %{$Self} );

    # beállított objektumtípusok lekérése
    $Self->{ObjectTypeConfig} = $Self->{ConfigObject}->Get('DynamicFields::ObjectType');

    # a mezők beállításának lekérése
    $Self->{FieldTypeConfig} = $Self->{ConfigObject}->Get('DynamicFields::Backend') || {};

    $Self->{DefaultValueMask} = '****';
    return $Self;
}
            

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint más osztályoknak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

sub Run {
    my ( $Self, %Param ) = @_;

    if ( $Self->{Subaction} eq 'Add' ) {
        return $Self->_Add(
            %Param,
        );
    }
    elsif ( $Self->{Subaction} eq 'AddAction' ) {

        # kihívási token ellenőrzése az írási művelethez
        $Self->{LayoutObject}->ChallengeTokenCheck();

        return $Self->_AddAction(
            %Param,
        );
    }
    if ( $Self->{Subaction} eq 'Change' ) {

        return $Self->_Change(
            %Param,
        );
    }
    elsif ( $Self->{Subaction} eq 'ChangeAction' ) {

        # kihívási token ellenőrzése az írási művelethez
        $Self->{LayoutObject}->ChallengeTokenCheck();

        return $Self->_ChangeAction(
            %Param,
        );
    }

    return $Self->{LayoutObject}->ErrorScreen(
        Message => "Meghatározatlan alművelet.",
    );
}
            

A Run a webkérés által meghívott alapértelmezett függvény. Megpróbáljuk ezt a függvényt annyira egyszerűvé tenni, amennyire csak lehetséges, és lehetővé tenni a segítő függvényeknek a „kemény” munka elvégzését.

sub _Add {
    my ( $Self, %Param ) = @_;

    my %GetParam;
    for my $Needed (qw(ObjectType FieldType FieldOrder)) {
        $GetParam{$Needed} = $Self->{ParamObject}->GetParam( Param => $Needed );
        if ( !$Needed ) {

            return $Self->{LayoutObject}->ErrorScreen(
                Message => "Szükséges: $Needed",
            );
        }
    }

    # az objektumtípus és a mezőtípus megjelenített nevének lekérése
    my $ObjectTypeName = $Self->{ObjectTypeConfig}->{ $GetParam{ObjectType} }->{DisplayName} || '';
    my $FieldTypeName  = $Self->{FieldTypeConfig}->{ $GetParam{FieldType} }->{DisplayName}   || '';

    return $Self->_ShowScreen(
        %Param,
        %GetParam,
        Mode           => 'Add',
        ObjectTypeName => $ObjectTypeName,
        FieldTypeName  => $FieldTypeName,
    );
}
            

Az _Add függvény is nagyon egyszerű, csak lekér néhány paramétert a webkérésből, és meghívja a _ShowScreen() függvényt. Normális esetben ezt a függvényt nem szükséges módosítani.

sub _AddAction {
    my ( $Self, %Param ) = @_;

    my %Errors;
    my %GetParam;

    for my $Needed (qw(Name Label FieldOrder)) {
        $GetParam{$Needed} = $Self->{ParamObject}->GetParam( Param => $Needed );
        if ( !$GetParam{$Needed} ) {
            $Errors{ $Needed . 'ServerError' }        = 'ServerError';
            $Errors{ $Needed . 'ServerErrorMessage' } = 'Ez a mező kötelező.';
        }
    }

    if ( $GetParam{Name} ) {

        # annak ellenőrzése, hogy a név csak betűket és számokat tartalmaz-e
        if ( $GetParam{Name} !~ m{\A ( ?: [a-zA-Z] | \d )+ \z}xms ) {

            # kiszolgálóhiba hibaosztály hozzáadása
            $Errors{NameServerError} = 'ServerError';
            $Errors{NameServerErrorMessage} =
                'A mező nem csak ASCII betűket és számokat tartalmaz.';
        }

        # annak ellenőrzése, hogy a név kettőzött-e
        my %DynamicFieldsList = %{
            $Self->{DynamicFieldObject}->DynamicFieldList(
                Valid      => 0,
                ResultType => 'HASH',
                )
        };

        %DynamicFieldsList = reverse %DynamicFieldsList;

        if ( $DynamicFieldsList{ $GetParam{Name} } ) {

            # kiszolgálóhiba hibaosztály hozzáadása
            $Errors{NameServerError}        = 'ServerError';
            $Errors{NameServerErrorMessage} = 'Már létezik egy másik ugyanilyen nevű mező.';
        }
    }

    if ( $GetParam{FieldOrder} ) {

        # annak ellenőrzése, hogy a mezősorrend számszerű és pozitív-e
        if ( $GetParam{FieldOrder} !~ m{\A ( ?: \d )+ \z}xms ) {

            # kiszolgálóhiba hibaosztály hozzáadása
            $Errors{FieldOrderServerError}        = 'ServerError';
            $Errors{FieldOrderServerErrorMessage} = 'A mezőnek számnak kell lennie.';
        }
    }

    for my $ConfigParam (
        qw(
        ObjectType ObjectTypeName FieldType FieldTypeName DefaultValue ValidID ShowValue
        ValueMask
        )
        )
    {
        $GetParam{$ConfigParam} = $Self->{ParamObject}->GetParam( Param => $ConfigParam );
    }

    # kijavíthatatlan hibák
    if ( !$GetParam{ValidID} ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Szükséges: ValidID",
        );
    }

    # visszatérés a hozzáadás képernyőre, ha hibák vannak
    if (%Errors) {

        return $Self->_ShowScreen(
            %Param,
            %Errors,
            %GetParam,
            Mode => 'Add',
        );
    }

    # bizonyos beállítások elvégzése
    my $FieldConfig = {
        DefaultValue => $GetParam{DefaultValue},
        ShowValue    => $GetParam{ShowValue},
        ValueMask    => $GetParam{ValueMask} || $Self->{DefaultValueMask},
    };

    # egy új mező létrehozása
    my $FieldID = $Self->{DynamicFieldObject}->DynamicFieldAdd(
        Name       => $GetParam{Name},
        Label      => $GetParam{Label},
        FieldOrder => $GetParam{FieldOrder},
        FieldType  => $GetParam{FieldType},
        ObjectType => $GetParam{ObjectType},
        Config     => $FieldConfig,
        ValidID    => $GetParam{ValidID},
        UserID     => $Self->{UserID},
    );

    if ( !$FieldID ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Nem sikerült létrehozni az új mezőt",
        );
    }

    return $Self->{LayoutObject}->Redirect(
        OP => "Action=AdminDynamicField",
    );
}
            

Az _AddAction függvény kéri le a beállítási paramétereket egy új dinamikus mezőből, és ellenőrzi, hogy a dinamikus mező neve csak betűket és számokat tartalmaz-e. Ez a függvény képes ellenőrizni bármilyen egyéb paramétert is.

A Name, Label, FieldOrder, Validity közös paraméterek az összes dinamikus mezőnél, és ezek kötelezők. Minden egyes dinamikus mezőnek megvan a saját különleges beállítása, amelynek tartalmaznia kell legalább a DefaultValue paramétert. Ebben az esetben a ShowValue és a ValueMask paraméterekkel is rendelkezik a jelszómezőnél.

Ha a mező rendelkezik egy rögzített listájú értékek tárolásának képességével, akkor azokat a PossibleValues paraméterben kell tárolni a különleges beállítási kivonaton belül.

Mint más adminisztrátori modulokban, ha egy paraméter nem érvényes, akkor ez a függvény visszatér a hozzáadás képernyőre, kiemelve a hibás űrlapmezőket.

Ha az összes paraméter helyes, akkor létrehoz egy új dinamikus mezőt.

sub _Change {
    my ( $Self, %Param ) = @_;

    my %GetParam;
    for my $Needed (qw(ObjectType FieldType)) {
        $GetParam{$Needed} = $Self->{ParamObject}->GetParam( Param => $Needed );
        if ( !$Needed ) {

            return $Self->{LayoutObject}->ErrorScreen(
                Message => "Szükséges: $Needed",
            );
        }
    }

    # az objektumtípus és a mezőtípus megjelenített nevének lekérése
    my $ObjectTypeName = $Self->{ObjectTypeConfig}->{ $GetParam{ObjectType} }->{DisplayName} || '';
    my $FieldTypeName  = $Self->{FieldTypeConfig}->{ $GetParam{FieldType} }->{DisplayName}   || '';

    my $FieldID = $Self->{ParamObject}->GetParam( Param => 'ID' );

    if ( !$FieldID ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Azonosító szükséges",
        );
    }

    # dinamikus mező adatainak lekérése
    my $DynamicFieldData = $Self->{DynamicFieldObject}->DynamicFieldGet(
        ID => $FieldID,
    );

    # érvényes dinamikus mező beállítások ellenőrzése
    if ( !IsHashRefWithData($DynamicFieldData) ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Nem sikerült lekérni az adatokat a dinamikus mezőhöz: $FieldID",
        );
    }

    my %Config = ();

    # beállítások kibontása
    if ( IsHashRefWithData( $DynamicFieldData->{Config} ) ) {
        %Config = %{ $DynamicFieldData->{Config} };
    }

    return $Self->_ShowScreen(
        %Param,
        %GetParam,
        %${DynamicFieldData},
        %Config,
        ID             => $FieldID,
        Mode           => 'Change',
        ObjectTypeName => $ObjectTypeName,
        FieldTypeName  => $FieldTypeName,
    );
}
            

A _Change függvény nagyon hasonló az _Add függvényhez, de mivel ezt a függvényt egy meglévő mező szerkesztéséhez használják, ellenőriznie kell a FieldID paramétert, és be kell gyűjtenie a jelenlegi dinamikus mező adatait.

sub _ChangeAction {
    my ( $Self, %Param ) = @_;

    my %Errors;
    my %GetParam;

    for my $Needed (qw(Name Label FieldOrder)) {
        $GetParam{$Needed} = $Self->{ParamObject}->GetParam( Param => $Needed );
        if ( !$GetParam{$Needed} ) {
            $Errors{ $Needed . 'ServerError' }        = 'ServerError';
            $Errors{ $Needed . 'ServerErrorMessage' } = 'Ez a mező kötelező.';
        }
    }

    my $FieldID = $Self->{ParamObject}->GetParam( Param => 'ID' );
    if ( !$FieldID ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Azonosító szükséges",
        );
    }

    if ( $GetParam{Name} ) {

        # annak ellenőrzése, hogy a név kisbetűs-e
        if ( $GetParam{Name} !~ m{\A ( ?: [a-zA-Z] | \d )+ \z}xms ) {

            # kiszolgálóhiba hibaosztály hozzáadása
            $Errors{NameServerError} = 'ServerError';
            $Errors{NameServerErrorMessage} =
                'A mező nem csak ASCII betűket és számokat tartalmaz.';
        }

        # annak ellenőrzése, hogy a név kettőzött-e
        my %DynamicFieldsList = %{
            $Self->{DynamicFieldObject}->DynamicFieldList(
                Valid      => 0,
                ResultType => 'HASH',
                )
        };

        %DynamicFieldsList = reverse %DynamicFieldsList;

        if (
            $DynamicFieldsList{ $GetParam{Name} } &&
            $DynamicFieldsList{ $GetParam{Name} } ne $FieldID
            )
        {

            # kiszolgálóhiba hibaosztály hozzáadása
            $Errors{NameServerError}        = 'ServerError';
            $Errors{NameServerErrorMessage} = 'Már létezik egy másik ugyanilyen nevű mező.';
        }
    }

    if ( $GetParam{FieldOrder} ) {

        # annak ellenőrzése, hogy a mezősorrend számszerű és pozitív-e
        if ( $GetParam{FieldOrder} !~ m{\A ( ?: \d )+ \z}xms ) {

            # add server error error class
            $Errors{FieldOrderServerError}        = 'ServerError';
            $Errors{FieldOrderServerErrorMessage} = 'A mezőnek számnak kell lennie.';
        }
    }

    for my $ConfigParam (
        qw(
        ObjectType ObjectTypeName FieldType FieldTypeName DefaultValue ValidID ShowValue
        ValueMask
        )
        )
    {
        $GetParam{$ConfigParam} = $Self->{ParamObject}->GetParam( Param => $ConfigParam );
    }

    # kijavíthatatlan hibák
    if ( !$GetParam{ValidID} ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Szükséges: ValidID",
        );
    }

    # a dinamikus mező adatainak lekérése
    my $DynamicFieldData = $Self->{DynamicFieldObject}->DynamicFieldGet(
        ID => $FieldID,
    );

    # érvényes dinamikus mező beállítások ellenőrzése
    if ( !IsHashRefWithData($DynamicFieldData) ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Nem sikerült lekérni az adatokat a dinamikus mezőhöz: $FieldID",
        );
    }

    # visszatérés a változtatás képernyőhöz, ha hibák vannak
    if (%Errors) {

        return $Self->_ShowScreen(
            %Param,
            %Errors,
            %GetParam,
            ID   => $FieldID,
            Mode => 'Change',
        );
    }

    # különleges beállítások elvégzése
    my $FieldConfig = {
        DefaultValue => $GetParam{DefaultValue},
        ShowValue    => $GetParam{ShowValue},
        ValueMask    => $GetParam{ValueMask},
    };

    # dinamikus mező frissítése (a FieldType és az ObjectType nem változtatható meg; régi értékek használata)
    my $UpdateSuccess = $Self->{DynamicFieldObject}->DynamicFieldUpdate(
        ID         => $FieldID,
        Name       => $GetParam{Name},
        Label      => $GetParam{Label},
        FieldOrder => $GetParam{FieldOrder},
        FieldType  => $DynamicFieldData->{FieldType},
        ObjectType => $DynamicFieldData->{ObjectType},
        Config     => $FieldConfig,
        ValidID    => $GetParam{ValidID},
        UserID     => $Self->{UserID},
    );

    if ( !$UpdateSuccess ) {

        return $Self->{LayoutObject}->ErrorScreen(
            Message => "Nem sikerült frissíteni a mezőt: $GetParam{Name}",
        );
    }

    return $Self->{LayoutObject}->Redirect(
        OP => "Action=AdminDynamicField",
    );
}
            

A _ChangeAction() nagyon hasonló az _AddAction() függvényhez, de át van írva egy meglévő mező frissítéséhez egy új létrehozása helyett.

sub _ShowScreen {
    my ( $Self, %Param ) = @_;

    $Param{DisplayFieldName} = 'New';

    if ( $Param{Mode} eq 'Change' ) {
        $Param{ShowWarning}      = 'ShowWarning';
        $Param{DisplayFieldName} = $Param{Name};
    }

    # fejléc
    my $Output = $Self->{LayoutObject}->Header();
    $Output .= $Self->{LayoutObject}->NavigationBar();

    # az összes mező lekérése
    my $DynamicFieldList = $Self->{DynamicFieldObject}->DynamicFieldListGet(
        Valid => 0,
    );

    # a sorrendszámok listájának lekérése (már rendezve van).
    my @DynamicfieldOrderList;
    for my $Dynamicfield ( @{$DynamicFieldList} ) {
        push @DynamicfieldOrderList, $Dynamicfield->{FieldOrder};
    }

    # hozzáadáskor létre kell hoznunk egy további sorrendszámot az új mezőhöz
    if ( $Param{Mode} eq 'Add' ) {

        # az utolsó elem lekérése a sorrendlistából, és 1 hozzáadása
        my $LastOrderNumber = $DynamicfieldOrderList[-1];
        $LastOrderNumber++;

        # ezen új sorrendszám hozzáadása a lista végéhez
        push @DynamicfieldOrderList, $LastOrderNumber;
    }

    my $DynamicFieldOrderSrtg = $Self->{LayoutObject}->BuildSelection(
        Data          => \@DynamicfieldOrderList,
        Name          => 'FieldOrder',
        SelectedValue => $Param{FieldOrder} || 1,
        PossibleNone  => 0,
        Class         => 'W50pc Validate_Number',
    );

    my %ValidList = $Self->{ValidObject}->ValidList();

    # az ellenőrzés kiválasztás létrehozása
    my $ValidityStrg = $Self->{LayoutObject}->BuildSelection(
        Data         => \%ValidList,
        Name         => 'ValidID',
        SelectedID   => $Param{ValidID} || 1,
        PossibleNone => 0,
        Translation  => 1,
        Class        => 'W50pc',
    );

    # a beállítási mezőre jellemző beállítások meghatározása
    my $DefaultValue = ( defined $Param{DefaultValue} ? $Param{DefaultValue} : '' );

    # az érték megjelenítése választás létrehozása
    my $ShowValueStrg = $Self->{LayoutObject}->BuildSelection(
        Data => [ 'No', 'Yes' ],
        Name => 'ShowValue',
        SelectedValue => $Param{ShowValue} || 'No',
        PossibleNone  => 0,
        Translation   => 1,
        Class         => 'W50pc',
    );

    # kimenet előállítása
    $Output .= $Self->{LayoutObject}->Output(
        TemplateFile => 'AdminDynamicFieldPassword',
        Data         => {
            %Param,
            ValidityStrg          => $ValidityStrg,
            DynamicFieldOrderSrtg => $DynamicFieldOrderSrtg,
            DefaultValue          => $DefaultValue,
            ShowValueStrg         => $ShowValueStrg,
            ValueMask             => $Param{ValueMask} || $Self->{DefaultValueMask},
        },
    );

    $Output .= $Self->{LayoutObject}->Footer();

    return $Output;
}

1;
            

A _ShowScreen függvényt használják egy sablonból történő HTML elemek és blokkok beállítására és meghatározására az adminisztrátori párbeszédablak HTML kódjának előállításához.

Dinamikus mező sablon az adminisztrátori párbeszédablak példához

A sablon az a hely, ahol a párbeszédablak HTML kódja el van tárolva.

Kódpélda:

Ebben a szakaszban a jelszó dinamikus mezőhöz egy adminisztrátori párbeszédablak sablon van megjelenítve és elmagyarázva.

# --
# AdminDynamicFieldPassword.tt - provides HTML form for AdminDynamicFieldPassword
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --
            

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban.

<div class="MainBox ARIARoleMain LayoutFixedSidebar SidebarFirst">
    <h1>[% Translate("Dynamic Fields") | html %] - [% Translate(Data.ObjectTypeName) | html %]: [% Translate(Data.Mode) | html %] [% Translate(Data.FieldTypeName) | html %] [% Translate("Mező") | html %]</h1>

    <div class="Clear"></div>

    <div class="SidebarColumn">
        <div class="WidgetSimple">
            <div class="Header">
                <h2>[% Translate("Műveletek") | html %]</h2>
            </div>
            <div class="Content">
                <ul class="ActionList">
                    <li>
                        <a href="[% Env("Baselink") %]Action=AdminDynamicField" class="CallForAction"><span>[% Translate("Ugrás vissza az áttekintőhöz") | html %]</span></a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
            

A kód ezen része rendelkezik a fő dobozzal és a műveletek oldalsávval is. Nincs szükség módosításokra ebben a szakaszban.

    <div class="ContentColumn">
        <form action="[% Env("CGIHandle") %]" method="post" class="Validate PreventMultipleSubmits">
            <input type="hidden" name="Action" value="AdminDynamicFieldPassword" />
            <input type="hidden" name="Subaction" value="[% Data.Mode | html %]Action" />
            <input type="hidden" name="ObjectType" value="[% Data.ObjectType | html %]" />
            <input type="hidden" name="FieldType" value="[% Data.FieldType | html %]" />
            <input type="hidden" name="ID" value="[% Data.ID | html %]" />
            

A kód ezen szakaszában van meghatározva a párbeszédablak jobboldali része. Figyelje meg, hogy a rejtett Action beviteli mező értékének egyeznie kell az adminisztrátori párbeszédablak nevével.

            <div class="WidgetSimple">
                <div class="Header">
                    <h2>[% Translate("Általános") | html %]</h2>
                </div>
                <div class="Content">
                    <div class="LayoutGrid ColumnsWithSpacing">
                        <div class="Size1of2">
                            <fieldset class="TableLike">
                                <label class="Mandatory" for="Name"><span class="Marker">*</span> [% Translate("Név") | html %]:</label>
                                <div class="Field">
                                    <input id="Name" class="W50pc [% Data.NameServerError | html %] [% Data.ShowWarning | html %]  Validate_Alphanumeric" type="text" maxlength="200" value="[% Data.Name | html %]" name="Name"/>
                                    <div id="NameError" class="TooltipErrorMessage"><p>[% Translate("Ez a mező kötelező, és az értéke csak betű és szám karakter lehet.") | html %]</p></div>
                                    <div id="NameServerError" class="TooltipErrorMessage"><p>[% Translate(Data.NameServerErrorMessage) | html %]</p></div>
                                    <p class="FieldExplanation">[% Translate("Egyedinek kell lennie, és csak betű és szám karaktereket fogad el.") | html %]</p>
                                    <p class="Warning Hidden">[% Translate("Az érték megváltoztatása kézi módosításokat fog igényelni a rendszeren.") | html %]</p>
                                </div>
                                <div class="Clear"></div>

                                <label class="Mandatory" for="Label"><span class="Marker">*</span> [% Translate("Címke") | html %]:</label>
                                <div class="Field">
                                    <input id="Label" class="W50pc [% Data.LabelServerError | html %] Validate_Required" type="text" maxlength="200" value="[% Data.Label | html %]" name="Label"/>
                                    <div id="LabelError" class="TooltipErrorMessage"><p>[% Translate("Ez a mező kötelező.") | html %]</p></div>
                                    <div id="LabelServerError" class="TooltipErrorMessage"><p>[% Translate(Data.LabelServerErrorMessage) | html %]</p></div>
                                    <p class="FieldExplanation">[% Translate("Ez azokon a képernyőkön megjelenítendő név, ahol a mező aktív.") | html %]</p>
                                </div>
                                <div class="Clear"></div>

                                <label class="Mandatory" for="FieldOrder"><span class="Marker">*</span> [% Translate("Mezősorrend") | html %]:</label>
                                <div class="Field">
                                    [% Data.DynamicFieldOrderSrtg %]
                                    <div id="FieldOrderError" class="TooltipErrorMessage"><p>[% Translate("Ez a mező kötelező, és csak számot tartalmazhat.") | html %]</p></div>
                                    <div id="FieldOrderServerError" class="TooltipErrorMessage"><p>[% Translate(Data.FieldOrderServerErrorMessage) | html %]</p></div>
                                    <p class="FieldExplanation">[% Translate("Ez az a sorrend, amelyben ez a mező meg fog jelenni a képernyőkön, ahol aktív.") | html %]</p>
                                </div>
                                <div class="Clear"></div>
                            </fieldset>
                        </div>
                        <div class="Size1of2">
                            <fieldset class="TableLike">
                                <label for="ValidID">[% Translate("Érvényesség") | html %]:</label>
                                <div class="Field">
                                    [% Data.ValidityStrg %]
                                </div>
                                <div class="Clear"></div>

                                <div class="SpacingTop"></div>
                                <label for="FieldTypeName">[% Translate("Mezőtípus") | html %]:</label>
                                <div class="Field">
                                    <input id="FieldTypeName" readonly="readonly" class="W50pc" type="text" maxlength="200" value="[% Data.FieldTypeName | html %]" name="FieldTypeName"/>
                                    <div class="Clear"></div>
                                </div>

                                <div class="SpacingTop"></div>
                                <label for="ObjectTypeName">[% Translate("Objektumtípus") | html %]:</label>
                                <div class="Field">
                                    <input id="ObjectTypeName" readonly="readonly" class="W50pc" type="text" maxlength="200" value="[% Data.ObjectTypeName | html %]" name="ObjectTypeName"/>
                                    <div class="Clear"></div>
                                </div>
                            </fieldset>
                        </div>
                    </div>
                </div>
            </div>
            

Ez az első felületi elem tartalmazza a szokásos űrlapattribútumokat a dinamikus mezőkhöz. A többi dinamikus mezővel való következetességért javasolt a kód ezen részének változatlanul hagyása.

            <div class="WidgetSimple">
                <div class="Header">
                    <h2>[% Translate(Data.FieldTypeName) | html %] [% Translate("Mezőbeállítások") | html %]</h2>
                </div>
                <div class="Content">
                    <fieldset class="TableLike">

                        <label for="DefaultValue">[% Translate("Alapértelmezett érték") | html %]:</label>
                        <div class="Field">
                            <input id="DefaultValue" class="W50pc" type="text" maxlength="200" value="[% Data.DefaultValue | html %]" name="DefaultValue"/>
                            <p class="FieldExplanation">[% Translate("Ez az alapértelmezett érték ehhez a mezőhöz.") | html %]</p>
                        </div>
                        <div class="Clear"></div>

                        <label for="ShowValue">[% Translate("Érték megjelenítése") | html %]:</label>
                        <div class="Field">
                            [% Data.ShowValueStrg %]
                            <p class="FieldExplanation">
                                [% Translate("A mezőérték felfedéséhez a nem szerkesztői képernyőkön (például jegynagyítás képernyő)") | html %]
                            </p>
                        </div>
                        <div class="Clear"></div>

                        <label for="ValueMask">[% Translate("Rejtett értékmaszk") | html %]:</label>
                        <div class="Field">
                            <input id="ValueMask" class="W50pc" type="text" maxlength="200" value="[% Data.ValueMask | html %]" name="ValueMask"/>
                            <p class="FieldExplanation">
                                [% Translate("Ez az alternatív érték annak megjelenítéséhez, ha az Érték megjelenítése „Nem” értékre van állítva (Alapértelmezett: **** ).") | html %]
                            </p>
                        </div>
                        <div class="Clear"></div>

                    </fieldset>
                </div>
            </div>
            

A második felületi elem a dinamikus mezőre jellemző űrlapattribútumokkal rendelkezik. Ez az a hely, ahol az új attribútumok beállíthatók, és használhatnak JavaScript és AJAX technológiákat, hogy egyszerűbbé és barátságosabbá tegyék a végfelhasználó számára.

            <fieldset class="TableLike">
                <div class="Field SpacingTop">
                    <button type="submit" class="Primary" value="[% Translate("Save") | html %]">[% Translate("Mentés") | html %]</button>
                    [% Translate("vagy") | html %]
                    <a href="[% Env("Baselink") %]Action=AdminDynamicField">[% Translate("Mégse") | html %]</a>
                </div>
                <div class="Clear"></div>
            </fieldset>
        </form>
    </div>
</div>
[% WRAPPER JSOnDocumentComplete %]
<script type="text/javascript">//<![CDATA[
$('.ShowWarning').bind('change keyup', function (Event) {
    $('p.Warning').removeClass('Hidden');
});

Core.Agent.Admin.DynamicField.ValidationInit();
//]]></script>
[% END %]
            

A fájl utolsó része tartalmazza a „Mentés” gombot és a „Mégse” hivatkozást, valamint az egyéb szükséges JavaScript kódot.

Dinamikus mező illesztőprogram példa

Az illesztőprogram maga a dinamikus mező. Számos olyan függvényt tartalmaz, amelyet széles körben használnak az OTRS keretrendszerben. Egy illesztőprogram örökölhet néhány függvényt az alaposztályokból, például a TextArea illesztőprogram a Base.pm és a BaseText.pm fájlokból örökli a függvények legnagyobb részét, és csak azokat a függvényeket valósítja meg, amelyek eltérő logikát vagy eredményeket igényelnek. A jelölőnégyzet mező illesztőprogram csak a Base.pm fájlból örököl, mivel az összes többi függvény nagyon eltérő bármely más alap illesztőprogramtól.

Megjegyzés

Nézze meg a /Kernel/System/DynmicField/Backend.pm modul Perl On-line Dokumentációját (POD) az összes attribútum listája és a lehetséges visszatérési adatok megismeréséhez az egyes függvényeknél.

Kódpélda:

Ebben a szakaszban a jelszó dinamikus mező illesztőprogram van bemutatva és elmagyarázva. Ez az illesztőprogram örököl néhány függvényt a Base.pm és a BaseText.pm fájlokból, és csak azokat a függvényeket valósítja meg, amelyek eltérő eredményeket igényelnek.

# --
# Kernel/System/DynamicField/Driver/Password.pm - Driver for DynamicField Password backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::DynamicField::Driver::Password;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(:all);
use Kernel::System::DynamicFieldValue;

use base qw(Kernel::System::DynamicField::Driver::BaseText);

our @ObjectDependencies = (
    'Kernel::Config',
    'Kernel::System::DynamicFieldValue',
    'Kernel::System::Main',
);
            

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva. Figyelje meg, hogy a BaseText osztályt használják alaposztályként.

sub new {
    my ( $Type, %Param ) = @_;

    # új kivonat lefoglalása az objektumhoz
    my $Self = {};
    bless( $Self, $Type );

    # mezőviselkedések beállítása
    $Self->{Behaviors} = {
        'IsACLReducible'               => 0,
        'IsNotificationEventCondition' => 1,
        'IsSortable'                   => 0,
        'IsFiltrable'                  => 0,
        'IsStatsCondition'             => 1,
        'IsCustomerInterfaceCapable'   => 1,
    };

    # a dinamikus mező háttérprogram egyéni kiterjesztéseinek lekérése
    my $DynamicFieldDriverExtensions
        = $Kernel::OM->Get('Kernel::Config')->Get('DynamicFields::Extension::Driver::Password');

    EXTENSION:
    for my $ExtensionKey ( sort keys %{$DynamicFieldDriverExtensions} ) {

        # érvénytelen kiterjesztések kihagyása
        next EXTENSION if !IsHashRefWithData( $DynamicFieldDriverExtensions->{$ExtensionKey} );

        # egy kiterjesztés beállítás gyors elérésének létrehozása
        my $Extension = $DynamicFieldDriverExtensions->{$ExtensionKey};

        # annak ellenőrzése, hogy a kiterjesztésnek van-e új modulja
        if ( $Extension->{Module} ) {

            # annak ellenőrzése, hogy a modul betölthető-e
            if (
                !$Kernel::OM->Get('Kernel::System::Main')->RequireBaseClass( $Extension->{Module} )
                )
            {
                die "Nem lehet betölteni a dinamikus mezők háttérprogram modulját:"
                    . " $Extension->{Module}! $@";
            }
        }

        # annak ellenőrzése, hogy a kiterjesztés tartalmaz-e további viselkedéseket
        if ( IsHashRefWithData( $Extension->{Behaviors} ) ) {

            %{ $Self->{Behaviors} } = (
                %{ $Self->{Behaviors} },
                %{ $Extension->{Behaviors} }
            );
        }
    }

    return $Self;
}
            

A new konstruktor hozza létre az osztály új példányát. A kódolási irányelvek szerint más osztályoknak azon objektumait kell a new konstruktorban létrehozni, amelyek ebben a modulban szükségesek.

Fontos a viselkedéseket helyesen meghatározni, mivel a mező lehet használható vagy lehet nem használható bizonyos képernyőkön. Azokat a függvényeket esetleg nem szükséges megvalósítani, amelyek olyan viselkedésektől függenek, amelyek nem aktívak ennél a bizonyos mezőnél.

Megjegyzés

Az illesztőprogramokat kizárólag a BackendObject hozza létre, és nem közvetlenül bármely egyéb modulból.

sub EditFieldRender {
    my ( $Self, %Param ) = @_;

    # beállítások átvétele a mezőbeállításokból
    my $FieldConfig = $Param{DynamicFieldConfig}->{Config};
    my $FieldName   = 'DynamicField_' . $Param{DynamicFieldConfig}->{Name};
    my $FieldLabel  = $Param{DynamicFieldConfig}->{Label};

    my $Value = '';

    # a mezőérték beállítása vagy alapértelmezett
    if ( $Param{UseDefaultValue} ) {
        $Value = ( defined $FieldConfig->{DefaultValue} ? $FieldConfig->{DefaultValue} : '' );
    }
    $Value = $Param{Value} if defined $Param{Value};

    # a dinamikus mező értékének kibontása a webkérésből
    my $FieldValue = $Self->EditFieldValueGet(
        %Param,
    );

    # értékek beállítása a paraméterobjektumból, ha létezik
    if ( defined $FieldValue ) {
        $Value = $FieldValue;
    }

    # osztály ellenőrzése és beállítása, ha szükséges
    my $FieldClass = 'DynamicFieldText W50pc';
    if ( defined $Param{Class} && $Param{Class} ne '' ) {
        $FieldClass .= ' ' . $Param{Class};
    }

    # mező beállítása kötelezőként
    $FieldClass .= ' Validate_Required' if $Param{Mandatory};

    # hiba CSS osztály beállítása
    $FieldClass .= ' ServerError' if $Param{ServerError};

    my $HTMLString = <<"EOF";
<input type="password" class="$FieldClass" id="$FieldName" name="$FieldName" title="$FieldLabel" value="$Value" />
EOF

    if ( $Param{Mandatory} ) {
        my $DivID = $FieldName . 'Error';

        # kliensoldali ellenőrzéshez
        $HTMLString .= <<"EOF";
    <div id="$DivID" class="TooltipErrorMessage">
        <p>
            \$Text{"Ez a mező kötelező."}
        </p>
    </div>
EOF
    }

    if ( $Param{ServerError} ) {

        my $ErrorMessage = $Param{ErrorMessage} || 'Ez a mező kötelező.';
        my $DivID = $FieldName . 'ServerError';

        # kiszolgálóoldali ellenőrzéshez
        $HTMLString .= <<"EOF";
    <div id="$DivID" class="TooltipErrorMessage">
        <p>
            \$Text{"$ErrorMessage"}
        </p>
    </div>
EOF
    }

    # az EditLabelRender meghívása a közös illesztőprogramon
    my $LabelString = $Self->EditLabelRender(
        %Param,
        DynamicFieldConfig => $Param{DynamicFieldConfig},
        Mandatory          => $Param{Mandatory} || '0',
        FieldName          => $FieldName,
    );

    my $Data = {
        Field => $HTMLString,
        Label => $LabelString,
    };

    return $Data;
}
            

Ez a függvény felelős a mező és annak címkéje HTML ábrázolásának létrehozásáért, és olyan szerkesztő képernyőkön használják, mint például az AgentTicketPhone, AgentTicketNote, stb.

sub DisplayValueRender {
    my ( $Self, %Param ) = @_;

    # a HTMLOutput beállítása alapértelmezettként, ha nincs megadva
    if ( !defined $Param{HTMLOutput} ) {
        $Param{HTMLOutput} = 1;
    }

    my $Value;
    my $Title;

    # annak ellenőrzése, hogy a mező be van-e állítva a jelszó megjelenítéséhez vagy sem
    if (
        defined $Param{DynamicFieldConfig}->{Config}->{ShowValue}
        && $Param{DynamicFieldConfig}->{Config}->{ShowValue} eq 'Yes'
        )
    {

        # a nyers Title és Value szövegek lekérése a mezőértékből
        $Value = defined $Param{Value} ? $Param{Value} : '';
        $Title = $Value;
    }
    else {

        # a maszk megjelenítése az érték helyett
        $Value = $Param{DynamicFieldConfig}->{Config}->{ValueMask} || '';
        $Title = 'A mező értéke rejtve van.'
    }

    # HTMLOutput átalakítások
    if ( $Param{HTMLOutput} ) {
        $Value = $Param{LayoutObject}->Ascii2Html(
            Text => $Value,
            Max => $Param{ValueMaxChars} || '',
        );

        $Title = $Param{LayoutObject}->Ascii2Html(
            Text => $Title,
            Max => $Param{TitleMaxChars} || '',
        );
    }
    else {
        if ( $Param{ValueMaxChars} && length($Value) > $Param{ValueMaxChars} ) {
            $Value = substr( $Value, 0, $Param{ValueMaxChars} ) . '...';
        }
        if ( $Param{TitleMaxChars} && length($Title) > $Param{TitleMaxChars} ) {
            $Title = substr( $Title, 0, $Param{TitleMaxChars} ) . '...';
        }
    }

    # visszatérési szerkezet létrehozása
    my $Data = {
        Value => $Value,
        Title => $Title,
    };

    return $Data;
}
            

A DisplayValueRender() függvény egyszerű szövegként adja vissza a mező értékét és annak feliratát (mindkettő lefordítható). Ennél a bizonyos példánál azt ellenőrizzük, hogy a jelszót meg kell-e mutatni, vagy egy beállítási paraméter által előre meghatározott maszkot kell-e megjeleníteni a dinamikus mezőben.

sub ReadableValueRender {
    my ( $Self, %Param ) = @_;

    my $Value;
    my $Title;

    # annak ellenőrzése, hogy a mező be van-e állítva a jelszó megjelenítéséhez vagy sem
    if (
        defined $Param{DynamicFieldConfig}->{Config}->{ShowValue}
        && $Param{DynamicFieldConfig}->{Config}->{ShowValue} eq 'Yes'
        )
    {

        # a nyers Title és Value szövegek lekérése a mezőértékből
        $Value = $Param{Value} // '';
        $Title = $Value;
    }
    else {

        # a maszk megjelenítése az érték helyett
        $Value = $Param{DynamicFieldConfig}->{Config}->{ValueMask} || '';
        $Title = 'A mező értéke rejtve van.'
    }

    # szövegek levágása, ha szükséges
    if ( $Param{ValueMaxChars} && length($Value) > $Param{ValueMaxChars} ) {
        $Value = substr( $Value, 0, $Param{ValueMaxChars} ) . '...';
    }
    if ( $Param{TitleMaxChars} && length($Title) > $Param{TitleMaxChars} ) {
        $Title = substr( $Title, 0, $Param{TitleMaxChars} ) . '...';
    }

    # visszatérési szerkezet létrehozása
    my $Data = {
        Value => $Value,
        Title => $Title,
    };

    return $Data;
}
            

Ez a függvény hasonló a DisplayValueRender() függvényhez, de olyan helyeken használják, ahol nincs LayoutObject.

Egyéb függvények:

A következők olyan egyéb függvények, amelyek talán szükségesek lehetnek, ha egy új dinamikus mező nem örököl más osztályokból. Ezen függvények teljes kódjának megtekintéséhez nézzen bele közvetlenül a Kernel/System/DynamicField/Driver/Base.pm és a Kernel/System/DynamicField/Driver/BaseText.pm fájlokba.

sub ValueGet { ... }
            

Ez a függvény lekéri az értéket a mezőből egy adott objektumnál. Ebben az esetben az első szövegértéket adjuk vissza, mivel a mező egyszerre csak egy szövegértéket tárol.

sub ValueSet { ... }
            

A ValueSet() függvényt egy dinamikus mező érték tárolásához használják. Ebben az esetben a mező csak egy szöveg típusú értéket tárol. Más mezők tárolhatnak egynél több értéket is a ValueText, a ValueDateTime vagy a ValueInt formátumnál.

sub ValueDelete { ... }
            

Ezt a függvényt egy mező értékének törléséhez használják, amely egy bizonyos objektumazonosítóhoz van csatolva. Például ha egy objektum példánynak törlésére készülnek, akkor nincs oka a mezőérték tárolásának az adatbázisban annál a bizonyos objektumpéldánynál.

sub AllValuesDelete { ... }
            

Az AllValuesDelete() függvényt az összes érték törléséhez használják egy bizonyos dinamikus mezőből. Ez a függvény nagyon hasznos, amikor egy dinamikus mező törlésre fog kerülni.

sub ValueValidate { ... }
            

A ValueValidate() függvényt annak ellenőrzéséhez használják, hogy az érték megegyezik-e a típusának.

sub SearchSQLGet { ... }
            

Ezt a függvényt a TicketSearch alapmodul használja egy jegy kereséséhez szükséges belső lekérdezés felépítéséhez, ezt a mezőt alapul véve keresési paraméterként.

sub SearchSQLOrderFieldGet { ... }
            

A SearchSQLOrderFieldGet szintén egy segítő a TicketSearch modulhoz. A $Param{TableAlias} paramétert meg kell tartani, és a value_text lecserélhető a value_date vagy a value_int paraméterrel a mezőtől függően.

sub EditFieldValueGet { ... }
            

Az EditFieldValueGet() egy olyan függvény, amelyet az OTRS szerkesztő képernyőin használnak, és a célja a mező értékének lekérése vagy egy sablonból (mint például az általános ügyintéző profilból), vagy egy webkérésből. Ez a függvény megkapja a webkérést a $Param{ParamObject} paraméterben, amely az előtétprogram-modul vagy a képernyő ParamObject objektumának egy másolata.

Két visszatérési formátum létezik ennél a függvénynél. A normál, amely egyszerűen a nyers érték, vagy egy szerkezet, amely a mezőnév => mezőérték páros. Például egy dátum dinamikus mező normális esetben a dátumot szövegként adja vissza, és ha egy szerkezetet kell visszaadnia, akkor a kivonatban egy párost ad vissza a dátum minden egyes részéhez.

Ha az eredménynek egy szerkezetnek kell lennie, akkor normális esetben ezt arra használják, hogy az értékét egy sablonban tárolja, mint például egy általános ügyintéző profilban. Például egy dátummező számos HTML összetevőt használ a mező felépítéséhez, mint például a „használt” jelölőnégyzetet és kiválasztókat az évhez, hónaphoz, naphoz, stb.

sub EditFieldValueValidate { ... }
            

Ennek a függvénynek biztosítania kell legalább egy metódust az ellenőrzéshez, ha a mező üres, és hibát kell visszaadnia, ha a mező üres és kötelező, de végrehajthat további ellenőrzéseket is a másfajta mezőknél, mint például ha a kiválasztott lehetőség érvényes, vagy ha egy dátumnak csak a múltban kell lennie, stb. Egy egyéni hibaüzenetet is biztosíthat.

sub SearchFieldRender { ... }
            

Ezt a függvényt a jegykeresés párbeszédablak használja, és hasonló a EditFieldRander() függvényhez, de normális esetben egy keresési képernyőn kisebb változtatásokat kell elvégezni az összes mezőnél. Például ebben az esetben egy HTML szöveges beviteli mező használunk egy jelszóbeviteli mező helyett. Más mezőkben (például legördülő mező) többválasztósként jelenik meg azért, hogy egyszerre több érték keresését tegye lehetővé a felhasználónak.

sub SearchFieldValueGet { ... }
            

Nagyon hasonló az EditFieldValueGet() függvényhez, de eltérő név előtagot használ a keresési párbeszédablak képernyőhöz átírva.

sub SearchFieldParameterBuild { ... }
            

A SearchFieldParameterBuild() függvényt is a jegykeresés párbeszédablak használja a helyes operátor és érték beállításához, hogy elvégezze a keresést ezen a mezőn. Azt is visszaadja, hogy az értéket hogyan kell megjeleníteni a használt keresési attribútumokban a találatok oldalon.

sub StatsFieldParameterBuild { ... }
            

Ezt a függvényt a statisztikák moduljai használják. Tartalmazza a mező meghatározást a statisztikák formátumában. A rögzített értékekkel rendelkező mezőknél tartalmazza az összes lehetséges értéket is, és ha azok lefordíthatók, akkor nézze meg a BaseSelect illesztőprogram kódját példaként arra, hogy azokat hogyan kell megvalósítani.

sub StatsSearchFieldParameterBuild { ... }
            

A StatsSearchFieldParameterBuild() nagyon hasonló a SearchFieldParameterBuild() függvényhez. A különbség az, hogy a SearchFieldParameterBuild() a keresési profilból kapja meg az értéket, és ez pedig közvetlenül a paramétereiből kapja meg az értéket.

Ezt a függvényt a statisztikák modul használja.

sub TemplateValueTypeGet { ... }
            

A TemplateValueTypeGet() függvényt annak megismeréséhez használják, hogy a dinamikus mező értékei hogyan vannak eltárolva egy olyan profilnál, amelyet le kell kérni (SCALAR vagy ARRAY formában), és meghatározza a mező helyes nevét is a profilban.

sub RandomValueSet { ... }
            

Ezt a függvényt az otrs.FillDB.pl parancsfájl használja, hogy feltöltse az adatbázist néhány teszt és véletlenszerű adattal. A függvény által beszúrt érték nem igazán fontos. Az egyetlen megkötés az, hogy az értéknek kompatibilisnek kell lennie a mezőérték típusával.

sub ObjectMatch { ... }
            

Az értesítési modulok használják. Ez a függvény 1-et ad vissza, ha a mező jelen van a $Param{ObjectAttributes} paraméterben, és ha megegyezik a megadott értékkel.

Egy dinamikus mező funkcionalitás kiterjesztés létrehozása

Ezen folyamat bemutatásához a Foo függvénynél egy új dinamikus mező funkcionalitás kiterjesztés lesz hozzáadva a háttérprogram objektumhoz, valamint a szövegmező illesztőprogramba.

A kiterjesztés létrehozásához három fájlt fogunk létrehozni: egy beállítófájlt (XML) a modulok regisztrálásához, egy háttérprogram kiterjesztést (Perl) az új függvény meghatározásához, és egy szövegmező illesztőprogram kiterjesztést (Perl), amely megvalósítja az új függvényt a szövegmezőknél.

Fájlszerkezet:

$HOME (például /opt/otrs/)
|
...
|--/Kernel/
|   |--/Config/
|   |   |--/Files/
|   |   |   |DynamicFieldFooExtension.xml
...
|   |--/System/
|   |   |--/DynamicField/
|   |   |   FooExtensionBackend.pm
|   |   |   |--/Driver/
|   |   |   |   |FooExtensionText.pm
...
        
Dinamikus mező Foo kiterjesztés fájlok
Dinamikus mező kiterjesztés beállítófájl példa

A beállítófájlokat használják a kiterjesztések regisztrálásához a háttérprogramnál és az illesztőprogramoknál, valamint az egyes illesztőprogramok új viselkedéseihez.

Megjegyzés

Ha egy illesztőprogramot kiterjesztenek egy új függvénnyel, akkor a háttérprogramnak is szüksége lesz egy kiterjesztésre ahhoz a függvényhez.

Kódpélda:

Ebben a szakaszban a Foo kiterjesztéshez egy beállítófájl van megjelenítve és elmagyarázva.

<?xml version="1.0" encoding="utf-8"?>
<otrs_config version="1.0" init="Application">
            

Ez a normál fejléc egy beállítófájlhoz.

    <ConfigItem Name="DynamicFields::Extension::Backend###100-Foo" Required="0" Valid="1">
        <Description Translatable="1">Dynamic Fields Extension.</Description>
        <Group>DynamicFieldFooExtension</Group>
        <SubGroup>DynamicFields::Extension::Registration</SubGroup>
        <Setting>
            <Hash>
                <Item Key="Module">Kernel::System::DynamicField::FooExtensionBackend</Item>
            </Hash>
        </Setting>
    </ConfigItem>
            

Ez a beállítás regisztrálja a kiterjeszt a Backend objektumban. A modul alaposztályként lesz betöltve a Backend objektumból.

    <ConfigItem Name="DynamicFields::Extension::Driver::Text###100-Foo" Required="0" Valid="1">
        <Description Translatable="1">Dynamic Fields Extension.</Description>
        <Group>DynamicFieldFooExtension</Group>
        <SubGroup>DynamicFields::Extension::Registration</SubGroup>
        <Setting>
            <Hash>
                <Item Key="Module">Kernel::System::DynamicField::Driver::FooExtensionText</Item>
                <Item Key="Behaviors">
                    <Hash>
                        <Item Key="Foo">1</Item>
                    </Hash>
                </Item>
            </Hash>
        </Setting>
    </ConfigItem>
            

Ez egy kiterjesztés regisztrációja a Text dinamikus mező illesztőprogramban. A modul alaposztályként lesz betöltve az illesztőprogramban. Figyeljen arra is, hogy új viselkedések is megadhatók. Ezek a kiterjesztett viselkedések lesznek hozzáadva azokhoz a viselkedésekhez, amelyekkel az illesztőprogram eredetileg rendelkezik, ebből adódóan a HasBehavior() hívásával azt ellenőrizve, hogy ezeknél az új viselkedéseknél teljesen átlátszó legyen.

</otrs_config>
            

Egy beállítófájl szabványos lezárása.

Dinamikus mező háttérprogram kiterjesztés példa

A háttérprogram kiterjesztések átláthatóan lesznek betöltve magába a háttérprogramba egy alaposztályként. A háttérprogramból az összes meghatározott objektum és tulajdonság elérhető lesz a kiterjesztésben.

Megjegyzés

A háttérprogram kiterjesztésben meghatározott összes új függvényt meg kell valósítani egy illesztőprogram kiterjesztésben.

Kódpélda:

Ebben a szakaszban a háttérprogramhoz készített Foo kiterjesztés van megjelenítve és elmagyarázva. A kiterjesztés csak a Foo() függvényt határozza meg.

# --
# Kernel/System/DynamicField/FooExtensionBackend.pm - Extension for DynamicField backend
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::DynamicField::FooExtensionBackend;

use strict;
use warnings;

use Kernel::System::VariableCheck qw(:all);

=head1 NAME

Kernel::System::DynamicField::FooExtensionBackend

=head1 SYNOPSIS

DynamicFields Extension for Backend

=head1 PUBLIC INTERFACE

=over 4

=cut
            

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva.

=item Foo()

Tesztelő függvény: 1-et ad vissza, ha a függvény elérhető egy dinamikus mező illesztőprogramnál.

    my $Success = $BackendObject->Foo(
        DynamicFieldConfig   => $DynamicFieldConfig,      # a dinamikus mező teljes beállítása
    );

Returns:
    $Success = 1;       # vagy undef

=cut

sub Foo {
    my ( $Self, %Param ) = @_;

    # a szükséges dolgok ellenőrzése
    for my $Needed (qw(DynamicFieldConfig)) {
        if ( !$Param{$Needed} ) {
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'error',
                Message  => "Szükséges: $Needed!",
            );

            return;
        }
    }

    # a DynamicFieldConfig ellenőrzése (általánosan)
    if ( !IsHashRefWithData( $Param{DynamicFieldConfig} ) ) {
        $Kernel::OM->Get('Kernel::System::Log')->Log(
            Priority => 'error',
            Message  => "A mező beállítása érvénytelen",
        );

        return;
    }

    # a DynamicFieldConfig ellenőrzése (belsőleg)
    for my $Needed (qw(ID FieldType ObjectType)) {
        if ( !$Param{DynamicFieldConfig}->{$Needed} ) {
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'error',
                Message  => "$Needed szükséges ebben: DynamicFieldConfig!",
            );

            return;
        }
    }

    # a dinamikus mezőre jellemző háttérprogram beállítása
    my $DynamicFieldBackend = 'DynamicField' . $Param{DynamicFieldConfig}->{FieldType} . 'Object';

    if ( !$Self->{$DynamicFieldBackend} ) {
        $Kernel::OM->Get('Kernel::System::Log')->Log(
            Priority => 'error',
            Message  => "A háttérprogram érvénytelen: $Param{DynamicFieldConfig}->{FieldType}!",
        );

        return;
    }

    # annak ellenőrzése, hogy a függvény elérhető-e
    return if !$Self->{$DynamicFieldBackend}->can('Foo');

    # a HasBehavior meghívása az adott háttérprogramnál
    return $Self->{$DynamicFieldBackend}->Foo(%Param);
}
            

A Foo() függvényt kizárólag tesztelési célokra használják. Először leellenőrzi a dinamikus mező beállításait, majd azt ellenőrzi, hogy a dinamikus mező illesztőprogram (típus) létezik-e, és betöltésre került-e. Annak megakadályozásához, hogy egy olyan illesztőprogramnál történjen függvényhívás, ahol nincs meghatározva, először azt ellenőrzi, hogy az illesztőprogram képes-e végrehajtani a függvényt, majd végrehajtja a függvényt az illesztőprogramban az összes paramétert átadva.

Megjegyzés

Lehetséges annak a lépésnek a kihagyása is, amely azt próbálja, hogy az illesztőprogram képes-e végrehajtani a függvényt. Ennek elvégzéséhez szükséges egy mechanizmus megvalósítása az előtétprogram modulban egy különleges viselkedés megköveteléséhez a dinamikus mezőnél, és csak azután hívja meg a függvényt a háttérprogram objektumban.

Dinamikus mező illesztőprogram kiterjesztés példa

Az illesztőprogram kiterjesztések átláthatóan lesznek betöltve magába az illesztőprogramba egy alaposztályként. Az illesztőprogramból az összes meghatározott objektum és tulajdonság elérhető lesz a kiterjesztésben.

Megjegyzés

Az illesztőprogram kiterjesztésben megvalósított összes új függvényt meg kell határozni egy háttérprogram kiterjesztésben, mivel minden függvény a háttérprogram objektumból kerül meghívásra.

Kódpélda:

Ebben a szakaszban a szövegmező illesztőprogramhoz készített Foo kiterjesztés van megjelenítve és elmagyarázva. A kiterjesztés csak a Foo() függvényt valósítja meg.

# --
# Kernel/System/DynamicField/Driver/FooExtensionText.pm - Extension for DynamicField Text Driver
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::DynamicField::Driver::FooExtensionText;

use strict;
use warnings;

=head1 NAME

Kernel::System::DynamicField::Driver::FooExtensionText

=head1 SYNOPSIS

DynamicFields Text Driver Extension

=head1 PUBLIC INTERFACE

This module extends the public interface of L<Kernel::System::DynamicField::Backend>.
Please look there for a detailed reference of the functions.

=over 4

=cut
            

Ez egy gyakori fejléc, amely megtalálható a szokásos OTRS modulokban. Az osztály/csomag neve a package kulcsszón keresztül van deklarálva.

sub Foo {
    my ( $Self, %Param ) = @_;
    return 1;
}
            

A Foo() függvénynek nincs különleges logikája. Csak tesztelésre van, és mindig 1-et ad vissza.

E-mail kezelés

Jegy levelezési modul

A levelezési modulokat a levelezési folyamat során használják. Kétféle levelezési modul létezik: PostMasterPre (egy e-mail feldolgozása után használják) és PostMasterPost (azután használják, amikor egy e-mail feldolgozásra került, és az adatbázisban van).

Ha saját levelezési szűrőket szeretne létrehozni, akkor egyszerűen hozza létre a saját modulját. Ezek a modulok a Kernel/System/PostMaster/Filter/*.pm fájlokban találhatók. Az alapértelmezett modulokért nézze meg az adminisztrátori kézikönyvet. Mindössze két függvényre van szüksége: new() és Run().

A következőkben egy példaszerű modul található az e-mailek egyeztetéséhez és az X-OTRS fejlécek beállításához (további információkért nézze meg a doc/X-OTRS-Headers.txt fájlt).

Kernel/Config/Files/MyModule.xml:

<ConfigItem Name="PostMaster::PreFilterModule###1-Example" Required="0" Valid="1">
    <Description Translatable="1">Példamodul a bejövő üzenetek szűréséhez és manipulálásához.</Description>
    <Group>Ticket</Group>
    <SubGroup>Core::PostMaster</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::System::PostMaster::Filter::Example</Item>
            <Item Key="Match">
                <Hash>
                    <Item Key="From">noreply@</Item>
                </Hash>
            </Item>
            <Item Key="Set">
                <Hash>
                    <Item Key="X-OTRS-Ignore">yes</Item>
                </Hash>
            </Item>
        </Hash>
    </Setting>
</ConfigItem>
        

És a tényleges szűrőkód a Kernel/System/PostMaster/Filter/Example.pm fájlban:

# --
# Copyright (C) 2001-2018 OTRS AG, https://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
# --

package Kernel::System::PostMaster::Filter::Example;

use strict;
use warnings;

our @ObjectDependencies = (
    'Kernel::System::Log',
);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {};
    bless ($Self, $Type);

    $Self->{Debug} = $Param{Debug} || 0;

    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;
    # get config options
    my %Config = ();
    my %Match = ();
    my %Set = ();
    if ($Param{JobConfig} && ref($Param{JobConfig}) eq 'HASH') {
        %Config = %{$Param{JobConfig}};
        if ($Config{Match}) {
            %Match = %{$Config{Match}};
        }
        if ($Config{Set}) {
            %Set = %{$Config{Set}};
        }
        }
        # match 'Match => ???' stuff
        my $Matched = '';
        my $MatchedNot = 0;
        for (sort keys %Match) {
        if ($Param{GetParam}->{$_} && $Param{GetParam}->{$_} =~ /$Match{$_}/i) {
            $Matched = $1 || '1';
            if ($Self->{Debug} > 1) {
                $Kernel::OM->Get('Kernel::System::Log')->Log(
                    Priority => 'debug',
                    Message => "'$Param{GetParam}->{$_}' =~ /$Match{$_}/i matched!",
                );
            }
        }
        else {
            $MatchedNot = 1;
            if ($Self->{Debug} > 1) {
                $Kernel::OM->Get('Kernel::System::Log')->Log(
                    Priority => 'debug',
                    Message => "'$Param{GetParam}->{$_}' =~ /$Match{$_}/i matched NOT!",
                );
            }
        }
        }
        # should I ignore the incoming mail?
        if ($Matched && !$MatchedNot) {
        for (keys %Set) {
            if ($Set{$_} =~ /\[\*\*\*\]/i) {
                $Set{$_} = $Matched;
            }
            $Param{GetParam}->{$_} = $Set{$_};
            $Kernel::OM->Get('Kernel::System::Log')->Log(
                Priority => 'notice',
                Message => "Set param '$_' to '$Set{$_}' (Message-ID: $Param{GetParam}->{'Message-ID'}) ",
            );
        }
    }

    return 1;
}

1;
        

A következő kép az e-mail feldolgozási folyamatát mutatja be.

3.4. ábra - E-mail feldolgozási folyamat

E-mail feldolgozási folyamat