Csomagátírás

OTRS 5-ről 6-ra
Dátum- és időszámítás
A fogd és vidd többszörös feltöltés hozzáadása
Az adminisztrációs képernyők továbbfejlesztései
Kenyérmorzsák hozzáadása az adminisztrációs képernyőkhöz
Mentés és Mentés és befejezés gombok hozzáadása az adminisztrációs képernyőkhöz
Beállítófájlok költöztetése
XML beállítófájl formátum
Perl beállítófájl formátum
Megváltoztatott Perl-dokumentáció szerkezet
Továbbfejlesztések a sablonozáshoz és a JavaScript használatával végzett munkához
A JavaScript eltávolításra került a sablonokból
A sablonfájlok eltávolításra kerültek a Rich Text szerkesztőből
Fordítások a JavaScript fájlokban
Adatok átadása Perlből JavaScriptbe
HTML sablonok a JavaScripthez
Felhasználói jogosultságok ellenőrzése
Jegy API változások
TicketGet()
LinkObject események
Bejegyzés API változások
Metabejegyzés API
Bejegyzés háttérprogram API
Bejegyzéskeresési index
Rendszerbeállítás API változások
LinkObject API változások
Kommunikációs napló támogatás a további levelezési szűrőkhöz
Levelezési sor feldolgozása az egységtesztekhez
Felületi elem kezelés a jegynagyítás képernyőn
OTRS 4-ről 5-re
Átszerkesztett Kernel/Output/HTML
Elő-kimenetszűrők
IE 8 és IE 9
Általános felület API változás a „Ticket” csatlakozóban
Előnézeti függvények a dinamikus statisztikákban
Eldobott HTML nyomtatás
Továbbfejlesztett fordítási szöveg kinyerés
OTRS 3.3-ról 4-re
Új objektumkezelés
Eltávolított CacheInternalObject
Áthelyezett ütemező háttérprogram fájlok
Kódszakaszok frissítése az SOPM fájlokban
Új sablonmotor
Új FontAwesome verzió
Egységtesztek
Egyéni jegy előzmény típusok

Az OTRS minden új hibajavító vagy fő verziójával át kell írnia a csomagjait, és meg kell győződnie arról, hogy azok továbbra is működnek az OTRS API-val.

OTRS 5-ről 6-ra

Ez a szakasz azokat a változtatásokat sorolja fel, amelyeket meg kell vizsgálnia, amikor átírja a csomagját az OTRS 5-ről 6-ra.

Dátum- és időszámítás

Az OTRS 6-ban egy új modul lett hozzáadva a dátum- és időszámításhoz: Kernel::System::DateTime. A Kernel::System::Time modul mostantól elavult, és többé nem szabad használni új kódoknál.

Az új Kernel::System::DateTime modul legfőbb előnye, hogy támogatja a valódi időzónákat (mint például Europe/Berlin) az órákban számított időeltolások (mint például +2) helyett. Ne feledje, hogy a régi Kernel::System::Time modult is továbbfejlesztették az időzónák támogatásához. Az időeltolások teljes mértékben eldobásra kerültek. Ez azt jelenti, hogy az összes olyan kódot, amely időeltolásokat használ a számításokhoz, át kell írni az új DateTime modul használatához. Azok a kódok, amelyek önmaguk nem foglalkoznak az időeltolásokkal, a legtöbb esetben maradhatnak érintetlenül. Mindössze arról kell meggyőződnie, hogy a Kernel::System::Time objektum létrehozásakor érvényes időzóna legyen megadva.

Itt egy példa az időeltolásos kód időzónákra történő átírásához:

# Feltételezzünk egy 0 időeltolást ennél az objektumnál.
my $TimeObject     = $Kernel::OM->Get('Kernel::System::Time');
my $SystemTime     = $TimeObject->TimeStamp2SystemTime( String => '2004-08-14 22:45:00' );
# Általában beállításon vagy paraméteren keresztül van lekérve.
my $UserTimeZone   = '+2';
my $UserSystemTime = $SystemTime + $UserTimeZone * 3600;
my $UserTimeStamp  = $TimeObject->SystemTime2TimeStamp( SystemTime => $UserSystemTime );
            

Az új Kernel::System::DateTime modult használó kód:

# Ez hallgatólagosan beállítja a beállított OTRS időzónát.
my $DateTimeObject = $Kernel::OM->Create('Kernel::System::DateTime');
# Általában beállításon vagy paraméteren keresztül van lekérve.
my $UserTimeZone   = 'Europe/Berlin';
$DateTimeObject->ToTimeZone( TimeZone => $UserTimeZone );
# Ne feledje, hogy az epoch független az időzónától, mindig az UTC-hez lesz kiszámítva.
my $SystemTime    = $DateTimeObject->ToEpoch();
my $UserTimeStamp = $DateTimeObject->ToString();
            

Ne feledje, hogy a Kernel::System::DateTime modulban lévő új Get() függvénnyel visszaadott időértékek vezető nulla nélkül lesznek a Kernel::System::Time modulban lévő SystemTime2Date() függvény által visszaadottak helyett. Az új Kernel::System::DateTime modulban a Format() függvény szövegként adja vissza a dátumot és időt a megadott formátum szerint.

A fogd és vidd többszörös feltöltés hozzáadása

Az OTRS 6-nál egy több mellékletet feltöltő funkcionalitás lett hozzáadva. Ahhoz, hogy a több melléklet feltöltését megvalósítsa az egyéb kiterjesztésekben, a melléklet rész, valamint a JSOnDocumentComplete részek eltávolítása szükséges a sablonfájlokból (AttachmentDelete és AttachmentUpload). Tartsa észben, hogy néhány esetben a JavaScript részek már kihelyezésre kerültek a Core.Agent.XXX fájlokba.

Megjegyzés

Ne feledje, hogy ez jelenleg csak olyan helyeknél alkalmazható, ahol tulajdonképpen van értelme a több fájl feltöltési lehetőségének (mint például AgentTicketPhone, AgentTicketCompose, stb.). Ez nem használható mindenféle beállítás nélkül az adminisztrátori képernyőknél.

Ahhoz, hogy az új több melléklet feltöltést tartalmazza a sablon, cserélje le a meglévő input type="file" elemet a következő kódra a .tt sablonfájlban:

<label>[% Translate("Attachments") | html %]:</label>
<div class="Field">
[% INCLUDE "FormElements/AttachmentList.tt" %]
</div>
<div class="Clear"></div>
            

Az is szükséges, hogy eltávolítsa az IsUpload változót és az összes egyéb IsUpload részt a Perl-modulból. Az olyan kódrészek nem szükségesek többé, mint a következők:

my $IsUpload = ( $ParamObject->GetParam( Param => 'AttachmentUpload' ) ? 1 : 0 );
            

Ezenkívül a melléklet megjelenítő blokkot is le kell cserélni:

$LayoutObject->Block(
    Name => 'Attachment',
    Data => $Attachment,
);
            

Cserélje le erre a kódra:

push @{ $Param{AttachmentList} }, $Attachment;
            

Ha a modul, ahová integrálni szeretné a többszörös feltöltést, támogatja a szabványos sablonokat, akkor győződjön meg arról, hogy hozzáadott-e egy szakaszt az ember által olvasható fájlméret formátumok megjelenítéséhez közvetlenül azután, hogy a kiválasztott sablon melléklete be lett töltve (nézze meg az AgentTicketPhone modult hivatkozásként):

for my $Attachment (@TicketAttachments) {
    $Attachment->{Filesize} = $LayoutObject->HumanReadableDataSize(
        Size => $Attachment->{Filesize},
    );
}
            

Mikor Selenium egységteszteket ad az átírt modulokhoz, akkor vessen egy pillantást a Selenium/Agent/MultiAttachmentUpload.t fájlra hivatkozásként.

Az adminisztrációs képernyők továbbfejlesztései

Kenyérmorzsák hozzáadása az adminisztrációs képernyőkhöz

Az OTRS 6-ban az összes adminisztrációs modulnak tartalmaznia kell egy kenyérmorzsát. A kenyérmorzsát csak a .tt sablonfájlban kell hozzáadni, és közvetlenül a h1 címsor után kell elhelyezni a fájl felső részén. Ezenkívül a címsornak meg kell kapnia az InvisibleText osztályt, hogy csak a képernyőfelolvasóknak legye láthatóvá.

