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,185 @@
<?php
namespace MiniFranske\FsMediaGallery\Service;
/***************************************************************
* Copyright notice
*
* (c) 2014 Frans Saris <franssaris@gmail.com>
* 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\Localization\LanguageService;
use TYPO3\CMS\Core\Resource\FolderInterface;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Abstract utility class for classes that want to add album add/edit buttons
* somewhere like a ClickMenuOptions class.
*/
abstract class AbstractBeAlbumButtons
{
/**
* Generate album add/edit buttons for click menu or toolbar
*/
protected function generateButtons(string $combinedIdentifier): array
{
$buttons = [];
// In some folder copy/move actions in file list a invalid id is passed
try {
/** @var $file \TYPO3\CMS\Core\Resource\Folder */
$folder = GeneralUtility::makeInstance(ResourceFactory::class)
->retrieveFileOrFolderObject($combinedIdentifier);
} catch (ResourceDoesNotExistException $exception) {
$folder = null;
}
if ($folder instanceof Folder &&
in_array(
$folder->getRole(),
[FolderInterface::ROLE_DEFAULT, FolderInterface::ROLE_USERUPLOAD]
)
) {
/** @var Utility $utility */
$utility = GeneralUtility::makeInstance(Utility::class);
$mediaFolders = $utility->getStorageFolders();
if (count($mediaFolders)) {
$collections = $utility->findFileCollectionRecordsForFolder(
$folder->getStorage()->getUid(),
$folder->getIdentifier(),
array_keys($mediaFolders)
);
foreach ($collections as $collection) {
$buttons[] = $this->createLink(
sprintf($this->sL('module.buttons.editAlbum'), $collection['title']),
sprintf(
$this->sL('module.buttons.editAlbum'),
mb_strimwidth($collection['title'], 0,12, '...')
),
$this->getIcon('edit-album'),
$this->buildEditUrl($collection['uid'])
);
}
if (!count($collections)) {
foreach ($mediaFolders as $uid => $title) {
// find parent album for auto setting parent album
$parentUid = 0;
$parents = $utility->findFileCollectionRecordsForFolder(
$folder->getStorage()->getUid(),
$folder->getParentFolder()->getIdentifier(),
[$uid]
);
// if parent(s) found we take the first one
if (count($parents)) {
$parentUid = $parents[0]['uid'];
}
$buttons[] = $this->createLink(
sprintf($this->sL('module.buttons.createAlbumIn'), $title),
sprintf(
$this->sL('module.buttons.createAlbumIn'),
mb_strimwidth($title, 0, 12, '...')
),
$this->getIcon('add-album'),
$this->buildAddUrl($uid, $parentUid, $folder)
);
}
}
// show hint button for admin users
// todo: make this better so it can also be used for editors with enough rights to create a storageFolder
} elseif ($GLOBALS['BE_USER']->isAdmin()) {
$buttons[] = $this->createLink(
$this->sL('module.buttons.createAlbum'),
$this->sL('module.buttons.createAlbum'),
$this->getIcon('add-album'),
'alert:' . $this->sL('module.alerts.firstCreateStorageFolder'),
false
);
}
}
return $buttons;
}
protected function buildEditUrl(int $mediaAlbumUid): string
{
return GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', [
'edit' => [
'sys_file_collection' => [
$mediaAlbumUid => 'edit'
]
],
'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
]);
}
/**
* Build Add new media album url
*/
protected function buildAddUrl(int $pid, int $parentAlbumUid, Folder $folder): string
{
return GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute('record_edit', [
'edit' => [
'sys_file_collection' => [
$pid => 'new'
]
],
'defVals' => [
'sys_file_collection' => [
'parentalbum' => $parentAlbumUid,
'title' => ucfirst(trim(str_replace('_', ' ', $folder->getName()))),
'storage' => $folder->getStorage()->getUid(),
'folder' => $folder->getIdentifier(),
'type' => 'folder',
]
],
'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
]);
}
abstract protected function createLink(string $title, string $shortTitle, Icon $icon, string $url, bool $addReturnUrl = true): array;
protected function getIcon(string $name): Icon
{
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
return $iconFactory->getIcon('action-' . $name, Icon::SIZE_SMALL);
}
protected function getLangService(): LanguageService
{
return $GLOBALS['LANG'];
}
/**
* Get language string
*/
protected function sL(string $key, string $languageFile = 'LLL:EXT:fs_media_gallery/Resources/Private/Language/locallang_be.xlf'): string
{
return $this->getLangService()->sL($languageFile . ':' . $key);
}
}

