Initial commit - Typo3 11.5.41

This commit is contained in:
Matteo Gallo
2026-07-03 17:53:31 +02:00
commit 5ca4743197
6811 changed files with 568848 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
<?php
namespace SJBR\StaticInfoTables\Cache;
/*
* Copyright notice
*
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Cached classes autoloader
*/
class CachedClassLoader
{
/**
* Extension key
*
* @var string
*/
protected static $extensionKey = 'static_info_tables';
/**
* Cached class loader class name
*
* @var string
*/
protected static $className = __CLASS__;
/**
* Name space of the Domain Model of StaticInfoTables
*
* @var string
*/
protected static $namespace = 'SJBR\\StaticInfoTables\\Domain\\Model\\';
/**
* The class loader is static, thus we do not allow instances of this class.
*/
private function __construct()
{
}
/**
* Registers the cached class loader
*
* @return bool TRUE in case of success
*/
public static function registerAutoloader()
{
return spl_autoload_register(static::$className . '::autoload', true, true);
}
/**
* Autoload function for cached classes
*
* @param string $className Class name
* @return void
*/
public static function autoload($className)
{
$className = ltrim($className, '\\');
if (strpos($className, static::$namespace) !== false) {
// Lookup the class in the array of static info entities and check its presence in the class cache
$entities = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][static::$extensionKey]['entities'] ?? [];
// ClassCacheManager instantiation creates the class cache if not already available
$classCacheManager = GeneralUtility::makeInstance(ClassCacheManager::class);
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
$classCache = $cacheManager->getCache(static::$extensionKey);
foreach ($entities as $entity) {
if ($className === static::$namespace . $entity) {
$entryIdentifier = 'DomainModel' . $entity;
if (!$classCache->has($entryIdentifier)) {
// The class cache needs to be rebuilt
$classCacheManager->reBuild();
}
$classCache->requireOnce($entryIdentifier);
break;
}
}
}
}
}

View File