<div class="MainBox ARIARoleMain LayoutFixedSidebar SidebarFirst">
    <h1 class="InvisibleText">[% Translate("Name of your module") | html %]</h1>
[% BreadcrumbPath = [
        {
            Name => Translate('Name of your module'),
        },
    ]
%]
[% INCLUDE "Breadcrumb.tt" Path = BreadcrumbPath %]
...
            

Győződjön meg arról, hogy hozzáadta-e a megfelelő kenyérmorzsát az adminisztrációs modul összes szintjéhez (például Subaction):

[% BreadcrumbPath = [
        {
            Name => Translate('Module Home Screen'),
            Link => Env("Action"),
        },
        {
            Name => Translate("Some Subaction"),
        },
    ]
%]

[% INCLUDE "Breadcrumb.tt" Path = BreadcrumbPath %]
                
Mentés és Mentés és befejezés gombok hozzáadása az adminisztrációs képernyőkhöz

Az OTRS 6-ban az adminisztrációs modulok nemcsak egy Mentés gombot tartalmaznak, hanem egy Mentés és befejezés gombot is. A Mentés gombnak ugyanazon a szerkesztőoldalon kell hagynia a felhasználót mentés után, míg a Mentés és befejezés gombnak vissza kell vinnie annak az entitásnak az áttekintőjére, amin a felhasználó jelenleg dolgozik. Nézze meg a meglévő OTRS adminisztrációs képernyőit hivatkozásként.

<div class="Field SpacingTop SaveButtons">
    <button class="Primary CallForAction" id="SubmitAndContinue" type="submit" value="[% Translate("Save") | html %]"><span>[% Translate("Save") | html %]</span></button>
    [% Translate("or") | html %]
    <button class="Primary CallForAction" id="Submit" type="submit" value="[% Translate("Save") | html %]"><span>[% Translate("Save and finish") | html %]</span></button>
    [% Translate("or") | html %]
    <a href="[% Env("Baselink") %]Action=[% Env("Action") %]"><span>[% Translate("Cancel") | html %]</span></a>
</div>
                

Beállítófájlok költöztetése

XML beállítófájl formátum

Az OTRS 6 egy új XML beállítófájl formátumot használ, és a beállítófájlok helye áthelyezésre került a Kernel/Config/Files mappából a Kernel/Config/Files/XML mappába. A meglévő XML beállítófájloknak az új formátumra és helyre történő átalakításához használhatja a következő eszközt, amely az OTRS keretrendszer része:

bin/otrs.Console.pl Dev::Tools::Migrate::ConfigXMLStructure --source-directory Kernel/Config/Files
Migrating configuration XML files...
Kernel/Config/Files/Calendar.xml -> Kernel/Config/Files/XML/Calendar.xml... Done.
Kernel/Config/Files/CloudServices.xml -> Kernel/Config/Files/XML/CloudServices.xml... Done.
Kernel/Config/Files/Daemon.xml -> Kernel/Config/Files/XML/Daemon.xml... Done.
Kernel/Config/Files/Framework.xml -> Kernel/Config/Files/XML/Framework.xml... Done.
Kernel/Config/Files/GenericInterface.xml -> Kernel/Config/Files/XML/GenericInterface.xml... Done.
Kernel/Config/Files/ProcessManagement.xml -> Kernel/Config/Files/XML/ProcessManagement.xml... Done.
Kernel/Config/Files/Ticket.xml -> Kernel/Config/Files/XML/Ticket.xml... Done.

Done.
                

Perl beállítófájl formátum

Az OTRS 6 felgyorsítja a beállítófájlok betöltését a régi beállítási formátum (1) támogatásának eldobásával, amely csak egymás utáni Perl kódot használ, és az eval által kellett futtatni, és ehelyett kényszerítve az új csomagalapú formátumot (1.1) a Perl beállítófájloknál. Az OTRS 6+ csak az ebben a formátumban lévő fájlokat tudja betölteni, ezért győződjön meg arról, hogy átalakította-e az összes egyéni fejlesztést erre (lásd Kernel/Config/Files/ZZZ*.pm például). Minden egyes Perl beállítófájlnak tartalmaznia kell egy csomagot a Load() metódussal.

Régebben a Perl beállítófájlokat néha rossz célra használták egy automatikus betöltő mechanizmusként a meglévő csomagokban lévő kód felülírásához. Ez többé nem szükséges, mivel az OTRS 6 biztosít egy dedikált Autoload mechanizmust. Nézze meg a Kernel/Autoload/Test.pm fájlt annak bemutatásához, hogy hogyan kell használni ezt a mechanizmust egy metódus hozzáadásához egy meglévő fájlba.

Megváltoztatott Perl-dokumentáció szerkezet

A Perl-fájlokban lévő POD szerkezete kis mértékben javítva lett, és alkalmazni kell az összes fájlban. A POD mostantól kényszerítve van, hogy szintaktikailag helyes legyen.

Amit korábban SYNOPSIS szakasznak hívtak, azt most DESCRIPTION névre változtatták, mivel a szinopszis jellemzően néhány népszerű kódhasználati példát biztosít, és nem magának a modulnak a leírását. Természetesen megadható további szinopszis. Itt egy példa arra, hogy hogyan:

=head1 NAME

Kernel::System::ObjectManager - Központi egyke kezelő és objektumpéldány előállító

=head1 SYNOPSIS

# Csak felső szintű parancsfájlokban!
local $Kernel::OM = Kernel::System::ObjectManager->new();

# Bárhol: egyke példány lekérése (és létrehozása, ha szükséges).
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');

# Egyke objektumok és az összes függőségük eltávolítása.
$Kernel::OM->ObjectsDiscard(
    Objects            => ['Kernel::System::Ticket', 'Kernel::System::Queue'],
);

=head1 DESCRIPTION

Az objektumkezelő egy központi hely az egyke OTRS objektumok létrehozásához
és hozzáféréséhez (a C<L</Get()>> metóduson keresztül), valamint szabályos
(nem kezelt) objektumpéldányok létrehozásához (a C<L</Create()>> metóduson
keresztül).

            

Abban az esetben, ha a DESCRIPTION nem ad hozzá semmilyen értéket a NAME szakaszban lévő sorhoz, akkor át kell írni vagy teljesen el kell távolítani.

A második fontos változtatás, hogy a függvények mostantól =head2 szakaszként vannak dokumentálva a korábban használt =item helyett.

=head2 Get()

Lekér egy egyke objektumot, és ha még nem létezik, akkor a háttérben létrehoz egyet.

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

# Második meghíváskor visszaadja ugyanazt a ConfigObject objektumot, mint ami fent van.
my $ConfigObject2 = $Kernel::OM->Get('Kernel::Config');

=cut

sub Get { ... }
            

Ezek a változtatások egy továbbfejlesztett internetes API dokumentációhoz vezetnek, amint az objektumkezelő dokumentációjában is látható az OTRS 5 és az OTRS 6 esetén.

Továbbfejlesztések a sablonozáshoz és a JavaScript használatával végzett munkához

A JavaScript eltávolításra került a sablonokból

Az OTRS 6-tal az összes JavaScript - különösen a JSOnDocumentComplete blokkokban lévők - eltávolításra kerültek a sablonfájlokból, és át lettek helyezve JavaScript fájlokba. Csak nagyon ritka feltételek esetén szükséges a JavaScript kódot a sablonfájlokon belül elhelyezni. Minden egyéb előfordulásnál tegye a JS kódot a modulra jellemző JavaScript fájlokba. Az ilyen JavaScript fájlokban lévő Init() metódus automatikusan végre lesz hajtva a fájl betöltésekor (az eseménykötések előkészítéséhez, stb.), ha regisztrálja a JavaScript fájlt az OTRS alkalmazásban. Ezt a Core.Init.RegisterNamespace(TargetNS, 'APP_MODULE'); végrehajtásával lehet elvégezni a névtér meghatározásának végén a JavaScript fájlon belül.

A sablonfájlok eltávolításra kerültek a Rich Text szerkesztőből

A sablonfájlokon belül lévő JavaScript újraírása mellett (lásd fent) a Rich Text szerkesztő (RichTextEditor.tt és CustomerRichTextEditor.tt) sablonfájljai is eltávolításra kerültek, mivel azok többé nem szükségesek.

Általában ezek a sablonfájlok voltak megtalálhatók a modulra jellemző sablonfájlokban egy blokkon belül:

[% RenderBlockStart("RichText") %]
[% InsertTemplate("RichTextEditor.tt") %]
[% RenderBlockEnd("RichText") %]
                

Erre többé nincs szükség, és eltávolítható. Ahelyett, hogy meghívná ezt a blokkot a Perl-modulból, mostantól szükség van a szükséges Rich Text paraméter beállítására ott. Ahelyett, hogy:

$LayoutObject->Block(
    Name => 'RichText',
    Data => \%Param,
);
                

mostantól ezt kell meghívnia:

$LayoutObject->SetRichTextParameters(
    Data => \%Param,
);
                

Ugyanez a szabály alkalmazható az ügyfélfelületre is. Távolítsa el a Rich Text blokkokat a CustomerRichTextEditor.tt fájlból, és inkább a következő kódot alkalmazza:

$LayoutObject->CustomerSetRichTextParameters(
    Data => \%Param,
);
                

Fordítások a JavaScript fájlokban

A lefordítható szövegek hozzáadása a JavaScript fájlokban eléggé nehéz volt az OTRS-ben. A szöveget le kellett fordítani a Perl-modulban vagy a sablonban, majd ezután kellett átküldeni a JavaScript függvénynek. Az OTRS 6-tal a szövegek lefordítása közvetlenül a JavaScript fájlokban lehetséges. Az összes egyéb kerülőmegoldást el kell távolítani, különösen a csak a sablonokban lévő, a szövegek lefordításához használt blokkokat.

Ehelyett az új Core.Language JavaScript fordítási névteret kell használni a szövegek lefordításához közvetlenül a JavaScript fájlokban:

Core.Language.Translate('The string to translate');
                

Lehetséges továbbá JavaScript változókat átadni, amelyek ki lesznek cserélve közvetlenül a szövegben:

Core.Language.Translate('The %s to %s', 'string', 'translate');
                

Minden egyes %s helykitöltő a további paraméterként átadott változóval lesz kicserélve. A paraméterek száma nincs korlátozva.

Adatok átadása Perlből JavaScriptbe

A sablonfájlok JavaScript kód nélküli eléréséhez néhány egyéb kerülőmegoldást is meg kellett tenni a megfelelő megoldáshoz. A fordítások mellett az adatok átadása a Perlből a JavaScriptbe továbbra is probléma az OTRS-ben. A kerülőmegoldás az volt, hogy egy JavaScript blokkot adtak a sablonba, amelyben a JavaScript változók meg lettek határozva és fel lettek töltve a sablon címkéivel a Perlből a sablonba átadott adatok alapján.

Az adatok Perlből JavaScriptbe történő átadásának folyamata mostantól sokkal egyszerűbb az OTRS 6-ban. Ahhoz, hogy bizonyos adatokat változóként küldjön át a Perlből a JavaScriptbe, valakinek csak egy függvényt kell meghívnia a Perl oldalon. Ezután az adatok automatikusa elérhetők lesznek a JavaScriptben.

A Perlben csak ezt kell meghívni:

$Self->{LayoutObject}->AddJSData(
    Key   => 'KeyToBeAvailableInJS',
    Value => $YourData,
);
                

A Value paraméter automatikusan át lesz alakítva JSON objektummá, és tartalmazhat összetett adatokat is.

A JavaScriptben az adatokat ezzel kaphatja meg:

Core.Config.Get('KeyToBeAvailableInJS');
            

Ez felváltja az összes kerülőmegoldást, amiket el kell távolítani egy modul OTRS 6-ra történő átírásakor, mert a sablonfájlokban lévő JavaScript mostantól csak nagyon ritka feltételek esetén engedélyezett (lást fent).

HTML sablonok a JavaScripthez

Az OTRS 6 egy új JavaScript API-t vezet be a Core.Template osztályon keresztül. Hasonló módon használhatja a JavaScript kódjában mint ahogy a TemplateToolkit modult használta a Perl kódból.

Itt egy példa a meglévő jQuery alapú kód átírásához az új sablon API-ra:

var DivID = 'MyDiv',
    DivText = 'Helló, Világ!';

$('<div />').addClass('CSSClass')
    .attr('id', DivID)
    .text(DivText)
    .appendTo('body');
                

Először győződjön meg arról, hogy létrehozott-e egy új sablonfájlt a Kernel/Output/JavaScript/Templates/Standard mappa alatt. Ehhez a következőket kell észben tartania:

  • Hozzon létre egy almappát a Modulja nevével.

  • Újrahasználhatja a meglévő almappa szerkezetet, de csak akkor, ha van értelme a komponensénél (például Agent/SajatModul/ vagy Agent/Admin/SajatModul/).

  • Használjon .html.tmpl kiterjesztést a sablonfájlnál.

  • Tömören és világosan nevezze el a sablonokat annak érdekében, hogy elkerülje a félreértéseket (például jó: Agent/SajatModul/SettingsDialog.html.tmpl, rossz: Agent/SettingsDialogTemplate.html.tmpl).

Ezután adja hozzá a HTML-t a sablonfájlhoz, meggyőződve arról, hogy helykitöltőket használ minden olyan változónál, amire szüksége lehet:

<div id="{{ DivID }}" class="CSSClass">
    {{ DivText | Translate }}
</div>
                

Majd egyszerűen jeleníttesse meg a HTML-t a Core.Template.Render metódusnak a sablon elérési útjával (kiterjesztés nélkül) és a változókat tartalmazó objektummal való meghívásával a helyettesítéshez:

var DivHTML = Core.Template.Render('Agent/MyModule/SettingsDialog', {
    DivID: 'MyDiv',
    DivText: 'Helló, Világ!'
});

$(DivHTML).appendTo('body');
                

Belsőleg a Core.Template a Nunjucks motort használja a sablonok feldolgozásához. Lényegében bármilyen érvényes Nunjucks szintaxis támogatott, nézze meg a dokumentációjukat a további információkért.

Itt van néhány tipp:

  • Használhatja a | Translate szűrőt a szövegek lefordításához az aktuális nyelvre.

  • Az összes {{ VarName }} változókimenet alapértelmezetten HTML elfedésben részesített. Ha valamilyen meglévő HTML-t szeretne kiíratni, akkor használja a | safe szűrőt az elfedés megkerüléséhez.

  • Használja az | urlencode szűrőt az URL paramétereinek kódolásához.

  • A helyettesítő objektumban lévő összetett szerkezetek is támogatottak, szóval nyugodtan átadhat tömböket vagy kivonatokat, és végiglépkedhet rajtuk közvetlenül a sablonban. Például nézze meg a {% for %} szintaxist a Nunjucks dokumentációjában.

Felhasználói jogosultságok ellenőrzése

Az OTRS 6 előtt a felhasználói jogosultságok a munkamenetben voltak eltárolva és attribútumként lettek átadva a LayoutObject objektumnak, amely viszont ezután hozzáfért a meghatározott felhasználói jogosultságokhoz, mint például if ($LayoutObject->{'UserIsGroup[admin]'}) { ... }.

Az OTRS 6-tal a jogosultságok többé nincsenek a munkamenetben eltárolva, és nem kerülnek átadásra a LayoutObject objektumnak sem. Cserélje ki a kódjában, hogy a PermissionCheck() metódust hívja meg a Kernel::System::Group modulon (ügyintézőknél) vagy a Kernel::System::CustomerGroup modulon (ügyfeleknél). Itt egy példa:

my $HasPermission = $Kernel::OM->Get('Kernel::System::Group')->PermissionCheck(
UserID    => $UserID,
GroupName => $GroupName,
Type      => 'move_into',
);
            

Jegy API változások

TicketGet()

Az OTRS 6-nál az összes kiterjesztést ellenőrizni kell, és át kell írni a $Ticket{SolutionTime} értékről $Ticket{Closed} értékre, ha a TicketGet() az Extended paraméterrel lett meghívva (nézze meg a 11872-s hibát).

Ezenkívül a ticket.create_time_unix adatbázisoszlop eltávolításra került, és hasonlóképpen a CreateTimeUnix érték is el lett távolítva a TicketGet() eredményeként kapott adatokból. Használja helyette a Created értéket (ticket.create_time adatbázisoszlop).

LinkObject események

Az OTRS 6-ban a régi, jegyekre jellemző LinkObject események el lettek dobva:

  • TicketSlaveLinkAdd

  • TicketSlaveLinkDelete

  • TicketMasterLinkDelete