View File

@@ -0,0 +1,258 @@
<?php
/*
* This source file is proprietary of Beech Applications bv.
* Created by: Ruud Silvrants
* Date: 30/04/2019
* All code (c) Beech Applications bv. all rights reserverd
*/
namespace MiniFranske\FsMediaGallery\Service;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Class SlugService
* @package MiniFranske\FsMediaGallery\Service
*/
class SlugService
{
protected $tableName = 'sys_file_collection';
protected $slugFieldName = 'slug';
/**
* @return bool
*/
public function typo3SupportsSlugs(): bool
{
return class_exists(SlugHelper::class);
}
/**
* @return int
*/
public function countOfSlugUpdates(): int
{
/** @var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
$queryBuilder->getRestrictions()->removeAll();
$elementCount = $queryBuilder->count('uid')
->from($this->tableName)
->where(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
$this->slugFieldName,
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
),
$queryBuilder->expr()->isNull($this->slugFieldName)
)
)
->execute()->fetchOne();
return $elementCount;
}
/**
* @return array
*/
public function performUpdateSlugs(): array
{
$databaseQueries = [];
/** @var Connection $connection */
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->tableName);
/** @var QueryBuilder $queryBuilder */
$queryBuilder = $connection->createQueryBuilder();
$queryBuilder->getRestrictions()->removeAll();
$fieldConfig = $GLOBALS['TCA'][$this->tableName]['columns'][$this->slugFieldName]['config'];
/** @var SlugHelper $slugHelper */
$slugHelper = GeneralUtility::makeInstance(SlugHelper::class, $this->tableName, $this->slugFieldName,
$fieldConfig);
$statement = $queryBuilder->select('*')
->from($this->tableName)
->where(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
$this->slugFieldName,
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
),
$queryBuilder->expr()->isNull($this->slugFieldName)
)
)
->execute();
while ($record = $statement->fetchAssociative()) {
//Use the core slughelper which is also used in the BE form
$slug = $slugHelper->generate($record, $record['pid']);
/** @var QueryBuilder $queryBuilder */
$queryBuilder = $connection->createQueryBuilder();
$queryBuilder->update($this->tableName)
->where(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT)
)
)
->set($this->slugFieldName, $slug);
$databaseQueries[] = $queryBuilder->getSQL();
$queryBuilder->execute();
}
return $databaseQueries;
}
/**
* Count valid entries from EXT:realurl table tx_realurl_uniqalias which can be migrated
* Checks also for existance of third party extension table 'tx_realurl_uniqalias'
* EXT:realurl requires not to be installed
*
* @return int
*/
public function countOfRealurlAliasMigrations(): int
{
$elementCount = 0;
// Check if table 'tx_realurl_uniqalias' exists
/** @var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_realurl_uniqalias');
$schemaManager = $queryBuilder->getConnection()->getSchemaManager();
if ($schemaManager->tablesExist(['tx_realurl_uniqalias']) === true) {
// Count valid aliases
$queryBuilder->getRestrictions()->removeAll();
$elementCount = $queryBuilder->selectLiteral('COUNT(DISTINCT ' . $this->tableName . '.uid)')
->from('tx_realurl_uniqalias')
->join(
'tx_realurl_uniqalias',
$this->tableName,
$this->tableName,
$queryBuilder->expr()->eq(
'tx_realurl_uniqalias.value_id',
$queryBuilder->quoteIdentifier($this->tableName . '.uid')
)
)
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
$this->tableName . '.' . $this->slugFieldName,
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
),
$queryBuilder->expr()->isNull($this->tableName . '.' . $this->slugFieldName)
),
$queryBuilder->expr()->eq(
$this->tableName . '.sys_language_uid',
'tx_realurl_uniqalias.lang'
),
$queryBuilder->expr()->eq(
'tx_realurl_uniqalias.tablename',
$queryBuilder->createNamedParameter($this->tableName, \PDO::PARAM_STR)
),
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
'tx_realurl_uniqalias.expire',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
),
$queryBuilder->expr()->gte(
'tx_realurl_uniqalias.expire',
$queryBuilder->createNamedParameter($GLOBALS['ACCESS_TIME'], \PDO::PARAM_INT)
)
)
)
)
->execute()->fetchOne(0);
}
return $elementCount;
}
/**
* Perform migration of EXT:realurl unique alias into fs_media_gallery slugs
*
* @return array
*/
public function performRealurlAliasMigration(): array
{
$databaseQueries = [];
// Check if table 'tx_realurl_uniqalias' exists
/** @var QueryBuilder $queryBuilderForRealurl */
$queryBuilderForRealurl = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_realurl_uniqalias');
$schemaManager = $queryBuilderForRealurl->getConnection()->getSchemaManager();
if ($schemaManager->tablesExist(['tx_realurl_uniqalias']) === true) {
/** @var Connection $connection */
$connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->tableName);
$queryBuilder = $connection->createQueryBuilder();
// Get entries to update
$statement = $queryBuilder
->selectLiteral(
'DISTINCT ' . $this->tableName . '.uid, tx_realurl_uniqalias.value_alias, ' . $this->tableName . '.uid'
)
->from($this->tableName)
->join(
$this->tableName,
'tx_realurl_uniqalias',
'tx_realurl_uniqalias',
$queryBuilder->expr()->eq(
$this->tableName . '.uid',
$queryBuilder->quoteIdentifier('tx_realurl_uniqalias.value_id')
)
)
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
$this->tableName . '.' . $this->slugFieldName,
$queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
),
$queryBuilder->expr()->isNull($this->tableName . '.' . $this->slugFieldName)
),
$queryBuilder->expr()->eq(
$this->tableName . '.sys_language_uid',
'tx_realurl_uniqalias.lang'
),
$queryBuilder->expr()->eq(
'tx_realurl_uniqalias.tablename',
$queryBuilder->createNamedParameter($this->tableName, \PDO::PARAM_STR)
),
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
'tx_realurl_uniqalias.expire',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
),
$queryBuilder->expr()->gte(
'tx_realurl_uniqalias.expire',
$queryBuilder->createNamedParameter($GLOBALS['ACCESS_TIME'], \PDO::PARAM_INT)
)
)
)
)
->execute();
// Update entries
while ($record = $statement->fetchAssociative()) {
$slug = (string)$record['value_alias'];
$queryBuilder = $connection->createQueryBuilder();
$queryBuilder->update($this->tableName)
->where(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT)
)
)
->set($this->slugFieldName, $slug);
$databaseQueries[] = $queryBuilder->getSQL();
$queryBuilder->execute();
}
}
return $databaseQueries;
}
}

