Files
scripts/Perl OTRS/Kernel/Output/HTML/Layout/Loader.pm
2024-10-14 00:08:40 +02:00

925 lines
27 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::Output::HTML::Layout::Loader;
use strict;
use warnings;
use File::stat;
use Digest::MD5;
use Kernel::Language qw(Translatable);
our $ObjectManagerDisabled = 1;
=head1 NAME
Kernel::Output::HTML::Layout::Loader - CSS/JavaScript
=head1 DESCRIPTION
All valid functions.
=head1 PUBLIC INTERFACE
=head2 LoaderCreateAgentCSSCalls()
Generate the minified CSS files and the tags referencing them,
taking a list from the Loader::Agent::CommonCSS config item.
$LayoutObject->LoaderCreateAgentCSSCalls(
Skin => 'MySkin', # optional, if not provided skin is the configured by default
);
=cut
sub LoaderCreateAgentCSSCalls {
my ( $Self, %Param ) = @_;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# get host based default skin configuration
my $SkinSelectedHostBased;
my $DefaultSkinHostBased = $ConfigObject->Get('Loader::Agent::DefaultSelectedSkin::HostBased');
if ( $DefaultSkinHostBased && $ENV{HTTP_HOST} ) {
REGEXP:
for my $RegExp ( sort keys %{$DefaultSkinHostBased} ) {
# do not use empty regexp or skin directories
next REGEXP if !$RegExp;
next REGEXP if !$DefaultSkinHostBased->{$RegExp};
# check if regexp is matching
if ( $ENV{HTTP_HOST} =~ /$RegExp/i ) {
$SkinSelectedHostBased = $DefaultSkinHostBased->{$RegExp};
}
}
}
# determine skin
# 1. use UserSkin setting from Agent preferences, if available
# 2. use HostBased skin setting, if available
# 3. use default skin from configuration
my $SkinSelected = $Self->{'UserSkin'};
# check if the skin is valid
my $SkinValid = 0;
if ($SkinSelected) {
$SkinValid = $Self->SkinValidate(
SkinType => 'Agent',
Skin => $SkinSelected,
);
}
if ( !$SkinValid ) {
$SkinSelected = $SkinSelectedHostBased
|| $ConfigObject->Get('Loader::Agent::DefaultSelectedSkin')
|| 'default';
}
# save selected skin
$Self->{SkinSelected} = $SkinSelected;
my $SkinHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/skins';
my $DoMinify = $ConfigObject->Get('Loader::Enabled::CSS');
my $ToolbarModuleSettings = $ConfigObject->Get('Frontend::ToolBarModule');
my $CustomerUserItemSettings = $ConfigObject->Get('Frontend::CustomerUser::Item');
{
my @FileList;
# get global css
my $CommonCSSList = $ConfigObject->Get('Loader::Agent::CommonCSS');
for my $Key ( sort keys %{$CommonCSSList} ) {
push @FileList, @{ $CommonCSSList->{$Key} };
}
# get toolbar module css
for my $Key ( sort keys %{$ToolbarModuleSettings} ) {
if ( $ToolbarModuleSettings->{$Key}->{CSS} ) {
push @FileList, $ToolbarModuleSettings->{$Key}->{CSS};
}
}
# get customer user item css
for my $Key ( sort keys %{$CustomerUserItemSettings} ) {
if ( $CustomerUserItemSettings->{$Key}->{CSS} ) {
push @FileList, $CustomerUserItemSettings->{$Key}->{CSS};
}
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'CommonCSS',
SkinHome => $SkinHome,
SkinType => 'Agent',
Skin => $SkinSelected,
);
}
# now handle module specific CSS
my $LoaderAction = $Self->{Action} || 'Login';
$LoaderAction = 'Login' if ( $LoaderAction eq 'Logout' );
{
my $Setting = $ConfigObject->Get("Loader::Module::$LoaderAction") || {};
my @FileList;
MODULE:
for my $Module ( sort keys %{$Setting} ) {
next MODULE if ref $Setting->{$Module}->{CSS} ne 'ARRAY';
@FileList = ( @FileList, @{ $Setting->{$Module}->{CSS} || [] } );
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ModuleCSS',
SkinHome => $SkinHome,
SkinType => 'Agent',
Skin => $SkinSelected,
);
}
# handle the responsive CSS
{
my @FileList;
my $ResponsiveCSSList = $ConfigObject->Get('Loader::Agent::ResponsiveCSS');
for my $Key ( sort keys %{$ResponsiveCSSList} ) {
push @FileList, @{ $ResponsiveCSSList->{$Key} };
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ResponsiveCSS',
SkinHome => $SkinHome,
SkinType => 'Agent',
Skin => $SkinSelected,
);
}
#print STDERR "Time: " . Time::HiRes::tv_interval([$t0]);
return 1;
}
=head2 LoaderCreateAgentJSCalls()
Generate the minified JavaScript files and the tags referencing them,
taking a list from the Loader::Agent::CommonJS config item.
$LayoutObject->LoaderCreateAgentJSCalls();
=cut
sub LoaderCreateAgentJSCalls {
my ( $Self, %Param ) = @_;
#use Time::HiRes;
#my $t0 = Time::HiRes::gettimeofday();
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $JSHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/js';
my $DoMinify = $ConfigObject->Get('Loader::Enabled::JS');
{
my @FileList;
# get global js
my $CommonJSList = $ConfigObject->Get('Loader::Agent::CommonJS');
KEY:
for my $Key ( sort keys %{$CommonJSList} ) {
next KEY if $Key eq '100-CKEditor' && !$ConfigObject->Get('Frontend::RichText');
push @FileList, @{ $CommonJSList->{$Key} };
}
# get toolbar module js
my $ToolbarModuleSettings = $ConfigObject->Get('Frontend::ToolBarModule');
for my $Key ( sort keys %{$ToolbarModuleSettings} ) {
if ( $ToolbarModuleSettings->{$Key}->{JavaScript} ) {
push @FileList, $ToolbarModuleSettings->{$Key}->{JavaScript};
}
}
$Self->_HandleJSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'CommonJS',
JSHome => $JSHome,
);
}
# now handle module specific JavaScript
{
my $LoaderAction = $Self->{Action} || 'Login';
$LoaderAction = 'Login' if ( $LoaderAction eq 'Logout' );
my $Setting = $ConfigObject->Get("Loader::Module::$LoaderAction") || {};
my @FileList;
MODULE:
for my $Module ( sort keys %{$Setting} ) {
next MODULE if ref $Setting->{$Module}->{JavaScript} ne 'ARRAY';
@FileList = ( @FileList, @{ $Setting->{$Module}->{JavaScript} || [] } );
}
$Self->_HandleJSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ModuleJS',
JSHome => $JSHome,
);
}
return 1;
}
=head2 LoaderCreateJavaScriptTemplateData()
Generate a minified file for the template data that
needs to be present on the client side for JavaScript based templates.
$LayoutObject->LoaderCreateJavaScriptTemplateData();
=cut
sub LoaderCreateJavaScriptTemplateData {
my ( $Self, %Param ) = @_;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
# load theme
my $Theme = $Self->{UserTheme} || $ConfigObject->Get('DefaultTheme') || Translatable('Standard');
# force a theme based on host name
my $DefaultThemeHostBased = $ConfigObject->Get('DefaultTheme::HostBased');
if ( $DefaultThemeHostBased && $ENV{HTTP_HOST} ) {
THEME:
for my $RegExp ( sort keys %{$DefaultThemeHostBased} ) {
# do not use empty regexp or theme directories
next THEME if !$RegExp;
next THEME if $RegExp eq '';
next THEME if !$DefaultThemeHostBased->{$RegExp};
# check if regexp is matching
if ( $ENV{HTTP_HOST} =~ /$RegExp/i ) {
$Theme = $DefaultThemeHostBased->{$RegExp};
}
}
}
# locate template files
my $JSStandardTemplateDir = $ConfigObject->Get('TemplateDir') . '/JavaScript/Templates/' . 'Standard';
my $JSTemplateDir = $ConfigObject->Get('TemplateDir') . '/JavaScript/Templates/' . $Theme;
# Check if 'Standard' fallback exists
if ( !-e $JSStandardTemplateDir ) {
$Self->FatalDie(
Message =>
"No existing template directory found ('$JSTemplateDir')! Check your Home in Kernel/Config.pm."
);
}
if ( !-e $JSTemplateDir ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Priority => 'error',
Message =>
"No existing template directory found ('$JSTemplateDir')!.
Default theme used instead.",
);
# Set TemplateDir to 'Standard' as a fallback.
$Theme = 'Standard';
$JSTemplateDir = $JSStandardTemplateDir;
}
my $JSCustomStandardTemplateDir = $ConfigObject->Get('CustomTemplateDir') . '/JavaScript/Templates/' . 'Standard';
my $JSCustomTemplateDir = $ConfigObject->Get('CustomTemplateDir') . '/JavaScript/Templates/' . $Theme;
my @TemplateFolders = (
"$JSCustomTemplateDir",
"$JSCustomStandardTemplateDir",
"$JSTemplateDir",
"$JSStandardTemplateDir",
);
my $JSHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/js';
my $TargetFilenamePrefix = "TemplateJS";
my $TemplateChecksum;
my $MainObject = $Kernel::OM->Get('Kernel::System::Main');
my $CacheObject = $Kernel::OM->Get('Kernel::System::Cache');
my $CacheType = 'Loader';
my $CacheKey = "LoaderCreateJavaScriptTemplateData:${Theme}:" . $ConfigObject->ConfigChecksum();
# Even getting the list of files recursively from the directories is expensive,
# so cache the checksum to avoid that.
$TemplateChecksum = $CacheObject->Get(
Type => $CacheType,
Key => $CacheKey,
);
if ( !$TemplateChecksum ) {
my %ChecksumData;
TEMPLATEFOLDER:
for my $TemplateFolder (@TemplateFolders) {
next TEMPLATEFOLDER if !-e $TemplateFolder;
# get main object
my @Templates = $MainObject->DirectoryRead(
Directory => $TemplateFolder,
Filter => '*.tmpl',
Recursive => 1,
);
TEMPLATE:
for my $Template ( sort @Templates ) {
next TEMPLATE if !-e $Template;
my $Key = $Template;
$Key =~ s/^$TemplateFolder\///xmsg;
$Key =~ s/\.(\w+)\.tmpl$//xmsg;
# check if a template with this name does already exist
next TEMPLATE if $ChecksumData{$Key};
# get file metadata
my $Stat = stat($Template);
if ( !$Stat ) {
print STDERR "Error: cannot stat file '$Template': $!";
next TEMPLATE;
}
$ChecksumData{$Key} = $Template . $Stat->mtime();
}
}
# generate a checksum only of the actual used files
for my $Checksum ( sort keys %ChecksumData ) {
$TemplateChecksum .= $ChecksumData{$Checksum};
}
$TemplateChecksum = Digest::MD5::md5_hex($TemplateChecksum);
$CacheObject->Set(
Type => $CacheType,
Key => $CacheKey,
TTL => 60 * 60 * 24,
Value => $TemplateChecksum,
);
}
# Check if cache already exists.
if ( -e "$JSHome/js-cache/${TargetFilenamePrefix}_$TemplateChecksum.js" ) {
$Self->Block(
Name => 'CommonJS',
Data => {
JSDirectory => 'js-cache/',
Filename => "${TargetFilenamePrefix}_$TemplateChecksum.js",
},
);
return 1;
}
# if it doesnt exist, go through the folders and get the template content
my %TemplateData;
TEMPLATEFOLDER:
for my $TemplateFolder (@TemplateFolders) {
next TEMPLATEFOLDER if !-e $TemplateFolder;
# get main object
my @Templates = $MainObject->DirectoryRead(
Directory => $TemplateFolder,
Filter => '*.tmpl',
Recursive => 1,
);
TEMPLATE:
for my $Template ( sort @Templates ) {
next TEMPLATE if !-e $Template;
my $Key = $Template;
$Key =~ s/^$TemplateFolder\///xmsg;
$Key =~ s/\.(\w+)\.tmpl$//xmsg;
# check if a template with this name does already exist
next TEMPLATE if $TemplateData{$Key};
my $TemplateContent = ${
$MainObject->FileRead(
Location => $Template,
Result => 'SCALAR',
)
};
# Remove DTL-style comments (lines starting with #)
$TemplateContent =~ s/^#.*\n//gm;
$TemplateData{$Key} = $TemplateContent;
}
}
my $TemplateDataJSON = $Kernel::OM->Get('Kernel::System::JSON')->Encode(
Data => \%TemplateData,
Pretty => 0,
);
my $Content = <<"EOF";
// The content of this file is automatically generated, do not edit.
Core.Template.Load($TemplateDataJSON);
EOF
my $MinifiedFile = $Kernel::OM->Get('Kernel::System::Loader')->MinifyFiles(
Checksum => $TemplateChecksum,
Content => $Content,
Type => 'JavaScript',
TargetDirectory => "$JSHome/js-cache/",
TargetFilenamePrefix => $TargetFilenamePrefix,
);
$Self->Block(
Name => 'CommonJS',
Data => {
JSDirectory => 'js-cache/',
Filename => $MinifiedFile,
},
);
return 1;
}
=head2 LoaderCreateJavaScriptTranslationData()
Generate a minified file for the translation data that
needs to be present on the client side for JavaScript based translations.
$LayoutObject->LoaderCreateJavaScriptTranslationData();
=cut
sub LoaderCreateJavaScriptTranslationData {
my ( $Self, %Param ) = @_;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $JSHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/js';
my $UserLanguage = $Self->{UserLanguage};
my $LanguageObject = $Self->{LanguageObject};
my $LanguageChecksum = $LanguageObject->LanguageChecksum();
my $TargetFilenamePrefix = "TranslationJS_$UserLanguage";
# Check if cache already exists.
if ( -e "$JSHome/js-cache/${TargetFilenamePrefix}_$LanguageChecksum.js" ) {
$Self->Block(
Name => 'CommonJS',
Data => {
JSDirectory => 'js-cache/',
Filename => "${TargetFilenamePrefix}_$LanguageChecksum.js",
},
);
return 1;
}
# Now create translation data for JavaScript.
my %TranslationData;
STRING:
for my $String ( @{ $LanguageObject->{JavaScriptStrings} // [] } ) {
next STRING if $TranslationData{$String};
$TranslationData{$String} = $LanguageObject->{Translation}->{$String};
}
my %LanguageMetaData = (
LanguageCode => $UserLanguage,
DateFormat => $LanguageObject->{DateFormat},
DateFormatLong => $LanguageObject->{DateFormatLong},
DateFormatShort => $LanguageObject->{DateFormatShort},
DateInputFormat => $LanguageObject->{DateInputFormat},
DateInputFormatLong => $LanguageObject->{DateInputFormatLong},
Completeness => $LanguageObject->{Completeness},
Separator => $LanguageObject->{Separator},
DecimalSeparator => $LanguageObject->{DecimalSeparator},
);
my $LanguageMetaDataJSON = $Kernel::OM->Get('Kernel::System::JSON')->Encode(
Data => \%LanguageMetaData,
SortKeys => 1,
Pretty => 0,
);
my $TranslationDataJSON = $Kernel::OM->Get('Kernel::System::JSON')->Encode(
Data => \%TranslationData,
SortKeys => 1,
Pretty => 0,
);
my $Content = <<"EOF";
// The content of this file is automatically generated, do not edit.
Core.Language.Load($LanguageMetaDataJSON, $TranslationDataJSON);
EOF
my $MinifiedFile = $Kernel::OM->Get('Kernel::System::Loader')->MinifyFiles(
Checksum => $LanguageChecksum,
Content => $Content,
Type => 'JavaScript',
TargetDirectory => "$JSHome/js-cache/",
TargetFilenamePrefix => $TargetFilenamePrefix,
);
$Self->Block(
Name => 'CommonJS',
Data => {
JSDirectory => 'js-cache/',
Filename => $MinifiedFile,
},
);
return 1;
}
=head2 LoaderCreateCustomerCSSCalls()
Generate the minified CSS files and the tags referencing them,
taking a list from the Loader::Customer::CommonCSS config item.
$LayoutObject->LoaderCreateCustomerCSSCalls();
=cut
sub LoaderCreateCustomerCSSCalls {
my ( $Self, %Param ) = @_;
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $SkinSelected = $ConfigObject->Get('Loader::Customer::SelectedSkin')
|| 'default';
# force a skin based on host name
my $DefaultSkinHostBased = $ConfigObject->Get('Loader::Customer::SelectedSkin::HostBased');
if ( $DefaultSkinHostBased && $ENV{HTTP_HOST} ) {
REGEXP:
for my $RegExp ( sort keys %{$DefaultSkinHostBased} ) {
# do not use empty regexp or skin directories
next REGEXP if !$RegExp;
next REGEXP if !$DefaultSkinHostBased->{$RegExp};
# check if regexp is matching
if ( $ENV{HTTP_HOST} =~ /$RegExp/i ) {
$SkinSelected = $DefaultSkinHostBased->{$RegExp};
}
}
}
my $SkinHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/skins';
my $DoMinify = $ConfigObject->Get('Loader::Enabled::CSS');
{
my $CommonCSSList = $ConfigObject->Get('Loader::Customer::CommonCSS');
my @FileList;
for my $Key ( sort keys %{$CommonCSSList} ) {
push @FileList, @{ $CommonCSSList->{$Key} };
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'CommonCSS',
SkinHome => $SkinHome,
SkinType => 'Customer',
Skin => $SkinSelected,
);
}
# now handle module specific CSS
my $LoaderAction = $Self->{Action} || 'Login';
$LoaderAction = 'Login' if ( $LoaderAction eq 'Logout' );
{
my $Setting = $ConfigObject->Get("Loader::Module::$LoaderAction") || {};
my @FileList;
MODULE:
for my $Module ( sort keys %{$Setting} ) {
next MODULE if ref $Setting->{$Module}->{CSS} ne 'ARRAY';
@FileList = ( @FileList, @{ $Setting->{$Module}->{CSS} || [] } );
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ModuleCSS',
SkinHome => $SkinHome,
SkinType => 'Customer',
Skin => $SkinSelected,
);
}
# handle the responsive CSS
{
my @FileList;
my $ResponsiveCSSList = $ConfigObject->Get('Loader::Customer::ResponsiveCSS');
for my $Key ( sort keys %{$ResponsiveCSSList} ) {
push @FileList, @{ $ResponsiveCSSList->{$Key} };
}
$Self->_HandleCSSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ResponsiveCSS',
SkinHome => $SkinHome,
SkinType => 'Customer',
Skin => $SkinSelected,
);
}
#print STDERR "Time: " . Time::HiRes::tv_interval([$t0]);
return 1;
}
=head2 LoaderCreateCustomerJSCalls()
Generate the minified JavaScript files and the tags referencing them,
taking a list from the Loader::Customer::CommonJS config item.
$LayoutObject->LoaderCreateCustomerJSCalls();
=cut
sub LoaderCreateCustomerJSCalls {
my ( $Self, %Param ) = @_;
#use Time::HiRes;
#my $t0 = Time::HiRes::gettimeofday();
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $JSHome = $ConfigObject->Get('Home') . '/var/httpd/htdocs/js';
my $DoMinify = $ConfigObject->Get('Loader::Enabled::JS');
{
my $CommonJSList = $ConfigObject->Get('Loader::Customer::CommonJS');
my @FileList;
KEY:
for my $Key ( sort keys %{$CommonJSList} ) {
next KEY if $Key eq '100-CKEditor' && !$ConfigObject->Get('Frontend::RichText');
push @FileList, @{ $CommonJSList->{$Key} };
}
$Self->_HandleJSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'CommonJS',
JSHome => $JSHome,
);
}
# now handle module specific JS
{
my $LoaderAction = $Self->{Action} || 'CustomerLogin';
$LoaderAction = 'CustomerLogin' if ( $LoaderAction eq 'Logout' );
my $Setting = $ConfigObject->Get("Loader::Module::$LoaderAction") || {};
my @FileList;
MODULE:
for my $Module ( sort keys %{$Setting} ) {
next MODULE if ref $Setting->{$Module}->{JavaScript} ne 'ARRAY';
@FileList = ( @FileList, @{ $Setting->{$Module}->{JavaScript} || [] } );
}
$Self->_HandleJSList(
List => \@FileList,
DoMinify => $DoMinify,
BlockName => 'ModuleJS',
JSHome => $JSHome,
);
}
#print STDERR "Time: " . Time::HiRes::tv_interval([$t0]);
return;
}
sub _HandleCSSList {
my ( $Self, %Param ) = @_;
my @Skins = ('default');
# validating selected custom skin, if any
if ( $Param{Skin} && $Param{Skin} ne 'default' && $Self->SkinValidate(%Param) ) {
push @Skins, $Param{Skin};
}
#load default css files
for my $Skin (@Skins) {
my @FileList;
CSSFILE:
for my $CSSFile ( @{ $Param{List} } ) {
my $SkinFile = "$Param{SkinHome}/$Param{SkinType}/$Skin/css/$CSSFile";
next CSSFILE if ( !-e $SkinFile );
if ( $Param{DoMinify} ) {
push @FileList, $SkinFile;
}
else {
$Self->Block(
Name => $Param{BlockName},
Data => {
Skin => $Skin,
CSSDirectory => 'css',
Filename => $CSSFile,
},
);
}
}
if ( $Param{DoMinify} && @FileList ) {
my $MinifiedFile = $Kernel::OM->Get('Kernel::System::Loader')->MinifyFiles(
List => \@FileList,
Type => 'CSS',
TargetDirectory => "$Param{SkinHome}/$Param{SkinType}/$Skin/css-cache/",
TargetFilenamePrefix => $Param{BlockName},
);
$Self->Block(
Name => $Param{BlockName},
Data => {
Skin => $Skin,
CSSDirectory => 'css-cache',
Filename => $MinifiedFile,
},
);
}
}
return 1;
}
sub _HandleJSList {
my ( $Self, %Param ) = @_;
my $Content = $Param{Content};
return if !$Param{List} && !$Content;
my %UsedFiles;
my @FileList;
JSFILE:
for my $JSFile ( @{ $Param{List} // [] } ) {
next JSFILE if $UsedFiles{$JSFile};
if ( $Param{DoMinify} ) {
push @FileList, "$Param{JSHome}/$JSFile";
}
else {
$Self->Block(
Name => $Param{BlockName},
Data => {
JSDirectory => '',
Filename => $JSFile,
},
);
}
# Save it for checking duplicates.
$UsedFiles{$JSFile} = 1;
}
return 1 if $Param{List} && !@FileList;
if ( $Param{DoMinify} ) {
my $MinifiedFile;
if (@FileList) {
$MinifiedFile = $Kernel::OM->Get('Kernel::System::Loader')->MinifyFiles(
List => \@FileList,
Type => 'JavaScript',
TargetDirectory => "$Param{JSHome}/js-cache/",
TargetFilenamePrefix => $Param{FilenamePrefix} // $Param{BlockName},
);
}
else {
$MinifiedFile = $Kernel::OM->Get('Kernel::System::Loader')->MinifyFiles(
Content => $Content,
Type => 'JavaScript',
TargetDirectory => "$Param{JSHome}/js-cache/",
TargetFilenamePrefix => $Param{FilenamePrefix} // $Param{BlockName},
);
}
$Self->Block(
Name => $Param{BlockName},
Data => {
JSDirectory => 'js-cache/',
Filename => $MinifiedFile,
},
);
}
return 1;
}
=head2 SkinValidate()
Returns 1 if skin is available for Agent or Customer frontends and 0 if not.
my $SkinIsValid = $LayoutObject->SkinValidate(
UserType => 'Agent' # Agent or Customer,
Skin => 'ExampleSkin',
);
=cut
sub SkinValidate {
my ( $Self, %Param ) = @_;
for my $Needed ( 'SkinType', 'Skin' ) {
if ( !$Param{$Needed} ) {
$Kernel::OM->Get('Kernel::System::Log')->Log(
Message => "Needed param: $Needed!",
Priority => 'error',
);
return;
}
}
if ( exists $Self->{SkinValidateCache}->{ $Param{SkinType} . '::' . $Param{Skin} } ) {
return $Self->{SkinValidateCache}->{ $Param{SkinType} . '::' . $Param{Skin} };
}
# get config object
my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
my $SkinType = $Param{SkinType};
my $PossibleSkins = $ConfigObject->Get("Loader::${SkinType}::Skin") || {};
my $Home = $ConfigObject->Get('Home');
my %ActiveSkins;
# prepare the list of active skins
for my $PossibleSkin ( values %{$PossibleSkins} ) {
if ( $PossibleSkin->{InternalName} eq $Param{Skin} ) {
my $SkinDir = $Home . "/var/httpd/htdocs/skins/$SkinType/" . $PossibleSkin->{InternalName};
if ( -d $SkinDir ) {
$Self->{SkinValidateCache}->{ $Param{SkinType} . '::' . $Param{Skin} } = 1;
return 1;
}
}
}
$Self->{SkinValidateCache}->{ $Param{SkinType} . '::' . $Param{Skin} } = undef;
return;
}
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