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,687 @@
# --
# 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::AgentFAQAdd;
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 );
# Get config of frontend module.
$Self->{Config} = $Kernel::OM->Get('Kernel::Config')->Get("FAQ::Frontend::$Self->{Action}") || '';
# Get the dynamic fields for this screen.
$Self->{DynamicField} = $Kernel::OM->Get('Kernel::System::DynamicField')->DynamicFieldListGet(
Valid => 1,
ObjectType => 'FAQ',
FieldFilter => $Self->{Config}->{DynamicField} || {},
);
return $Self;
}
sub Run {
my ( $Self, %Param ) = @_;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# Permission check.
if ( !$Self->{AccessRw} ) {
return $LayoutObject->NoPermission(
Message => Translatable('You need rw permission!'),
WithHeader => 'yes',
);
}
my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request');
# Get parameters from web request.
my %GetParam;
for my $ParamName (
qw(Title CategoryID StateID LanguageID ValidID Keywords Approved Field1 Field2 Field3 Field4 Field5 Field6)
)
{
$GetParam{$ParamName} = $ParamObject->GetParam( Param => $ParamName );
}
my $FAQObject = $Kernel::OM->Get('Kernel::System::FAQ');
# Get categories (with category long names) where user has rights.
my $UserCategoriesLongNames = $FAQObject->GetUserCategoriesLongNames(
Type => 'rw',
UserID => $Self->{UserID},
);
# Check that there are categories available for this user.
if (
!$UserCategoriesLongNames
|| ref $UserCategoriesLongNames ne 'HASH'
|| !%{$UserCategoriesLongNames}
)
{
return $LayoutObject->ErrorScreen(
Message => Translatable('No categories found where user has read/write permissions!'),
Comment => Translatable('Please contact the administrator.'),
);
}
# Get dynamic field values form http request.
my %DynamicFieldValues;
my $DynamicFieldBackendObject = $Kernel::OM->Get('Kernel::System::DynamicField::Backend');
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
# Extract the dynamic field value form the web request.
$DynamicFieldValues{ $DynamicFieldConfig->{Name} } = $DynamicFieldBackendObject->EditFieldValueGet(
DynamicFieldConfig => $DynamicFieldConfig,
ParamObject => $ParamObject,
LayoutObject => $LayoutObject,
);
}
my $UploadCacheObject = $Kernel::OM->Get('Kernel::System::Web::UploadCache');
my $FormID = $ParamObject->GetParam( Param => 'FormID' );
if ( !$FormID ) {
$FormID = $UploadCacheObject->FormIDCreate();
}
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# set content type
my $ContentType = 'text/plain';
if ( $LayoutObject->{BrowserRichText} && $ConfigObject->Get('FAQ::Item::HTML') ) {
$ContentType = 'text/html';
}
my $QueueObject = $Kernel::OM->Get('Kernel::System::Queue');
# ------------------------------------------------------------ #
# Show the FAQ add screen.
# ------------------------------------------------------------ #
if ( !$Self->{Subaction} ) {
# Create HTML strings for all dynamic fields.
my %DynamicFieldHTML;
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
# Get field HTML.
$DynamicFieldHTML{ $DynamicFieldConfig->{Name} } =
$DynamicFieldBackendObject->EditFieldRender(
DynamicFieldConfig => $DynamicFieldConfig,
Mandatory =>
$Self->{Config}->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
LayoutObject => $LayoutObject,
ParamObject => $ParamObject,
);
}
my $Output = $LayoutObject->Header();
$Output .= $LayoutObject->NavigationBar();
if ( $ConfigObject->Get('FAQ::ApprovalRequired') ) {
# Get Approval queue name.
my $ApprovalQueue = $ConfigObject->Get('FAQ::ApprovalQueue') || '';
# Check if Approval queue exists.
my $ApprovalQueueID = $QueueObject->QueueLookup(
Queue => $ApprovalQueue,
);
# Show notification if Approval queue does not exists.
if ( !$ApprovalQueueID ) {
$Output .= $LayoutObject->Notify(
Priority => 'Error',
Info => "FAQ Approval is enabled but queue '$ApprovalQueue' does not exists",
Link => $LayoutObject->{Baselink}
. 'Action=AdminSystemConfiguration;Subaction=ViewCustomGroup;Names=FAQ::ApprovalQueue',
);
}
}
$Output .= $Self->_MaskNew(
FormID => $FormID,
UserCategoriesLongNames => $UserCategoriesLongNames,
DynamicFieldHTML => \%DynamicFieldHTML,
# Last viewed category from session (written by FAQ explorer).
CategoryID => $Self->{LastViewedCategory},
ContentType => $ContentType,
);
# footer
$Output .= $LayoutObject->Footer();
return $Output;
}
# ------------------------------------------------------------ #
# Save the FAQ.
# ------------------------------------------------------------ #
elsif ( $Self->{Subaction} eq 'Save' ) {
# Challenge token check for write action.
$LayoutObject->ChallengeTokenCheck();
my $Output = $LayoutObject->Header();
$Output .= $LayoutObject->NavigationBar();
my %Error;
for my $ParamName (qw(Title CategoryID)) {
# If required field is not given, add server error class.
if ( !$GetParam{$ParamName} ) {
$Error{ $ParamName . 'ServerError' } = 'ServerError';
}
}
# Create HTML strings for all dynamic fields.
my %DynamicFieldHTML;
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
my $ValidationResult = $DynamicFieldBackendObject->EditFieldValueValidate(
DynamicFieldConfig => $DynamicFieldConfig,
ParamObject => $ParamObject,
Mandatory =>
$Self->{Config}->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
);
if ( !IsHashRefWithData($ValidationResult) ) {
return $LayoutObject->ErrorScreen(
Message => $LayoutObject->{LanguageObject}->Translate(
'Could not perform validation on field %s!',
$DynamicFieldConfig->{Label},
),
Comment => Translatable('Please contact the administrator.'),
);
}
# Propagate validation error to the Error variable to be detected by the frontend.
if ( $ValidationResult->{ServerError} ) {
$Error{ $DynamicFieldConfig->{Name} } = ' ServerError';
}
# Get field HTML.
$DynamicFieldHTML{ $DynamicFieldConfig->{Name} } =
$DynamicFieldBackendObject->EditFieldRender(
DynamicFieldConfig => $DynamicFieldConfig,
Mandatory =>
$Self->{Config}->{DynamicField}->{ $DynamicFieldConfig->{Name} } == 2,
ServerError => $ValidationResult->{ServerError} || '',
ErrorMessage => $ValidationResult->{ErrorMessage} || '',
LayoutObject => $LayoutObject,
ParamObject => $ParamObject,
);
}
# Send server error if any required parameter is missing.
if (%Error) {
# Get all attachments meta data.
my @Attachments = $UploadCacheObject->FormIDGetAllFilesMeta(
FormID => $FormID,
);
if ( $ConfigObject->Get('FAQ::ApprovalRequired') ) {
my $ApprovalQueue = $ConfigObject->Get('FAQ::ApprovalQueue') || '';
# Check if Approval queue exists.
my $ApprovalQueueID = $QueueObject->QueueLookup(
Queue => $ApprovalQueue,
);
# Show notification if Approval queue does not exists.
if ( !$ApprovalQueueID ) {
$Output .= $LayoutObject->Notify(
Priority => 'Error',
Info =>
"FAQ Approval is enabled but queue '$ApprovalQueue' does not exists",
Link => $LayoutObject->{Baselink}
. 'Action=AdminSystemConfiguration;Subaction=ViewCustomGroup;Names=FAQ::ApprovalQueue',
);
}
}
$Output .= $Self->_MaskNew(
UserCategoriesLongNames => $UserCategoriesLongNames,
Attachments => \@Attachments,
%GetParam,
%Error,
FormID => $FormID,
DynamicFieldHTML => \%DynamicFieldHTML,
ContentType => $ContentType,
);
$Output .= $LayoutObject->Footer();
return $Output;
}
# Add the new FAQ item.
my $ItemID = $FAQObject->FAQAdd(
%GetParam,
ContentType => $ContentType,
UserID => $Self->{UserID},
);
# Show error if FAQ item could not be added.
if ( !$ItemID ) {
return $LayoutObject->ErrorScreen();
}
# Get all attachments from upload cache.
my @Attachments = $UploadCacheObject->FormIDGetAllFilesData(
FormID => $FormID,
);
# Write attachments
ATTACHMENT:
for my $Attachment (@Attachments) {
# Check if attachment is an inline attachment.
my $Inline = 0;
if ( $Attachment->{ContentID} ) {
# Remember that it is inline.
$Inline = 1;
# Remember if this inline attachment is used in any FAQ article.
my $ContentIDFound;
# Check all fields for content-id.
FIELD:
for my $Number ( 1 .. 6 ) {
my $Field = $GetParam{ 'Field' . $Number };
# Skip empty fields.
next FIELD if !$Field;
# Skip fields that do not contain the content-id.
next FIELD if $Field !~ m{ $Attachment->{ContentID} }xms;
$ContentIDFound = 1;
last FIELD;
}
# We do not want to keep this attachment, because it was deleted in the rich-text editor
next ATTACHMENT if !$ContentIDFound;
}
my $FileID = $FAQObject->AttachmentAdd(
%{$Attachment},
ItemID => $ItemID,
Inline => $Inline,
UserID => $Self->{UserID},
);
if ( !$FileID ) {
return $LayoutObject->FatalError();
}
next ATTACHMENT if !$Inline;
next ATTACHMENT if !$LayoutObject->{BrowserRichText};
# Rewrite the URLs of the inline images for the uploaded pictures.
my $Success = $FAQObject->FAQInlineAttachmentURLUpdate(
Attachment => $Attachment,
FormID => $FormID,
ItemID => $ItemID,
FileID => $FileID,
UserID => $Self->{UserID},
);
if ( !$Success ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Could not update the inline image URLs for FAQ Item# '$ItemID'!",
);
}
}
# Delete the upload cache.
$UploadCacheObject->FormIDRemove(
FormID => $FormID,
);
# Set dynamic fields.
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
my $Success = $DynamicFieldBackendObject->ValueSet(
DynamicFieldConfig => $DynamicFieldConfig,
ObjectID => $ItemID,
Value => $DynamicFieldValues{ $DynamicFieldConfig->{Name} },
UserID => $Self->{UserID},
);
}
# Redirect to FAQ zoom.
return $LayoutObject->Redirect( OP => 'Action=AgentFAQZoom;ItemID=' . $ItemID );
}
}
sub _MaskNew {
my ( $Self, %Param ) = @_;
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# Get list type.
my $TreeView = 0;
if ( $ConfigObject->Get('Ticket::Frontend::ListType') eq 'tree' ) {
$TreeView = 1;
}
# Get valid list.
my %ValidList = $Kernel::OM->Get('Kernel::System::Valid')->ValidList();
my %ValidListReverse = reverse %ValidList;
my %Data;
my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
# Build valid selection.
$Data{ValidOption} = $LayoutObject->BuildSelection(
Data => \%ValidList,
Name => 'ValidID',
SelectedID => $Param{ValidID} || $ValidListReverse{valid},
Class => 'Modernize',
);
# Set no server error class as default.
$Param{CategoryIDServerError} ||= '';
# Build category selection.
$Data{CategoryOption} = $LayoutObject->BuildSelection(
Data => $Param{UserCategoriesLongNames},
Name => 'CategoryID',
SelectedID => $Param{CategoryID},
PossibleNone => 1,
Class => 'Validate_Required Modernize ' . $Param{CategoryIDServerError},
Translation => 0,
TreeView => 1,
);
my $FAQObject = $Kernel::OM->Get('Kernel::System::FAQ');
my %Languages = $FAQObject->LanguageList(
UserID => $Self->{UserID},
);
# Get the selected language.
my $SelectedLanguage;
if ( $Param{LanguageID} && $Languages{ $Param{LanguageID} } ) {
# Get language from given LanguageID.
$SelectedLanguage = $Languages{ $Param{LanguageID} };
}
else {
# Use the user language, or if not found 'en'
$SelectedLanguage = $LayoutObject->{UserLanguage} || 'en';
# Get user LanguageID
my $SelectedLanguageID = $FAQObject->LanguageLookup(
Name => $SelectedLanguage,
);
# Check if LanduageID does not exists
if ( !$SelectedLanguageID ) {
# Get the lowest languageID from the FAQ languages list
my @LanguageIDs = sort keys %Languages;
$SelectedLanguageID = $LanguageIDs[0];
# Set the language with lowest LanguageID as selected language,
# as this is the first and (we assumed) the most used language
$SelectedLanguage = $Languages{$SelectedLanguageID};
}
}
# Build the language selection.
$Data{LanguageOption} = $LayoutObject->BuildSelection(
Data => \%Languages,
Name => 'LanguageID',
SelectedValue => $SelectedLanguage,
Translation => 0,
Class => 'Modernize',
);
my @StateTypes = $ConfigObject->Get('FAQ::Agent::StateTypes');
my %States = $FAQObject->StateList(
Types => @StateTypes,
UserID => $Self->{UserID},
);
# Get the selected state.
my $SelectedState;
if ( $Param{StateID} && $States{ $Param{StateID} } ) {
# Get state from given StateID.
$SelectedState = $States{ $Param{StateID} };
}
else {
# Get default state.
$SelectedState = $ConfigObject->Get('FAQ::Default::State') || 'internal (agent)';
}
# Build the state selection.
$Data{StateOption} = $LayoutObject->BuildSelection(
Data => \%States,
Name => 'StateID',
SelectedValue => $SelectedState,
Translation => 1,
Class => 'Modernize',
);
# Show attachments.
ATTACHMENT:
my @AttachmentList;
for my $Attachment ( @{ $Param{Attachments} } ) {
# Do not show inline images as attachments (they have a ContentID).
if ( $Attachment->{ContentID} && $LayoutObject->{BrowserRichText} ) {
next ATTACHMENT;
}
push @{ $Param{AttachmentList} }, $Attachment;
}
$LayoutObject->Block(
Name => 'FAQAdd',
Data => {
%Param,
%Data,
},
);
# Show languages field.
my $MultiLanguage = $ConfigObject->Get('FAQ::MultiLanguage');
if ($MultiLanguage) {
$LayoutObject->Block(
Name => 'Language',
Data => {
%Param,
%Data,
},
);
}
else {
# Get default language.
my $DefaultLanguage = $ConfigObject->Get('FAQ::Default::Language') || 'en';
# Get default LanguageID
my $LanguageID = $FAQObject->LanguageLookup(
Name => $DefaultLanguage,
);
# Create default language if it was deleted or does not exists.
if ( !$LanguageID ) {
my $InsertLanguage = $FAQObject->LanguageAdd(
Name => $DefaultLanguage,
UserID => 1,
);
if ( !$InsertLanguage ) {
# Return with error screen.
return $LayoutObject->ErrorScreen(
Message => Translatable('No default language found and can\'t create a new one.'),
Comment => Translatable('Please contact the administrator.'),
);
}
# Get default LanguageID.
$LanguageID = $FAQObject->LanguageLookup(
Name => $DefaultLanguage,
);
}
$Param{LanguageID} = $LanguageID;
$LayoutObject->Block(
Name => 'NoLanguage',
Data => {
%Param,
%Data,
},
);
}
# Show approval field.
if ( $ConfigObject->Get('FAQ::ApprovalRequired') ) {
# Check permission.
my %Groups = reverse $Kernel::OM->Get('Kernel::System::Group')->GroupMemberList(
UserID => $Self->{UserID},
Type => 'ro',
Result => 'HASH',
);
# Get the FAQ approval group from config.
my $ApprovalGroup = $ConfigObject->Get('FAQ::ApprovalGroup') || '';
# Build the approval selection if user is in the approval group.
if ( $Groups{$ApprovalGroup} ) {
$Data{ApprovalOption} = $LayoutObject->BuildSelection(
Name => 'Approved',
Data => {
0 => Translatable('No'),
1 => Translatable('Yes'),
},
SelectedID => $Param{Approved} || 0,
Class => 'Modernize',
);
$LayoutObject->Block(
Name => 'Approval',
Data => {
%Data,
},
);
}
}
# Get config of frontend module.
my $Config = $ConfigObject->Get("FAQ::Frontend::$Self->{Action}") || '';
# Add rich text editor JavaScript only if activated and the browser can handle it
# otherwise just a text-area is shown
if ( $LayoutObject->{BrowserRichText} && $ConfigObject->Get('FAQ::Item::HTML') ) {
# Use height/width defined for this screen.
$Param{RichTextHeight} = $Config->{RichTextHeight} || 0;
$Param{RichTextWidth} = $Config->{RichTextWidth} || 0;
# Set up rich text editor.
$LayoutObject->SetRichTextParameters(
Data => \%Param,
);
}
# Set default interface settings.
my $InterfaceStates = $FAQObject->StateTypeList(
Types => @StateTypes,
UserID => $Self->{UserID},
);
# Show FAQ Content.
$LayoutObject->FAQContentShow(
FAQObject => $FAQObject,
InterfaceStates => $InterfaceStates,
FAQData => {
%Param,
},
UserID => $Self->{UserID},
);
# Dynamic fields
DYNAMICFIELD:
for my $DynamicFieldConfig ( @{ $Self->{DynamicField} } ) {
next DYNAMICFIELD if !IsHashRefWithData($DynamicFieldConfig);
# Skip fields that HTML could not be retrieved.
next DYNAMICFIELD if !IsHashRefWithData(
$Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} }
);
# Get the HTML strings form $Param.
my $DynamicFieldHTML = $Param{DynamicFieldHTML}->{ $DynamicFieldConfig->{Name} };
$LayoutObject->Block(
Name => 'DynamicField',
Data => {
Name => $DynamicFieldConfig->{Name},
Label => $DynamicFieldHTML->{Label},
Field => $DynamicFieldHTML->{Field},
},
);
# Example of dynamic fields order customization.
$LayoutObject->Block(
Name => 'DynamicField_' . $DynamicFieldConfig->{Name},
Data => {
Name => $DynamicFieldConfig->{Name},
Label => $DynamicFieldHTML->{Label},
Field => $DynamicFieldHTML->{Field},
},
);
}
return $LayoutObject->Output(
TemplateFile => 'AgentFAQAdd',
Data => \%Param,
);
}
1;