Ehelyett az ezekre figyelő összes eseménykezelőt át kell írni az két új eseményre:

  • LinkObjectLinkAdd

  • LinkObjectLinkDelete

Ezek az új események mindig aktiválva lesznek, amikor egy kapcsolatot hozzáad vagy töröl a LinkObject, tekintet nélkül az objektum típusára. A Data paraméter tartalmazni fogja az összes információt, amire az eseménykezelőjének szüksége lehet a további feldolgozáshoz, például:

SourceObject

A kapcsolat forrásobjektumának neve (például Ticket).

SourceKey

A kapcsolat forrásobjektumának kulcsa (például TicketID).

TargetObject

A kapcsolat célobjektumának neve (például FAQItem).

TargetKey

A kapcsolat célobjektumának kulcsa (például FAQItemID).

Type

A kapcsolat típusa (például ParentChild).

State

A kapcsolat állapota (Valid vagy Temporary).

Ezekkel az új eseményekkel az egyéni LinkObject modulra jellemző bármely esemény megvalósításai eldobhatók, és az összes eseménykezelő átírható ezek használatára helyette. Mivel a forrás- és a célobjektumnevek magában az eseményben is meg vannak adva, magától értetődő lehet, hogy csak különleges helyzetekben legyenek futtatva.

Ahhoz, hogy az eseménykezelőt regisztrálja ezekhez az új eseményekhez, győződjön meg arról, hogy hozzáadott-e egy regisztrációt a beállításokhoz, például:

<!-- OLD STYLE -->
<ConfigItem Name="LinkObject::EventModulePost###1000-SampleModule" Required="0" Valid="1">
    <Description Translatable="1">Event handler for sample link object module.</Description>
    <Group>Framework</Group>
    <SubGroup>Core::Event::Package</SubGroup>
    <Setting>
        <Hash>
            <Item Key="Module">Kernel::System::LinkObject::Event::SampleModule</Item>
            <Item Key="Event">(LinkObjectLinkAdd|LinkObjectLinkDelete)</Item>
            <Item Key="Transaction">1</Item>
        </Hash>
    </Setting>
</ConfigItem>

<!-- NEW STYLE -->
<Setting Name="LinkObject::EventModulePost###1000-SampleModule" Required="0" Valid="1">
    <Description Translatable="1">Event handler for sample link object module.</Description>
    <Navigation>Core::Event::Package</Navigation>
    <Value>
        <Hash>
            <Item Key="Module">Kernel::System::LinkObject::Event::SampleModule</Item>
            <Item Key="Event">(LinkObjectLinkAdd|LinkObjectLinkDelete)</Item>
            <Item Key="Transaction">1</Item>
        </Hash>
    </Value>
</Setting>
                

Bejegyzés API változások

Az OTRS 6-ban változások történtek a bejegyzés API-n az új Omni Channel infrastruktúra előkészítéséhez.

Metabejegyzés API

A bejegyzés objektum mostantól olyan felső szintű bejegyzésfüggvényeket biztosít, amelyek nem vonják be a háttérprogramhoz kapcsolódó adatokat.

A következő, bejegyzésre vonatkozó metódusok át lettek helyezve a Kernel::System::Ticket::Article objektumba:

  • ArticleFlagSet()

  • ArticleFlagDelete()

  • ArticleFlagGet()

  • ArticleFlagsOfTicketGet()

  • ArticleAccountedTimeGet()

  • ArticleAccountedTimeDelete()

  • ArticleSenderTypeList()

  • ArticleSenderTypeLookup()

  • SearchStringStopWordsFind()

  • SearchStringStopWordsUsageWarningActive()

Ha hivatkozik ezen metódusok bármelyikére a Kernel::System::Ticket objektumon keresztül a kódjában, akkor váltson át a bejegyzés objektum használatára helyette. Például:

    my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article');

    my %ArticleSenderTypeList = $ArticleObject->ArticleSenderTypeList();
                

Az új ArticleList() metódust mostantól a bejegyzés objektum biztosítja, és bejegyzések felsorolásához és kereséséhez használható. Ez a metódus szűrőket és bejegyzésszámozást valósít meg, valamint a bejegyzés metaadatait csak rendezett listaként adja vissza. Például:

my @Articles = $ArticleObject->ArticleList(
    TicketID             => 123,
    CommunicationChannel => 'Email',            # elhagyható, korlátozás egy bizonyos kommunikációs csatornára
    SenderType           => 'customer',         # elhagyható, korlátozás egy bizonyos bejegyzés küldőtípusra
    IsVisibleForCustomer => 1,                  # elhagyható, korlátozás egy bizonyos láthatóságra
    OnlyFirst            => 1,                  # elhagyható, csak az első egyezést adja vissza, vagy
    OnlyLast             => 1,                  # elhagyható, csak az utolsó egyezést adja vissza
);
                

A következő, bejegyzésekre vonatkozó metódusok mindegyike el lett dobva. Ha ezek közül bármelyiket használja a kódjában, akkor értékelje ki az alternatívák lehetőségeit.

  • ArticleFirstArticle() (használja az ArticleList( OnlyFirst => 1 ) metódust helyette)

  • ArticleLastCustomerArticle() (használja az ArticleList( SenderType => 'customer', OnlyLast => 1 ) metódust vagy hasonlót)

  • ArticleCount() (használja az ArticleList() metódust helyette)

  • ArticlePage() (újraírva az AgentTicketZoom modulban)

  • ArticleTypeList()

  • ArticleTypeLookup()

  • ArticleIndex() (használja az ArticleList() metódust helyette)

  • ArticleContentIndex()

A bejegyzésadatokkal való munkához használja az új bejegyzés háttérprogram API-t. A bejegyzés megfelelő háttérprogram-objektumának lekéréséhez használja a következőt:

  • BackendForArticle(%Article)

  • BackendForChannel( ChannelName => $ChannelName )

A BackendForArticle() visszaadja a megfelelő háttérprogramot egy adott bejegyzésnél vagy az érvénytelen háttérprogramot azért, hogy mindig számíthasson egy háttérprogram-objektum példányra, amelyet használhat sorozatos hívásoknál.

my $ArticleBackendObject = $ArticleObject->BackendForArticle( TicketID => 42, ArticleID => 123 );
                

A BackendForChannel() visszaadja a megfelelő háttérprogramot egy adott kommunikációs csatornánál.

my $ArticleBackendObject = $ArticleObject->BackendForChannel( ChannelName => 'Email' );
                

Bejegyzés háttérprogram API

Az összes többi bejegyzésadat és a hozzájuk kapcsolódó metódus át lett helyezve külön háttérprogramokba. Minden egyes kommunikációs csatorna mostantól rendelkezik egy dedikált háttérprogram API-val, amely kezeli a bejegyzésadatokat és használható azok manipulálásához.

Az OTRS 6 Free néhány alapértelmezett csatornával és a megfelelő háttérprogramokkal érkezik:

  • E-mail (egyenértékű a régi email bejegyzéstípusokkal)

  • Telefon (egyenértékű a régi phone bejegyzéstípusokkal)

  • Belső (egyenértékű a régi note bejegyzéstípusokkal)

  • Csevegés (egyenértékű a régi chat bejegyzéstípusokkal)

Megjegyzés

Miközben a csevegés bejegyzés háttérprogram elérhető az OTRS 6 Free verziójában, csak akkor használható, ha a rendszer érvényes OTRS Business Solution™ telepítéssel rendelkezik.

A bejegyzés adatainak manipulálása a következő háttérprogram-metódusokon keresztül végezhető el:

  • ArticleCreate()

  • ArticleUpdate()

  • ArticleGet()

  • ArticleDelete()

Ezen metódusok mindegyikéből el lett dobva a bejegyzéstípus paraméter, amelyet a SenderType és az IsVisibleForCustomer paraméterek kombinációjával kell helyettesíteni. Ezenkívül mostantól ezen metódusok mindegyike igényli a TicketID és a UserID paramétereket.

Megjegyzés

Mivel a bejegyzés API-ban lévő változások rendszerszintűek, a régi API-t használó összes kódot át kell írni az OTRS 6-hoz. Ebbe beletartozik például az összes webszolgáltatás meghatározás, amely kihasználja ezeket a metódusokat közvetlenül az általános felületen keresztül. Ezeket újra meg kell vizsgálni és hozzá kell igazítani ahhoz, hogy az összes szükséges paramétert biztosítsák az új API-hoz a kérések közben, és kezeljék a rájuk adott válaszokat az új formátumban.

