first commit

This commit is contained in:
salam committed 2026-10-06 19:40:28 +02:00
commit e81864e683
2984 files changed
+267797

No files matched your search

@@ -0,0 +1,60 @@
<?php declare(strict_types=1);
/*
* This file is part of the package bk2k/bootstrap-package.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BK2K\BootstrapPackage\Service;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Package\Event\AfterPackageActivationEvent;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* BrandingService
*/
class BrandingService
{
public function __invoke(AfterPackageActivationEvent $event): void
{
if ($event->getPackageKey() === 'bootstrap_package') {
$this->setBackendStyling();
}
}
public function setBackendStyling(): void
{
if (class_exists(ExtensionConfiguration::class)) {
$extensionConfiguration = GeneralUtility::makeInstance(
ExtensionConfiguration::class
);
$backendConfiguration = $extensionConfiguration->get('backend');
if (!isset($backendConfiguration['loginLogo']) || trim($backendConfiguration['loginLogo']) === '') {
$backendConfiguration['loginLogo'] = 'EXT:bootstrap_package/Resources/Public/Images/Backend/login-logo.svg';
}
if (!isset($backendConfiguration['loginBackgroundImage']) || trim($backendConfiguration['loginBackgroundImage']) === '') {
$backendConfiguration['loginBackgroundImage'] = 'EXT:bootstrap_package/Resources/Public/Images/Backend/login-background-image.jpg';
}
if (!isset($backendConfiguration['backendLogo']) || trim($backendConfiguration['backendLogo']) === '') {
$backendConfiguration['backendLogo'] = 'EXT:bootstrap_package/Resources/Public/Images/Backend/backend-logo.svg';
}
// Workaround for
// https://review.typo3.org/c/Packages/TYPO3.CMS/+/62650
$reflection = new \ReflectionClass(ExtensionConfiguration::class);
$parameters = $reflection->getMethod('set')->getParameters();
$arguments = [];
$arguments[] = 'backend';
if (count($parameters) === 3) {
$arguments[] = '';
}
$arguments[] = $backendConfiguration;
$extensionConfiguration->set(...$arguments);
}
}
}
@@ -0,0 +1,142 @@
<?php declare(strict_types=1);
/*
* This file is part of the package bk2k/bootstrap-package.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BK2K\BootstrapPackage\Service;
use BK2K\BootstrapPackage\Parser\ParserInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* This service handles the parsing of css files for the frontend.
*/
class CompileService
{
/**
* @var string
*/
protected $tempDirectory = 'typo3temp/assets/bootstrappackage/css/';
/**
* @var string
*/
protected $tempDirectoryRelativeToRoot = '../../../../';
/**
* @param string $file
* @return string|null
* @throws \Exception
*/
public function getCompiledFile(string $file): ?string
{
$absoluteFile = GeneralUtility::getFileAbsFileName($file);
$configuration = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_bootstrappackage.']['settings.'] ?? [];
// Ensure cache directory exists
if (!file_exists(Environment::getPublicPath() . '/' . $this->tempDirectory)) {
GeneralUtility::mkdir_deep(Environment::getPublicPath() . '/' . $this->tempDirectory);
}
// Settings
$settings = [
'file' => [
'absolute' => $absoluteFile,
'relative' => $file,
'info' => pathinfo($absoluteFile)
],
'cache' => [
'tempDirectory' => $this->tempDirectory,
'tempDirectoryRelativeToRoot' => $this->tempDirectoryRelativeToRoot,
],
'options' => [
'override' => $configuration['overrideParserVariables'] ? true: false,
'sourceMap' => $configuration['cssSourceMapping'] ? true : false,
'compress' => true
],
'variables' => []
];
// Parser
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/css']['parser'])
&& is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/css']['parser'])
) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/css']['parser'] as $className) {
$parser = GeneralUtility::makeInstance($className);
if ($parser instanceof ParserInterface
&& isset($settings['file']['info']['extension'])
&& $parser->supports($settings['file']['info']['extension'])
) {
if ($configuration['overrideParserVariables']) {
$settings['variables'] = $this->getVariablesFromConstants($settings['file']['info']['extension']);
}
try {
return $parser->compile($file, $settings);
} catch (\Exception $e) {
$this->clearCompilerCaches();
throw $e;
}
}
}
}
return null;
}
/**
* @param string $extension
* @return array
*/
protected function getVariablesFromConstants(string $extension): array
{
$constants = $this->getConstants();
$extension = strtolower($extension);
$variables = [];
// Fetch Google Font
$variables['google-webfont'] = 'sans-serif';
if (isset($constants['page.theme.googleFont.enable'])
&& (bool) $constants['page.theme.googleFont.enable']
&& isset($constants['page.theme.googleFont.font'])
&& $constants['page.theme.googleFont.font'] !== ''
) {
$variables['google-webfont'] = $constants['page.theme.googleFont.font'];
}
// Fetch settings
$prefix = 'plugin.bootstrap_package.settings.' . $extension . '.';
foreach ($constants as $constant => $value) {
if (strpos($constant, $prefix) === 0) {
$variables[substr($constant, strlen($prefix))] = $value;
}
}
return $variables;
}
/**
* @return array
*/
protected function getConstants(): array
{
if ($GLOBALS['TSFE']->tmpl->flatSetup === null
|| !is_array($GLOBALS['TSFE']->tmpl->flatSetup)
|| count($GLOBALS['TSFE']->tmpl->flatSetup) === 0) {
$GLOBALS['TSFE']->tmpl->generateConfig();
}
return $GLOBALS['TSFE']->tmpl->flatSetup;
}
/**
* Clear all caches for the compiler.
*/
protected function clearCompilerCaches(): void
{
GeneralUtility::rmdir(Environment::getPublicPath() . '/' . $this->tempDirectory, true);
}
}
@@ -0,0 +1,157 @@
<?php
declare(strict_types = 1);
/*
* This file is part of the package bk2k/bootstrap-package.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BK2K\BootstrapPackage\Service;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\RequestFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* GoogleFontService
*/
class GoogleFontService
{
/**
* @var string
*/
protected $tempDirectory = 'typo3temp/assets/bootstrappackage/fonts';
/**
* @var string
*/
protected $googleFontApiUrl = 'fonts.googleapis.com/css';
/**
* @param string $file
* @return string|null
* @throws \Exception
*/
public function getCachedFile(string $file): ?string
{
if (!$this->supports($file)) {
return null;
}
if ($this->isCached($file)) {
return $this->getCssFileCacheName($file);
}
return $this->cacheFile($file) ? $this->getCssFileCacheName($file) : null;
}
/**
* @param string $file
* @return bool
*/
protected function cacheFile(string $file): bool
{
/** @var RequestFactory */
$requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
/** @var ResponseInterface */
$response = $requestFactory->request($file, 'GET', [
'headers' => ['User-Agent' => 'Mozilla/5.0 Gecko/20100101 Firefox/94.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55']
]);
if ($response->getStatusCode() >= 300) {
return false;
} else {
$content = $response->getBody()->getContents();
}
// Ensure cache directory exists
GeneralUtility::mkdir_deep($this->tempDirectory . '/' . $this->getCacheIdentifier($file));
// Find and Download font files
$pattern = '%url\((.*?)\)%';
preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
$fontFiles = [];
foreach ($matches as $match) {
$fontFiles[$match[1]] = $match[1];
}
foreach ($fontFiles as $fontFile) {
$localFontFile = $this->getCacheDirectory($file) . '/' . basename($fontFile);
/** @var ResponseInterface */
$response = $requestFactory->request($fontFile);
if ($response->getStatusCode() >= 300) {
continue;
} else {
$fontFileContent = $response->getBody()->getContents();
}
file_put_contents($localFontFile, $fontFileContent);
GeneralUtility::fixPermissions($localFontFile);
$content = str_replace($fontFile, basename($fontFile), $content);
}
// Save CSS File
$cacheFile = $this->getCacheDirectory($file) . '/' . 'webfont.css';
file_put_contents(GeneralUtility::getFileAbsFileName($cacheFile), $content);
GeneralUtility::fixPermissions($cacheFile);
return true;
}
/**
* @param string $file
* @return bool
*/
protected function supports(string $file): bool
{
return (bool) strpos($file, $this->googleFontApiUrl);
}
/**
* @param string $file
* @return bool
*/
protected function isCached(string $file): bool
{
$cacheFile = $this->getCssFileCacheName($file);
$absoluteFile = GeneralUtility::getFileAbsFileName($cacheFile);
if (!file_exists($absoluteFile)) {
return false;
}
// Discard cache after 24 hours
if ((time() - (int) filemtime($absoluteFile)) > 86400) {
GeneralUtility::rmdir($this->getCacheDirectory($file));
return false;
}
return true;
}
/**
* @param string $file
* @return string
*/
protected function getCssFileCacheName(string $file): string
{
return $this->getCacheDirectory($file) . '/' . 'webfont.css';
}
/**
* @param string $file
* @return string
*/
protected function getCacheDirectory(string $file): string
{
return $this->tempDirectory . '/' . $this->getCacheIdentifier($file);
}
/**
* @param string $file
* @return string
*/
protected function getCacheIdentifier(string $file): string
{
return hash('sha256', $file);
}
}
@@ -0,0 +1,88 @@
<?php
declare(strict_types = 1);
/*
* This file is part of the package bk2k/bootstrap-package.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BK2K\BootstrapPackage\Service;
use BK2K\BootstrapPackage\Icons\IconProviderInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* IconService
*/
class IconService
{
public function getIconSetItems(array &$configuration): void
{
$iconSets = [];
$iconSets[] = ['LLL:EXT:bootstrap_package/Resources/Private/Language/Backend.xlf:option.none', ''];
$iconProviders = $this->getIconProviders();
foreach ($iconProviders as $iconProvider) {
$iconSets[] = [
$iconProvider->getName(),
$iconProvider->getIdentifier()
];
}
$configuration['items'] = $iconSets;
}
public function getIconItems(array &$configuration): void
{
$iconItems = [];
$iconItems[] = [
'LLL:EXT:bootstrap_package/Resources/Private/Language/Backend.xlf:option.none',
0,
'EXT:bootstrap_package/Resources/Public/Images/Icons/none.svg'
];
$iconSetField = $configuration['config']['itemsProcConfig']['iconSetField'] ?? 'icon_set';
$iconProviderIdentifier = $configuration['row'][$iconSetField][0] ?? '';
$iconProvider = $this->getIconProviderForIdentifier($iconProviderIdentifier);
if ($iconProvider !== null) {
$icons = $iconProvider->getIconList()->getIcons();
foreach ($icons as $icon) {
$iconItems[] = [
$icon->getName(),
$icon->getIdentifier(),
$icon->getPreviewImage()
];
}
}
$configuration['items'] = $iconItems;
}
public function getIconProviderForIdentifier(string $identifier): ?IconProviderInterface
{
$iconProviders = $this->getIconProviders();
foreach ($iconProviders as $iconProvider) {
if ($iconProvider->supports($identifier)) {
return $iconProvider;
}
}
return null;
}
public function getIconProviders(): array
{
$iconProviders = [];
if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/icons']['provider'])
&& is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/icons']['provider'])
) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/bootstrap-package/icons']['provider'] as $className) {
$iconProviders[] = GeneralUtility::makeInstance($className);
}
}
return $iconProviders;
}
}