View File

@@ -0,0 +1,259 @@
<?php
namespace MiniFranske\FsMediaGallery\Service;
/***************************************************************
* Copyright notice
*
* (c) 2014 Frans Saris <franssaris@gmail.com>
* 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\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\FolderInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Utility class
*/
class Utility implements SingletonInterface
{
/**
* Get storage folders marked as media gallery
*
* @return array
*/
public function getStorageFolders()
{
$pages = [];
if ($this->getBeUser()) {
$q = $this->getDatabaseConnection()->createQueryBuilder();
$q->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
$quotedIdentifiers = $q->createNamedParameter(['mediagal'], Connection::PARAM_STR_ARRAY);
$q->select('uid', 'title')
->from('pages')
->where(
$q->expr()->andX(
$q->expr()->eq('doktype', 254),
$q->expr()->in('module', $quotedIdentifiers)
)
)
->orderBy('title');
$statement = $q->execute();
while ($row = $statement->fetchAssociative()) {
if (BackendUtility::readPageAccess($row['uid'], $this->getBeUser()->getPagePermsClause(1))) {
$pages[$row['uid']] = $row['title'];
}
}
}
return $pages;
}
/**
* Clear pageCache defined at the storage of the collection/album
*
* @param FolderInterface $folder
*/
public function clearMediaGalleryPageCache(FolderInterface $folder)
{
$collections = $this->findFileCollectionRecordsForFolder(
$folder->getStorage()->getUid(),
$folder->getIdentifier(),
array_keys($this->getStorageFolders())
);
if (!$collections) {
return;
}
/** @var DataHandler $tce */
$tce = GeneralUtility::makeInstance(DataHandler::class);
$tce->start([], []);
foreach ($collections as $collection) {
$pageConfig = BackendUtility::getPagesTSconfig($collection['pid']);
if (!empty($pageConfig['TCEMAIN.']['clearCacheCmd'])) {
$clearCacheCommands = GeneralUtility::trimExplode(',', $pageConfig['TCEMAIN.']['clearCacheCmd'], true);
$clearCacheCommands = array_unique($clearCacheCommands);
foreach ($clearCacheCommands as $clearCacheCommand) {
$tce->clear_cacheCmd($clearCacheCommand);
}
}
}
}
/**
* Gets the first parentCollections of the given folder and mediaFolderUid(storagepid)
*/
public function getFirstParentCollections(Folder $folder, int $mediaFolderUid): array
{
$parentCollection = [];
$evalPermissions = $folder->getStorage()->getEvaluatePermissions();
$folder->getStorage()->setEvaluatePermissions(false);
// If not root folder (for root folder parent === folder)
if ($folder->getParentFolder()->getIdentifier() !== $folder->getIdentifier()) {
$parentCollection = $this->findFileCollectionRecordsForFolder(
$folder->getStorage()->getUid(),
$folder->getParentFolder()->getIdentifier(),
[$mediaFolderUid]
);
if (!count($parentCollection)) {
$parentCollection = $this->getFirstParentCollections($folder->getParentFolder(), $mediaFolderUid);
}
}
$folder->getStorage()->setEvaluatePermissions($evalPermissions);
return $parentCollection;
}
/**
* Update file_collection record after move/rename folder
*/
public function updateFolderRecord(int $oldStorageUid, string $oldIdentifier, int $newStorageUid, string $newIdentifier, ?int $newParentAlbum = 0): void
{
$updatedData = [
'storage' => $newStorageUid,
'folder' => $newIdentifier
];
if ($newParentAlbum !== null) {
$updatedData['parentalbum'] = $newParentAlbum;
}
$this->getDatabaseConnection()->update(
'sys_file_collection',
$updatedData,
[
'storage' => (int)$oldStorageUid,
'folder' => $oldIdentifier,
]
);
}
/**
* Delete file_collection when folder is deleted
*
* @param int $storageUid
* @param string $identifier
*/
public function deleteFolderRecord($storageUid, $identifier)
{
$this->getDatabaseConnection()->update(
'sys_file_collection',
['deleted' => 1],
['folder' => $identifier, 'storage' => $storageUid]
);
}
/**
* Creates a folderRecord (sys_file_collection)
*
* @param string $title The title of the folder(album_name)
* @param int $collectionStoragePid The pid of the collection/mediaStorage
* @param int $storageUid The uid of the storage (fileStorage)
* @param string $identifier The identifier of the folder
* @param int $parentAlbum The uid of the parentAlbum
*/
public function createFolderRecord($title, $collectionStoragePid, $storageUid, $identifier, $parentAlbum = 0)
{
$folderRecord = [
'pid' => (int)$collectionStoragePid,
'deleted' => 0,
'hidden' => 0,
'type' => 'folder',
'storage' => (int)$storageUid,
'folder' => $identifier,
'title' => $title,
'parentalbum' => (int)$parentAlbum,
'webdescription' => '',
];
// Create slug
$slugTCAConfig = $GLOBALS['TCA']['sys_file_collection']['columns']['slug']['config'];
/** @var SlugHelper $slugHelper */
$slugHelper = GeneralUtility::makeInstance(
SlugHelper::class,
'sys_file_collection',
'slug',
$slugTCAConfig
);
$slug = $slugHelper->generate($folderRecord, $collectionStoragePid);
$folderRecord['slug'] = $slug;
$this->getDatabaseConnection()->insert('sys_file_collection', $folderRecord);
}
/**
* @param null|int[] $pids
*/
public function findFileCollectionRecordsForFolder(int $storageUid, string $folder, ?array $pids = null): ?array
{
$q = $this->getDatabaseConnection()->createQueryBuilder();
$q->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
$q->select('uid', 'pid', 'title', 'type', 'hidden', 'parentalbum')
->from('sys_file_collection')
->where(
$q->expr()->andX(
$q->expr()->eq('storage', $q->createNamedParameter($storageUid, \PDO::PARAM_INT)),
$q->expr()->eq('folder', $q->createNamedParameter($folder))
)
);
if (is_array($pids) && count($pids) > 0) {
$q->andWhere(
$q->expr()->in('pid', $pids)
);
}
return $q->execute()->fetchAllAssociative();
}
protected function getDatabaseConnection(string $table = 'sys_file_collection'): Connection
{
return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
}
protected function getBeUser(): ?BackendUserAuthentication
{
return $GLOBALS['BE_USER'] ?? null;
}
}