Ne feledje, hogy az ArticleGet() visszatérési kivonata megváltozott, és néhány dolog (mint például a jegyadatok) hiányozhatnak. Használja a DynamicFields => 1 és a RealNames => 1 paramétereket, hogy további információ kapjon.

Ezenkívül a melléklet adatai többé nem lesznek visszaadva, használja a következő metódusok kombinációját a bejegyzés háttérprogramokból:

  • ArticleAttachmentIndex()

  • ArticleAttachment()

Ne feledje, hogy az ArticleAttachmentIndex() paraméterei és működése is megváltozott. A régi paraméterdarabok helyett használja az új ExcludePlainText, ExcludeHTMLBody és ExcludeInline kombinációját.

Példaként itt van, hogy az összes bejegyzés- és mellékletadatot hogyan lehet lekérni ugyanabban a kivonatban:

my @Articles = $ArticleObject->ArticleList(
    TicketID => $TicketID,
);

ARTICLE:
for my $Article (@Articles) {

    # Győződjön meg arról, hogy lekérte-e a háttérprogram-objektumot ehhez a bizonyos bejegyzéshez.
    my $ArticleBackendObject = $ArticleObject->BackendForArticle( %{$Article} );

    my %ArticleData = $ArticleBackendObject->ArticleGet(
        %{$Article},
        DynamicFields => 1,
        UserID        => $UserID,
    );
    $Article = \%ArticleData;

    # Mellékletindex lekérése (mellékletek nélkül).
    my %AtmIndex = $ArticleBackendObject->ArticleAttachmentIndex(
        ArticleID => $Article->{ArticleID},
        UserID    => $UserID,
    );
    next ARTICLE if !%AtmIndex;

    my @Attachments;
    ATTACHMENT:
    for my $FileID ( sort keys %AtmIndex ) {
        my %Attachment = $ArticleBackendObject->ArticleAttachment(
            ArticleID => $Article->{ArticleID},
            FileID    => $FileID,
            UserID    => $UserID,
        );
        next ATTACHMENT if !%Attachment;

        $Attachment{FileID} = $FileID;
        $Attachment{Content} = encode_base64( $Attachment{Content} );

        push @Attachments, \%Attachment;
    }

    # Mellékletadatok felvétele a bejegyzés kivonatába.
    $Article->{Atms} = \@Attachments;
}
                

Bejegyzéskeresési index

A bejegyzésindexelés általánosabbá tételéhez a bejegyzés háttérprogramok mostantól biztosítják a bejegyzésadatok megfelelő indexeléséhez szükséges információkat. Az index hasonlóan lesz létrehozva a régi StaticDB mechanizmushoz, és egy dedikált bejegyzéskeresési táblában lesznek eltárolva.

Mivel mostantól minden egyes bejegyzés háttérprogram képes keresést biztosítani a bejegyzés mezőinek tetszőleges számán, használja a BackendSearchableFieldsGet() metódust a velük kapcsolatos információk lekéréséhez. Ezek az adatok használhatók a kérések formázásánál is a TicketSearch() metódushoz. Véletlenül néhány TicketSearch() paraméter megváltoztatta a nevét, hogy tartalmazza a bejegyzés háttérprogram információit is, például:

Régi paraméterÚj paraméter
FromMIMEBase_From
ToMIMEBase_To
CcMIMEBase_Cc
SubjectMIMEBase_Subject
BodyMIMEBase_Body
AttachmentNameMIMEBase_AttachmentName

Ezenkívül a bejegyzéskeresési indexelés mostantól aszinkron hívásban lesz végrehajtva annak érdekében, hogy kitegye az index kiszámítását egy különálló feladatba. Míg ez rendben van a produktív rendszereknél, aközben új problémákat hozhat létre bizonyos helyzetekben, például egységteszteknél. Ha kézzel hozza létre a bejegyzéseket az egységtesztben, és arra számít, hogy azonnal kereshető lesz a létrehozás után, akkor győződjön meg arról, hogy meghívta-e kézzel az új ArticleSearchIndexBuild() metódust a bejegyzésobjektumon.

Rendszerbeállítás API változások

Ne feledje, hogy az OTRS 6-ban a rendszerbeállítások API megváltozott, ezért ellenőriznie kell, hogy a metódusok léteznek-e még. Például a ConfigItemUpdate() el lett távolítva. A helyettesítéshez a következő metódusok kombinációját kell használnia:

  • SettingLock()

  • SettingUpdate()

  • ConfigurationDeploy()

Abban az esetben, ha frissíteni szeretne egy konfigurációs beállítást egy csomag CodeInstall szakasza közben, akkor használhatja a SettingsSet() metódust. Ez elvégzi a korábban említett összes lépést, és használható egyszerre több beállításnál is.

Megjegyzés

Ne használja a SettingSet() metódust magán a rendszerbeállítás grafikus felhasználói felületén.

my $Success = $SysConfigObject->SettingsSet(
    UserID   => 1,                                      # (kötelező) Felhasználó-azonosító.
    Comments => 'Üzembe állítási megjegyzés.',          # (elhagyható) Megjegyzés.
    Settings => [                                       # (kötelező) Frissítendő beállítások listája.
        {
            Name                   => 'Setting::Name',  # (kötelező)
            EffectiveValue         => 'Value',          # (elhagyható)
            IsValid                => 1,                # (elhagyható)
            UserModificationActive => 1,                # (elhagyható)
        },
        ...
    ],
);
            

LinkObject API változások

Ne feledje, hogy a LinkObject kissé módosult az OTRS 6-ban, valamint a LinkList() és a LinkKeyList() metódusok különböző eredményt adhatnak vissza, ha a Direction paramétert használják. Fontolja meg a Direction paraméter megváltoztatását.

Régi kód:

my $LinkList = $LinkObject->LinkList(
    Object    => 'Ticket',
    Key       => '321',
    Object2   => 'FAQ',
    State     => 'Valid',
    Type      => 'ParentChild',
    Direction => 'Target',
    UserID    => 1,
);
            

Új kód:

my $LinkList = $LinkObject->LinkList(
    Object    => 'Ticket',
    Key       => '321',
    Object2   => 'FAQ',
    State     => 'Valid',
    Type      => 'ParentChild',
    Direction => 'Source',
    UserID    => 1,
);
            

Kommunikációs napló támogatás a további levelezési szűrőkhöz

Az OTRS 6 e-mail kezelési továbbfejlesztésének részeként egy új naplózó mechanizmus lett hozzáadva az OTRS 6-hoz, kifejezetten a bejövő és kimenő kommunikációk használatához. Az összes levelezési szűrő fel lett javítva ezzel az új kommunikációs napló API-val, amely azt jelenti, hogy a csomagokkal érkező bármely további szűrő is kihasználhatja az új naplózási funkciót.

Ha a csomagja további levelezési szűrőket valósít meg, akkor győződjön meg arról, hogy megismerje az API használati utasításokat. Kap egy példát is azzal kapcsolatban, hogy ezt a naplózási mechanizmust hogyan kell megvalósítani, ha belenéz a Kernel::System::PostMaster::NewTicket kódjába.

Levelezési sor feldolgozása az egységtesztekhez

Az OTRS 6 e-mail kezelési továbbfejlesztésének részeként az összes e-mail mostantól aszinkron módon lesz elküldve, amely azt jelenti, hogy egy várakozási sorba lesznek elmentve a későbbi feldolgozáshoz.

Ahhoz, hogy az e-mailektől függő egységtesztek továbbra is megfelelően működjenek, az e-mail várakozási sor feldolgozásának kényszerítése szükséges.

Győződjön meg arról, hogy egy tiszta várakozási sorral indul:

                my $MailQueueObject = $Kernel::OM->Get('Kernel::System::MailQueue');
                $MailQueueObject->Delete();
            

Ha néhány esetben nem tudja teljesen kitakarítani a várakozási sort (például Selenium egységteszteknél), akkor egyszerűen törölje azokat az elemeket, amelyek a tesztek során jöttek létre:

                my $MailQueueObject = $Kernel::OM->Get('Kernel::System::MailQueue');
                my %MailQueueCurrentItems = map { $_->{ID} => $_ } @{ $MailQueueObject->List() || [] };

                my $Items = $MailQueueObject->List();
                MAIL_QUEUE_ITEM:
                for my $Item ( @{$Items} ) {
                    next MAIL_QUEUE_ITEM if $MailQueueCurrentItems{ $Item->{ID} };
                    $MailQueueObject->Delete(
                        ID => $Item->{ID},
                    );
                }
            

