This commit is contained in:
2024-10-14 00:08:40 +02:00
parent dbfba56f66
commit 1462d52e13
4572 changed files with 2658864 additions and 0 deletions

View File

@@ -0,0 +1,611 @@
# --
# 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::CustomerFAQZoom;
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 );
if ( !defined $Self->{DoNotShowBrowserLinkMessage} ) {
my %UserPreferences = $Kernel::OM->Get('Kernel::System::CustomerUser')->GetPreferences(
UserID => $Self->{UserID},
);
if ( $UserPreferences{UserCustomerDoNotShowBrowserLinkMessage} ) {
$Self->{DoNotShowBrowserLinkMessage} = 1;
}
else {
$Self->{DoNotShowBrowserLinkMessage} = 0;
}
}
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
# get params
my %GetParam;
$GetParam{ItemID} = $ParamObject->GetParam( Param => 'ItemID' );
$GetParam{Rate} = $ParamObject->GetParam( Param => 'Rate' );
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# save, if browser link message was closed
if ( $Self->{Subaction} eq 'BrowserLinkMessage' ) {
$Kernel::OM->Get('Kernel::System::CustomerUser')->SetPreferences(
UserID => $Self->{UserID},
Key => 'UserCustomerDoNotShowBrowserLinkMessage',
Value => 1,
);
return $LayoutObject->Attachment(
ContentType => 'text/html',
Content => 1,
Type => 'inline',
NoCache => 1,
);
}
if ( !$GetParam{ItemID} ) {
return $LayoutObject->CustomerFatalError(
Message => Translatable('Need ItemID!'),
);
}
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->CustomerFatalError();
}
# get the valid ids
my @ValidIDs = $Kernel::OM->Get('Kernel::System::Valid')->ValidIDsGet();
my %ValidIDLookup = map { $_ => 1 } @ValidIDs;
# check user permission
my $Permission = $FAQObject->CheckCategoryCustomerPermission(
CustomerUser => $Self->{UserLogin},
CategoryID => $FAQData{CategoryID},
UserID => $Self->{UserID},
);
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# get interface state list
my $InterfaceStates = $FAQObject->StateTypeList(
Types => $ConfigObject->Get('FAQ::Customer::StateTypes'),
UserID => $Self->{UserID},
);
# permission check
if (
!$Permission
|| !$FAQData{Approved}
|| !$ValidIDLookup{ $FAQData{ValidID} }
|| !$InterfaceStates->{ $FAQData{StateTypeID} }
)
{
return $LayoutObject->CustomerNoPermission( WithHeader => 'yes' );
}
# store the last screen in session
$Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID(
SessionID => $Self->{SessionID},
Key => 'LastScreenView',
Value => $Self->{RequestedURL},
);
# ---------------------------------------------------------- #
# HTMLView Subaction
# ---------------------------------------------------------- #
if ( $Self->{Subaction} eq 'HTMLView' ) {
# get params
my $Field = $ParamObject->GetParam( Param => "Field" );
for my $Needed (qw( ItemID Field )) {
if ( !$Needed ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Needed Param: $Needed!",
);
return;
}
}
# get the Field content
my $FieldContent = $FAQObject->ItemFieldGet(
ItemID => $GetParam{ItemID},
Field => $Field,
UserID => $Self->{UserID},
);
# rewrite handle and action
$FieldContent
=~ s{ index[.]pl [?] Action=AgentFAQZoom }{customer.pl?Action=CustomerFAQZoom}gxms;
# take care of old style before FAQ 2.0.x
$FieldContent =~ s{
index[.]pl [?] Action=AgentFAQ [&](amp;)? Subaction=Download [&](amp;)?
}{customer.pl?Action=CustomerFAQZoom;Subaction=DownloadAttachment;}gxms;
# build base URL for inline images
my $SessionID = '';
if ( $Self->{SessionID} && !$Self->{SessionIDCookie} ) {
$SessionID = ';' . $Self->{SessionName} . '=' . $Self->{SessionID};
$FieldContent =~ s{
(Action=CustomerFAQZoom;Subaction=DownloadAttachment;ItemID=\d+;FileID=\d+)
}{$1$SessionID}gmsx;
}
my $HTMLUtilsObject = $Kernel::OM->Get('Kernel::System::HTMLUtils');
# 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,
) || '';
}
# 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 Subaction
# ---------------------------------------------------------- #
if ( $Self->{Subaction} eq 'DownloadAttachment' ) {
# manage parameters
$GetParam{FileID} = $ParamObject->GetParam( Param => 'FileID' );
if ( !defined $GetParam{FileID} ) {
return $LayoutObject->CustomerFatalError(
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->CustomerFatalError();
}
}
my $Output = $LayoutObject->CustomerHeader(
Value => $FAQData{Title},
);
$Output .= $LayoutObject->CustomerNavigationBar();
# set default interface settings
my $Interface = $FAQObject->StateTypeGet(
Name => 'external',
UserID => $Self->{UserID},
);
# get voting default option
my $Voting = $ConfigObject->Get('FAQ::Voting');
# 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 Subaction
# ---------------------------------------------------------- #
if ( $Self->{Subaction} eq 'Vote' ) {
# customer can't use this sub-action if is not enabled
if ( !$Voting ) {
$LayoutObject->CustomerFatalError(
Message => Translatable('The voting mechanism is not enabled!'),
);
}
# user can vote only once per FAQ revision
if ($AlreadyVoted) {
$Output .= $LayoutObject->Notify(
Priority => 'Error',
Info => Translatable('You have already voted!'),
);
}
# 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->CustomerFatalError(
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},
);
if ( !%FAQData ) {
return $LayoutObject->CustomerFatalError();
}
$Output .= $LayoutObject->Notify(
Info => Translatable('Thanks for your vote!'),
);
}
}
# user is able to vote but no rate has been selected
else {
$Output .= $LayoutObject->Notify(
Priority => 'Error',
Info => Translatable('No rate selected!'),
);
}
}
# prepare fields data (Still needed for PlainText)
FIELD:
for my $Field (qw(Field1 Field2 Field3 Field4 Field5 Field6)) {
next FIELD if !$FAQData{$Field};
# rewrite links to embedded images for customer interface
if ( $Interface->{Name} eq 'external' ) {
# rewrite handle and action
$FAQData{$Field}
=~ s{ index[.]pl [?] Action=AgentFAQZoom }{customer.pl?Action=CustomerFAQZoom}gxms;
# take care of old style before FAQ 2.0.x
$FAQData{$Field} =~ s{
index[.]pl [?] Action=AgentFAQ [&](amp;)? Subaction=Download [&](amp;)?
}{customer.pl?Action=CustomerFAQZoom;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,
);
}
# set voting results
$Param{VotingResultColor} = $LayoutObject->GetFAQItemVotingRateColor(
Rate => $FAQData{VoteResult},
);
if ( !$Param{VotingResultColor} || $FAQData{Votes} eq '0' ) {
$Param{VotingResultColor} = 'Gray';
}
# show back link
$LayoutObject->Block(
Name => 'Back',
Data => \%Param,
);
# get multi-language default option
my $MultiLanguage = $ConfigObject->Get('FAQ::MultiLanguage');
# show language
if ($MultiLanguage) {
$LayoutObject->Block(
Name => 'Language',
Data => {%FAQData},
);
}
# show votes
if ($Voting) {
# always displays Votes result even if its 0
$LayoutObject->Block(
Name => 'ViewVotes',
Data => {%FAQData},
);
}
# show FAQ path
my $ShowFAQPath = $LayoutObject->FAQPathShow(
FAQObject => $FAQObject,
CategoryID => $FAQData{CategoryID},
PathForItem => 1,
UserID => $Self->{UserID},
);
if ($ShowFAQPath) {
$LayoutObject->Block(
Name => 'FAQPathItemElement',
Data => {%FAQData},
);
}
# 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,
},
);
}
}
# output rating stars
if ($Voting) {
$LayoutObject->FAQRatingStarsShow(
VoteResult => $FAQData{VoteResult},
Votes => $FAQData{Votes},
);
}
# output attachments if any
my @AttachmentIndex = $FAQObject->AttachmentIndex(
ItemID => $GetParam{ItemID},
ShowInline => 0,
UserID => $Self->{UserID},
);
# output 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
$LayoutObject->FAQContentShow(
FAQObject => $FAQObject,
InterfaceStates => $InterfaceStates,
FAQData => {%FAQData},
UserID => $Self->{UserID},
);
# 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} || {},
);
my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{$DynamicField} ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
my $Value = $DynamicFieldBackendObject->ValueGet(
DynamicFieldConfig => $DynamicFieldConfig,
ObjectID => $GetParam{ItemID},
);
# get print string for this dynamic field
my $ValueStrg = $DynamicFieldBackendObject->DisplayValueRender(
DynamicFieldConfig => $DynamicFieldConfig,
Value => $Value,
ValueMaxChars => 250,
LayoutObject => $LayoutObject,
);
my $Label = $DynamicFieldConfig->{Label};
$LayoutObject->Block(
Name => 'FAQDynamicField',
Data => {
Label => $Label,
Value => $ValueStrg->{Value},
Title => $ValueStrg->{Title},
},
);
# example of dynamic fields order customization
$LayoutObject->Block(
Name => 'FAQDynamicField_' . $DynamicFieldConfig->{Name},
Data => {
Label => $Label,
Value => $ValueStrg->{Value},
Title => $ValueStrg->{Title},
},
);
}
# 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} );
}
}
}
# log access to this FAQ item
$FAQObject->FAQLogAdd(
ItemID => $ParamObject->GetParam( Param => 'ItemID' ),
Interface => $Interface->{Name},
UserID => $Self->{UserID},
);
$Output .= $LayoutObject->Output(
TemplateFile => 'CustomerFAQZoom',
Data => {
%FAQData,
%GetParam,
%Param,
},
);
$Output .= $LayoutObject->CustomerFooter();
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;