# -- # 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::Output::HTML::Layout::ITSMConfigItem; use strict; use warnings; our $ObjectManagerDisabled = 1; =head1 NAME Kernel::Output::HTML::Layout::ITSMConfigItem - all ConfigItem-related HTML functions =head1 DESCRIPTION All ITSM Configuration Management-related HTML functions =head1 PUBLIC INTERFACE =head2 ITSMConfigItemOutputStringCreate() returns an output string my $String = $LayoutObject->ITSMConfigItemOutputStringCreate( Value => 11, # (optional) Item => $ItemRef, Print => 1, # (optional, default 0) ); =cut sub ITSMConfigItemOutputStringCreate { my ( $Self, %Param ) = @_; # check needed stuff if ( !$Param{Item} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => 'Need Item!', ); return; } # load backend my $BackendObject = $Self->_ITSMLoadLayoutBackend( Type => $Param{Item}->{Input}->{Type}, ); return '' if !$BackendObject; # generate output string my $String = $BackendObject->OutputStringCreate(%Param); return $String; } =head2 ITSMConfigItemFormDataGet() returns the values from the html form as hash reference my $FormDataRef = $LayoutObject->ITSMConfigItemFormDataGet( Key => 'Item::1::Node::3', Item => $ItemRef, ConfigItemID => 123, ); =cut sub ITSMConfigItemFormDataGet { my ( $Self, %Param ) = @_; # check needed stuff for my $Argument (qw(Key Item ConfigItemID)) { if ( !$Param{$Argument} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Need $Argument!" ); return; } } # load backend my $BackendObject = $Self->_ITSMLoadLayoutBackend( Type => $Param{Item}->{Input}->{Type}, ); return {} if !$BackendObject; # get form data my $FormData = $BackendObject->FormDataGet(%Param); return $FormData; } =head2 ITSMConfigItemInputCreate() returns a input field html string my $String = $LayoutObject->ITSMConfigItemInputCreate( Key => 'Item::1::Node::3', Value => 11, # (optional) Item => $ItemRef, ); =cut sub ITSMConfigItemInputCreate { my ( $Self, %Param ) = @_; # check needed stuff for my $Argument (qw(Key Item)) { if ( !$Param{$Argument} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Need $Argument!" ); return; } } # load backend my $BackendObject = $Self->_ITSMLoadLayoutBackend( Type => $Param{Item}->{Input}->{Type}, ); return '' if !$BackendObject; # lookup item value my $String = $BackendObject->InputCreate(%Param); return $String; } =head2 ITSMConfigItemSearchFormDataGet() returns the values from the search html form my $ArrayRef = $LayoutObject->ITSMConfigItemSearchFormDataGet( Key => 'Item::1::Node::3', Item => $ItemRef, ); =cut sub ITSMConfigItemSearchFormDataGet { my ( $Self, %Param ) = @_; # check needed stuff for my $Argument (qw(Key Item)) { if ( !$Param{$Argument} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Need $Argument!" ); return; } } # load backend my $BackendObject = $Self->_ITSMLoadLayoutBackend( Type => $Param{Item}->{Input}->{Type}, ); return [] if !$BackendObject; # get form data my $Values = $BackendObject->SearchFormDataGet(%Param); return $Values; } =head2 ITSMConfigItemSearchInputCreate() returns a search input field html string my $String = $LayoutObject->ITSMConfigItemSearchInputCreate( Key => 'Item::1::Node::3', Item => $ItemRef, ); =cut sub ITSMConfigItemSearchInputCreate { my ( $Self, %Param ) = @_; # check needed stuff for my $Argument (qw(Key Item)) { if ( !$Param{$Argument} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Need $Argument!" ); return; } } # load backend my $BackendObject = $Self->_ITSMLoadLayoutBackend( Type => $Param{Item}->{Input}->{Type}, ); return '' if !$BackendObject; # lookup item value my $String = $BackendObject->SearchInputCreate(%Param); return $String; } =head2 _ITSMLoadLayoutBackend() load a input type backend module $BackendObject = $LayoutObject->_ITSMLoadLayoutBackend( Type => 'GeneralCatalog', ); =cut sub _ITSMLoadLayoutBackend { my ( $Self, %Param ) = @_; # get log object my $LogObject = $Kernel::OM->Get('Kernel::System::Log'); if ( !$Param{Type} ) { $LogObject->Log( Priority => 'error', Message => 'Need Type!', ); return; } my $GenericModule = "Kernel::Output::HTML::ITSMConfigItem::Layout$Param{Type}"; # load the backend module if ( !$Kernel::OM->Get('Kernel::System::Main')->Require($GenericModule) ) { $LogObject->Log( Priority => 'error', Message => "Can't load backend module $Param{Type}!" ); return; } # create new instance my $BackendObject = $GenericModule->new( %{$Self}, %Param, LayoutObject => $Self, ); if ( !$BackendObject ) { $LogObject->Log( Priority => 'error', Message => "Can't create a new instance of backend module $Param{Type}!", ); return; } return $BackendObject; } =head2 ITSMConfigItemListShow() Returns a list of configuration items with sort and pagination capabilities. This function is similar to L in F. my $Output = $LayoutObject->ITSMConfigItemListShow( ConfigItemIDs => $ConfigItemIDsRef, # total list of config item ids, that can be listed Total => scalar @{ $ConfigItemIDsRef }, # total number of list items, config items in this case View => $Self->{View}, # optional, the default value is 'Small' Filter => 'All', Filters => \%NavBarFilter, FilterLink => $LinkFilter, TitleName => 'Overview: Config Item: Computer', TitleValue => $Self->{Filter}, Env => $Self, LinkPage => $LinkPage, LinkSort => $LinkSort, Frontend => 'Agent', # optional (Agent|Customer), default: Agent, indicates from which frontend this function was called ); =cut sub ITSMConfigItemListShow { my ( $Self, %Param ) = @_; # take object ref to local, remove it from %Param (prevent memory leak) my $Env = delete $Param{Env}; # lookup latest used view mode if ( !$Param{View} && $Self->{ 'UserITSMConfigItemOverview' . $Env->{Action} } ) { $Param{View} = $Self->{ 'UserITSMConfigItemOverview' . $Env->{Action} }; } # set frontend my $Frontend = $Param{Frontend} || 'Agent'; # set defaut view mode to 'small' my $View = $Param{View} || 'Small'; # store latest view mode $Kernel::OM->Get('Kernel::System::AuthSession')->UpdateSessionID( SessionID => $Self->{SessionID}, Key => 'UserITSMConfigItemOverview' . $Env->{Action}, Value => $View, ); # get needed objects my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); # get backend from config my $Backends = $ConfigObject->Get('ITSMConfigItem::Frontend::Overview'); if ( !$Backends ) { return $LayoutObject->FatalError( Message => 'Need config option ITSMConfigItem::Frontend::Overview', ); } # check for hash-ref if ( ref $Backends ne 'HASH' ) { return $LayoutObject->FatalError( Message => 'Config option ITSMConfigItem::Frontend::Overview needs to be a HASH ref!', ); } # check for config key if ( !$Backends->{$View} ) { return $LayoutObject->FatalError( Message => "No config option found for the view '$View'!", ); } # nav bar my $StartHit = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'StartHit', ) || 1; # get personal page shown count my $PageShownPreferencesKey = 'UserConfigItemOverview' . $View . 'PageShown'; my $PageShown = $Self->{$PageShownPreferencesKey} || 10; my $Group = 'ConfigItemOverview' . $View . 'PageShown'; # check start option, if higher then elements available, set # it to the last overview page (Thanks to Stefan Schmidt!) if ( $StartHit > $Param{Total} ) { my $Pages = int( ( $Param{Total} / $PageShown ) + 0.99999 ); $StartHit = ( ( $Pages - 1 ) * $PageShown ) + 1; } # get data selection my %Data; my $Config = $ConfigObject->Get('PreferencesGroups'); if ( $Config && $Config->{$Group} && $Config->{$Group}->{Data} ) { %Data = %{ $Config->{$Group}->{Data} }; } # set page limit and build page nav my $Limit = $Param{Limit} || 20_000; my %PageNav = $LayoutObject->PageNavBar( Limit => $Limit, StartHit => $StartHit, PageShown => $PageShown, AllHits => $Param{Total} || 0, Action => 'Action=' . $Env->{Action}, Link => $Param{LinkPage}, ); # build shown ticket a page $Param{RequestedURL} = $Param{RequestedURL} || "Action=$Self->{Action};$Param{LinkPage}"; $Param{Group} = $Group; $Param{PreferencesKey} = $PageShownPreferencesKey; $Param{PageShownString} = $Self->BuildSelection( Name => $PageShownPreferencesKey, SelectedID => $PageShown, Data => \%Data, Translation => 0, Sort => 'NumericValue', Class => 'Modernize', ); # build navbar content $LayoutObject->Block( Name => 'OverviewNavBar', Data => \%Param, ); # back link if ( $Param{LinkBack} ) { $LayoutObject->Block( Name => 'OverviewNavBarPageBack', Data => \%Param, ); $LayoutObject->AddJSData( Key => 'ITSMConfigItemSearch', Value => { Profile => $Param{Profile}, ClassID => $Param{ClassID}, }, ); } # get filters if ( $Param{Filters} ) { # get given filters my @NavBarFilters; for my $Prio ( sort keys %{ $Param{Filters} } ) { push @NavBarFilters, $Param{Filters}->{$Prio}; } # build filter content $LayoutObject->Block( Name => 'OverviewNavBarFilter', Data => { %Param, }, ); # loop over filters my $Count = 0; for my $Filter (@NavBarFilters) { # increment filter count and build filter item $Count++; $LayoutObject->Block( Name => 'OverviewNavBarFilterItem', Data => { %Param, %{$Filter}, }, ); # filter is selected if ( $Filter->{Filter} eq $Param{Filter} ) { $LayoutObject->Block( Name => 'OverviewNavBarFilterItemSelected', Data => { %Param, %{$Filter}, }, ); } else { $LayoutObject->Block( Name => 'OverviewNavBarFilterItemSelectedNot', Data => { %Param, %{$Filter}, }, ); } } } # loop over configured backends for my $Backend ( sort keys %{$Backends} ) { # build navbar view mode $LayoutObject->Block( Name => 'OverviewNavBarViewMode', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); # current view is configured in backend if ( $View eq $Backend ) { $LayoutObject->Block( Name => 'OverviewNavBarViewModeSelected', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); } else { $LayoutObject->Block( Name => 'OverviewNavBarViewModeNotSelected', Data => { %Param, %{ $Backends->{$Backend} }, Filter => $Param{Filter}, View => $Backend, }, ); } } # check if page nav is available if (%PageNav) { $LayoutObject->Block( Name => 'OverviewNavBarPageNavBar', Data => \%PageNav, ); # don't show context settings in AJAX case (e. g. in customer ticket history), # because the submit with page reload will not work there if ( !$Param{AJAX} ) { $LayoutObject->Block( Name => 'ContextSettings', Data => { %PageNav, %Param, }, ); } } # check if bulk feature is enabled my $BulkFeature = 0; if ( $ConfigObject->Get('ITSMConfigItem::Frontend::BulkFeature') ) { my @Groups; if ( $ConfigObject->Get('ITSMConfigItem::Frontend::BulkFeatureGroup') ) { @Groups = @{ $ConfigObject->Get('ITSMConfigItem::Frontend::BulkFeatureGroup') }; } if ( !@Groups ) { $BulkFeature = 1; } else { GROUP: for my $Group (@Groups) { next GROUP if !$Kernel::OM->Get('Kernel::System::Group')->PermissionCheck( UserID => $Self->{UserID}, GroupName => $Group, Type => 'rw', ); $BulkFeature = 1; last GROUP; } } } # show the bulk action button if feature is enabled if ($BulkFeature) { $LayoutObject->Block( Name => 'BulkAction', Data => { %PageNav, %Param, }, ); } # build html content my $OutputNavBar = $LayoutObject->Output( TemplateFile => 'AgentITSMConfigItemOverviewNavBar', Data => {%Param}, ); # create output my $OutputRaw = ''; if ( !$Param{Output} ) { $LayoutObject->Print( Output => \$OutputNavBar, ); } else { $OutputRaw .= $OutputNavBar; } # load module if ( !$Kernel::OM->Get('Kernel::System::Main')->Require( $Backends->{$View}->{Module} ) ) { return $LayoutObject->FatalError(); } # check for backend object my $Object = $Backends->{$View}->{Module}->new( %{$Env} ); return if !$Object; # run module my $Output = $Object->Run( %Param, Limit => $Limit, StartHit => $StartHit, PageShown => $PageShown, AllHits => $Param{Total} || 0, Frontend => $Frontend, ); # create output if ( !$Param{Output} ) { $LayoutObject->Print( Output => \$Output, ); } else { $OutputRaw .= $Output; } # create overview nav bar $LayoutObject->Block( Name => 'OverviewNavBar', Data => {%Param}, ); # return content if available return $OutputRaw; } =head2 XMLData2Hash() returns a hash reference with the requested attributes data for a config item Return $Data = { 'HardDisk::2' => { Value => 'HD2', Name => 'Hard Disk', }, 'CPU::1' => { Value => '', Name => 'CPU', }, 'HardDisk::2::Capacity::1' => { Value => '780 GB', Name => 'Capacity', }, }; my $Data = $LayoutObject->XMLData2Hash( XMLDefinition => $Version->{XMLDefinition}, XMLData => $Version->{XMLData}->[1]->{Version}->[1], Attributes => ['CPU::1', 'HardDrive::2::Capacity::1', ...], Data => \%DataHashRef, # optional Prefix => 'HardDisk::1', # optional ); =cut sub XMLData2Hash { my ( $Self, %Param ) = @_; # check needed stuff return if !$Param{XMLData}; return if !$Param{XMLDefinition}; return if !$Param{Attributes}; return if ref $Param{XMLData} ne 'HASH'; return if ref $Param{XMLDefinition} ne 'ARRAY'; return if ref $Param{Attributes} ne 'ARRAY'; # to store the return data my $Data = $Param{Data} || {}; # create a lookup structure my %RelevantAttributes = map { $_ => 1 } @{ $Param{Attributes} }; ITEM: for my $Item ( @{ $Param{XMLDefinition} } ) { my $CountMax = $Item->{CountMax} || 1; COUNTER: for my $Counter ( 1 .. $CountMax ) { # add prefix my $Prefix = $Item->{Key} . '::' . $Counter; if ( $Param{Prefix} ) { $Prefix = $Param{Prefix} . '::' . $Prefix; } # skip not needed elements and sub elements next COUNTER if !grep { $_ =~ m{\A$Prefix} } @{ $Param{Attributes} }; # lookup value my $Value = $Kernel::OM->Get('Kernel::System::ITSMConfigItem')->XMLValueLookup( Item => $Item, Value => $Param{XMLData}->{ $Item->{Key} }->[$Counter]->{Content} // '', ); # only if value is defined if ( defined $Value ) { # create output string $Value = $Self->ITSMConfigItemOutputStringCreate( Value => $Value, Item => $Item, Print => $Param{Print}, ); } if ( $RelevantAttributes{$Prefix} ) { # store the item in hash $Data->{$Prefix} = { Name => $Item->{Name}, Value => $Value // '', }; } # start recursion, if "Sub" was found if ( $Item->{Sub} ) { $Data = $Self->XMLData2Hash( XMLDefinition => $Item->{Sub}, XMLData => $Param{XMLData}->{ $Item->{Key} }->[$Counter], Prefix => $Prefix, Data => $Data, Attributes => $Param{Attributes}, ); } } } return $Data; } 1; =head1 TERMS AND CONDITIONS This software is part of the OTRS project (L). 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. =cut