@@ -0,0 +1,284 @@
<?php
namespace SJBR\StaticInfoTables\Cache;
/*
* Copyright notice
* (c) 2012 Georg Ringer <typo3@ringerge.org>
* (c) 2013-2022 Stanislas Rolland <typo3AAAA(arobas)sjbr.ca>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This copyright notice MUST APPEAR in all copies of the script!
*/
use TYPO3\CMS\Core\Cache\Backend\FileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class Cache Manager
*/
class ClassCacheManager implements SingletonInterface
{
/**
* Extension key
*
* @var string
*/
protected $extensionKey = 'static_info_tables';
/**
* @var array Cache configurations
*/
protected $cacheConfiguration = [
'static_info_tables' => [
'frontend' => PhpFrontend::class,
'backend' => FileBackend::class,
'options' => [],
'groups' => ['all'],
],
];
/**
* Cache manager
*
* @var CacheManager
*/
private $cacheManager;
/**
* @var FrontendInterface
*/
protected $cacheInstance;
/**
* Constructor
*/
public function __construct(CacheManager $cacheManager)
{
$this->cacheManager = $cacheManager;
$this->initializeCache();
}
/**
* Initialize cache instance to be ready to use
*
* @return void
*/
protected function initializeCache()
{
if (!$this->cacheManager->hasCache($this->extensionKey)) {
if (isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey]) &&
is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey])) {
ArrayUtility::mergeRecursiveWithOverrule($this->cacheConfiguration[$this->extensionKey], $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$this->extensionKey]);
}
$this->cacheManager->setCacheConfigurations($this->cacheConfiguration);
}
$this->cacheInstance = $this->cacheManager->getCache($this->extensionKey);
}
/**
* Builds and caches the proxy files
*
* @return void
* @throws \Exception
*/
public function build()
{
$extensibleExtensions = $this->getExtensibleExtensions();
$entities = $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS'][$this->extensionKey]['entities'] ?? [];
foreach ($entities as $entity) {
$key = 'Domain/Model/' . $entity;
// Get the file from static_info_tables itself, this needs to be loaded as first
$path = ExtensionManagementUtility::extPath($this->extensionKey) . 'Classes/' . $key . '.php';
if (!is_file($path)) {
throw new \Exception('given file "' . $path . '" does not exist');
}
$code = $this->parseSingleFile($path, false);
// Get the files from all other extensions that are extending this domain model class
if (isset($extensibleExtensions[$key]) && is_array($extensibleExtensions[$key]) && count($extensibleExtensions[$key]) > 0) {
$extensionsWithThisClass = array_keys($extensibleExtensions[$key]);
foreach ($extensionsWithThisClass as $extension) {
$path = ExtensionManagementUtility::extPath($extension) . 'Classes/' . $key . '.php';
if (is_file($path)) {
$code .= $this->parseSingleFile($path);
}
}
}
// Close the class definition and the php tag
$code = $this->closeClassDefinition($code);
// The file is added to the class cache
$entryIdentifier = str_replace('/', '', $key);
try {
$this->cacheInstance->set($entryIdentifier, $code);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
/**
* Get all loaded extensions which try to extend EXT:static_info_tables
*
* @return array
*/
protected function getExtensibleExtensions()
{
$loadedExtensions = array_unique(ExtensionManagementUtility::getLoadedExtensionListArray());
// Get the extensions which want to extend static_info_tables
$extensibleExtensions = [];
foreach ($loadedExtensions as $extensionKey) {
$extensionInfoFile = ExtensionManagementUtility::extPath($extensionKey) . 'Configuration/DomainModelExtension/StaticInfoTables.txt';
if (file_exists($extensionInfoFile)) {
$info = GeneralUtility::getUrl($extensionInfoFile);
$classes = GeneralUtility::trimExplode(LF, $info, true);
foreach ($classes as $class) {
$extensibleExtensions[$class][$extensionKey] = 1;
}
}
}
return $extensibleExtensions;
}
/**
* Parse a single file and does some magic
* - Remove the php tags
* - Remove the class definition (if set)
*
* @param string $filePath path of the file
* @param bool $removeClassDefinition If class definition should be removed
* @return string path of the saved file
* @throws \Exception
* @throws \InvalidArgumentException
*/
public function parseSingleFile($filePath, $removeClassDefinition = true)
{
if (!is_file($filePath)) {
throw new \InvalidArgumentException(sprintf('File "%s" could not be found', $filePath));
}
$code = GeneralUtility::getUrl($filePath);
return $this->changeCode($code, $filePath, $removeClassDefinition);
}
/**
* @param string $code
* @param string $filePath
* @param bool $removeClassDefinition
* @param bool $renderPartialInfo
* @return string
* @throws \Exception
*/
protected function changeCode($code, $filePath, $removeClassDefinition = true, $renderPartialInfo = true)
{
if (empty($code)) {
throw new \InvalidArgumentException(sprintf('File "%s" could not be fetched or is empty', $filePath));
}
$code = trim($code);
$code = str_replace(['<?php', '?>'], '', $code);
$code = trim($code);
// Remove everything before 'class ', including namespaces,
// comments and require-statements.
if ($removeClassDefinition) {
$pos = strpos($code, 'class ');
$pos2 = strpos($code, '{', $pos);
$code = substr($code, $pos2 + 1);
}
$code = trim($code);
// Add some information for each partial
if ($renderPartialInfo) {
$code = $this->getPartialInfo($filePath) . $code;
}
// Remove last }
$pos = strrpos($code, '}');
$code = substr($code, 0, $pos);
$code = trim($code);
return $code . LF . LF;
}
protected function getPartialInfo($filePath)
{
return '/*' . str_repeat('*', 70) . LF .
' * this is partial from: ' . $filePath . LF . str_repeat('*', 70) . '*/' . LF . chr(9);
}
protected function closeClassDefinition($code)
{
return $code . LF . '}';
}
/**
* Clear the class cache
*
* @return void
*/
public function clear()
{
$this->cacheInstance->flush();
if (isset($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->user)) {
$GLOBALS['BE_USER']->writelog(3, 1, 0, 0, '[StaticInfoTables]: User %s has cleared the class cache', [$GLOBALS['BE_USER']->user['username']]);
}
}
/**
* Rebuild the class cache
*
* @param array $parameters
* @return void
* @throws \Exception
*/
public function reBuild(array $parameters = [])
{
$isValidCall = (
empty($parameters)
|| (
!empty($parameters['cacheCmd'])
&& GeneralUtility::inList('all,temp_cached', $parameters['cacheCmd'])
&& isset($GLOBALS['BE_USER'])
)
);
if ($isValidCall) {
$this->clear();
$this->clearReflectionCache();
$this->build();
}
}
/**
* Drop the reflection cache
*/
protected function clearReflectionCache()
{
if ($this->cacheManager->hasCache('extbase_reflection')) {
$this->cacheManager->getCache('extbase_reflection')->flush();
}
if ($this->cacheManager->hasCache('extbase_datamapfactory_datamap')) {
$this->cacheManager->getCache('extbase_datamapfactory_datamap')->flush();
}
}
}