Dolgozza fel a várakozási sort azután a kód után, amely várhatóan elküldi az e-maileket:

                my $MailQueueObject = $Kernel::OM->Get('Kernel::System::MailQueue');
                my $QueueItems      = $MailQueueObject->List();
                for my $Item ( @{$QueueItems} ) {
                    $MailQueueObject->Send( %{$Item} );
                }
            

Vagy csak azokat dolgozza fel, amelyek a tesztek során jöttek létre:

                my $MailQueueObject = $Kernel::OM->Get('Kernel::System::MailQueue');
                my $QueueItems      = $MailQueueObject->List();
                MAIL_QUEUE_ITEM:
                for my $Item ( @{$QueueItems} ) {
                    next MAIL_QUEUE_ITEM if $MailQueueCurrentItems{ $Item->{ID} };
                    $MailQueueObject->Send( %{$Item} );
                }
            

Az esettől függően esetleg ki kell takarítania a várakozási sort a feldolgozása után vagy előtt.

Felületi elem kezelés a jegynagyítás képernyőn

A jegynagyítás képernyőn lévő felületi elemek továbbfejlesztésre kerültek, hogy általánosabb módon működjenek. Az OTRS 6-tal mostantól lehetőség van új felületi elemek hozzáadására a jegynagyítás képernyőhöz a rendszerbeállításokon keresztül. Lehetőség van beállítani a használt modult, a felületi elem helyzetét (például oldalsáv) és hogy a tartalmat szinkron módon (alapértelmezett) vagy AJAX kérésen keresztül kell betölteni.

Itt egy beállítási példa az alapértelmezett felületi elemekhez:

<Setting Name="Ticket::Frontend::AgentTicketZoom###Widgets###0100-TicketInformation" Required="0" Valid="1">
    <Description Translatable="1">AgentTicketZoom widget that displays ticket data in the side bar.</Description>
    <Navigation>Frontend::Agent::View::TicketZoom</Navigation>
    <Value>
        <Hash>
            <Item Key="Module">Kernel::Output::HTML::TicketZoom::TicketInformation</Item>
            <Item Key="Location">Sidebar</Item>
        </Hash>
    </Value>
</Setting>
<Setting Name="Ticket::Frontend::AgentTicketZoom###Widgets###0200-CustomerInformation" Required="0" Valid="1">
    <Description Translatable="1">AgentTicketZoom widget that displays customer information for the ticket in the side bar.</Description>
    <Navigation>Frontend::Agent::View::TicketZoom</Navigation>
    <Value>
        <Hash>
            <Item Key="Module">Kernel::Output::HTML::TicketZoom::CustomerInformation</Item>
            <Item Key="Location">Sidebar</Item>
            <Item Key="Async">1</Item>
        </Hash>
    </Value>
</Setting>
            

Megjegyzés

Ezzel a változtatással a felületi elem kódjában lévő sablonblokkok eltávolításra kerültek, ezért ellenőriznie kell, ha a régi felületi elem blokkokat használja néhány kimeneti szűrőben a Frontend::Template::GenerateBlockHooks funkcionalitáson keresztül, és meg kell valósítania az új módszer szerint.

OTRS 4-ről 5-re

Ez a szakasz azokat a változtatásokat sorolja fel, amelyeket meg kell vizsgálnia, amikor átírja a csomagját az OTRS 4-ről 5-re.

Átszerkesztett Kernel/Output/HTML

Az OTRS 5-ben a Kernel/Output/HTML átszerkesztésre került. Az összes Perl modul (kivéve a Layout.pm fájlt) alkönyvtárakba került áthelyezésre (minden modulréteghez egybe). A sablonfájlok (témák) is áthelyezésre kerültek a Kernel/Output/HTML/Standard könyvtárból a Kernel/Output/HTML/Templates/Standard könyvtárba. Végezze el ezeket a költöztetéseket a saját kódjában is.

Elő-kimenetszűrők

Az OTRS 5-tel többé nincs támogatás a pre kimenetszűrőkhöz. Ezek a szűrők azelőtt változtatták meg a sablon tartalmát, mielőtt az feldolgozásra került volna, és potenciálisan rossz teljesítményproblémákhoz vezethettek, ugyanis a sablonokat többé nem lehetett gyorstárazni, és minden alkalommal fel kellett dolgozni és le kellett fordítani.

Egyszerűen váltson a pre kimenetszűrőről a post kimenetszűrőre. 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 új 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.

IE 8 és IE 9

Az IE 8 és IE 9 támogatást eldobták. Eltávolíthat minden kerülőmegoldást a kódjából, amelyet ezekhez a platformokhoz készített, valamint az összes olyan régi <CSS_IE7> vagy <CSS_IE8> betöltő címkét, amely még esetleg megbújik az XML beállítófájljaiban.

Általános felület API változás a „Ticket” csatlakozóban

A TicketGet() művelet másképpen ad vissza dinamikus mező adatokat a jegyből és a bejegyzésből mint az OTRS 4-ben. Mostantól ezek tisztán el vannak választva a többi statikus jegy- és bejegyzésmezőktől - innentől kezdve csoportosítva vannak egy DynamicField nevű listába. Eszerint alakítson át minden olyan alkalmazást, amely ezt a műveletet használja.

# megváltoztatva erről:

Ticket => [
{
    TicketNumber       => '20101027000001',
    Title              => 'valamilyen cím',
    ...
    DynamicField_X     => 'x_ertek',
},
]

# erre:

Ticket => [
{
    TicketNumber       => '20101027000001',
    Title              => 'valamilyen cím',
    ...
    DynamicField => [
        {
            Name  => 'valamilyen név',
            Value => 'valamilyen érték',
        },
    ],
},
]
            

Előnézeti függvények a dinamikus statisztikákban

Az új statisztikák grafikus felhasználói felülete egy előnézetet biztosít a jelenlegi beállításhoz. Ezt meg kell valósítani a statisztikák moduljaiban, és általában hamis vagy véletlenszerű adatokat adnak vissza sebességi okokból. Így minden olyan dinamikus (mátrix) statisztikánál, amely a GetStatElement() metódust biztosítja, hozzá kell adnia egy GetStatElementPreview() metódust is, valamint minden olyan dinamikus (tábla) statisztikánál, amely a GetStatTable() metódust biztosítja, hozzá kell adnia egy GetStatTablePreview() metódust ennek megfelelően. Egyébként az új statisztikák grafikus felhasználói felületén lévő előnézet nem fog működni a saját statisztikáinál. Példamegvalósításokat találhat az alapértelmezett OTRS statisztikákban.

Eldobott HTML nyomtatás

Az OTRS 5-ig a PDF::API2 Perl modul nem volt megtalálható minden rendszeren. Ezért létezett egy tartalék HTML nyomtatási mód. Az OTRS 5-tel a modul mostantól mellékelve van, és a HTML nyomtatás eldobásra került. A $LayoutObject->PrintHeader() és a PrintFooter() többé nem érhető el. Távolítsa el a tartalék HTML nyomtatást a kódjából, és változtassa meg a PDF előállításához, ha szükséges.

Továbbfejlesztett fordítási szöveg kinyerés

Az OTRS 5-ig a lefordítható szövegeket nem lehetett kinyerni a Perl kódból és az adatbázis XML meghatározásokból. Ez mostantól lehetséges, és elavulttá tette az olyan üres sablonokat, mint például az AAA*.tt sablont. A részletekért nézze meg ezt a szakaszt.

OTRS 3.3-ról 4-re

Ez a szakasz azokat a változtatásokat sorolja fel, amelyeket meg kell vizsgálnia, amikor átírja a csomagját az OTRS 3.3-ról 4-re.

Új objektumkezelés

Az OTRS 4-ig az objektumokat mind központilag, mind helyileg létre kellett hozni, és ekkor az összes objektumot le kellett kezelni a konstruktornak átadva azokat. Az OTRS 4-es és későbbi verzióinál mostantól létezik egy ObjectManager objektum, amely központosítja az egyke objektum létrehozását és hozzáférését.

