# --
# 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).
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