Files
scripts/Perl OTRS/Kernel/System/GeneralCatalog.pm
2024-10-14 00:08:40 +02:00

702 lines
19 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::GeneralCatalog;
use strict;
use warnings;
our @ObjectDependencies = (
'Kernel::Config',
'Kernel::System::Cache',
'Kernel::System::CheckItem',
'Kernel::System::DB',
'Kernel::System::Log',
'Kernel::System::Main',
);
=head1 NAME
Kernel::System::GeneralCatalog - general catalog lib
=head1 PUBLIC INTERFACE
=cut
=head2 new()
create an object
use Kernel::System::ObjectManager;
local $Kernel::OM = Kernel::System::ObjectManager->new();
my $GeneralCatalogObject = $Kernel::OM->Get('Kernel::System::GeneralCatalog');
=cut
sub new {
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
# load generator preferences module
my $GeneratorModule = $Kernel::OM->Get('Kernel::Config')->Get('GeneralCatalog::PreferencesModule')
|| 'Kernel::System::GeneralCatalog::PreferencesDB';
if ( $Kernel::OM->Get('Kernel::System::Main')->Require($GeneratorModule) ) {
$Self->{PreferencesObject} = $GeneratorModule->new(%Param);
}
# define cache settings
$Self->{CacheType} = 'GeneralCatalog';
$Self->{CacheTTL} = 60 * 60 * 3;
return $Self;
}
=head2 ClassList()
return an array reference of all general catalog classes
my $ArrayRef = $GeneralCatalogObject->ClassList();
=cut
sub ClassList {
my ( $Self, %Param ) = @_;
# ask database
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT DISTINCT(general_catalog_class) '
. 'FROM general_catalog ORDER BY general_catalog_class',
);
# fetch the result
my @ClassList;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
push @ClassList, $Row[0];
}
# cache the result
my $CacheKey = 'ClassList';
$Kernel::OM->Get('Kernel::System::Cache')->Set(
Type => $Self->{CacheType},
TTL => $Self->{CacheTTL},
Key => $CacheKey,
Value => \@ClassList,
);
return \@ClassList;
}
=head2 ClassRename()
rename a general catalog class
my $True = $GeneralCatalogObject->ClassRename(
ClassOld => 'ITSM::ConfigItem::State',
ClassNew => 'ITSM::ConfigItem::DeploymentState',
);
=cut
sub ClassRename {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(ClassOld ClassNew)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# cleanup given params
for my $Argument (qw(ClassOld ClassNew)) {
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
StringRef => \$Param{$Argument},
RemoveAllNewlines => 1,
RemoveAllTabs => 1,
RemoveAllSpaces => 1,
);
}
return 1 if $Param{ClassNew} eq $Param{ClassOld};
# check if new class name already exists
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM general_catalog WHERE general_catalog_class = ?',
Bind => [ \$Param{ClassNew} ],
Limit => 1,
);
# fetch the result
my $AlreadyExists = 0;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$AlreadyExists = 1;
}
if ($AlreadyExists) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Can't rename class $Param{ClassOld}! New classname already exists."
);
return;
}
# reset cache
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
Type => $Self->{CacheType},
);
# rename general catalog class
return $Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => 'UPDATE general_catalog SET general_catalog_class = ? '
. 'WHERE general_catalog_class = ?',
Bind => [ \$Param{ClassNew}, \$Param{ClassOld} ],
);
}
=head2 ItemList()
returns a list as a hash reference of one general catalog class
my $HashRef = $GeneralCatalogObject->ItemList(
Class => 'ITSM::Service::Type',
Valid => 0, # (optional) default 1
Preferences => { # (optional) default {}
Permission => 2, # or whatever preferences can be used
},
);
=cut
sub ItemList {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{Class} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need Class!'
);
return;
}
# set default value
if ( !defined $Param{Valid} ) {
$Param{Valid} = 1;
}
my $PreferencesCacheKey = '';
my $PreferencesTable = '';
my $PreferencesWhere = '';
my @PreferencesBind;
# handle given preferences
if ( exists $Param{Preferences} && ref $Param{Preferences} eq 'HASH' ) {
$PreferencesTable = ', general_catalog_preferences';
my @Wheres;
# add all preferences given to where-clause
for my $Key ( sort keys %{ $Param{Preferences} } ) {
if ( ref( $Param{Preferences}->{$Key} ) ne 'ARRAY' ) {
$Param{Preferences}->{$Key} = [ $Param{Preferences}->{$Key} ];
}
push @Wheres, '(pref_key = ? AND pref_value IN ('
. join( ', ', map {'?'} @{ $Param{Preferences}->{$Key} } )
. '))';
push @PreferencesBind, \$Key, map { \$_ } @{ $Param{Preferences}->{$Key} };
# add functionality list to cache key
$PreferencesCacheKey .= '####' if $PreferencesCacheKey;
$PreferencesCacheKey .= join q{####}, $Key, map {$_} @{ $Param{Preferences}->{$Key} };
}
$PreferencesWhere = 'AND general_catalog.id = general_catalog_preferences.general_catalog_id';
$PreferencesWhere .= ' AND ' . join ' AND ', @Wheres;
}
# create sql string
my $SQL = "SELECT id, name FROM general_catalog $PreferencesTable "
. "WHERE general_catalog_class = ? $PreferencesWhere ";
my @BIND = ( \$Param{Class}, @PreferencesBind );
# add valid string to sql string
if ( $Param{Valid} ) {
$SQL .= 'AND valid_id = 1 ';
}
# create cache key
my $CacheKey = 'ItemList::' . $Param{Class} . '####' . $Param{Valid} . '####' . $PreferencesCacheKey;
# check if result is already cached
my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get(
Type => $Self->{CacheType},
Key => $CacheKey,
);
return $Cache if $Cache;
# ask database
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => $SQL,
Bind => \@BIND,
);
# fetch the result
my %Data;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$Data{ $Row[0] } = $Row[1];
}
# just return without logging an error and without caching the empty result
return if !%Data;
# cache the result
$Kernel::OM->Get('Kernel::System::Cache')->Set(
Type => $Self->{CacheType},
TTL => $Self->{CacheTTL},
Key => $CacheKey,
Value => \%Data,
);
return \%Data;
}
=head2 ItemGet()
get item attributes
my $ItemDataRef = $GeneralCatalogObject->ItemGet(
ItemID => 3,
);
or
my $ItemDataRef = $GeneralCatalogObject->ItemGet(
Class => 'ITSM::Service::Type',
Name => 'Underpinning Contract',
);
returns
my $Item = {
'ItemID' => '23',
'Class' => 'ITSM::Service::Type',
'Name' => 'Underpinning Contract'
'Comment' => 'Some Comment',
'ValidID' => '1',
'CreateTime' => '2012-01-12 09:36:24',
'CreateBy' => '1',
'ChangeTime' => '2012-01-12 09:36:24',
'ChangeBy' => '1',
};
=cut
sub ItemGet {
my ( $Self, %Param ) = @_;
# check needed stuff
if ( !$Param{ItemID} && ( !$Param{Class} || $Param{Name} eq '' ) ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Need ItemID OR Class and Name!'
);
return;
}
# create sql string
my $SQL = 'SELECT id, general_catalog_class, name, valid_id, comments, '
. 'create_time, create_by, change_time, change_by FROM general_catalog WHERE ';
my @BIND;
# add options to sql string
if ( $Param{Class} && $Param{Name} ne '' ) {
# check if result is already cached
my $CacheKey = 'ItemGet::Class::' . $Param{Class} . '::' . $Param{Name};
my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get(
Type => $Self->{CacheType},
Key => $CacheKey,
);
return $Cache if $Cache;
# add class and name to sql string
$SQL .= 'general_catalog_class = ? AND name = ?';
push @BIND, ( \$Param{Class}, \$Param{Name} );
}
else {
# check if result is already cached
my $CacheKey = 'ItemGet::ItemID::' . $Param{ItemID};
my $Cache = $Kernel::OM->Get('Kernel::System::Cache')->Get(
Type => $Self->{CacheType},
Key => $CacheKey,
);
return $Cache if $Cache;
# add item id to sql string
$SQL .= 'id = ?';
push @BIND, \$Param{ItemID};
}
# ask database
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => $SQL,
Bind => \@BIND,
Limit => 1,
);
# fetch the result
my %ItemData;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$ItemData{ItemID} = $Row[0];
$ItemData{Class} = $Row[1];
$ItemData{Name} = $Row[2];
$ItemData{ValidID} = $Row[3];
$ItemData{Comment} = $Row[4] || '';
$ItemData{CreateTime} = $Row[5];
$ItemData{CreateBy} = $Row[6];
$ItemData{ChangeTime} = $Row[7];
$ItemData{ChangeBy} = $Row[8];
}
# check item
if ( !$ItemData{ItemID} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => 'Item not found in database!',
);
return;
}
# get general catalog preferences
my %Preferences = $Self->GeneralCatalogPreferencesGet( ItemID => $ItemData{ItemID} );
# merge hash
if (%Preferences) {
%ItemData = ( %ItemData, %Preferences );
}
# cache the result
$Kernel::OM->Get('Kernel::System::Cache')->Set(
Type => $Self->{CacheType},
TTL => $Self->{CacheTTL},
Key => 'ItemGet::Class::' . $ItemData{Class} . '::' . $ItemData{Name},
Value => \%ItemData,
);
$Kernel::OM->Get('Kernel::System::Cache')->Set(
Type => $Self->{CacheType},
TTL => $Self->{CacheTTL},
Key => 'ItemGet::ItemID::' . $ItemData{ItemID},
Value => \%ItemData,
);
return \%ItemData;
}
=head2 ItemAdd()
add a new general catalog item
my $ItemID = $GeneralCatalogObject->ItemAdd(
Class => 'ITSM::Service::Type',
Name => 'Item Name',
ValidID => 1,
Comment => 'Comment', # (optional)
UserID => 1,
);
=cut
sub ItemAdd {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(Class ValidID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# name must be not empty, but number zero (0) is allowed
if ( !( defined $Param{Name} ) || !( length $Param{Name} ) ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need Name!",
);
return;
}
# set default values
for my $Argument (qw(Comment)) {
$Param{$Argument} ||= '';
}
# cleanup given params
for my $Argument (qw(Class)) {
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
StringRef => \$Param{$Argument},
RemoveAllNewlines => 1,
RemoveAllTabs => 1,
RemoveAllSpaces => 1,
);
}
for my $Argument (qw(Name Comment)) {
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
StringRef => \$Param{$Argument},
RemoveAllNewlines => 1,
RemoveAllTabs => 1,
);
}
# find exiting item with same name
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM general_catalog '
. 'WHERE general_catalog_class = ? AND name = ?',
Bind => [ \$Param{Class}, \$Param{Name} ],
Limit => 1,
);
# fetch the result
my $NoAdd;
while ( $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$NoAdd = 1;
}
# abort insert of new item, if item name already exists
if ($NoAdd) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message =>
"Can't add new item! General catalog item with same name already exists in this class.",
);
return;
}
# reset cache
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
Type => $Self->{CacheType},
);
# insert new item
return if !$Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => 'INSERT INTO general_catalog '
. '(general_catalog_class, name, valid_id, comments, '
. 'create_time, create_by, change_time, change_by) VALUES '
. '(?, ?, ?, ?, current_timestamp, ?, current_timestamp, ?)',
Bind => [
\$Param{Class}, \$Param{Name},
\$Param{ValidID},
\$Param{Comment}, \$Param{UserID},
\$Param{UserID},
],
);
# find id of new item
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM general_catalog '
. 'WHERE general_catalog_class = ? AND name = ?',
Bind => [ \$Param{Class}, \$Param{Name} ],
Limit => 1,
);
# fetch the result
my $ItemID;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$ItemID = $Row[0];
}
return $ItemID;
}
=head2 ItemUpdate()
update an existing general catalog item
my $True = $GeneralCatalogObject->ItemUpdate(
ItemID => 123,
Name => 'Item Name',
ValidID => 1,
Comment => 'Comment', # (optional)
UserID => 1,
);
=cut
sub ItemUpdate {
my ( $Self, %Param ) = @_;
# check needed stuff
for my $Argument (qw(ItemID ValidID UserID)) {
if ( !$Param{$Argument} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need $Argument!",
);
return;
}
}
# name must be not empty, but number zero (0) is allowed
if ( $Param{Name} eq '' ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Need Name!",
);
return;
}
# set default values
for my $Argument (qw(Comment)) {
$Param{$Argument} ||= '';
}
# cleanup given params
for my $Argument (qw(Class)) {
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
StringRef => \$Param{$Argument},
RemoveAllNewlines => 1,
RemoveAllTabs => 1,
RemoveAllSpaces => 1,
);
}
for my $Argument (qw(Name Comment)) {
$Kernel::OM->Get('Kernel::System::CheckItem')->StringClean(
StringRef => \$Param{$Argument},
RemoveAllNewlines => 1,
RemoveAllTabs => 1,
);
}
# get class of item
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT general_catalog_class FROM general_catalog WHERE id = ?',
Bind => [ \$Param{ItemID} ],
Limit => 1,
);
# fetch the result
my $Class;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
$Class = $Row[0];
}
if ( !$Class ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message => "Can't update item! General catalog item not found in this class.",
);
return;
}
# find exiting item with same name
$Kernel::OM->Get('Kernel::System::DB')->Prepare(
SQL => 'SELECT id FROM general_catalog WHERE general_catalog_class = ? AND name = ?',
Bind => [ \$Class, \$Param{Name} ],
Limit => 1,
);
# fetch the result
my $Update = 1;
while ( my @Row = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) {
if ( $Param{ItemID} ne $Row[0] ) {
$Update = 0;
}
}
if ( !$Update ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message =>
"Can't update item! General catalog item with same name already exists in this class.",
);
return;
}
# reset cache
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
Type => $Self->{CacheType},
);
return $Kernel::OM->Get('Kernel::System::DB')->Do(
SQL => 'UPDATE general_catalog SET '
. 'name = ?, valid_id = ?, comments = ?, '
. 'change_time = current_timestamp, change_by = ? '
. 'WHERE id = ?',
Bind => [
\$Param{Name},
\$Param{ValidID}, \$Param{Comment},
\$Param{UserID}, \$Param{ItemID},
],
);
}
=head2 GeneralCatalogPreferencesSet()
set GeneralCatalog preferences
$GeneralCatalogObject->GeneralCatalogPreferencesSet(
ItemID => 123,
Key => 'UserComment',
Value => 'some comment',
);
=cut
sub GeneralCatalogPreferencesSet {
my ( $Self, %Param ) = @_;
# delete cache
$Kernel::OM->Get('Kernel::System::Cache')->CleanUp(
Type => $Self->{CacheType},
);
return $Self->{PreferencesObject}->GeneralCatalogPreferencesSet(%Param);
}
=head2 GeneralCatalogPreferencesGet()
get GeneralCatalog preferences
my %Preferences = $QueueObject->GeneralCatalogPreferencesGet(
ItemID => 123,
);
=cut
sub GeneralCatalogPreferencesGet {
my ( $Self, %Param ) = @_;
return $Self->{PreferencesObject}->GeneralCatalogPreferencesGet(%Param);
}
1;
=head1 TERMS AND CONDITIONS
This Software is part of the OTRS project (http://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