# -- # 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::AgentStatistics; use strict; use warnings; use List::Util qw( first ); use Kernel::System::VariableCheck qw(:all); use Kernel::Language qw(Translatable); our $ObjectManagerDisabled = 1; sub new { my ( $Type, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); # allocate new hash for object my $Self = {}; bless( $Self, $Type ); for my $NeededData (qw( UserID Subaction AccessRo SessionID )) { if ( !$Param{$NeededData} ) { $LayoutObject->FatalError( Message => $LayoutObject->{LanguageObject}->Translate( 'Parameter %s is missing.', $NeededData ), ); } $Self->{$NeededData} = $Param{$NeededData}; } # AccessRw controls the adding/editing of statistics. for my $Param (qw( AccessRw RequestedURL )) { if ( $Param{$Param} ) { $Self->{$Param} = $Param{$Param}; } } return $Self; } sub Run { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); # set breadcrumbpath for overview screen and it will be used as base for other screens @{ $Self->{BreadcrumbPath} } = ( { Name => $LayoutObject->{LanguageObject}->Translate('Statistics Overview'), Link => 'AgentStatistics;Subaction=Overview', } ); my $Subaction = $Self->{Subaction}; my %RoSubactions = ( Overview => 'OverviewScreen', View => 'ViewScreen', Run => 'RunAction', ); if ( $RoSubactions{$Subaction} ) { if ( !$Self->{AccessRo} ) { return $LayoutObject->NoPermission( WithHeader => 'yes' ); } my $Method = $RoSubactions{$Subaction}; return $Self->$Method(); } my %RwSubactions = ( Add => 'AddScreen', AddAction => 'AddAction', Edit => 'EditScreen', EditAction => 'EditAction', Import => 'ImportScreen', ImportAction => 'ImportAction', ExportAction => 'ExportAction', DeleteAction => 'DeleteAction', ExportAction => 'ExportAction', GeneralSpecificationsWidgetAJAX => 'GeneralSpecificationsWidgetAJAX', ); if ( $RwSubactions{$Subaction} ) { if ( !$Self->{AccessRw} ) { return $LayoutObject->NoPermission( WithHeader => 'yes' ); } my $Method = $RwSubactions{$Subaction}; return $Self->$Method(); } # No (known) subaction? return $LayoutObject->ErrorScreen( Message => Translatable('Invalid Subaction.'), ); } sub OverviewScreen { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); # Get Params $Param{SearchPageShown} = $ConfigObject->Get('Stats::SearchPageShown') || 50; $Param{SearchLimit} = $ConfigObject->Get('Stats::SearchLimit') || 1000; $Param{OrderBy} = $ParamObject->GetParam( Param => 'OrderBy' ) || 'ID'; $Param{Direction} = $ParamObject->GetParam( Param => 'Direction' ) || 'ASC'; $Param{StartHit} = int( $ParamObject->GetParam( Param => 'StartHit' ) || 1 ); # get all Stats from the db my $Result = $Kernel::OM->Get('Kernel::System::Stats')->GetStatsList( AccessRw => $Self->{AccessRw}, OrderBy => $Param{OrderBy}, Direction => $Param{Direction}, UserID => $Self->{UserID}, ); if ( $Param{StartHit} > 1 && $Param{StartHit} > scalar @{ $Result || [] } ) { return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" ); } my %Order2CSSSort = ( ASC => 'SortAscending', DESC => 'SortDescending', ); my %InverseSorting = ( ASC => 'DESC', DESC => 'ASC', ); $Param{ 'CSSSort' . $Param{OrderBy} } = $Order2CSSSort{ $Param{Direction} }; for my $Type (qw(ID Title Object)) { $Param{"LinkSort$Type"} = ( $Param{OrderBy} eq $Type ) ? $InverseSorting{ $Param{Direction} } : 'ASC'; } # build the info my %Pagination = $LayoutObject->PageNavBar( Limit => $Param{SearchLimit}, StartHit => $Param{StartHit}, PageShown => $Param{SearchPageShown}, AllHits => $#{$Result} + 1, Action => 'Action=AgentStatistics;Subaction=Overview', Link => ";Direction=$Param{Direction};OrderBy=$Param{OrderBy};", IDPrefix => 'AgentStatisticsOverview' ); # list result my $Index = -1; for ( my $Z = 0; ( $Z < $Param{SearchPageShown} && $Index < $#{$Result} ); $Z++ ) { $Index = $Param{StartHit} + $Z - 1; my $StatID = $Result->[$Index]; my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet( StatID => $StatID, NoObjectAttributes => 1, UserID => $Self->{UserID}, ); # get the object name if ( $Stat->{StatType} eq 'static' ) { $Stat->{ObjectName} = $Stat->{File}; } # if no object name is defined use an empty string $Stat->{ObjectName} ||= ''; $LayoutObject->Block( Name => 'Result', Data => { %$Stat, AccessRw => $Self->{AccessRw}, }, ); } # build output my $Output = $LayoutObject->Header( Title => Translatable('Overview'), Area => 'Statistics', ); $Output .= $LayoutObject->NavigationBar(); $Output .= $LayoutObject->Output( Data => { %Pagination, %Param, AccessRw => $Self->{AccessRw}, BreadcrumbPath => $Self->{BreadcrumbPath}, }, TemplateFile => 'AgentStatisticsOverview', ); $Output .= $LayoutObject->Footer(); return $Output; } sub ImportScreen { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my %Errors = %{ $Param{Errors} // {} }; my $Output = $LayoutObject->Header( Title => Translatable('Import'), Area => 'Statistics', ); $Output .= $LayoutObject->NavigationBar(); $Output .= $LayoutObject->Output( TemplateFile => 'AgentStatisticsImport', Data => { %Errors, BreadcrumbPath => $Self->{BreadcrumbPath}, }, ); $Output .= $LayoutObject->Footer(); return $Output; } sub ImportAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my %Errors; # challenge token check for write action $LayoutObject->ChallengeTokenCheck(); my $UploadFile = $ParamObject->GetParam( Param => 'File' ); if ($UploadFile) { my %UploadStuff = $ParamObject->GetUploadAll( Param => 'File', Encoding => 'Raw' ); if ( $UploadStuff{Content} =~ m{}x ) { my $StatID = $Kernel::OM->Get('Kernel::System::Stats')->Import( Content => $UploadStuff{Content}, UserID => $Self->{UserID}, ); if ( !$StatID ) { $Errors{FileServerError} = 'ServerError'; $Errors{FileServerErrorMessage} = Translatable("Statistic could not be imported."); } else { # Redirect to statistic edit page. return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Edit;StatID=$StatID" ); } } else { $Errors{FileServerError} = 'ServerError'; $Errors{FileServerErrorMessage} = Translatable("Please upload a valid statistic file."); } } else { $Errors{FileServerError} = 'ServerError'; $Errors{FileServerErrorMessage} = Translatable("This field is required."); } return $Self->ImportScreen( Errors => \%Errors ); } sub ExportAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); $LayoutObject->ChallengeTokenCheck(); my $StatID = $Kernel::OM->Get('Kernel::System::Web::Request')->GetParam( Param => 'StatID' ); if ( !$StatID ) { return $LayoutObject->ErrorScreen( Message => Translatable('Export: Need StatID!'), ); } my $ExportFile = $Kernel::OM->Get('Kernel::System::Stats')->Export( StatID => $StatID, UserID => $Self->{UserID}, ); return $LayoutObject->Attachment( Filename => $ExportFile->{Filename}, Content => $ExportFile->{Content}, ContentType => 'text/xml', ); } sub DeleteAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $StatID = $ParamObject->GetParam( Param => 'StatID' ); if ( !$StatID ) { return $LayoutObject->ErrorScreen( Message => Translatable('Delete: Get no StatID!'), ); } # challenge token check for write action $LayoutObject->ChallengeTokenCheck(); $Kernel::OM->Get('Kernel::System::Stats')->StatsDelete( StatID => $StatID, UserID => $Self->{UserID}, ); return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" ); } sub EditScreen { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); # get param if ( !( $Param{StatID} = $ParamObject->GetParam( Param => 'StatID' ) ) ) { return $LayoutObject->ErrorScreen( Message => Translatable('Need StatID!'), ); } my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet( StatID => $Param{StatID}, UserID => $Self->{UserID}, ); my %Frontend; $Frontend{GeneralSpecificationsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->GeneralSpecificationsWidget( StatID => $Stat->{StatID}, UserID => $Self->{UserID}, ); if ( $Stat->{StatType} eq 'dynamic' ) { $Frontend{XAxisWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->XAxisWidget( Stat => $Stat, UserID => $Self->{UserID}, ); $Frontend{YAxisWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->YAxisWidget( Stat => $Stat, UserID => $Self->{UserID}, ); $Frontend{RestrictionsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->RestrictionsWidget( Stat => $Stat, UserID => $Self->{UserID}, ); $Frontend{PreviewWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->PreviewWidget( Stat => $Stat, UserID => $Self->{UserID}, ); } my $Output = $LayoutObject->Header( Title => Translatable('Edit'), Area => 'Statistics', ); $Output .= $LayoutObject->NavigationBar(); $Output .= $LayoutObject->Output( TemplateFile => 'AgentStatisticsEdit', Data => { %Frontend, %{$Stat}, BreadcrumbPath => $Self->{BreadcrumbPath}, }, ); $Output .= $LayoutObject->Footer(); return $Output; } sub EditAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my %Errors; my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet( StatID => $ParamObject->GetParam( Param => 'StatID' ), UserID => $Self->{UserID}, ); if ( !$Stat ) { return $LayoutObject->ErrorScreen( Message => Translatable('Need StatID!'), ); } # # General Specification # my %Data; for my $Key (qw(Title Description Valid)) { $Data{$Key} = $ParamObject->GetParam( Param => $Key ) // ''; if ( !length $Data{$Key} ) { # Valid can be 0 $Errors{ $Key . 'ServerError' } = 'ServerError'; } } if ( length $ParamObject->GetParam( Param => 'TimeZone' ) ) { $Data{TimeZone} = $ParamObject->GetParam( Param => 'TimeZone' ); } for my $Key (qw(SumRow SumCol Cache ShowAsDashboardWidget)) { $Data{$Key} = $ParamObject->GetParam( Param => $Key ) // ''; } for my $Key (qw(Permission Format)) { $Data{$Key} = [ $ParamObject->GetArray( Param => $Key ) ]; if ( !@{ $Data{$Key} } ) { $Errors{ $Key . 'ServerError' } = 'ServerError'; #$Data{$Key} = ''; } } # # X Axis # if ( $Stat->{StatType} eq 'dynamic' ) { my $SelectedElement = $ParamObject->GetParam( Param => 'XAxisSelectedElement' ); $Data{StatType} = $Stat->{StatType}; OBJECTATTRIBUTE: for my $ObjectAttribute ( @{ $Stat->{UseAsXvalue} } ) { next OBJECTATTRIBUTE if !defined $SelectedElement; next OBJECTATTRIBUTE if $SelectedElement ne 'XAxis' . $ObjectAttribute->{Element}; my @Array = $ParamObject->GetArray( Param => $SelectedElement ); $Data{UseAsXvalue}[0]{SelectedValues} = \@Array; $Data{UseAsXvalue}[0]{Element} = $ObjectAttribute->{Element}; $Data{UseAsXvalue}[0]{Block} = $ObjectAttribute->{Block}; $Data{UseAsXvalue}[0]{Selected} = 1; my $Fixed = $ParamObject->GetParam( Param => 'Fixed' . $SelectedElement ); $Data{UseAsXvalue}[0]{Fixed} = $Fixed ? 1 : 0; # Check if Time was selected next OBJECTATTRIBUTE if $ObjectAttribute->{Block} ne 'Time'; # This part is only needed if the block time is selected # perhaps a separate function is better my %Time; $Data{UseAsXvalue}[0]{TimeScaleCount} = $ParamObject->GetParam( Param => $SelectedElement . 'TimeScaleCount' ) || 1; my $TimeSelect = $ParamObject->GetParam( Param => $SelectedElement . 'TimeSelect' ) || 'Absolut'; if ( $TimeSelect eq 'Absolut' ) { for my $Limit (qw(Start Stop)) { for my $Unit (qw(Year Month Day Hour Minute Second)) { if ( defined( $ParamObject->GetParam( Param => "$SelectedElement$Limit$Unit" ) ) ) { $Time{ $Limit . $Unit } = $ParamObject->GetParam( Param => "$SelectedElement$Limit$Unit", ); } } if ( !defined( $Time{ $Limit . 'Hour' } ) ) { if ( $Limit eq 'Start' ) { $Time{StartHour} = 0; $Time{StartMinute} = 0; $Time{StartSecond} = 0; } elsif ( $Limit eq 'Stop' ) { $Time{StopHour} = 23; $Time{StopMinute} = 59; $Time{StopSecond} = 59; } } elsif ( !defined( $Time{ $Limit . 'Second' } ) ) { if ( $Limit eq 'Start' ) { $Time{StartSecond} = 0; } elsif ( $Limit eq 'Stop' ) { $Time{StopSecond} = 59; } } $Data{UseAsXvalue}[0]{"Time$Limit"} = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $Time{ $Limit . 'Year' }, $Time{ $Limit . 'Month' }, $Time{ $Limit . 'Day' }, $Time{ $Limit . 'Hour' }, $Time{ $Limit . 'Minute' }, $Time{ $Limit . 'Second' }, ); } } else { $Data{UseAsXvalue}[0]{TimeRelativeUnit} = $ParamObject->GetParam( Param => $SelectedElement . 'TimeRelativeUnit' ); $Data{UseAsXvalue}[0]{TimeRelativeCount} = $ParamObject->GetParam( Param => $SelectedElement . 'TimeRelativeCount' ); $Data{UseAsXvalue}[0]{TimeRelativeUpcomingCount} = $ParamObject->GetParam( Param => $SelectedElement . 'TimeRelativeUpcomingCount' ); } } } # # Y Axis # if ( $Stat->{StatType} eq 'dynamic' ) { my $Index = 0; $Data{StatType} = $Stat->{StatType}; OBJECTATTRIBUTE: for my $ObjectAttribute ( @{ $Stat->{UseAsValueSeries} } ) { my $Element = 'YAxis' . $ObjectAttribute->{Element}; if ( !$ParamObject->GetParam( Param => "Select$Element" ) ) { next OBJECTATTRIBUTE; } my @Array = $ParamObject->GetArray( Param => $Element ); $Data{UseAsValueSeries}[$Index]{SelectedValues} = \@Array; $Data{UseAsValueSeries}[$Index]{Element} = $ObjectAttribute->{Element}; $Data{UseAsValueSeries}[$Index]{Block} = $ObjectAttribute->{Block}; $Data{UseAsValueSeries}[$Index]{Selected} = 1; my $FixedElement = 'Fixed' . $Element; my $Fixed = $ParamObject->GetParam( Param => $FixedElement ); $Data{UseAsValueSeries}[$Index]{Fixed} = $Fixed ? 1 : 0; # Check if Time was selected if ( $ObjectAttribute->{Block} eq 'Time' ) { # for working with extended time $Data{UseAsValueSeries}[$Index]{TimeScaleCount} = $ParamObject->GetParam( Param => $Element . 'TimeScaleCount' ) || 1; # check if the current selected value is allowed for the x axis selected time scale my $SelectedXAxisTimeScaleValue = $Data{UseAsXvalue}[0]{SelectedValues}[0]; my $TimeScale = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->_TimeScale( SelectedXAxisValue => $SelectedXAxisTimeScaleValue, ); my %TimeScaleLookup = map { $_ => 1 } sort keys %{$TimeScale}; # set the first allowed time scale value as default if ( !$Data{UseAsValueSeries}[$Index]{SelectedValues}[0] || !exists $TimeScaleLookup{ $Data{UseAsValueSeries}[$Index]{SelectedValues}[0] } ) { my @TimeScaleSorted = sort { $TimeScale->{$a}->{Position} <=> $TimeScale->{$b}->{Position} } keys %{$TimeScale}; $Data{UseAsValueSeries}[$Index]{SelectedValues}[0] = $TimeScaleSorted[0]; } } $Index++; } $Data{UseAsValueSeries} ||= []; } # # Restrictions # if ( $Stat->{StatType} eq 'dynamic' ) { my $Index = 0; $Data{StatType} = $Stat->{StatType}; OBJECTATTRIBUTE: for my $ObjectAttribute ( @{ $Stat->{UseAsRestriction} } ) { my $Element = 'Restrictions' . $ObjectAttribute->{Element}; if ( !$ParamObject->GetParam( Param => "Select$Element" ) ) { next OBJECTATTRIBUTE; } my @Array = $ParamObject->GetArray( Param => $Element ); $Data{UseAsRestriction}[$Index]{SelectedValues} = \@Array; $Data{UseAsRestriction}[$Index]{Element} = $ObjectAttribute->{Element}; $Data{UseAsRestriction}[$Index]{Block} = $ObjectAttribute->{Block}; $Data{UseAsRestriction}[$Index]{Selected} = 1; my $Fixed = $ParamObject->GetParam( Param => 'Fixed' . $Element ); $Data{UseAsRestriction}[$Index]{Fixed} = $Fixed ? 1 : 0; if ( $ObjectAttribute->{Block} eq 'Time' ) { my %Time; my $TimeSelect = $ParamObject->GetParam( Param => $Element . 'TimeSelect' ) || 'Absolut'; if ( $TimeSelect eq 'Absolut' ) { for my $Limit (qw(Start Stop)) { for my $Unit (qw(Year Month Day Hour Minute Second)) { if ( defined( $ParamObject->GetParam( Param => "$Element$Limit$Unit" ) ) ) { $Time{ $Limit . $Unit } = $ParamObject->GetParam( Param => "$Element$Limit$Unit", ); } } if ( !defined( $Time{ $Limit . 'Hour' } ) ) { if ( $Limit eq 'Start' ) { $Time{StartHour} = 0; $Time{StartMinute} = 0; $Time{StartSecond} = 0; } elsif ( $Limit eq 'Stop' ) { $Time{StopHour} = 23; $Time{StopMinute} = 59; $Time{StopSecond} = 59; } } elsif ( !defined( $Time{ $Limit . 'Second' } ) ) { if ( $Limit eq 'Start' ) { $Time{StartSecond} = 0; } elsif ( $Limit eq 'Stop' ) { $Time{StopSecond} = 59; } } $Data{UseAsRestriction}[$Index]{"Time$Limit"} = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $Time{ $Limit . 'Year' }, $Time{ $Limit . 'Month' }, $Time{ $Limit . 'Day' }, $Time{ $Limit . 'Hour' }, $Time{ $Limit . 'Minute' }, $Time{ $Limit . 'Second' }, ); } } else { $Data{UseAsRestriction}[$Index]{TimeRelativeUnit} = $ParamObject->GetParam( Param => $Element . 'TimeRelativeUnit' ); $Data{UseAsRestriction}[$Index]{TimeRelativeCount} = $ParamObject->GetParam( Param => $Element . 'TimeRelativeCount' ); $Data{UseAsRestriction}[$Index]{TimeRelativeUpcomingCount} = $ParamObject->GetParam( Param => $Element . 'TimeRelativeUpcomingCount' ); } } $Index++; } $Data{UseAsRestriction} ||= []; } # my @Notify = $Kernel::OM->Get('Kernel::System::Stats')->CompletenessCheck( # StatData => { # %{$Stat}, # %Data, # }, # Section => 'Specification' # ); if (%Errors) { return $Self->EditScreen( Errors => \%Errors, GetParam => \%Data, ); } $Kernel::OM->Get('Kernel::System::Stats')->StatsUpdate( StatID => $Stat->{StatID}, Hash => \%Data, UserID => $Self->{UserID}, ); if ( $ParamObject->GetParam( Param => 'ReturnToStatisticOverview' ) ) { return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Overview" ); } return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Edit;StatID=$Stat->{StatID}" ); } sub ViewScreen { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my @Errors; if ( ref $Param{Errors} eq 'ARRAY' ) { @Errors = @{ $Param{Errors} || [] }; } # get StatID my $StatID = $ParamObject->GetParam( Param => 'StatID' ); if ( !$StatID ) { return $LayoutObject->ErrorScreen( Message => Translatable('Need StatID!'), ); } # get message if one available #my $Message = $ParamObject->GetParam( Param => 'Message' ); # Get all statistics that the current user may see (does permission check). my $StatsList = $Kernel::OM->Get('Kernel::System::Stats')->StatsListGet( UserID => $Self->{UserID}, ); if ( !IsHashRefWithData( $StatsList->{$StatID} ) ) { return $LayoutObject->ErrorScreen( Message => Translatable('Could not load stat.'), ); } my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet( StatID => $StatID, UserID => $Self->{UserID}, ); # get param if ( !IsHashRefWithData($Stat) ) { return $LayoutObject->ErrorScreen( Message => Translatable('Could not load stat.'), ); } my %Frontend; $Frontend{StatsParamsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsParamsWidget( Stat => $Stat, UserID => $Self->{UserID}, ); my $Output = $LayoutObject->Header( Title => Translatable('View'), Area => 'Statistics', ); $Output .= $LayoutObject->NavigationBar(); $Output .= $LayoutObject->Output( TemplateFile => 'AgentStatisticsView', Data => { AccessRw => $Self->{AccessRw}, Errors => \@Errors, %Frontend, %{$Stat}, BreadcrumbPath => $Self->{BreadcrumbPath}, }, ); $Output .= $LayoutObject->Footer(); return $Output; } sub AddScreen { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); # In case of page reload because of errors my %Errors = %{ $Param{Errors} // {} }; my %GetParam = %{ $Param{GetParam} // {} }; my %Frontend; my $DynamicFiles = $Kernel::OM->Get('Kernel::System::Stats')->GetDynamicFiles(); DYNAMIC_FILE: for my $DynamicFile ( sort keys %{ $DynamicFiles // {} } ) { my $ObjectName = 'Kernel::System::Stats::Dynamic::' . $DynamicFile; next DYNAMIC_FILE if !$Kernel::OM->Get('Kernel::System::Main')->Require($ObjectName); my $Object = $ObjectName->new(); next DYNAMIC_FILE if !$Object; if ( $Object->can('GetStatElement') ) { $Frontend{ShowAddDynamicMatrixButton}++; } else { $Frontend{ShowAddDynamicListButton}++; } } my $StaticFiles = $Kernel::OM->Get('Kernel::System::Stats')->GetStaticFiles( OnlyUnusedFiles => 1, UserID => $Self->{UserID}, ); if ( scalar keys %{$StaticFiles} ) { $Frontend{ShowAddStaticButton}++; } # This is a page reload because of validation errors if (%Errors) { $Frontend{StatisticPreselection} = $ParamObject->GetParam( Param => 'StatisticPreselection' ); $Frontend{GeneralSpecificationsWidget} = $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->GeneralSpecificationsWidget( Errors => \%Errors, GetParam => \%GetParam, UserID => $Self->{UserID}, ); $Frontend{ShowFormInitially} = 1; } # generate manual link my $ManualVersion = $Kernel::OM->Get('Kernel::Config')->Get('Version'); $ManualVersion =~ m{^(\d{1,2}).+}; $ManualVersion = $1; # build output my $Output = $LayoutObject->Header( Title => Translatable('Add New Statistic'), Area => 'Statistics', ); $Output .= $LayoutObject->NavigationBar(); $Output .= $LayoutObject->Output( TemplateFile => 'AgentStatisticsAdd', Data => { %Frontend, %Errors, ManualVersion => $ManualVersion, BreadcrumbPath => $Self->{BreadcrumbPath}, }, ); $Output .= $LayoutObject->Footer(); return $Output; } sub AddAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my %Errors; my %Data; for my $Key (qw(Title Description ObjectModule StatType Valid)) { $Data{$Key} = $ParamObject->GetParam( Param => $Key ) // ''; if ( !length $Data{$Key} ) { # Valid can be 0 $Errors{ $Key . 'ServerError' } = 'ServerError'; } } if ( length $ParamObject->GetParam( Param => 'TimeZone' ) ) { $Data{TimeZone} = $ParamObject->GetParam( Param => 'TimeZone' ); } # This seems to be historical metadata that is needed for display. my $Object = $Data{ObjectModule}; $Object = [ split( m{::}, $Object ) ]->[-1]; if ( $Data{StatType} eq 'static' ) { $Data{File} = $Object; } else { $Data{Object} = $Object; } my $StatsObject = $Kernel::OM->Get('Kernel::System::Stats'); my $ObjectModuleCheck = $StatsObject->ObjectModuleCheck( StatType => $Data{StatType}, ObjectModule => $Data{ObjectModule}, CheckAlreadyUsedStaticObject => 1, ); if ( !$ObjectModuleCheck ) { $Errors{ObjectModuleServerError} = 'ServerError'; } for my $Key (qw(SumRow SumCol Cache ShowAsDashboardWidget)) { $Data{$Key} = $ParamObject->GetParam( Param => $Key ) // ''; } for my $Key (qw(Permission Format)) { $Data{$Key} = [ $ParamObject->GetArray( Param => $Key ) ]; if ( !@{ $Data{$Key} } ) { $Errors{ $Key . 'ServerError' } = 'ServerError'; #$Data{$Key} = ''; } } # my @Notify = $Kernel::OM->Get('Kernel::System::Stats')->CompletenessCheck( # StatData => \%Data, # Section => 'Specification' # ); if (%Errors) { return $Self->AddScreen( Errors => \%Errors, GetParam => \%Data, ); } $Param{StatID} = $StatsObject->StatsAdd( UserID => $Self->{UserID}, ); if ( !$Param{StatID} ) { return $LayoutObject->ErrorScreen( Message => Translatable('Could not create statistic.'), ); } $StatsObject->StatsUpdate( StatID => $Param{StatID}, Hash => \%Data, UserID => $Self->{UserID}, ); # For static stats, the configuration is finished if ( $Data{StatType} eq 'static' ) { return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=View;StatID=$Param{StatID}", ); } # Continue configuration for dynamic stats return $LayoutObject->Redirect( OP => "Action=AgentStatistics;Subaction=Edit;StatID=$Param{StatID}", ); } sub RunAction { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); my $ParamObject = $Kernel::OM->Get('Kernel::System::Web::Request'); my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); for my $Name (qw(Format StatID Name Cached)) { $Param{$Name} = $ParamObject->GetParam( Param => $Name ); } my @RequiredParams = (qw(Format StatID)); if ( $Param{Cached} ) { push @RequiredParams, 'Name'; } for my $Required (@RequiredParams) { if ( !$Param{$Required} ) { return $LayoutObject->ErrorScreen( Message => $LayoutObject->{LanguageObject}->Translate( 'Run: Get no %s!', $Required ), ); } } my $Stat = $Kernel::OM->Get('Kernel::System::Stats')->StatsGet( StatID => $Param{StatID}, UserID => $Self->{UserID}, ); # permission check if ( !$Self->{AccessRw} ) { my $UserPermission = 0; return $LayoutObject->NoPermission( WithHeader => 'yes' ) if !$Stat->{Valid}; # get user groups my %GroupList = $Kernel::OM->Get('Kernel::System::Group')->PermissionUserGet( UserID => $Self->{UserID}, Type => 'ro', ); GROUPID: for my $GroupID ( @{ $Stat->{Permission} } ) { next GROUPID if !$GroupID; next GROUPID if !$GroupList{$GroupID}; $UserPermission = 1; last GROUPID; } return $LayoutObject->NoPermission( WithHeader => 'yes' ) if !$UserPermission; } # get params my %GetParam = eval { $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsParamsGet( Stat => $Stat, UserID => $Self->{UserID}, ); }; if ($@) { return $Self->ViewScreen( Errors => $@ ); } # run stat... my @StatArray; # called from within the dashboard. will use the same mechanism and configuration like in # the dashboard stats - the (cached) result will be the same as seen in the dashboard if ( $Param{Cached} ) { # get settings for specified stats by using the dashboard configuration for the agent my %Preferences = $Kernel::OM->Get('Kernel::System::User')->GetPreferences( UserID => $Self->{UserID}, ); my $PrefKeyStatsConfiguration = 'UserDashboardStatsStatsConfiguration' . $Param{Name}; my $StatsSettings = {}; if ( $Preferences{$PrefKeyStatsConfiguration} ) { $StatsSettings = $Kernel::OM->Get('Kernel::System::JSON')->Decode( Data => $Preferences{$PrefKeyStatsConfiguration}, ); } @StatArray = @{ $Kernel::OM->Get('Kernel::System::Stats')->StatsResultCacheGet( StatID => $Param{StatID}, UserGetParam => $StatsSettings, UserID => $Self->{UserID}, ); }; } # called normally within the stats area - generate stats now and use provided configuraton else { @StatArray = @{ $Kernel::OM->Get('Kernel::System::Stats')->StatsRun( StatID => $Param{StatID}, GetParam => \%GetParam, UserID => $Self->{UserID}, ); }; } return $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View')->StatsResultRender( StatArray => \@StatArray, Stat => $Stat, TimeZone => $GetParam{TimeZone}, UserID => $Self->{UserID}, %Param ); } sub GeneralSpecificationsWidgetAJAX { my ( $Self, %Param ) = @_; my $LayoutObject = $Kernel::OM->Get('Kernel::Output::HTML::Layout'); return $LayoutObject->Attachment( ContentType => 'text/html', Content => $Kernel::OM->Get('Kernel::Output::HTML::Statistics::View') ->GeneralSpecificationsWidget( UserID => $Self->{UserID} ), Type => 'inline', NoCache => 1, ); } # ATTENTION: this function delivers only approximations!!! sub _TimeInSeconds { my ( $Self, %Param ) = @_; # check if need params are available if ( !$Param{TimeUnit} ) { return $Kernel::OM->Get('Kernel::Output::HTML::Layout') ->ErrorScreen( Message => '_TimeInSeconds: Need TimeUnit!' ); } my %TimeInSeconds = ( Year => 31536000, # 60 * 60 * 24 * 365 HalfYear => 15724800, # 60 * 60 * 24 * 182 Quarter => 7862400, # 60 * 60 * 24 * 91 Month => 2592000, # 60 * 60 * 24 * 30 Week => 604800, # 60 * 60 * 24 * 7 Day => 86400, # 60 * 60 * 24 Hour => 3600, # 60 * 60 Minute => 60, Second => 1, ); return $TimeInSeconds{ $Param{TimeUnit} }; } 1;