1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9use strict;
10use warnings;
11use utf8;
12
13use vars (qw($Self));
14
15my $DynamicFieldObject = $Kernel::OM->Get('Kernel::System::DynamicField');
16my $BackendObject      = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
17my $TicketObject       = $Kernel::OM->Get('Kernel::System::Ticket');
18my $UserObject         = $Kernel::OM->Get('Kernel::System::User');
19my $CustomerUserObject = $Kernel::OM->Get('Kernel::System::CustomerUser');
20
21# Get helper object.
22$Kernel::OM->ObjectParamAdd(
23    'Kernel::System::UnitTest::Helper' => {
24        RestoreDatabase  => 1,
25        UseTmpArticleDir => 1,
26    },
27);
28my $Helper = $Kernel::OM->Get('Kernel::System::UnitTest::Helper');
29
30my $RandomID = $Helper->GetRandomID();
31my ( $TestUserLogin, $UserID ) = $Helper->TestUserCreate(
32    Groups => ['users'],
33);
34
35my $NotificationLanguage = 'en';
36my $UserLanguage         = 'de';
37
38my @DynamicFieldsToAdd = (
39    {
40        Name       => 'Replace1password' . $RandomID,
41        Label      => 'a description',
42        FieldOrder => 9998,
43        FieldType  => 'Text',
44        ObjectType => 'Ticket',
45        Config     => {
46            Name        => 'Replace1password' . $RandomID,
47            Description => 'Description for Dynamic Field.',
48        },
49        Reorder => 0,
50        ValidID => 1,
51        UserID  => 1,
52    },
53    {
54        Name       => 'Replace2' . $RandomID,
55        Label      => 'a description',
56        FieldOrder => 9999,
57        FieldType  => 'Dropdown',
58        ObjectType => 'Ticket',
59        Config     => {
60            Name           => 'Replace2' . $RandomID,
61            Description    => 'Description for Dynamic Field.',
62            PossibleValues => {
63                1 => 'A',
64                2 => 'B',
65            }
66        },
67        Reorder => 0,
68        ValidID => 1,
69        UserID  => 1,
70    },
71);
72
73my %AddedDynamicFieldIds;
74my %DynamicFieldConfigs;
75
76for my $DynamicField (@DynamicFieldsToAdd) {
77
78    my $DynamicFieldID = $DynamicFieldObject->DynamicFieldAdd(
79        %{$DynamicField},
80    );
81    $Self->IsNot(
82        $DynamicFieldID,
83        undef,
84        'DynamicFieldAdd()',
85    );
86
87    # Remember added DynamicFields.
88    $AddedDynamicFieldIds{$DynamicFieldID} = $DynamicField->{Name};
89
90    my $DynamicFieldConfig = $DynamicFieldObject->DynamicFieldGet(
91        Name => $DynamicField->{Name},
92    );
93    $Self->Is(
94        ref $DynamicFieldConfig,
95        'HASH',
96        'DynamicFieldConfig must be a hash reference',
97    );
98
99    # Remember the DF config.
100    $DynamicFieldConfigs{ $DynamicField->{FieldType} } = $DynamicFieldConfig;
101}
102
103# Create template generator after the dynamic field are created as it gathers all DF in the
104# constructor.
105my $TemplateGeneratorObject = $Kernel::OM->Get('Kernel::System::TemplateGenerator');
106
107my $TestCustomerLogin = $Helper->TestCustomerUserCreate(
108    Language => $UserLanguage,
109);
110
111my %TestCustomerData = $CustomerUserObject->CustomerUserDataGet(
112    User => $TestCustomerLogin,
113);
114
115# Add a random secret for the customer user.
116$CustomerUserObject->SetPreferences(
117    Key    => 'UserGoogleAuthenticatorSecretKey',
118    Value  => $Helper->GetRandomID(),
119    UserID => $TestCustomerLogin,
120);
121
122# Generate a token for the customer user.
123$CustomerUserObject->TokenGenerate(
124    UserID => $TestCustomerLogin,
125);
126
127my @TestUsers;
128for ( 1 .. 4 ) {
129    my $TestUserLogin = $Helper->TestUserCreate(
130        Language => $UserLanguage,
131    );
132    my %TestUser = $UserObject->GetUserData(
133        User => $TestUserLogin,
134    );
135
136    # Add a random secret for the user.
137    $UserObject->SetPreferences(
138        Key    => 'UserGoogleAuthenticatorSecretKey',
139        Value  => $Helper->GetRandomID(),
140        UserID => $TestUser{UserID},
141    );
142
143    # Generate a token for the user.
144    $UserObject->TokenGenerate(
145        UserID => $TestUser{UserID},
146    );
147
148    push @TestUsers, \%TestUser;
149}
150
151# Create time for time tags check.
152my $SystemTime = $Kernel::OM->Create(
153    'Kernel::System::DateTime',
154    ObjectParams => {
155        String => '2017-07-05 11:00:00',
156    },
157)->ToEpoch();
158
159# Set the fixed time.
160$Helper->FixedTimeSet($SystemTime);
161
162# Create test queue with escalation times.
163my $QueueID = $Kernel::OM->Get('Kernel::System::Queue')->QueueAdd(
164    Name                => 'Queue' . $RandomID,
165    ValidID             => 1,
166    GroupID             => 1,
167    FirstResponseTime   => 30,
168    FirstResponseNotify => 80,
169    UpdateTime          => 40,
170    UpdateNotify        => 80,
171    SolutionTime        => 50,
172    SolutionNotify      => 80,
173    SystemAddressID     => 1,
174    SalutationID        => 1,
175    SignatureID         => 1,
176    UserID              => 1,
177    Comment             => "Test Queue",
178);
179$Self->True(
180    $QueueID,
181    "QueueID $QueueID - created"
182);
183
184my $TicketID = $TicketObject->TicketCreate(
185    Title         => 'Some Ticket_Title',
186    QueueID       => $QueueID,
187    Lock          => 'unlock',
188    Priority      => '3 normal',
189    State         => 'open',
190    CustomerNo    => '123465',
191    CustomerUser  => $TestCustomerLogin,
192    OwnerID       => $TestUsers[0]->{UserID},
193    ResponsibleID => $TestUsers[1]->{UserID},
194    UserID        => $TestUsers[2]->{UserID},
195);
196$Self->IsNot(
197    $TicketID,
198    undef,
199    'TicketCreate() TicketID',
200);
201
202my $Success = $BackendObject->ValueSet(
203    DynamicFieldConfig => $DynamicFieldConfigs{Text},
204    ObjectID           => $TicketID,
205    Value              => 'otrs',
206    UserID             => 1,
207);
208$Self->True(
209    $Success,
210    'DynamicField ValueSet() for Dynamic Field Text - with true',
211);
212
213$Success = $BackendObject->ValueSet(
214    DynamicFieldConfig => $DynamicFieldConfigs{Dropdown},
215    ObjectID           => $TicketID,
216    Value              => 1,
217    UserID             => 1,
218);
219$Self->True(
220    $Success,
221    'DynamicField ValueSet() Dynamic Field Dropdown - with true',
222);
223
224my $ArticleBackendObject = $Kernel::OM->Get('Kernel::System::Ticket::Article')->BackendForChannel(
225    ChannelName => 'Internal',
226);
227
228# Add 5 minutes for escalation times evaluation.
229$Helper->FixedTimeAddSeconds(300);
230
231my $ArticleID = $ArticleBackendObject->ArticleCreate(
232    TicketID             => $TicketID,
233    IsVisibleForCustomer => 0,
234    SenderType           => 'agent',
235    From                 => 'Some Agent <email@example.com>',
236    To                   => 'Some Customer <customer-a@example.com>',
237    Subject              => 'some short description',
238    Body                 => 'the message text',
239    ContentType          => 'text/plain; charset=ISO-8859-15',
240    HistoryType          => 'OwnerUpdate',
241    HistoryComment       => 'Some free text!',
242    UserID               => 1,
243    NoAgentNotify        => 1,                                          # if you don't want to send agent notifications
244);
245$Self->IsNot(
246    $ArticleID,
247    undef,
248    'ArticleCreate() ArticleID',
249);
250
251# Renew object because of transaction.
252$Kernel::OM->ObjectsDiscard( Objects => ['Kernel::System::Ticket'] );
253$TicketObject = $Kernel::OM->Get('Kernel::System::Ticket');
254
255my @Tests = (
256    {
257        Name => 'Simple replace',
258        Data => {
259            From => 'test@home.com',
260        },
261        RichText => 0,
262        Template => 'Test <OTRS_CUSTOMER_From>',
263        Result   => 'Test test@home.com',
264    },
265    {
266        Name => 'Simple replace, case insensitive',
267        Data => {
268            From => 'test@home.com',
269        },
270        RichText => 0,
271        Template => 'Test <OTRS_CUSTOMER_FROM>',
272        Result   => 'Test test@home.com',
273    },
274    {
275        Name => 'remove unknown tags',
276        Data => {
277            From => 'test@home.com',
278        },
279        RichText => 0,
280        Template => 'Test <OTRS_CUSTOMER_INVALID_TAG>',
281        Result   => 'Test -',
282    },
283    {
284        Name => 'OTRS customer subject',    # <OTRS_CUSTOMER_SUBJECT>
285        Data => {
286            From    => 'test@home.com',
287            Subject => 'otrs',
288        },
289        RichText => 0,
290        Template => 'Test <OTRS_CUSTOMER_SUBJECT>',
291        Result   => 'Test otrs',
292    },
293    {
294        Name => 'OTRS customer subject 3 letters',    # <OTRS_CUSTOMER_SUBJECT[20]>
295        Data => {
296            From    => 'test@home.com',
297            Subject => 'otrs',
298        },
299        RichText => 0,
300        Template => 'Test <OTRS_CUSTOMER_SUBJECT[3]>',
301        Result   => 'Test otr [...]',
302    },
303    {
304        Name => 'OTRS customer subject 20 letters + garbarge',    # <OTRS_CUSTOMER_SUBJECT[20]>
305        Data => {
306            From    => 'test@home.com',
307            Subject => 'RE: otrs',
308        },
309        RichText => 0,
310        Template => 'Test <OTRS_CUSTOMER_SUBJECT[20]>',
311        Result   => 'Test otrs',
312    },
313    {
314        Name => 'OTRS responsible firstname',                     # <OTRS_RESPONSIBLE_UserFirstname>
315        Data => {
316            From => 'test@home.com',
317        },
318        RichText => 0,
319        Template => 'Test <OTRS_RESPONSIBLE_UserFirstname> <OTRS_RESPONSIBLE_nonexisting>',
320        Result   => "Test $TestUsers[1]->{UserFirstname} -",
321    },
322    {
323        Name => 'OTRS_TICKET_RESPONSIBLE firstname',              # <OTRS_RESPONSIBLE_UserFirstname>
324        Data => {
325            From => 'test@home.com',
326        },
327        RichText => 0,
328        Template => 'Test <OTRS_TICKET_RESPONSIBLE_UserFirstname> <OTRS_TICKET_RESPONSIBLE_nonexisting>',
329        Result   => "Test $TestUsers[1]->{UserFirstname} -",
330    },
331    {
332        Name => 'OTRS responsible password (masked)',
333        Data => {
334            From => 'test@home.com',
335        },
336        RichText => 0,
337        Template => 'Test <OTRS_RESPONSIBLE_UserPw> <OTRS_RESPONSIBLE_SomeOtherValue::Password>',
338        Result   => "Test xxx -",
339    },
340    {
341        Name => 'OTRS responsible secrets (masked)',
342        Data => {
343            From => 'test@home.com',
344        },
345        RichText => 0,
346        Template => 'Test <OTRS_RESPONSIBLE_UserGoogleAuthenticatorSecretKey> <OTRS_RESPONSIBLE_UserToken>',
347        Result   => 'Test xxx xxx',
348    },
349    {
350        Name => 'OTRS owner firstname',    # <OTRS_OWNER_*>
351        Data => {
352            From => 'test@home.com',
353        },
354        RichText => 0,
355        Template => 'Test <OTRS_OWNER_UserFirstname> <OTRS_OWNER_nonexisting>',
356        Result   => "Test $TestUsers[0]->{UserFirstname} -",
357    },
358    {
359        Name => 'OTRS_TICKET_OWNER firstname',    # <OTRS_OWNER_*>
360        Data => {
361            From => 'test@home.com',
362        },
363        RichText => 0,
364        Template => 'Test <OTRS_TICKET_OWNER_UserFirstname> <OTRS_TICKET_OWNER_nonexisting>',
365        Result   => "Test $TestUsers[0]->{UserFirstname} -",
366    },
367    {
368        Name => 'OTRS owner password (masked)',
369        Data => {
370            From => 'test@home.com',
371        },
372        RichText => 0,
373        Template => 'Test <OTRS_OWNER_UserPw> <OTRS_OWNER_SomeOtherValue::Password>',
374        Result   => "Test xxx -",
375    },
376    {
377        Name => 'OTRS owner secrets (masked)',
378        Data => {
379            From => 'test@home.com',
380        },
381        RichText => 0,
382        Template => 'Test <OTRS_OWNER_UserGoogleAuthenticatorSecretKey> <OTRS_OWNER_UserToken>',
383        Result   => 'Test xxx xxx',
384    },
385    {
386        Name => 'OTRS current firstname',    # <OTRS_CURRENT_*>
387        Data => {
388            From => 'test@home.com',
389        },
390        RichText => 0,
391        Template => 'Test <OTRS_CURRENT_UserFirstname> <OTRS_CURRENT_nonexisting>',
392        Result   => "Test $TestUsers[2]->{UserFirstname} -",
393    },
394    {
395        Name => 'OTRS current password (masked)',
396        Data => {
397            From => 'test@home.com',
398        },
399        RichText => 0,
400        Template => 'Test <OTRS_CURRENT_UserPw> <OTRS_CURRENT_SomeOtherValue::Password>',
401        Result   => 'Test xxx -',
402    },
403    {
404        Name => 'OTRS current secrets (masked)',
405        Data => {
406            From => 'test@home.com',
407        },
408        RichText => 0,
409        Template => 'Test <OTRS_CURRENT_UserGoogleAuthenticatorSecretKey> <OTRS_CURRENT_UserToken>',
410        Result   => 'Test xxx xxx',
411    },
412    {
413        Name => 'OTRS ticket ticketid',    # <OTRS_TICKET_*>
414        Data => {
415            From => 'test@home.com',
416        },
417        RichText => 0,
418        Template => 'Test <OTRS_TICKET_TicketID>',
419        Result   => 'Test ' . $TicketID,
420    },
421    {
422        Name => 'OTRS dynamic field (text)',    # <OTRS_TICKET_DynamicField_*>
423        Data => {
424            From => 'test@home.com',
425        },
426        RichText => 0,
427        Template => 'Test <OTRS_TICKET_DynamicField_Replace1password' . $RandomID . '>',
428        Result   => 'Test otrs',
429    },
430    {
431        Name => 'OTRS dynamic field value (text)',    # <OTRS_TICKET_DynamicField_*_Value>
432        Data => {
433            From => 'test@home.com',
434        },
435        RichText => 0,
436        Template => 'Test <OTRS_TICKET_DynamicField_Replace1password' . $RandomID . '_Value>',
437        Result   => 'Test otrs',
438    },
439    {
440        Name => 'OTRS dynamic field (Dropdown)',      # <OTRS_TICKET_DynamicField_*>
441        Data => {
442            From => 'test@home.com',
443        },
444        RichText => 0,
445        Template => 'Test <OTRS_TICKET_DynamicField_Replace2' . $RandomID . '>',
446        Result   => 'Test 1',
447    },
448    {
449        Name => 'OTRS dynamic field value (Dropdown)',    # <OTRS_TICKET_DynamicField_*_Value>
450        Data => {
451            From => 'test@home.com',
452        },
453        RichText => 0,
454        Template => 'Test <OTRS_TICKET_DynamicField_Replace2' . $RandomID . '_Value>',
455        Result   => 'Test A',
456    },
457    {
458        Name     => 'OTRS config value',                  # <OTRS_CONFIG_*>
459        Data     => {},
460        RichText => 0,
461        Template => 'Test <OTRS_CONFIG_DefaultTheme>',
462        Result   => 'Test Standard',
463    },
464    {
465        Name     => 'OTRS secret config values, must be masked (even unknown settings)',
466        Data     => {},
467        RichText => 0,
468        Template =>
469            'Test <OTRS_CONFIG_DatabasePw> <OTRS_CONFIG_Core::MirrorDB::Password> <OTRS_CONFIG_SomeOtherValue::Password> <OTRS_CONFIG_SomeOtherValue::Pw>',
470        Result => 'Test xxx xxx xxx xxx',
471    },
472    {
473        Name     => 'OTRS secret config value and normal config value',
474        Data     => {},
475        RichText => 0,
476        Template => 'Test <OTRS_CONFIG_DatabasePw> and <OTRS_CONFIG_DefaultTheme>',
477        Result   => 'Test xxx and Standard',
478    },
479    {
480        Name     => 'OTRS secret config values with numbers',
481        Data     => {},
482        RichText => 0,
483        Template =>
484            'Test <OTRS_CONFIG_AuthModule::LDAP::SearchUserPw1> and <OTRS_CONFIG_AuthModule::LDAP::SearchUserPassword1>',
485        Result => 'Test xxx and xxx',
486    },
487    {
488        Name => 'mailto-Links RichText enabled',
489        Data => {
490            From => 'test@home.com',
491        },
492        RichText => 1,
493        Template =>
494            'mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20%3COTRS_CUSTOMER_From%3E&amp;body=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Subject und Body</a><br />
495<br />
496mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Subject</a><br />
497<br />
498mailto-Link <a href="mailto:skywalker@otrs.org?body=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Body</a><br />',
499        Result =>
500            'mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20test%40home.com&amp;body=From%3A%20test%40home.com">E-Mail mit Subject und Body</a><br /><br />mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20test%40home.com">E-Mail mit Subject</a><br /><br />mailto-Link <a href="mailto:skywalker@otrs.org?body=From%3A%20test%40home.com">E-Mail mit Body</a><br />',
501    },
502    {
503        Name => 'mailto-Links',
504        Data => {
505            From => 'test@home.com',
506        },
507        RichText => 0,
508        Template =>
509            'mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20%3COTRS_CUSTOMER_From%3E&amp;body=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Subject und Body</a><br />
510<br />
511mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Subject</a><br />
512<br />
513mailto-Link <a href="mailto:skywalker@otrs.org?body=From%3A%20%3COTRS_CUSTOMER_From%3E">E-Mail mit Body</a><br />',
514        Result =>
515            'mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20test%40home.com&amp;body=From%3A%20test%40home.com">E-Mail mit Subject und Body</a><br />
516<br />
517mailto-Link <a href="mailto:skywalker@otrs.org?subject=From%3A%20test%40home.com">E-Mail mit Subject</a><br />
518<br />
519mailto-Link <a href="mailto:skywalker@otrs.org?body=From%3A%20test%40home.com">E-Mail mit Body</a><br />',
520    },
521    {
522        Name => 'OTRS AGENT + CUSTOMER FROM',    # <OTRS_TICKET_DynamicField_*_Value>
523        Data => {
524            From => 'testcustomer@home.com',
525        },
526        DataAgent => {
527            From => 'testagent@home.com',
528        },
529        RichText => 0,
530        Template => 'Test <OTRS_AGENT_From> - <OTRS_CUSTOMER_From>',
531        Result   => 'Test testagent@home.com - testcustomer@home.com',
532    },
533    {
534        Name =>
535            'OTRS AGENT + CUSTOMER BODY',   # this is an special case, it sets the Body as it is since is the Data param
536        Data => {
537            Body => "Line1\nLine2\nLine3",
538        },
539        DataAgent => {
540            Body => "Line1\nLine2\nLine3",
541        },
542        RichText => 0,
543        Template => 'Test <OTRS_AGENT_BODY> - <OTRS_CUSTOMER_BODY>',
544        Result   => "Test Line1\nLine2\nLine3 - Line1\nLine2\nLine3",
545    },
546    {
547        Name =>
548            'OTRS AGENT + CUSTOMER BODY With RichText enabled'
549        ,    # this is an special case, it sets the Body as it is since is the Data param
550        Data => {
551            Body => "Line1\nLine2\nLine3",
552        },
553        DataAgent => {
554            Body => "Line1\nLine2\nLine3",
555        },
556        RichText => 1,
557        Template => 'Test &lt;OTRS_AGENT_BODY&gt; - &lt;OTRS_CUSTOMER_BODY&gt;',
558        Result   => "Test Line1<br/>
559Line2<br/>
560Line3 - Line1<br/>
561Line2<br/>
562Line3",
563    },
564    {
565        Name => 'OTRS AGENT + CUSTOMER BODY[2]',
566        Data => {
567            Body => "Line1\nLine2\nLine3",
568        },
569        DataAgent => {
570            Body => "Line1\nLine2\nLine3",
571        },
572        RichText => 0,
573        Template => 'Test <OTRS_AGENT_BODY[2]> - <OTRS_CUSTOMER_BODY[2]>',
574        Result   => "Test > Line1\n> Line2 - > Line1\n> Line2",
575    },
576    {
577        Name => 'OTRS AGENT + CUSTOMER BODY[7] with RichText enabled',
578        Data => {
579            Body => "Line1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8\nLine9",
580        },
581        DataAgent => {
582            Body => "Line1\nLine2\nLine3\nLine4\nLine5\nLine6\nLine7\nLine8\nLine9",
583        },
584        RichText => 1,
585        Template => 'Test &lt;OTRS_AGENT_BODY[7]&gt; - &lt;OTRS_CUSTOMER_BODY[7]&gt;',
586        Result =>
587            'Test <div  type="cite" style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">Line1<br/>
588Line2<br/>
589Line3<br/>
590Line4<br/>
591Line5<br/>
592Line6<br/>
593Line7</div> - <div  type="cite" style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">Line1<br/>
594Line2<br/>
595Line3<br/>
596Line4<br/>
597Line5<br/>
598Line6<br/>
599Line7</div>',
600    },
601    {
602        Name => 'OTRS AGENT + CUSTOMER EMAIL',    # EMAIL without [ ] does not exists
603        Data => {
604            Body => "Line1\nLine2\nLine3",
605        },
606        DataAgent => {
607            Body => "Line1\nLine2\nLine3",
608        },
609        RichText => 0,
610        Template => 'Test <OTRS_AGENT_EMAIL> - <OTRS_CUSTOMER_EMAIL>',
611        Result   => "Test Line1\nLine2\nLine3 - Line1\nLine2\nLine3",
612    },
613    {
614        Name => 'OTRS AGENT + CUSTOMER EMAIL[2]',
615        Data => {
616            Body => "Line1\nLine2\nLine3",
617        },
618        DataAgent => {
619            Body => "Line1\nLine2\nLine3",
620        },
621        RichText => 0,
622        Template => 'Test <OTRS_AGENT_EMAIL[2]> - <OTRS_CUSTOMER_EMAIL[2]>',
623        Result   => "Test > Line1\n> Line2 - > Line1\n> Line2",
624    },
625    {
626        Name => 'OTRS COMMENT',
627        Data => {
628            Body => "Line1\nLine2\nLine3",
629        },
630        RichText => 0,
631        Template => 'Test <OTRS_COMMENT>',
632        Result   => "Test > Line1\n> Line2\n> Line3",
633    },
634
635    {
636        Name => 'OTRS COMMENT[2]',
637        Data => {
638            Body => "Line1\nLine2\nLine3",
639        },
640        RichText => 0,
641        Template => 'Test <OTRS_COMMENT[2]>',
642        Result   => "Test > Line1\n> Line2",
643    },
644    {
645        Name => 'OTRS AGENT + CUSTOMER SUBJECT[2]',
646        Data => {
647            Subject => '0123456789'
648        },
649        DataAgent => {
650            Subject => '987654321'
651        },
652        RichText => 0,
653        Template => 'Test <OTRS_AGENT_SUBJECT[2]> - <OTRS_CUSTOMER_SUBJECT[2]>',
654        Result   => "Test 98 [...] - 01 [...]",
655    },
656    {
657        Name     => 'OTRS CUSTOMER REALNAME',
658        Data     => {},
659        RichText => 0,
660        Template => 'Test <OTRS_CUSTOMER_REALNAME>',
661        Result   => "Test $TestCustomerLogin $TestCustomerLogin",
662    },
663    {
664        Name     => 'OTRS CUSTOMER DATA UserFirstname',
665        Data     => {},
666        RichText => 0,
667        Template => 'Test <OTRS_CUSTOMER_DATA_UserFirstname>',
668        Result   => "Test $TestCustomerLogin",
669    },
670    {
671        Name     => 'OTRS CUSTOMER DATA UserPassword (masked)',
672        Data     => {},
673        RichText => 0,
674        Template => 'Test <OTRS_CUSTOMER_DATA_UserPassword>',
675        Result   => 'Test xxx',
676    },
677    {
678        Name     => 'OTRS CUSTOMER DATA secret (masked)',
679        Data     => {},
680        RichText => 0,
681        Template => 'Test <OTRS_CUSTOMER_DATA_UserGoogleAuthenticatorSecretKey> <OTRS_CUSTOMER_DATA_UserToken>',
682        Result   => 'Test xxx xxx',
683    },
684    {
685        Name     => 'OTRS <OTRS_NOTIFICATION_RECIPIENT_UserFullname>',
686        Data     => {},
687        RichText => 0,
688        Template => 'Test <OTRS_NOTIFICATION_RECIPIENT_UserFullname> <OTRS_NOTIFICATION_RECIPIENT_nonexisting>',
689        Result   => "Test $TestUsers[3]->{UserFullname} -",
690    },
691    {
692        Name     => 'OTRS <OTRS_TICKET_EscalationResponseTime>',
693        Data     => {},
694        RichText => 0,
695        Template => 'Test <OTRS_TICKET_EscalationResponseTime>',
696        Result   => "Test 07/05/2017 11:30",
697    },
698    {
699        Name     => 'OTRS <OTRS_TICKET_EscalationUpdateTime>',
700        Data     => {},
701        RichText => 0,
702        Template => 'Test <OTRS_TICKET_EscalationUpdateTime>',
703        Result   => "Test 07/05/2017 11:45",
704    },
705    {
706        Name     => 'OTRS <OTRS_TICKET_EscalationSolutionTime>',
707        Data     => {},
708        RichText => 0,
709        Template => 'Test <OTRS_TICKET_EscalationSolutionTime>',
710        Result   => "Test 07/05/2017 11:50",
711    },
712    {
713        Name     => 'OTRS <OTRS_TICKET_EscalationTimeWorkingTime>',
714        Data     => {},
715        RichText => 0,
716        Template => 'Test <OTRS_TICKET_EscalationTimeWorkingTime>',
717        Result   => "Test 25 m",
718    },
719    {
720        Name     => 'OTRS <OTRS_TICKET_EscalationTime>',
721        Data     => {},
722        RichText => 0,
723        Template => 'Test <OTRS_TICKET_EscalationTime>',
724        Result   => "Test 25 m",
725    },
726    {
727        Name     => 'OTRS <OTRS_TICKET_FirstResponseTimeWorkingTime>',
728        Data     => {},
729        RichText => 0,
730        Template => 'Test <OTRS_TICKET_FirstResponseTimeWorkingTime>',
731        Result   => "Test 25 m",
732    },
733    {
734        Name     => 'OTRS <OTRS_TICKET_FirstResponseTime>',
735        Data     => {},
736        RichText => 0,
737        Template => 'Test <OTRS_TICKET_FirstResponseTime>',
738        Result   => "Test 25 m",
739    },
740    {
741        Name     => 'OTRS <OTRS_TICKET_UpdateTimeWorkingTime>',
742        Data     => {},
743        RichText => 0,
744        Template => 'Test <OTRS_TICKET_UpdateTimeWorkingTime>',
745        Result   => "Test 40 m",
746    },
747    {
748        Name     => 'OTRS <OTRS_TICKET_UpdateTime>',
749        Data     => {},
750        RichText => 0,
751        Template => 'Test <OTRS_TICKET_UpdateTime>',
752        Result   => "Test 40 m",
753    },
754    {
755        Name     => 'OTRS <OTRS_TICKET_SolutionTimeWorkingTime>',
756        Data     => {},
757        RichText => 0,
758        Template => 'Test <OTRS_TICKET_SolutionTimeWorkingTime>',
759        Result   => "Test 45 m",
760    },
761    {
762        Name     => 'OTRS <OTRS_TICKET_SolutionTime>',
763        Data     => {},
764        RichText => 0,
765        Template => 'Test <OTRS_TICKET_SolutionTime>',
766        Result   => "Test 45 m",
767    },
768);
769
770my %Ticket = $TicketObject->TicketGet(
771    TicketID      => $TicketID,
772    DynamicFields => 1,
773);
774
775for my $Test (@Tests) {
776    my $Result = $TemplateGeneratorObject->_Replace(
777        Text        => $Test->{Template},
778        Data        => $Test->{Data},
779        DataAgent   => $Test->{DataAgent},
780        RichText    => $Test->{RichText},
781        TicketData  => \%Ticket,
782        UserID      => $TestUsers[2]->{UserID},
783        RecipientID => $TestUsers[3]->{UserID},
784        Language    => $NotificationLanguage,
785    );
786    $Self->Is(
787        $Result,
788        $Test->{Result},
789        "$Test->{Name} - _Replace()",
790    );
791}
792
793# Set state to 'pending reminder'.
794$Success = $TicketObject->TicketStateSet(
795    State    => 'pending reminder',
796    TicketID => $TicketID,
797    UserID   => $TestUsers[2]->{UserID},
798);
799$Self->True(
800    $Success,
801    "TicketID $TicketID - set state to pending reminder successfully",
802);
803
804$Success = $TicketObject->TicketPendingTimeSet(
805    String   => '2017-07-06 10:00:00',
806    TicketID => $TicketID,
807    UserID   => 1,
808);
809$Self->True(
810    $Success,
811    "Set pending time successfully",
812);
813
814# Check 'UntilTime' and 'RealTillTimeNotUsed' tags (see bug#8301).
815@Tests = (
816    {
817        Name     => 'OTRS <OTRS_TICKET_UntilTime>',
818        Data     => {},
819        RichText => 0,
820        Template => 'Test <OTRS_TICKET_UntilTime>',
821        Result   => "Test 22 h 55 m",
822    },
823    {
824        Name     => 'OTRS <OTRS_TICKET_RealTillTimeNotUsed>',
825        Data     => {},
826        RichText => 0,
827        Template => 'Test <OTRS_TICKET_RealTillTimeNotUsed>',
828        Result   => "Test 07/06/2017 10:00",
829    }
830);
831
832%Ticket = $TicketObject->TicketGet(
833    TicketID      => $TicketID,
834    DynamicFields => 1,
835);
836
837for my $Test (@Tests) {
838    my $Result = $TemplateGeneratorObject->_Replace(
839        Text        => $Test->{Template},
840        Data        => $Test->{Data},
841        DataAgent   => $Test->{DataAgent},
842        RichText    => $Test->{RichText},
843        TicketData  => \%Ticket,
844        UserID      => $TestUsers[2]->{UserID},
845        RecipientID => $TestUsers[3]->{UserID},
846        Language    => $NotificationLanguage,
847    );
848    $Self->Is(
849        $Result,
850        $Test->{Result},
851        "$Test->{Name} - _Replace()",
852    );
853}
854
855# Test for bug#14948 Appointment description tag replace with line brakes.
856my %Calendar = $Kernel::OM->Get('Kernel::System::Calendar')->CalendarCreate(
857    CalendarName => "My Calendar $RandomID",
858    Color        => '#3A87AD',
859    GroupID      => 1,
860    UserID       => $UserID,
861    ValidID      => 1,
862);
863$Self->True(
864    $Calendar{CalendarID},
865    "CalendarID $Calendar{CalendarID} is created.",
866);
867
868my $AppointmentID = $Kernel::OM->Get('Kernel::System::Calendar::Appointment')->AppointmentCreate(
869    CalendarID  => $Calendar{CalendarID},
870    Title       => "Test Appointment $RandomID",
871    Description => "Test
872description
873$RandomID",
874    Location  => 'Germany',
875    StartTime => '2016-09-01 00:00:00',
876    EndTime   => '2016-09-01 01:00:00',
877    UserID    => $UserID,
878);
879$Self->True(
880    $AppointmentID,
881    "AppointmentID $AppointmentID is created.",
882);
883
884$Helper->ConfigSettingChange(
885    Valid => 1,
886    Key   => 'Frontend::RichText',
887    Value => 1,
888);
889
890my $Result = $Kernel::OM->Get('Kernel::System::CalendarTemplateGenerator')->_Replace(
891    Text          => 'Description &lt;OTRS_APPOINTMENT_DESCRIPTION&gt;',
892    RichText      => 1,
893    AppointmentID => $AppointmentID,
894    CalendarID    => $Calendar{CalendarID},
895    UserID        => $UserID,
896);
897$Self->Is(
898    $Result,
899    "Description Test<br/>
900description<br/>
901$RandomID",
902    "Appointment description tag correctly replaced.",
903);
904
905# Cleanup is done by RestoreDatabase.
906
9071;
908