Files
2024-10-14 00:08:40 +02:00

445 lines
12 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::System::ImportExport::FormatBackend::CSV;
use strict;
use warnings;
use Kernel::Language qw(Translatable);
our @ObjectDependencies = (
'Kernel::System::ImportExport',
'Kernel::System::Log',
'Kernel::System::Main',
);
=head1 NAME
Kernel::System::ImportExport::FormatBackend::CSV - import/export backend for CSV
=head1 DESCRIPTION
All functions to import and export a csv format
=cut
=head2 new()
Create an object
use Kernel::System::ObjectManager;
local $Kernel::OM = Kernel::System::ObjectManager->new();
my $ImportExportCSVBackendObject = $Kernel::OM->Get('Kernel::System::ImportExport::FormatBackend::CSV');
=cut
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
if ( !$Kernel::OM->Get('Kernel::System::Main')->Require('Text::CSV') ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "CPAN module Text::CSV is required to use the CSV import/export module!",
);
return;
}
# define available separators
$Self->{AvailableSeparators} = {
Tabulator => "\t",
Semicolon => ';',
Colon => ':',
Dot => '.',
Comma => ',',
};
return $Self;
}
=head2 FormatAttributesGet()
Get the format attributes of a format as array/hash reference
my $Attributes = $FormatBackend->FormatAttributesGet(
UserID => 1,
);
=cut
sub FormatAttributesGet {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{UserID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need UserID!',
);
return;
}
my $Attributes = [
{
Key => 'ColumnSeparator',
Name => Translatable('Column Separator'),
Input => {
Type => 'Selection',
Data => {
Tabulator => Translatable('Tabulator (TAB)'),
Semicolon => Translatable('Semicolon (;)'),
Colon => Translatable('Colon (:)'),
Dot => Translatable('Dot (.)'),
Comma => Translatable('Comma (,)'),
},
Required => 1,
Translation => 1,
PossibleNone => 1,
},
},
{
Key => 'Charset',
Name => Translatable('Charset'),
Input => {
Type => 'Text',
ValueDefault => 'UTF-8',
Required => 1,
Translation => 0,
Size => 20,
MaxLength => 20,
Readonly => 1,
},
},
{
Key => 'IncludeColumnHeaders',
Name => Translatable('Include Column Headers'),
Input => {
Type => 'Selection',
Data => {
0 => Translatable('No'),
1 => Translatable('Yes'),
},
Translation => 1,
PossibleNone => 0,
},
},
];
return $Attributes;
}
=head2 MappingFormatAttributesGet()
Get the mapping attributes of an format as array/hash reference
my $Attributes = $FormatBackend->MappingFormatAttributesGet(
UserID => 1,
);
=cut
sub MappingFormatAttributesGet {
my ( $Self, %Param ) = @_;
# check needed object
if ( !$Param{UserID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need UserID!',
);
return;
}
my $Attributes = [
{
Key => 'Column',
Name => Translatable('Column'),
Input => {
Type => 'TT',
Data => '',
Required => 0,
},
},
];
return $Attributes;
}
=head2 ImportDataGet()
Get import data as C<2D-array> reference
my $ImportData = $FormatBackend->ImportDataGet(
TemplateID => 123,
SourceContent => $StringRef, # (optional)
UserID => 1,
);
=cut
sub ImportDataGet {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
return [] if !defined $Param{SourceContent};
# check source content
if ( ref $Param{SourceContent} ne 'SCALAR' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'SourceContent must be a scalar reference',
);
return;
}
# get format data
my $FormatData = $Kernel::OM->Get('Kernel::System::ImportExport')->FormatDataGet(
TemplateID => $Param{TemplateID},
UserID => $Param{UserID},
);
# check format data
if ( !$FormatData || ref $FormatData ne 'HASH' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No format data found for the template id $Param{TemplateID}",
);
return;
}
# get charset
my $Charset = $FormatData->{Charset} ||= '';
# check the charset
if ( $Charset ne 'UTF-8' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No valid charset found for the template id $Param{TemplateID}. Charset must be UTF-8!",
);
return;
}
# get separator
$FormatData->{ColumnSeparator} ||= '';
my $Separator = $Self->{AvailableSeparators}->{ $FormatData->{ColumnSeparator} } || '';
# check the separator
if ( !$Separator ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No valid separator found for the template id $Param{TemplateID}",
);
return;
}
# create the parser object
my $ParseObject = Text::CSV->new(
{
quote_char => '"',
escape_char => '"',
sep_char => $Separator,
eol => '',
always_quote => 1,
binary => 1,
keep_meta_info => 0,
allow_loose_quotes => 0,
allow_loose_escapes => 0,
allow_whitespace => 0,
blank_is_undef => 0,
verbatim => 0,
}
);
# create an in memory temp file and open it
my $FileContent = '';
open my $FH, '+<', \$FileContent; ## no critic
# write source content
print $FH ${ $Param{SourceContent} };
# rewind file handle
seek $FH, 0, 0;
# parse the content
my $LineCount = 1;
my @ImportData;
# it is important to use this syntax "while ( !eof($FH) )"
# as the CPAN module Text::CSV_XS might show errors if the
# getline call is within the while test
# have a look at http://bugs.otrs.org/show_bug.cgi?id=9270
while ( !eof($FH) ) {
my $Column = $ParseObject->getline($FH);
push @ImportData, $Column;
$LineCount++;
}
# error handling
my ( $ParseErrorCode, $ParseErrorString ) = $ParseObject->error_diag();
if ($ParseErrorCode) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "ImportError at line $LineCount, "
. "ErrorCode: $ParseErrorCode '$ParseErrorString' ",
);
}
# close the in memory file handle
close $FH;
# set utf8 flag
for my $Row (@ImportData) {
for my $Cell ( @{$Row} ) {
Encode::_utf8_on($Cell);
}
}
return \@ImportData;
}
=head2 ExportDataSave()
Export one row of the export data
my $DestinationContent = $FormatBackend->ExportDataSave(
TemplateID => 123,
ExportDataRow => $ArrayRef,
UserID => 1,
);
=cut
sub ExportDataSave {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(TemplateID ExportDataRow UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# check export data row
if ( ref $Param{ExportDataRow} ne 'ARRAY' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'ExportDataRow must be an array reference',
);
return;
}
# get format data
my $FormatData = $Kernel::OM->Get('Kernel::System::ImportExport')->FormatDataGet(
TemplateID => $Param{TemplateID},
UserID => $Param{UserID},
);
# check format data
if ( !$FormatData || ref $FormatData ne 'HASH' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No format data found for the template id $Param{TemplateID}",
);
return;
}
# get charset
my $Charset = $FormatData->{Charset} ||= '';
# check the charset
if ( $Charset ne 'UTF-8' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No valid charset found for the template id $Param{TemplateID}. Charset must be UTF-8!",
);
return;
}
# get columnn separator
$FormatData->{ColumnSeparator} ||= '';
my $Separator = $Self->{AvailableSeparators}->{ $FormatData->{ColumnSeparator} } || '';
# check the separator
if ( !$Separator ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "No valid separator found for the template id $Param{TemplateID}",
);
return;
}
# create the parser object
my $ParseObject = Text::CSV->new(
{
quote_char => '"',
escape_char => '"',
sep_char => $Separator,
eol => '',
always_quote => 1,
binary => 1,
keep_meta_info => 0,
allow_loose_quotes => 0,
allow_loose_escapes => 0,
allow_whitespace => 0,
blank_is_undef => 0,
verbatim => 0,
}
);
if ( !$ParseObject->combine( @{ $Param{ExportDataRow} } ) ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Can't combine the export data to a string!",
);
return;
}
# create the CSV string
my $String = $ParseObject->string();
# set utf8 flag
Encode::_utf8_on($String);
return $String;
}
1;
=head1 TERMS AND CONDITIONS
This software is part of the OTRS project (L<https://otrs.org/>).
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 L<https://www.gnu.org/licenses/gpl-3.0.txt>.
=cut