897 lines
27 KiB
Perl
897 lines
27 KiB
Perl
# --
|
|
# Copyright (C) 2001-2019 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::AgentFAQZoom;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Kernel::Language qw(Translatable);
|
|
use Kernel::System::VariableCheck qw(:all);
|
|
|
|
our $ObjectManagerDisabled = 1;
|
|
|
|
sub new {
|
|
my ( $Type, %Param ) = @_;
|
|
|
|
# Allocate new hash for object.
|
|
my $Self = {%Param};
|
|
bless( $Self, $Type );
|
|
|
|
my %UserPreferences = $Kernel::OM->Get('Kernel::System::User')->GetPreferences(
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
if ( !defined $Self->{DoNotShowBrowserLinkMessage} ) {
|
|
if ( $UserPreferences{UserAgentDoNotShowBrowserLinkMessage} ) {
|
|
$Self->{DoNotShowBrowserLinkMessage} = 1;
|
|
}
|
|
else {
|
|
$Self->{DoNotShowBrowserLinkMessage} = 0;
|
|
}
|
|
}
|
|
|
|
return $Self;
|
|
}
|
|
|
|
sub Run {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
# Permission check.
|
|
if ( !$Self->{AccessRo} ) {
|
|
return $LayoutObject->NoPermission(
|
|
Message => Translatable('You need ro permission!'),
|
|
WithHeader => 'yes',
|
|
);
|
|
}
|
|
|
|
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
|
|
|
|
# Get parameters from web request.
|
|
my %GetParam;
|
|
$GetParam{ItemID} = $ParamObject->GetParam( Param => 'ItemID' );
|
|
$GetParam{Rate} = $ParamObject->GetParam( Param => 'Rate' );
|
|
|
|
# Get navigation bar option.
|
|
my $Nav = $ParamObject->GetParam( Param => 'Nav' ) || '';
|
|
|
|
if ( !$GetParam{ItemID} ) {
|
|
return $LayoutObject->ErrorScreen(
|
|
Message => Translatable('No ItemID is given!'),
|
|
Comment => Translatable('Please contact the administrator.'),
|
|
);
|
|
}
|
|
|
|
my $FAQObject = $Kernel::OM->Get('Kernel::System::FAQ');
|
|
|
|
my %FAQData = $FAQObject->FAQGet(
|
|
ItemID => $GetParam{ItemID},
|
|
ItemFields => 1,
|
|
UserID => $Self->{UserID},
|
|
DynamicFields => 1,
|
|
);
|
|
if ( !%FAQData ) {
|
|
return $LayoutObject->ErrorScreen();
|
|
}
|
|
|
|
# Check user permission.
|
|
my $Permission = $FAQObject->CheckCategoryUserPermission(
|
|
UserID => $Self->{UserID},
|
|
CategoryID => $FAQData{CategoryID},
|
|
Type => 'ro',
|
|
);
|
|
if ( !$Permission ) {
|
|
return $LayoutObject->NoPermission(
|
|
Message => Translatable('You have no permission for this category!'),
|
|
WithHeader => 'yes',
|
|
);
|
|
}
|
|
|
|
my $HTMLUtilsObject = $Kernel::OM->Get('Kernel::System::HTMLUtils');
|
|
|
|
# ---------------------------------------------------------- #
|
|
# HTMLView Sub-action
|
|
# ---------------------------------------------------------- #
|
|
if ( $Self->{Subaction} eq 'HTMLView' ) {
|
|
|
|
# gGet parameters from web request.
|
|
my $Field = $ParamObject->GetParam( Param => "Field" );
|
|
|
|
for my $Needed (qw( ItemID Field )) {
|
|
if ( !$Needed ) {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Message => "Needed Param: $Needed!",
|
|
Priority => 'error',
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Get the Field content.
|
|
my $FieldContent = $FAQObject->ItemFieldGet(
|
|
ItemID => $GetParam{ItemID},
|
|
Field => $Field,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Rewrite handle and action, take care of old style before FAQ 2.0.x.
|
|
$FieldContent =~ s{
|
|
Action=AgentFAQ [&](amp;)? Subaction=Download [&](amp;)?
|
|
}{Action=AgentFAQZoom;Subaction=DownloadAttachment;}gxms;
|
|
|
|
# Build base URL for in-line images.
|
|
my $SessionID = '';
|
|
if ( $Self->{SessionID} && !$Self->{SessionIDCookie} ) {
|
|
$SessionID = ';' . $Self->{SessionName} . '=' . $Self->{SessionID};
|
|
$FieldContent =~ s{
|
|
(Action=AgentFAQZoom;Subaction=DownloadAttachment;ItemID=\d+;FileID=\d+)
|
|
}{$1$SessionID}gmsx;
|
|
}
|
|
|
|
# Convert content to HTML if needed.
|
|
if (
|
|
$Kernel::OM->Get('Kernel::Config')->Get('FAQ::Item::HTML')
|
|
&& $LayoutObject->{BrowserRichText}
|
|
&& $FAQData{ContentType} ne 'text/html'
|
|
)
|
|
{
|
|
$FieldContent = $HTMLUtilsObject->ToHTML(
|
|
String => $FieldContent,
|
|
) || '';
|
|
}
|
|
|
|
# Detect all plain text links and put them into an HTML <a> tag.
|
|
$FieldContent = $HTMLUtilsObject->LinkQuote(
|
|
String => $FieldContent,
|
|
);
|
|
|
|
# Set target="_blank" attribute to all HTML <a> tags the LinkQuote function needs to be
|
|
# called again
|
|
$FieldContent = $HTMLUtilsObject->LinkQuote(
|
|
String => $FieldContent,
|
|
TargetAdd => 1,
|
|
);
|
|
|
|
# Add needed HTML headers.
|
|
$FieldContent = $HTMLUtilsObject->DocumentComplete(
|
|
String => $FieldContent,
|
|
Charset => 'utf-8',
|
|
);
|
|
|
|
# Return complete HTML as an attachment.
|
|
return $LayoutObject->Attachment(
|
|
Type => 'inline',
|
|
ContentType => 'text/html',
|
|
Content => $FieldContent,
|
|
);
|
|
}
|
|
|
|
# ---------------------------------------------------------- #
|
|
# DownloadAttachment Sub-action
|
|
# ---------------------------------------------------------- #
|
|
if ( $Self->{Subaction} eq 'DownloadAttachment' ) {
|
|
|
|
$GetParam{FileID} = $ParamObject->GetParam( Param => 'FileID' );
|
|
|
|
if ( !defined $GetParam{FileID} ) {
|
|
return $LayoutObject->FatalError(
|
|
Message => Translatable('Need FileID!'),
|
|
);
|
|
}
|
|
|
|
# Get attachments.
|
|
my %File = $FAQObject->AttachmentGet(
|
|
ItemID => $GetParam{ItemID},
|
|
FileID => $GetParam{FileID},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
if (%File) {
|
|
return $LayoutObject->Attachment(%File);
|
|
}
|
|
else {
|
|
$Kernel::OM->Get('Kernel::System::Log')->Log(
|
|
Message => "No such attachment ($GetParam{FileID})! May be an attack!!!",
|
|
Priority => 'error',
|
|
);
|
|
return $LayoutObject->ErrorScreen();
|
|
}
|
|
}
|
|
|
|
# ---------------------------------------------------------- #
|
|
# Other sub-actions continues here
|
|
# ---------------------------------------------------------- #
|
|
my $Output;
|
|
if ( $Nav eq 'None' ) {
|
|
$Output = $LayoutObject->Header( Type => 'Small' );
|
|
}
|
|
else {
|
|
$Output = $LayoutObject->Header(
|
|
Value => $FAQData{Title},
|
|
);
|
|
$Output .= $LayoutObject->NavigationBar();
|
|
}
|
|
|
|
# Define different notifications.
|
|
my %Notifications = (
|
|
Thanks => {
|
|
Priority => 'Info',
|
|
Info => Translatable('Thanks for your vote!'),
|
|
},
|
|
AlreadyVoted => {
|
|
Priority => 'Error',
|
|
Info => Translatable('You have already voted!'),
|
|
},
|
|
NoRate => {
|
|
Priority => 'Error',
|
|
Info => Translatable('No rate selected!'),
|
|
},
|
|
);
|
|
|
|
# Output notifications if any.
|
|
my $Notify = $ParamObject->GetParam( Param => 'Notify' ) || '';
|
|
if ( $Notify && IsHashRefWithData( $Notifications{$Notify} ) ) {
|
|
$Output .= $LayoutObject->Notify(
|
|
%{ $Notifications{$Notify} },
|
|
);
|
|
}
|
|
|
|
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
|
|
|
|
# Get default options.
|
|
my $MultiLanguage = $ConfigObject->Get('FAQ::MultiLanguage');
|
|
my $Voting = $ConfigObject->Get('FAQ::Voting');
|
|
|
|
# Set default interface settings.
|
|
my $Interface = $FAQObject->StateTypeGet(
|
|
Name => 'internal',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
my $InterfaceStates = $FAQObject->StateTypeList(
|
|
Types => $ConfigObject->Get('FAQ::Agent::StateTypes'),
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Get FAQ vote information.
|
|
my $VoteData;
|
|
if ($Voting) {
|
|
$VoteData = $FAQObject->VoteGet(
|
|
CreateBy => $Self->{UserID},
|
|
ItemID => $FAQData{ItemID},
|
|
Interface => $Interface->{StateID},
|
|
IP => $ENV{'REMOTE_ADDR'},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
}
|
|
|
|
# Check if user already voted this FAQ item.
|
|
my $AlreadyVoted;
|
|
if ($VoteData) {
|
|
|
|
my $ItemChangedSystemTime = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $FAQData{Changed} || '',
|
|
}
|
|
)->ToEpoch();
|
|
|
|
my $VoteCreatedSystemTime = $Kernel::OM->Create(
|
|
'Kernel::System::DateTime',
|
|
ObjectParams => {
|
|
String => $VoteData->{Created} || '',
|
|
}
|
|
)->ToEpoch();
|
|
|
|
if ( $ItemChangedSystemTime <= $VoteCreatedSystemTime ) {
|
|
$AlreadyVoted = 1;
|
|
}
|
|
}
|
|
|
|
# ---------------------------------------------------------- #
|
|
# Vote Sub-action
|
|
# ---------------------------------------------------------- #
|
|
if ( $Self->{Subaction} eq 'Vote' ) {
|
|
|
|
# User can't use this sub-action if is not enabled.
|
|
if ( !$Voting ) {
|
|
$LayoutObject->FatalError(
|
|
Message => Translatable('The voting mechanism is not enabled!'),
|
|
);
|
|
}
|
|
|
|
# User can vote only once per FAQ revision.
|
|
if ($AlreadyVoted) {
|
|
|
|
# Redirect to FAQ zoom.
|
|
return $LayoutObject->Redirect(
|
|
OP => 'Action=AgentFAQZoom;ItemID='
|
|
. $GetParam{ItemID}
|
|
. ';Nav=$Nav;Notify=AlreadyVoted'
|
|
);
|
|
}
|
|
|
|
# Set the vote if any.
|
|
elsif ( defined $GetParam{Rate} ) {
|
|
|
|
# Get rates config.
|
|
my $VotingRates = $ConfigObject->Get('FAQ::Item::Voting::Rates');
|
|
my $Rate = $GetParam{Rate};
|
|
|
|
# Send error if rate is not defined in config.
|
|
if ( !$VotingRates->{$Rate} ) {
|
|
$LayoutObject->FatalError(
|
|
Message => Translatable('The vote rate is not defined!'),
|
|
);
|
|
}
|
|
|
|
# Otherwise add the vote.
|
|
else {
|
|
$FAQObject->VoteAdd(
|
|
CreatedBy => $Self->{UserID},
|
|
ItemID => $GetParam{ItemID},
|
|
IP => $ENV{'REMOTE_ADDR'},
|
|
Interface => $Interface->{StateID},
|
|
Rate => $GetParam{Rate},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Do not show the voting form.
|
|
$AlreadyVoted = 1;
|
|
|
|
# Refresh FAQ item data.
|
|
%FAQData = $FAQObject->FAQGet(
|
|
ItemID => $GetParam{ItemID},
|
|
ItemFields => 1,
|
|
UserID => $Self->{UserID},
|
|
DynamicFields => 1,
|
|
);
|
|
if ( !%FAQData ) {
|
|
return $LayoutObject->ErrorScreen();
|
|
}
|
|
|
|
# Redirect to FAQ zoom.
|
|
return $LayoutObject->Redirect(
|
|
OP => 'Action=AgentFAQZoom;ItemID='
|
|
. $GetParam{ItemID}
|
|
. ';Nav=$Nav;Notify=Thanks'
|
|
);
|
|
}
|
|
}
|
|
|
|
# User is able to vote but no rate has been selected.
|
|
else {
|
|
|
|
# Redirect to FAQ zoom
|
|
return $LayoutObject->Redirect(
|
|
OP => 'Action=AgentFAQZoom;ItemID=' . $GetParam{ItemID} . ';Nav=$Nav;Notify=NoRate'
|
|
);
|
|
}
|
|
}
|
|
|
|
# Prepare fields data (Still needed for PlainText).
|
|
FIELD:
|
|
for my $Field (qw(Field1 Field2 Field3 Field4 Field5 Field6)) {
|
|
next FIELD if !$FAQData{$Field};
|
|
|
|
# Rewrite handle and action, take care of old style before FAQ 2.0.x.
|
|
$FAQData{$Field} =~ s{
|
|
Action=AgentFAQ [&](amp;)? Subaction=Download [&](amp;)?
|
|
}{Action=AgentFAQZoom;Subaction=DownloadAttachment;}gxms;
|
|
|
|
# No quoting if HTML view is enabled.
|
|
next FIELD if $ConfigObject->Get('FAQ::Item::HTML');
|
|
|
|
# HTML quoting.
|
|
$FAQData{$Field} = $LayoutObject->Ascii2Html(
|
|
NewLine => 0,
|
|
Text => $FAQData{$Field},
|
|
VMax => 5000,
|
|
HTMLResultMode => 1,
|
|
LinkFeature => 1,
|
|
);
|
|
}
|
|
|
|
my $UserObject = $Kernel::OM->Get('Kernel::System::User');
|
|
|
|
# Get user info (CreatedBy).
|
|
my %UserInfo = $UserObject->GetUserData(
|
|
UserID => $FAQData{CreatedBy}
|
|
);
|
|
$Param{CreatedByUser} = "$UserInfo{UserFullname}";
|
|
|
|
# Get user info (ChangedBy).
|
|
%UserInfo = $UserObject->GetUserData(
|
|
UserID => $FAQData{ChangedBy}
|
|
);
|
|
$Param{ChangedByUser} = "$UserInfo{UserFullname}";
|
|
|
|
# Set voting results.
|
|
$Param{VotingResultColor} = $LayoutObject->GetFAQItemVotingRateColor(
|
|
Rate => $FAQData{VoteResult},
|
|
);
|
|
|
|
if ( !$Param{VotingResultColor} || $FAQData{Votes} eq '0' ) {
|
|
$Param{VotingResultColor} = 'Gray';
|
|
}
|
|
|
|
if ( $Nav ne 'None' ) {
|
|
|
|
# Run FAQ menu modules.
|
|
if ( ref $ConfigObject->Get('FAQ::Frontend::MenuModule') eq 'HASH' ) {
|
|
my %Menus = %{ $ConfigObject->Get('FAQ::Frontend::MenuModule') };
|
|
my $Counter = 0;
|
|
for my $Menu ( sort keys %Menus ) {
|
|
|
|
# Load module.
|
|
if ( $Kernel::OM->Get('Kernel::System::Main')->Require( $Menus{$Menu}->{Module} ) ) {
|
|
my $Object = $Menus{$Menu}->{Module}->new(
|
|
%{$Self},
|
|
ItemID => $FAQData{ItemID},
|
|
);
|
|
|
|
# Set CSS classes.
|
|
if ( $Menus{$Menu}->{Target} ) {
|
|
|
|
if ( $Menus{$Menu}->{Target} eq 'PopUp' ) {
|
|
$Menus{$Menu}->{Class} = 'AsPopup';
|
|
}
|
|
elsif ( $Menus{$Menu}->{Target} eq 'Back' ) {
|
|
$Menus{$Menu}->{Class} = 'HistoryBack';
|
|
}
|
|
elsif ( $Menus{$Menu}->{Target} eq 'ConfirmationDialog' ) {
|
|
$Menus{$Menu}->{Class} = 'AsConfirmationDialog';
|
|
}
|
|
|
|
}
|
|
|
|
# Run module.
|
|
$Counter = $Object->Run(
|
|
%Param,
|
|
FAQItem => {%FAQData},
|
|
Counter => $Counter,
|
|
Config => $Menus{$Menu},
|
|
MenuID => 'Menu' . $Menu,
|
|
);
|
|
}
|
|
else {
|
|
return $LayoutObject->FatalError();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Output approval state.
|
|
if ( $ConfigObject->Get('FAQ::ApprovalRequired') ) {
|
|
$Param{Approval} = $FAQData{Approved} ? 'Yes' : 'No';
|
|
$LayoutObject->Block(
|
|
Name => 'ViewApproval',
|
|
Data => {%Param},
|
|
);
|
|
}
|
|
|
|
if ($Voting) {
|
|
|
|
# Output votes number if any.
|
|
if ( $FAQData{Votes} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'ViewVotes',
|
|
Data => {%FAQData},
|
|
);
|
|
}
|
|
|
|
# Otherwise display a No Votes found message.
|
|
else {
|
|
$LayoutObject->Block( Name => 'ViewNoVotes' );
|
|
}
|
|
}
|
|
|
|
my $ShowFAQPath = $LayoutObject->FAQPathShow(
|
|
FAQObject => $FAQObject,
|
|
CategoryID => $FAQData{CategoryID},
|
|
UserID => $Self->{UserID},
|
|
PathForItem => 1,
|
|
Nav => $Nav,
|
|
);
|
|
if ($ShowFAQPath) {
|
|
$LayoutObject->Block(
|
|
Name => 'FAQPathItemElement',
|
|
Data => {%FAQData},
|
|
Nav => $Nav,
|
|
);
|
|
}
|
|
|
|
# Show keywords as search links.
|
|
if ( $FAQData{Keywords} ) {
|
|
|
|
# Replace commas and semicolons.
|
|
$FAQData{Keywords} =~ s/,/ /g;
|
|
$FAQData{Keywords} =~ s/;/ /g;
|
|
|
|
my @Keywords = split /\s+/, $FAQData{Keywords};
|
|
for my $Keyword (@Keywords) {
|
|
$LayoutObject->Block(
|
|
Name => 'Keywords',
|
|
Data => {
|
|
Keyword => $Keyword,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# Show languages.
|
|
if ($MultiLanguage) {
|
|
$LayoutObject->Block(
|
|
Name => 'Language',
|
|
Data => {
|
|
%FAQData,
|
|
},
|
|
);
|
|
}
|
|
|
|
# Output rating stars.
|
|
if ($Voting) {
|
|
$LayoutObject->FAQRatingStarsShow(
|
|
VoteResult => $FAQData{VoteResult},
|
|
Votes => $FAQData{Votes},
|
|
);
|
|
}
|
|
if ( $Nav ne 'None' ) {
|
|
|
|
# Output existing attachments.
|
|
my @AttachmentIndex = $FAQObject->AttachmentIndex(
|
|
ItemID => $GetParam{ItemID},
|
|
ShowInline => 0,
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Output header and all attachments.
|
|
if (@AttachmentIndex) {
|
|
$LayoutObject->Block(
|
|
Name => 'AttachmentHeader',
|
|
);
|
|
for my $Attachment (@AttachmentIndex) {
|
|
$LayoutObject->Block(
|
|
Name => 'AttachmentRow',
|
|
Data => {
|
|
%FAQData,
|
|
%{$Attachment},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Show message about links in iframes, if user didn't close it already.
|
|
if ( !$Self->{DoNotShowBrowserLinkMessage} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'BrowserLinkMessage',
|
|
);
|
|
}
|
|
|
|
# Show FAQ Content.
|
|
my $FAQBody = $LayoutObject->FAQContentShow(
|
|
FAQObject => $FAQObject,
|
|
InterfaceStates => $InterfaceStates,
|
|
FAQData => {%FAQData},
|
|
UserID => $Self->{UserID},
|
|
ReturnContent => 1,
|
|
);
|
|
|
|
# Get config of frontend module.
|
|
my $Config = $ConfigObject->Get("FAQ::Frontend::$Self->{Action}");
|
|
|
|
# Get the dynamic fields for this screen.
|
|
my $DynamicField = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
|
|
Valid => 1,
|
|
ObjectType => 'FAQ',
|
|
FieldFilter => $Config->{DynamicField} || {},
|
|
);
|
|
|
|
DYNAMICFIELD:
|
|
for my $DynamicFieldConfig ( @{$DynamicField} ) {
|
|
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
|
|
|
|
# Get print string for this dynamic field.
|
|
my $ValueStrg = $Kernel::OM->Get('Kernel::System::DynamicField::Backend')->DisplayValueRender(
|
|
DynamicFieldConfig => $DynamicFieldConfig,
|
|
Value => $FAQData{ 'DynamicField_' . $DynamicFieldConfig->{Name} },
|
|
ValueMaxChars => 250,
|
|
LayoutObject => $LayoutObject,
|
|
);
|
|
|
|
my $Label = $DynamicFieldConfig->{Label};
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'FAQDynamicField',
|
|
Data => {
|
|
Label => $Label,
|
|
},
|
|
);
|
|
|
|
if ( $ValueStrg->{Link} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'FAQDynamicFieldLink',
|
|
Data => {
|
|
Value => $ValueStrg->{Value},
|
|
Title => $ValueStrg->{Title},
|
|
Link => $ValueStrg->{Link},
|
|
$DynamicFieldConfig->{Name} => $ValueStrg->{Title},
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'FAQDynamicFieldPlain',
|
|
Data => {
|
|
Value => $ValueStrg->{Value},
|
|
Title => $ValueStrg->{Title},
|
|
},
|
|
);
|
|
}
|
|
|
|
# Example of dynamic fields order customization.
|
|
$LayoutObject->Block(
|
|
Name => 'FAQDynamicField_' . $DynamicFieldConfig->{Name},
|
|
Data => {
|
|
Label => $Label,
|
|
},
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'FAQDynamicField_' . $DynamicFieldConfig->{Name} . '_Plain',
|
|
Data => {
|
|
Value => $ValueStrg->{Value},
|
|
Title => $ValueStrg->{Title},
|
|
},
|
|
);
|
|
}
|
|
|
|
if ( $Nav ne 'None' ) {
|
|
|
|
# Show FAQ Voting.
|
|
if ($Voting) {
|
|
|
|
# Get voting config.
|
|
my $ShowVotingConfig = $ConfigObject->Get('FAQ::Item::Voting::Show');
|
|
if ( $ShowVotingConfig->{ $Interface->{Name} } ) {
|
|
|
|
# Check if the user already voted after last change.
|
|
if ( !$AlreadyVoted ) {
|
|
$Self->_FAQVoting( FAQData => {%FAQData} );
|
|
}
|
|
}
|
|
}
|
|
|
|
# Get linked objects.
|
|
my $LinkListWithData = $Kernel::OM->Get('Kernel::System::LinkObject')->LinkListWithData(
|
|
Object => 'FAQ',
|
|
Key => $GetParam{ItemID},
|
|
State => 'Valid',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
my $LinkTableViewMode = $ConfigObject->Get('LinkObject::ViewMode');
|
|
|
|
# Create the link table.
|
|
my $LinkTableStrg = $LayoutObject->LinkObjectTableCreate(
|
|
LinkListWithData => $LinkListWithData,
|
|
ViewMode => $LinkTableViewMode,
|
|
Object => 'FAQ',
|
|
Key => $GetParam{ItemID},
|
|
);
|
|
|
|
# Output the link table.
|
|
if ($LinkTableStrg) {
|
|
$LayoutObject->Block(
|
|
Name => 'LinkTable' . $LinkTableViewMode,
|
|
Data => {
|
|
LinkTableStrg => $LinkTableStrg,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
# Log access to this FAQ item.
|
|
$FAQObject->FAQLogAdd(
|
|
ItemID => $ParamObject->GetParam( Param => 'ItemID' ),
|
|
Interface => $Interface->{Name},
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Start template output.
|
|
if ( $Nav && $Nav eq 'None' ) {
|
|
|
|
# Only convert HTML to plain text if rich text editor is not used.
|
|
if ( $ConfigObject->Get('Frontend::RichText') ) {
|
|
$FAQData{FullBody} = $FAQBody;
|
|
}
|
|
else {
|
|
$FAQData{FullBody} = $HTMLUtilsObject->ToAscii(
|
|
String => $FAQBody,
|
|
);
|
|
}
|
|
|
|
# Get the public state type.
|
|
my $PublicStateType = $FAQObject->StateTypeGet(
|
|
Name => 'public',
|
|
UserID => $Self->{UserID},
|
|
);
|
|
|
|
# Remove in-line image links to FAQ images.
|
|
$FAQData{FullBody}
|
|
=~ s{ <img [^<>]+ Action=(Agent|Customer|Public)FAQ [^<>]+ > }{}gxms;
|
|
|
|
# Get configuration options for Ticket Compose.
|
|
my $TicketComposeConfig = $ConfigObject->Get('FAQ::TicketCompose');
|
|
|
|
$Param{UpdateArticleSubject} = $TicketComposeConfig->{UpdateArticleSubject} || 0;
|
|
if ( $Param{UpdateArticleSubject} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'UpdateArticleSubject',
|
|
Data => {},
|
|
);
|
|
}
|
|
|
|
# Send data to JS.
|
|
$LayoutObject->AddJSData(
|
|
Key => 'TicketCompose.UpdateArticleSubject',
|
|
Value => $Param{UpdateArticleSubject},
|
|
);
|
|
|
|
my $ShowOrBlock;
|
|
|
|
# Show "Insert Text" button.
|
|
if ( $TicketComposeConfig->{ShowInsertTextButton} ) {
|
|
if (
|
|
defined $TicketComposeConfig->{InsertMethod}
|
|
&& $TicketComposeConfig->{InsertMethod} eq 'Full'
|
|
)
|
|
{
|
|
$LayoutObject->Block(
|
|
Name => 'InsertFull',
|
|
Data => {},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'InsertText',
|
|
Data => {},
|
|
);
|
|
}
|
|
|
|
$ShowOrBlock = 1;
|
|
}
|
|
|
|
# Check if FAQ article is public.
|
|
if ( $FAQData{StateTypeID} == $PublicStateType->{StateID} ) {
|
|
|
|
my $HTTPType = $ConfigObject->Get('HttpType');
|
|
my $FQDN = $ConfigObject->Get('FQDN');
|
|
my $Baselink = $LayoutObject->{Baselink};
|
|
|
|
# Rewrite handle.
|
|
$Baselink
|
|
=~ s{ index[.]pl [?] }{public.pl?}gxms;
|
|
|
|
$FAQData{Publiclink} = $HTTPType . '://' . $FQDN . $Baselink
|
|
. "Action=PublicFAQZoom;ItemID=$FAQData{ItemID}";
|
|
|
|
#Sshow "Insert Link" button.
|
|
if ( $TicketComposeConfig->{ShowInsertLinkButton} ) {
|
|
$LayoutObject->Block(
|
|
Name => 'InsertLink',
|
|
Data => {},
|
|
);
|
|
$ShowOrBlock = 1;
|
|
}
|
|
|
|
# Show "Insert Text and Link" button.
|
|
if ( $TicketComposeConfig->{ShowInsertTextAndLinkButton} ) {
|
|
if (
|
|
defined $TicketComposeConfig->{InsertMethod}
|
|
&& $TicketComposeConfig->{InsertMethod} eq 'Full'
|
|
)
|
|
{
|
|
$LayoutObject->Block(
|
|
Name => 'InsertFullAndLink',
|
|
Data => {},
|
|
);
|
|
}
|
|
else {
|
|
$LayoutObject->Block(
|
|
Name => 'InsertTextAndLink',
|
|
Data => {},
|
|
);
|
|
}
|
|
$ShowOrBlock = 1;
|
|
}
|
|
}
|
|
|
|
my $CancelButtonClass = 'ZoomSmallButton';
|
|
|
|
# Show the "Or" block between the buttons and the Cancel & close window label.
|
|
if ($ShowOrBlock) {
|
|
$LayoutObject->Block(
|
|
Name => 'Or',
|
|
Data => {},
|
|
);
|
|
|
|
# Set the $CancelButtonClass to ''.
|
|
$CancelButtonClass = '';
|
|
}
|
|
|
|
# Send data to JS.
|
|
$LayoutObject->AddJSData(
|
|
Key => 'AgentFAQZoomSmall',
|
|
Value => 1,
|
|
);
|
|
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'AgentFAQZoomSmall',
|
|
Data => {
|
|
%FAQData,
|
|
%GetParam,
|
|
%Param,
|
|
CancelButtonClass => $CancelButtonClass || '',
|
|
},
|
|
);
|
|
}
|
|
else {
|
|
$Output .= $LayoutObject->Output(
|
|
TemplateFile => 'AgentFAQZoom',
|
|
Data => {
|
|
%FAQData,
|
|
%GetParam,
|
|
%Param,
|
|
},
|
|
);
|
|
}
|
|
if ( $Nav && $Nav eq 'None' ) {
|
|
$Output .= $LayoutObject->Footer( Type => 'Small' );
|
|
}
|
|
else {
|
|
$Output .= $LayoutObject->Footer();
|
|
}
|
|
|
|
return $Output;
|
|
}
|
|
|
|
sub _FAQVoting {
|
|
my ( $Self, %Param ) = @_;
|
|
|
|
my %FAQData = %{ $Param{FAQData} };
|
|
|
|
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'FAQVoting',
|
|
Data => {%FAQData},
|
|
);
|
|
|
|
# Get Voting rates setting.
|
|
my $VotingRates = $Kernel::OM->Get('Kernel::Config')->Get('FAQ::Item::Voting::Rates');
|
|
for my $RateValue ( sort { $a <=> $b } keys %{$VotingRates} ) {
|
|
|
|
# Create data structure for output.
|
|
my %Data = (
|
|
Value => $RateValue,
|
|
Title => $VotingRates->{$RateValue},
|
|
);
|
|
|
|
$LayoutObject->Block(
|
|
Name => 'FAQVotingRateRow',
|
|
Data => {%Data},
|
|
);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
1;
|