Ez mindenek előtt azt fogja igényelni, hogy változtassa meg az összes felső szintű Perl parancsfájlt (csak a .pl fájlokat!) az ObjectManager betöltéséhez és biztosításához az összes OTRS objektumnál. Példaként nézzük meg az otrs.CheckDB.pl parancsfájlt az OTRS 3.3-ból:

use strict;
use warnings;

use File::Basename;
use FindBin qw($RealBin);
use lib dirname($RealBin);
use lib dirname($RealBin) . '/Kernel/cpan-lib';
use lib dirname($RealBin) . '/Custom';

use Kernel::Config;
use Kernel::System::Encode;
use Kernel::System::Log;
use Kernel::System::Main;
use Kernel::System::DB;

# a szokásos objektumok létrehozása
my %CommonObject = ();
$CommonObject{ConfigObject} = Kernel::Config->new();
$CommonObject{EncodeObject} = Kernel::System::Encode->new(%CommonObject);
$CommonObject{LogObject}    = Kernel::System::Log->new(
    LogPrefix    => 'OTRS-otrs.CheckDB.pl',
    ConfigObject => $CommonObject{ConfigObject},
);
$CommonObject{MainObject} = Kernel::System::Main->new(%CommonObject);
$CommonObject{DBObject}   = Kernel::System::DB->new(%CommonObject);
            

Láthatjuk, hogy rengeteg kódot használnak a csomagok betöltéséhez és a gyakori objektumok létrehozásához, amelyet a parancsfájlban át kell adni a használandó OTRS objektumoknak. Az OTRS 4-gyel ez egy kicsit máshogy néz ki:

use strict;
use warnings;

use File::Basename;
use FindBin qw($RealBin);
use lib dirname($RealBin);
use lib dirname($RealBin) . '/Kernel/cpan-lib';
use lib dirname($RealBin) . '/Custom';

use Kernel::System::ObjectManager;

# a szokásos objektumok létrehozása
local $Kernel::OM = Kernel::System::ObjectManager->new(
'Kernel::System::Log' => {
    LogPrefix => 'OTRS-otrs.CheckDB.pl',
},
);

# az adatbázis-objektum lekérése
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
            

Az új kód egy kicsivel rövidebb mint a régi. Többé nem szükséges az összes csomag betöltése, elég csak az ObjectManager objektumot. Azután a $Kernel::OM->Get('Sajat::Perl::Csomag') használható az objektumok példányainak lekéréséhez, amelyeket csak egyszer kell létrehozni. A LogPrefix beállítás vezérli azokat a naplóüzeneteket, amelyeket a Kernel::System::Log ír ki, így az szintén elhagyható.

Ebből a példából kikövetkeztetheti az általános átírási irányelvet is, amikor az objektumok hozzáférése jön: többé ne tárolja azokat a $Self változóban (hacsak bizonyos okokból ez nem szükséges). Egyszerűen kérje le és használja az objektumokat igény szerint, úgymint $Kernel::OM->Get('Kernel::System::Log')->Log(...). Ennek megvan az az előnye is, hogy a Log objektumot csak akkor kell majd létrehozni, ha valamit naplózni kell. Néha hasznos lehet helyi változókat is létrehozni, ha egy objektumot többször használnak egy függvényben, mint például a fenti példában lévő $DBObject objektumot.

Nem kell sokkal többet tudnia az olyan csomagok átírásakor, amelyeknek betölthetőnek kell lenniük az ObjectManager használatával. Meg kell határozniuk azokat a modulokat, amelyeket használnak (a $Kernel::OM->Get() függvényen keresztül) ehhez hasonlóan:

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

Az @ObjectDependencies meghatározás szükséges az ObjectManager objektumhoz a helyes sorrend megtartásához az objektumok megsemmisítésekor.

Nézzük meg a Valid.pm fájlt az OTRS 3.3-ból és a 4-ből, hogy lássuk a különbséget. A régi:

package Kernel::System::Valid;

use strict;
use warnings;

use Kernel::System::CacheInternal;

...

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 EncodeObject MainObject)) {
    $Self->{$Object} = $Param{$Object} || die "Nincs $Object!";
}

$Self->{CacheInternalObject} = Kernel::System::CacheInternal->new(
    %{$Self},
    Type => 'Valid',
    TTL  => 60 * 60 * 24 * 20,
);

return $Self;
}

...

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

# gyorsítótár olvasása
my $CacheKey = 'ValidList';
my $Cache = $Self->{CacheInternalObject}->Get( Key => $CacheKey );
return %{$Cache} if $Cache;

# lista lekérése az adatbázisból
return if !$Self->{DBObject}->Prepare( SQL => 'SELECT id, name FROM valid' );

# az eredmény lekérése
my %Data;
while ( my @Row = $Self->{DBObject}->FetchrowArray() ) {
    $Data{ $Row[0] } = $Row[1];
}

# gyorsítótár beállítása
$Self->{CacheInternalObject}->Set( Key => $CacheKey, Value => \%Data );

return %Data;
}
            

Az új:

package Kernel::System::Valid;

use strict;
use warnings;

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

...

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

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

$Self->{CacheType} = 'Valid';
$Self->{CacheTTL}  = 60 * 60 * 24 * 20;

return $Self;
}

...

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

# gyorsítótár olvasása
my $CacheKey = 'ValidList';
my $Cache    = $Kernel::OM->Get('Kernel::System::Cache')->Get(
    Type => $Self->{CacheType},
    Key  => $CacheKey,
);
return %{$Cache} if $Cache;

# adatbázis-objektum lekérése
my $DBObject = $Kernel::OM->Get('Kernel::System::DB');

# lista lekérése az adatbázisból
return if !$DBObject->Prepare( SQL => 'SELECT id, name FROM valid' );

# az eredmény lekérése
my %Data;
while ( my @Row = $DBObject->FetchrowArray() ) {
    $Data{ $Row[0] } = $Row[1];
}

# gyorsítótár beállítása
$Kernel::OM->Get('Kernel::System::Cache')->Set(
    Type  => $Self->{CacheType},
    TTL   => $Self->{CacheTTL},
    Key   => $CacheKey,
    Value => \%Data
);

return %Data;
}
            

Láthatja, hogy meg vannak határozva a függőségek, és az objektumok csak igény szerint vannak lekérve. A következő szakaszban a CacheInternalObject objektumról fogunk beszélni.

Eltávolított CacheInternalObject

Mivel a Kernel::System::Cache mostantól képes a memóriában is gyorstárazni, a Kernel::System::CacheInternal eldobásra került. Nézze meg az előző példát, hogy a kódot hogyan kell átköltöztetni: a globális Cache objektumot kell használnia, és át kell adnia a Type beállítást a Get(), Set(), Delete() és CleanUp() függvények minden egyes hívásához. A TTL paraméter mostantól elhagyható, és alapértelmezetten 20 nap, így csak akkor kell megadnia a Get() függvényben, ha eltérő TTL értékre van szüksége.

Figyelem

Különösen fontos a Type paraméter hozzáadása a CleanUp() függvényhez, mivel különben nem csak a jelenlegi gyorsítótártípus, hanem a teljes gyorsítótár törölve lehet.

Áthelyezett ütemező háttérprogram fájlok

Az ütemező háttérprogram fájljai áthelyezésre kerültek a Kernel/Scheduler mappából a Kernel/System/Scheduler mappába. Ha valamilyen egyéni feladatkezelő moduljai vannak, akkor azokat is át kell helyeznie.

Kódszakaszok frissítése az SOPM fájlokban

Az SOPM fájlokban lévő kódcímkéket is frissíteni kell. Többé ne használja a $Self változót. Régebben ezt használták az olyan OTRS objektumokhoz való hozzáféréshez, mint például a MainObject. Mostantól használja az ObjectManager objektumot. Itt egy példa a régi stílusra:

<CodeInstall Type="post">

# függvénynév meghatározása
my $FunctionName = 'CodeInstall';

# a csomagnév létrehozása
my $CodeModule = 'var::packagesetup::' . $Param{Structure}->{Name}->{Content};

# a modul betöltése
if ( $Self->{MainObject}->Require($CodeModule) ) {

# új példány létrehozása
my $CodeObject = $CodeModule->new( %{$Self} );

if ($CodeObject) {

    # metódus elindítása
    if ( !$CodeObject->$FunctionName(%{$Self}) ) {
        $Self->{LogObject}->Log(
            Priority => 'error',
            Message  => "Nem sikerült meghívni a(z) $FunctionName() metódust ebben: $CodeModule.pm."
        );
    }
}

# hibakezelés
else {
    $Self->{LogObject}->Log(
        Priority => 'error',
        Message  => "Nem sikerült meghívni a new() metódust ebben: $CodeModule.pm."
    );
}
}

</CodeInstall>
            

Most ezt a következővel kell helyettesíteni:

<CodeInstall Type="post"><![CDATA[
$Kernel::OM->Get('var::packagesetup::SajatCsomag')->CodeInstall();
]]></CodeInstall>
            

Új sablonmotor

Az OTRS 4-gyel a DTL sablonmotort a Template::Toolkit váltotta. A részletekért nézze meg a sablonozó szakaszt, hogy hogyan néz ki az új sablonszintaxis.

Ezek azok a változtatások, amelyet alkalmaznia kell, amikor a meglévő DTL sablonokat az új Template::Toolkit szintaxisra alakítja át:

4.1. táblázat - Sablonváltoztatások az OTRS 3.3-ról 4-re

DTL címke Template::Toolkit címke
$Data{"Name"} [% Data.Name %]
$Data{"Complex-Name"} [% Data.item("Complex-Name") %]
$QData{"Name"} [% Data.Name | html %]
$QData{"Name", "$Length"} [% Data.Name | truncate($Length) | html %]
$LQData{"Name"} [% Data.Name | uri %]
$Quote{"Szöveg", "$Length"} nem lehet közvetlenül lecserélni, lásd a lenti példákat
$Quote{"$Config{"Name"}"} [% Config("Name") | html %]
$Quote{"$Data{"Name"}", "$Length"} [% Data.Name | truncate($Length) | html %]
$Quote{"$Data{"Content"}","$QData{"MaxLength"}"} [% Data.Name | truncate(Data.MaxLength) | html %]
$Quote{"$Text{"$Data{"Content"}"}","$QData{"MaxLength"}"} [% Data.Content | Translate | truncate(Data.MaxLength) | html %]
$Config{"Name"} [% Config("Name") %]
$Env{"Name"} [% Env("Name") %]
$QEnv{"Name"} [% Env("Name") | html %]
$Text{"Szöveg %s helykitöltőkkel", "String"} [% Translate("Szöveg %s helykitöltőkkel", "String") | html %]
$Text{"Szöveg dinamikus %s helykitöltőkkel", "$QData{Name}"} [% Translate("Szöveg dinamikus %s helykitöltőkkel", Data.Name) | html %]
'$JSText{"Szöveg dinamikus %s helykitöltőkkel", "$QData{Name}"}' [% Translate("Szöveg dinamikus %s helykitöltőkkel", Data.Name) | JSON %]
"$JSText{"Szöveg dinamikus %s helykitöltőkkel", "$QData{Name}"}" [% Translate("Szöveg dinamikus %s helykitöltőkkel", Data.Name) | JSON %]
$TimeLong{"$Data{"CreateTime"}"} [% Data.CreateTime | Localize("TimeLong") %]
$TimeShort{"$Data{"CreateTime"}"} [% Data.CreateTime | Localize("TimeShort") %]
$Date{"$Data{"CreateTime"}"} [% Data.CreateTime | Localize("Date") %]
<-- dtl:block:Name -->...<-- dtl:block:Name --> [% RenderBlockStart("Name") %]...[% RenderBlockEnd("Name") %]
<-- dtl:js_on_document_complete -->...<-- dtl:js_on_document_complete --> [% WRAPPER JSOnDocumentComplete %]...[% END %]
<-- dtl:js_on_document_complete_placeholder --> [% PROCESS JSOnDocumentCompleteInsert %]
$Include{"Copyright"} [% InsertTemplate("Copyright") %]

Létezik egy bin/otrs.MigrateDTLtoTT.pl segítő parancsfájl is, amely automatikusan át fogja írni önnek a DTL-fájlokat a Template::Toolkit szintaxisra. Sikertelen lehet, ha hibák találhatók a DTL-jében, ezért először javítsa ki ezeket, és azután futtassa újra a parancsfájlt.

Van még további néhány dolog, amelyet tudomásul kell vennie a kód átírásakor az új sablonmotorra:

  • Az összes nyelvi fájlnak mostantól rendelkeznie kell a use utf8; kikötéssel.

  • A Layout::Get() mostantól elavult. Használja a Layout::Translate() függvényt helyette.

  • A Perl-kódban a $Text{""} összes előfordulását mostantól le kell cserélni a Layout::Translate() hívásaival.

    Ez azért van, mert a DTL-ben nem volt különválasztás a sablon és az adatok között. Ha DTL-címkék voltak beszúrva valamilyen adat részeként, akkor a motornak továbbra is fel kellene dolgozni azokat. Ez többé nincs a Template::Toolkit esetén, mert itt a sablon és az adatok szigorú különválasztása van.

    Tipp: ha valamikor interpolálnia kell a címkéket az adatokban, akkor ehhez használhatja az Interpolate szűrőt ([% Data.Name | Interpolate %]). Ez nem ajánlott biztonsági és teljesítménybeli okok miatt!

  • Hasonló okból a dtl:js_on_document_complete által körbezárt dinamikusan beágyazott JavaScript sem fog működni többé. Használja a Layout::AddJSOnDocumentComplete() függvényt ahelyett, hogy ezt sablonadatként ágyazná be.

    Erre találhat egy példát a Kernel/System/DynamicField/Driver/BaseSelect.pm fájlban.

  • Legyen óvatos a pre kimenetszűrőkkel (a Frontend::Output::FilterElementPre objektumban beállítottakkal). Ezek továbbra is működnek, de meg fogják akadályozni a sablont, hogy gyorstárazza azokat. Ez komoly teljesítményproblémákhoz vezethet. Határozottan ne legyen egyetlen olyan pre kimenetszűrője sem, amely az összes sablonnal dolgozik, hanem korlátozza azokat bizonyos sablonokra a konfigurációs beállításokon keresztül.

    A post kimenetszűrőknek (Frontend::Output::FilterElementPost) nincsenek ilyen erős negatív teljesítményhatásaik. Azonban ezeket is körültekintéssel kell használni, és nem minden sablonnál.

Új FontAwesome verzió

Az OTRS 4-gyel egy új verzióra frissítettük a FontAwesome betűkészletet is. Ennek következtében az ikonok CSS-osztályai megváltoztak. Miközben a korábbi ikonok egy icon-{ikonnév} szerű sémával voltak meghatározva, ezt mostantól a fa fa-{ikonnév} formában kell megadni.

Ezen változtatás miatt meg kell győződnie arról, hogy frissítette-e az összes olyan egyéni előtétprogram-modul regisztrációit, amelyek ikonokat használnak (például a felső navigációs sávnál) az új séma használatához. Ez igaz az olyan sablonoknál is, ahol ikonelemeket használ, mint például <i class="icon-{ikonnév}"></i>.

Egységtesztek

Az OTRS 4-gyel az egységtesztekben a $Self többé nem szolgáltat olyan gyakori objektumokat, mint például a MainObject. Mindig a $Kernel::OM->Get('...') függvényt használja ezen objektumok lekéréséhez.

Egyéni jegy előzmény típusok

Ha bármilyen egyéni jegy előzmény típusokat használ, akkor két lépést kell elvégeznie, hogy azok helyesen legyenek megjelenítve az OTRS 4+ AgentTicketHistory képernyőjén.

Először regisztrálnia kell az egyéni jegy előzmény típusait a rendszerbeállításokon keresztül. Ez így nézhet ki:

<ConfigItem Name="Ticket::Frontend::HistoryTypes###100-MyCustomModule" Required="1" Valid="1">
<Description Translatable="1">Controls how to display the ticket history entries as readable values.</Description>
<Group>Ticket</Group>
<SubGroup>Frontend::Agent::Ticket::ViewHistory</SubGroup>
<Setting>
    <Hash>
        <Item Key="MyCustomType" Translatable="1">Added information (%s)</Item>
    </Hash>
</Setting>
</ConfigItem>
            

A második lépés az egyéni jegy előzmény típusnál biztosított angol szöveg lefordítása a nyelvi fájljaiban, ha szükséges. Ennyi!

Ha érdeklődik a részletek iránt, akkor nézze meg ezt a véglegesítést azon változtatásokkal kapcsolatos további információkról, amelyek az OTRS-ben történtek.