Initial commit - Typo3 11.5.41
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\ContextMenu\ItemProviders;
|
||||
|
||||
use MiniFranske\FsMediaGallery\Service\Utility;
|
||||
use TYPO3\CMS\Backend\ContextMenu\ItemProviders\AbstractProvider;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
use TYPO3\CMS\Core\Resource\FolderInterface;
|
||||
use TYPO3\CMS\Core\Resource\ResourceFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
class FsMediaGalleryProvider extends AbstractProvider
|
||||
{
|
||||
protected $itemsConfiguration = [];
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canHandle(): bool
|
||||
{
|
||||
return $this->table === 'sys_file';
|
||||
}
|
||||
|
||||
/**
|
||||
* @var Folder
|
||||
*/
|
||||
protected $folder;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 90;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize file object
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$resource = GeneralUtility::makeInstance(ResourceFactory::class)
|
||||
->retrieveFileOrFolderObject($this->identifier);
|
||||
if ($resource instanceof Folder
|
||||
&& in_array(
|
||||
$resource->getRole(),
|
||||
[FolderInterface::ROLE_DEFAULT, FolderInterface::ROLE_USERUPLOAD],
|
||||
true
|
||||
)
|
||||
) {
|
||||
$this->folder = $resource;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the media album add/edit menu items
|
||||
*
|
||||
* @param array $items
|
||||
* @return array
|
||||
*/
|
||||
public function addItems(array $items): array
|
||||
{
|
||||
$this->initialize();
|
||||
if (!($this->folder instanceof Folder)) {
|
||||
return $items;
|
||||
}
|
||||
|
||||
/** @var \MiniFranske\FsMediaGallery\Service\Utility $utility */
|
||||
$utility = GeneralUtility::makeInstance(Utility::class);
|
||||
$mediaFolders = $utility->getStorageFolders();
|
||||
|
||||
if (count($mediaFolders) === 0) {
|
||||
|
||||
$this->itemsConfiguration['add-media-gallery'] = [
|
||||
'label' => $this->sL('module.buttons.createAlbum'),
|
||||
'iconIdentifier' => 'action-add-album',
|
||||
'callbackAction' => 'missingMediaFolder',
|
||||
'title' => $this->sL('module.alerts.firstCreateStorageFolder')
|
||||
];
|
||||
}
|
||||
|
||||
if (count($mediaFolders) > 0) {
|
||||
|
||||
$collections = $utility->findFileCollectionRecordsForFolder(
|
||||
$this->folder->getStorage()->getUid(),
|
||||
$this->folder->getIdentifier(),
|
||||
array_keys($mediaFolders)
|
||||
);
|
||||
|
||||
foreach ($collections as $collection) {
|
||||
$this->itemsConfiguration['edit-media-gallery-' . $collection['uid']] = [
|
||||
'label' => sprintf($this->sL('module.buttons.editAlbum'), $collection['title']),
|
||||
'iconIdentifier' => 'action-edit-album',
|
||||
'callbackAction' => 'mediaAlbum',
|
||||
'uid' => $collection['uid'],
|
||||
];
|
||||
}
|
||||
|
||||
if (!count($collections)) {
|
||||
foreach ($mediaFolders as $uid => $title) {
|
||||
|
||||
// Find parent album for auto setting parent album
|
||||
$parentUid = 0;
|
||||
$parents = $utility->findFileCollectionRecordsForFolder(
|
||||
$this->folder->getStorage()->getUid(),
|
||||
$this->folder->getParentFolder()->getIdentifier(),
|
||||
[$uid]
|
||||
);
|
||||
|
||||
// If parent(s) found we take the first one
|
||||
if (count($parents)) {
|
||||
$parentUid = $parents[0]['uid'];
|
||||
}
|
||||
|
||||
$this->itemsConfiguration['add-media-gallery-' . $uid] = [
|
||||
'label' => sprintf($this->sL('module.buttons.createAlbumIn'), $title),
|
||||
'iconIdentifier' => 'action-add-album',
|
||||
'callbackAction' => 'mediaAlbum',
|
||||
'pid' => $uid,
|
||||
'parentUid' => $parentUid,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->itemsConfiguration !== []) {
|
||||
$items += $this->prepareItems(
|
||||
['media_gallery_divider' => ['type' => 'divider']]
|
||||
+ $this->itemsConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $itemName
|
||||
* @return array
|
||||
*/
|
||||
protected function getAdditionalAttributes(string $itemName): array
|
||||
{
|
||||
$itemInfo = $this->itemsConfiguration[$itemName] ?? [];
|
||||
|
||||
return [
|
||||
'data-callback-module' => 'TYPO3/CMS/FsMediaGallery/ContextMenuActions',
|
||||
'data-album-record-uid' => $itemInfo['uid'] ?? 0,
|
||||
'data-pid' => $itemInfo['pid'] ?? 0,
|
||||
'data-parent-uid' => $itemInfo['parentUid'] ?? 0,
|
||||
'data-title' => $itemInfo['title'] ?? ucfirst(trim(str_replace('_', ' ', $this->folder->getName()))),
|
||||
'data-storage' => $this->folder->getStorage()->getUid(),
|
||||
'data-folder' => $this->folder->getIdentifier(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language string
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $languageFile
|
||||
* @return string
|
||||
*/
|
||||
protected function sL($key, $languageFile = 'LLL:EXT:fs_media_gallery/Resources/Private/Language/locallang_be.xlf')
|
||||
{
|
||||
return $this->languageService->sL($languageFile . ':' . $key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
<?php
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Controller;
|
||||
|
||||
/***************************************************************
|
||||
* 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 3 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 GeorgRinger\NumberedPagination\NumberedPagination;
|
||||
use MiniFranske\FsMediaGallery\Pagination\ExtendedArrayPaginator;
|
||||
use MiniFranske\FsMediaGallery\Utility\TypoScriptUtility;
|
||||
use MiniFranske\FsMediaGallery\Domain\Repository\MediaAlbumRepository;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TYPO3\CMS\Core\Pagination\ArrayPaginator;
|
||||
use TYPO3\CMS\Core\Pagination\SimplePagination;
|
||||
use TYPO3\CMS\Extbase\Http\ForwardResponse;
|
||||
use TYPO3\CMS\Frontend\Controller\ErrorController;
|
||||
use TYPO3\CMS\Core\Http\ImmediateResponseException;
|
||||
use MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
|
||||
/**
|
||||
* MediaAlbumController
|
||||
*/
|
||||
class MediaAlbumController extends ActionController
|
||||
{
|
||||
|
||||
/**
|
||||
* mediaAlbumRepository
|
||||
*
|
||||
* @var \MiniFranske\FsMediaGallery\Domain\Repository\MediaAlbumRepository
|
||||
*/
|
||||
protected $mediaAlbumRepository;
|
||||
|
||||
/**
|
||||
* Injects the Configuration Manager
|
||||
*
|
||||
* @param ConfigurationManagerInterface $configurationManager Instance of the Configuration Manager
|
||||
* @return void
|
||||
*/
|
||||
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
|
||||
$frameworkSettings = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
|
||||
'fsmediagallery',
|
||||
'fsmediagallery_mediagallery'
|
||||
);
|
||||
$flexformSettings = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS
|
||||
);
|
||||
|
||||
// merge Framework (TypoScript) and Flexform settings
|
||||
if (isset($frameworkSettings['settings']['overrideFlexformSettingsIfEmpty'])) {
|
||||
/** @var $typoScriptUtility \MiniFranske\FsMediaGallery\Utility\TypoScriptUtility */
|
||||
$typoScriptUtility = GeneralUtility::makeInstance(TypoScriptUtility::class);
|
||||
$mergedSettings = $typoScriptUtility->override($flexformSettings, $frameworkSettings);
|
||||
$this->settings = $mergedSettings;
|
||||
} else {
|
||||
$this->settings = $flexformSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* sync persistence.storagePid=settings.startingpoint and persistence.recursive=settings.recursive
|
||||
*/
|
||||
// overwrite persistence.storagePid if settings.startingpoint is defined in flexform
|
||||
if (!empty($this->settings['startingpoint'])) {
|
||||
$frameworkSettings['persistence']['storagePid'] = $this->settings['startingpoint'];
|
||||
// if settings.startingpoint is not set in flexform, use persistence.storagePid from TS
|
||||
} elseif (!empty($frameworkSettings['persistence']['storagePid'])) {
|
||||
$this->settings['startingpoint'] = $frameworkSettings['persistence']['storagePid'];
|
||||
// startingpoint/storagePid is not set via TS nor flexforms > fallback to current pid
|
||||
} else {
|
||||
$this->settings['startingpoint'] = $frameworkSettings['persistence']['storagePid'] = $GLOBALS['TSFE']->id;
|
||||
}
|
||||
|
||||
// set persistence.recursive if settings.recursive is defined in flexform
|
||||
if (!empty($this->settings['recursive'])) {
|
||||
$frameworkSettings['persistence']['recursive'] = $this->settings['recursive'];
|
||||
// if settings.recursive is not set in flexform, use persistence.recursive from TS
|
||||
} elseif (!empty($frameworkSettings['persistence']['recursive'])) {
|
||||
$this->settings['recursive'] = $frameworkSettings['persistence']['recursive'];
|
||||
// recursive is not set via TS nor flexforms
|
||||
} else {
|
||||
$this->settings['recursive'] = $frameworkSettings['persistence']['recursive'] = 0;
|
||||
}
|
||||
|
||||
// write back altered configuration
|
||||
$this->configurationManager->setConfiguration($frameworkSettings);
|
||||
|
||||
// check some settings
|
||||
if (!isset($this->settings['list']['pagination']['itemsPerPage']) || $this->settings['list']['pagination']['itemsPerPage'] < 1) {
|
||||
$this->settings['list']['pagination']['itemsPerPage'] = 12;
|
||||
}
|
||||
if (!isset($this->settings['album']['pagination']['itemsPerPage']) || $this->settings['album']['pagination']['itemsPerPage'] < 1) {
|
||||
$this->settings['album']['pagination']['itemsPerPage'] = 12;
|
||||
}
|
||||
// correct resizeMode 's' set in flexforms (flexforms value '' is used for inherit/definition by TS)
|
||||
if (isset($this->settings['list']['thumb']['resizeMode']) && $this->settings['list']['thumb']['resizeMode'] == 's') {
|
||||
$this->settings['list']['thumb']['resizeMode'] = '';
|
||||
}
|
||||
if (isset($this->settings['album']['thumb']['resizeMode']) && $this->settings['album']['thumb']['resizeMode'] == 's') {
|
||||
$this->settings['album']['thumb']['resizeMode'] = '';
|
||||
}
|
||||
if (isset($this->settings['detail']['asset']['resizeMode']) && $this->settings['detail']['asset']['resizeMode'] == 's') {
|
||||
$this->settings['detail']['asset']['resizeMode'] = '';
|
||||
}
|
||||
if (isset($this->settings['random']['thumb']['resizeMode']) && $this->settings['random']['thumb']['resizeMode'] == 's') {
|
||||
$this->settings['random']['thumb']['resizeMode'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects the MediaAlbumRepository
|
||||
*
|
||||
* @param \MiniFranske\FsMediaGallery\Domain\Repository\MediaAlbumRepository $mediaAlbumRepository
|
||||
* @return void
|
||||
*/
|
||||
public function injectMediaAlbumRepository(
|
||||
MediaAlbumRepository $mediaAlbumRepository
|
||||
)
|
||||
{
|
||||
$this->mediaAlbumRepository = $mediaAlbumRepository;
|
||||
if (!empty($this->settings['allowedAssetMimeTypes'])) {
|
||||
$this->mediaAlbumRepository->setAllowedAssetMimeTypes(GeneralUtility::trimExplode(',',
|
||||
$this->settings['allowedAssetMimeTypes']));
|
||||
}
|
||||
if (isset($this->settings['album']['assets']['orderBy'])) {
|
||||
$this->mediaAlbumRepository->setAssetsOrderBy($this->settings['album']['assets']['orderBy']);
|
||||
}
|
||||
if (isset($this->settings['album']['assets']['orderDirection'])) {
|
||||
$this->mediaAlbumRepository->setAssetsOrderDirection($this->settings['album']['assets']['orderDirection']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set album uid restrictions as defined in settings
|
||||
* By setting this in the repository also the MediaAlbum::getAlbums()
|
||||
* and MediaAlbum::getRandomAlbum() is restricted to these uids.
|
||||
*/
|
||||
protected function setAlbumUidRestrictions()
|
||||
{
|
||||
$mediaAlbumsUids = GeneralUtility::trimExplode(',', $this->settings['mediaAlbumsUids'], true);
|
||||
$this->mediaAlbumRepository->setAlbumUids($mediaAlbumsUids);
|
||||
$this->mediaAlbumRepository->setUseAlbumUidsAsExclude(!empty($this->settings['useAlbumFilterAsExclude']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Index Action
|
||||
* As switchableControllerActions can be limited in EM this function
|
||||
* is needed as default action (with no output).
|
||||
* It is set as default action in flexform to make sure the
|
||||
* correct tabs/fields are shown when a new plugin is added.
|
||||
*/
|
||||
public function indexAction(): ResponseInterface
|
||||
{
|
||||
return $this->htmlResponse('<i>Please select a display mode in the plugin.</i>');
|
||||
}
|
||||
|
||||
/**
|
||||
* NestedList Action
|
||||
* Displays a (nested) list of albums; default/show action in fs_media_gallery <= 1.0.0
|
||||
*
|
||||
* @param int $mediaAlbum (this is not directly mapped to an object to handle 404 on our own)
|
||||
*/
|
||||
public function nestedListAction(int $mediaAlbum = 0): ResponseInterface
|
||||
{
|
||||
$mediaAlbums = null;
|
||||
$mediaAlbum = (int)$mediaAlbum ?: null;
|
||||
$showBackLink = true;
|
||||
|
||||
$this->setAlbumUidRestrictions();
|
||||
|
||||
// Single view
|
||||
if ($mediaAlbum) {
|
||||
/** @var MediaAlbum $mediaAlbum */
|
||||
$mediaAlbum = $this->mediaAlbumRepository->findByUid($mediaAlbum);
|
||||
if (!$mediaAlbum) {
|
||||
return $this->pageNotFound(LocalizationUtility::translate('no_album_found', 'fs_media_gallery'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No album selected and album restriction set, find all "root" albums
|
||||
* Albums without parent or with parent not selected as allowed
|
||||
*/
|
||||
if ($mediaAlbum === null && $this->mediaAlbumRepository->getAlbumUids() !== []) {
|
||||
$mediaAlbums = [];
|
||||
$all = $this->mediaAlbumRepository->findAll((bool)$this->settings['list']['hideEmptyAlbums'], $this->settings['list']['orderBy'], $this->settings['list']['orderDirection']);
|
||||
/** @var MediaAlbum $album */
|
||||
foreach ($all as $album) {
|
||||
$parent = $album->getParentalbum();
|
||||
if ($parent === null
|
||||
|| (!$this->mediaAlbumRepository->getUseAlbumUidsAsExclude() && !in_array($parent->getUid(),
|
||||
$this->mediaAlbumRepository->getAlbumUids()))
|
||||
|| ($this->mediaAlbumRepository->getUseAlbumUidsAsExclude() && in_array($parent->getUid(),
|
||||
$this->mediaAlbumRepository->getAlbumUids()))
|
||||
) {
|
||||
$mediaAlbums[] = $album;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$mediaAlbums = $this->mediaAlbumRepository->findByParentalbum($mediaAlbum,
|
||||
$this->settings['list']['hideEmptyAlbums'], $this->settings['list']['orderBy'],
|
||||
$this->settings['list']['orderDirection']);
|
||||
}
|
||||
|
||||
// when only 1 album skip gallery view
|
||||
if ($mediaAlbum === null && !empty($this->settings['list']['skipListWhenOnlyOneAlbum']) && count($mediaAlbums) === 1) {
|
||||
$mediaAlbum = $mediaAlbums[0];
|
||||
$mediaAlbums = $this->mediaAlbumRepository->findByParentalbum($mediaAlbum,
|
||||
$this->settings['list']['hideEmptyAlbums'], $this->settings['list']['orderBy'],
|
||||
$this->settings['list']['orderDirection']);
|
||||
$showBackLink = false;
|
||||
}
|
||||
|
||||
if ($mediaAlbum && $mediaAlbum->getParentalbum() && (
|
||||
$this->mediaAlbumRepository->getAlbumUids() === []
|
||||
||
|
||||
(!$this->mediaAlbumRepository->getUseAlbumUidsAsExclude() && in_array($mediaAlbum->getParentalbum()->getUid(),
|
||||
$this->mediaAlbumRepository->getAlbumUids()))
|
||||
||
|
||||
($this->mediaAlbumRepository->getUseAlbumUidsAsExclude() && !in_array($mediaAlbum->getParentalbum()->getUid(),
|
||||
$this->mediaAlbumRepository->getAlbumUids()))
|
||||
)
|
||||
) {
|
||||
$this->view->assign('parentAlbum', $mediaAlbum->getParentalbum());
|
||||
}
|
||||
|
||||
$this->view->assign('showBackLink', $showBackLink);
|
||||
$this->view->assign('mediaAlbums', $mediaAlbums);
|
||||
$this->view->assign('mediaAlbum', $mediaAlbum);
|
||||
|
||||
if ($mediaAlbums) {
|
||||
$this->view->assign('mediaAlbumsPagination', $this->getAlbumsPagination($mediaAlbums));
|
||||
}
|
||||
if ($mediaAlbum) {
|
||||
$this->view->assign('mediaAlbumPagination', $this->getAlbumPagination($mediaAlbum));
|
||||
}
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* FlatList Action
|
||||
* Displays a (one-dimensional, flattened) list of albums
|
||||
*
|
||||
* @param int $mediaAlbum (this is not directly mapped to an object to handle 404 on our own)
|
||||
*/
|
||||
public function flatListAction(int $mediaAlbum = 0): ResponseInterface
|
||||
{
|
||||
$showBackLink = true;
|
||||
if ($mediaAlbum) {
|
||||
// if an album is given, display it
|
||||
$mediaAlbum = $this->mediaAlbumRepository->findByUid($mediaAlbum);
|
||||
if (!$mediaAlbum) {
|
||||
return $this->pageNotFound(LocalizationUtility::translate('no_album_found', 'fs_media_gallery'));
|
||||
}
|
||||
$this->view->assign('displayMode', 'album');
|
||||
$this->view->assign('mediaAlbum', $mediaAlbum);
|
||||
} else {
|
||||
// display the album list
|
||||
$mediaAlbums = $this->mediaAlbumRepository->findAll($this->settings['list']['hideEmptyAlbums'],
|
||||
$this->settings['list']['orderBy'], $this->settings['list']['orderDirection']);
|
||||
$this->view->assign('displayMode', 'flatList');
|
||||
$this->view->assign('mediaAlbums', $mediaAlbums);
|
||||
$showBackLink = false;
|
||||
}
|
||||
$this->view->assign('showBackLink', $showBackLink);
|
||||
|
||||
if ($mediaAlbum) {
|
||||
$this->view->assign('mediaAlbumPagination', $this->getAlbumPagination($mediaAlbum));
|
||||
}
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show single Album (defined in FlexForm/TS) Action
|
||||
* As showAlbumAction() displays any album by the given param this function gets its value from TS/Felxform
|
||||
* This could be merged with showAlbumAction() if there is a way to determine which switchableControllerActions is defined in Felxform.
|
||||
*/
|
||||
public function showAlbumByConfigAction(): ResponseInterface
|
||||
{
|
||||
// get all request arguments (e.g. pagination widget)
|
||||
$arguments = $this->request->getArguments();
|
||||
// set album id from settings
|
||||
$arguments['mediaAlbum'] = $this->settings['mediaAlbum'];
|
||||
|
||||
return (new ForwardResponse('showAlbum'))->withArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show single Album Action
|
||||
*
|
||||
* @param int $mediaAlbum (this is not directly mapped to an object to handle 404 on our own)
|
||||
*/
|
||||
public function showAlbumAction(int $mediaAlbum = null): ResponseInterface
|
||||
{
|
||||
$mediaAlbum = (int)$mediaAlbum ?: null;
|
||||
if (empty($mediaAlbum)) {
|
||||
$mediaAlbum = (int)$this->settings['mediaAlbum'];
|
||||
}
|
||||
// if album uid is set through settings (typoscript or flexform) we skip the storage check
|
||||
$respectStorage = true;
|
||||
if ((int)$this->settings['mediaAlbum'] === (int)$mediaAlbum) {
|
||||
$respectStorage = false;
|
||||
}
|
||||
$mediaAlbum = $this->mediaAlbumRepository->findByUid($mediaAlbum, $respectStorage);
|
||||
$this->view->assign('mediaAlbum', $mediaAlbum);
|
||||
$this->view->assign('showBackLink', false);
|
||||
$this->view->assign('mediaAlbumPagination', $this->getAlbumPagination($mediaAlbum));
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show single media asset from album
|
||||
*
|
||||
* @param \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum $mediaAlbum
|
||||
* @param int $mediaAssetUid
|
||||
* @TYPO3\CMS\Extbase\Annotation\IgnoreValidation("")
|
||||
*/
|
||||
public function showAssetAction(MediaAlbum $mediaAlbum, int $mediaAssetUid): ResponseInterface
|
||||
{
|
||||
|
||||
if (isset($this->settings['album']['assets']['orderBy'])) {
|
||||
$mediaAlbum->setAssetsOrderBy($this->settings['album']['assets']['orderBy']);
|
||||
}
|
||||
|
||||
if (isset($this->settings['album']['assets']['orderDirection'])) {
|
||||
$mediaAlbum->setAssetsOrderDirection($this->settings['album']['assets']['orderDirection']);
|
||||
}
|
||||
|
||||
list($previousAsset, $mediaAsset, $nextAsset) = $mediaAlbum->getPreviousCurrentAndNext($mediaAssetUid);
|
||||
if (!$mediaAsset) {
|
||||
$message = LocalizationUtility::translate('asset_not_found', 'fs_media_gallery');
|
||||
return $this->pageNotFound((empty($message) ? 'Asset not found.' : $message));
|
||||
}
|
||||
$this->view->assign('previousAsset', $previousAsset);
|
||||
$this->view->assign('nextAsset', $nextAsset);
|
||||
$this->view->assign('mediaAsset', $mediaAsset);
|
||||
$this->view->assign('mediaAlbum', $mediaAlbum);
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show random media asset
|
||||
*/
|
||||
public function randomAssetAction(): ResponseInterface
|
||||
{
|
||||
|
||||
$this->setAlbumUidRestrictions();
|
||||
|
||||
$mediaAlbum = $this->mediaAlbumRepository->findRandom();
|
||||
$this->view->assign('mediaAlbum', $mediaAlbum);
|
||||
|
||||
return $this->htmlResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* If there were validation errors, we don't want to write details like
|
||||
* "An error occurred while trying to call Tx_Community_Controller_UserController->updateAction()"
|
||||
*
|
||||
* @return string|boolean The flash message or FALSE if no flash message should be set
|
||||
*/
|
||||
protected function getErrorFlashMessage(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page not found wrapper
|
||||
*
|
||||
* @throws ImmediateResponseException
|
||||
*/
|
||||
protected function pageNotFound(string $message): ResponseInterface
|
||||
{
|
||||
if (!empty($GLOBALS['TSFE'])) {
|
||||
$response = GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction($GLOBALS['TYPO3_REQUEST'], $message);
|
||||
throw new ImmediateResponseException($response);
|
||||
}
|
||||
|
||||
return $this->htmlResponse($message);
|
||||
}
|
||||
|
||||
private function getAlbumPagination(MediaAlbum $album): array
|
||||
{
|
||||
$paginationConfiguration = $this->settings['album']['pagination'] ?? [];
|
||||
|
||||
$itemsPerPage = (int)($paginationConfiguration['itemsPerPage'] ?? 10);
|
||||
$maximumNumberOfLinks = (int)($paginationConfiguration['maximumNumberOfLinks'] ?? 0);
|
||||
|
||||
$currentPage = $this->request->hasArgument('currentPage') ? (int)$this->request->getArgument('currentPage') : 1;
|
||||
$paginator = GeneralUtility::makeInstance(ExtendedArrayPaginator::class, $album->getAssets(), $currentPage, $itemsPerPage);
|
||||
$paginationClass = $paginationConfiguration['class'] ?? SimplePagination::class;
|
||||
if ($paginationClass === NumberedPagination::class && $maximumNumberOfLinks) {
|
||||
$pagination = GeneralUtility::makeInstance(NumberedPagination::class, $paginator, $maximumNumberOfLinks);
|
||||
} else {
|
||||
$pagination = GeneralUtility::makeInstance(SimplePagination::class, $paginator);
|
||||
}
|
||||
|
||||
return [
|
||||
'currentPage' => $currentPage,
|
||||
'paginator' => $paginator,
|
||||
'pagination' => $pagination,
|
||||
];
|
||||
}
|
||||
|
||||
private function getAlbumsPagination(array $albums): array
|
||||
{
|
||||
$paginationConfiguration = $this->settings['list']['pagination'] ?? [];
|
||||
|
||||
$itemsPerPage = (int)($paginationConfiguration['itemsPerPage'] ?? 10);
|
||||
$maximumNumberOfLinks = (int)($paginationConfiguration['maximumNumberOfLinks'] ?? 0);
|
||||
|
||||
$currentPage = $this->request->hasArgument('currentAlbumPage') ? (int)$this->request->getArgument('currentAlbumPage') : 1;
|
||||
$paginator = GeneralUtility::makeInstance(ArrayPaginator::class, $albums, $currentPage, $itemsPerPage);
|
||||
$paginationClass = $paginationConfiguration['class'] ?? SimplePagination::class;
|
||||
if ($paginationClass === NumberedPagination::class && $maximumNumberOfLinks) {
|
||||
$pagination = GeneralUtility::makeInstance(NumberedPagination::class, $paginator, $maximumNumberOfLinks);
|
||||
} else {
|
||||
$pagination = GeneralUtility::makeInstance(SimplePagination::class, $paginator);
|
||||
}
|
||||
|
||||
return [
|
||||
'currentPage' => $currentPage,
|
||||
'paginator' => $paginator,
|
||||
'pagination' => $pagination,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,519 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Domain\Model;
|
||||
|
||||
/***************************************************************
|
||||
* 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 3 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\Extbase\DomainObject\AbstractEntity;
|
||||
use TYPO3\CMS\Core\Resource\FileCollectionRepository;
|
||||
use MiniFranske\FsMediaGallery\Domain\Repository\MediaAlbumRepository;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Resource\FileInterface;
|
||||
use TYPO3\CMS\Core\Resource\FileReference;
|
||||
|
||||
/**
|
||||
* Media album
|
||||
*/
|
||||
class MediaAlbum extends AbstractEntity
|
||||
{
|
||||
|
||||
/**
|
||||
* fileCollectionRepository
|
||||
*
|
||||
* @var \TYPO3\CMS\Core\Resource\FileCollectionRepository
|
||||
*/
|
||||
protected $fileCollectionRepository;
|
||||
|
||||
/**
|
||||
* mediaAlbumRepository
|
||||
*
|
||||
* @var \MiniFranske\FsMediaGallery\Domain\Repository\MediaAlbumRepository
|
||||
*/
|
||||
protected $mediaAlbumRepository;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $assetCache;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedMimeTypes = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $assetsOrderBy = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $assetsOrderDirection = 'asc';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $excludeEmptyAlbums = false;
|
||||
|
||||
/**
|
||||
* Assets
|
||||
* An array of File or FileReference
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $assets;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
protected $assetsCount;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $hidden;
|
||||
|
||||
/**
|
||||
* Title
|
||||
*
|
||||
* @var \string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* Description visible online
|
||||
*
|
||||
* @var \string
|
||||
*/
|
||||
protected $webdescription;
|
||||
|
||||
/**
|
||||
* @var \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum|NULL
|
||||
* @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
|
||||
*/
|
||||
protected $parentalbum;
|
||||
|
||||
/**
|
||||
* Main asset
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Domain\Model\FileReference
|
||||
*/
|
||||
protected $mainAsset;
|
||||
|
||||
/**
|
||||
* Child albums
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum>
|
||||
* @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
|
||||
*/
|
||||
public $albumCache;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
protected $datetime;
|
||||
|
||||
public function injectFileCollectionRepository(FileCollectionRepository $fileCollectionRepository): void
|
||||
{
|
||||
$this->fileCollectionRepository = $fileCollectionRepository;
|
||||
}
|
||||
|
||||
public function injectMediaAlbumRepository(MediaAlbumRepository $mediaAlbumRepository): void
|
||||
{
|
||||
$this->mediaAlbumRepository = $mediaAlbumRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allowedMimeTypes
|
||||
*
|
||||
* @param array $allowedMimeTypes
|
||||
*/
|
||||
public function setAllowedMimeTypes($allowedMimeTypes)
|
||||
{
|
||||
$this->allowedMimeTypes = $allowedMimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowedMimeTypes
|
||||
*
|
||||
* @return array $allowedMimeTypes
|
||||
*/
|
||||
public function getAllowedMimeTypes()
|
||||
{
|
||||
return $this->allowedMimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assetsOrderBy
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAssetsOrderBy()
|
||||
{
|
||||
return $this->assetsOrderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assetsOrderBy
|
||||
*
|
||||
* @param string $assetsOrderBy
|
||||
*/
|
||||
public function setAssetsOrderBy($assetsOrderBy)
|
||||
{
|
||||
$this->assetsOrderBy = $assetsOrderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assetsOrderDirection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAssetsOrderDirection()
|
||||
{
|
||||
return $this->assetsOrderDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assetsOrderDirection
|
||||
*
|
||||
* @param string $assetsOrderDirection
|
||||
*/
|
||||
public function setAssetsOrderDirection($assetsOrderDirection)
|
||||
{
|
||||
$this->assetsOrderDirection = strtolower($assetsOrderDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get excludeEmptyAlbums
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getExcludeEmptyAlbums()
|
||||
{
|
||||
return $this->excludeEmptyAlbums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set excludeEmptyAlbums
|
||||
*
|
||||
* @param bool $excludeEmptyAlbums
|
||||
*/
|
||||
public function setExcludeEmptyAlbums($excludeEmptyAlbums)
|
||||
{
|
||||
$this->excludeEmptyAlbums = (bool)$excludeEmptyAlbums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hidden
|
||||
*
|
||||
* @param boolean $hidden
|
||||
*/
|
||||
public function setHidden($hidden)
|
||||
{
|
||||
$this->hidden = $hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hidden
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getHidden()
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title
|
||||
*
|
||||
* @return \string $title
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title
|
||||
*
|
||||
* @param \string $title
|
||||
* @return void
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the webdescription
|
||||
*
|
||||
* @return \string $webdescription
|
||||
*/
|
||||
public function getWebdescription()
|
||||
{
|
||||
return $this->webdescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the webdescription
|
||||
*
|
||||
* @param \string $webdescription
|
||||
* @return void
|
||||
*/
|
||||
public function setWebdescription($webdescription)
|
||||
{
|
||||
$this->webdescription = $webdescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parentalbum
|
||||
*
|
||||
* @param \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum $parentalbum
|
||||
*/
|
||||
public function setParentalbum(\MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum $parentalbum)
|
||||
{
|
||||
$this->parentalbum = $parentalbum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parentalbum
|
||||
*
|
||||
* @return \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum
|
||||
*/
|
||||
public function getParentalbum()
|
||||
{
|
||||
return $this->parentalbum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File[]|FileReference[]
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
if ($this->assetCache === null) {
|
||||
try {
|
||||
/** @var $fileCollection \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection */
|
||||
$fileCollection = $this->fileCollectionRepository->findByUid($this->getUid());
|
||||
$fileCollection->loadContents();
|
||||
$files = $fileCollection->getItems();
|
||||
// check if file has right mimeType
|
||||
if (count($this->allowedMimeTypes) > 0) {
|
||||
foreach ($files as $key => $fileObject) {
|
||||
/** @var $fileObject File|FileReference */
|
||||
if (!in_array($fileObject->getMimeType(), $this->allowedMimeTypes)) {
|
||||
unset($files[$key]);
|
||||
}
|
||||
}
|
||||
// reset keys
|
||||
$files = array_values($files);
|
||||
}
|
||||
if (trim($this->assetsOrderBy) !== '') {
|
||||
$files = $this->orderAssets($files, $this->assetsOrderBy, $this->assetsOrderDirection);
|
||||
}
|
||||
$this->assetCache = $files;
|
||||
} catch (\Exception $exception) {
|
||||
// failing albums get disabled
|
||||
$this->setHidden(true);
|
||||
$this->mediaAlbumRepository->update($this);
|
||||
$this->assetCache = [];
|
||||
}
|
||||
}
|
||||
return $this->assetCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get asset by uid
|
||||
*
|
||||
* @param int $assetUid
|
||||
* @return File|FileReference|NULL
|
||||
*/
|
||||
public function getAssetByUid($assetUid)
|
||||
{
|
||||
foreach ($assets = $this->getAssets() as $asset) {
|
||||
/** @var $asset File|FileReference */
|
||||
if ((int)$assetUid === (int)$asset->getUid()) {
|
||||
return $asset;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pevious, current and next asset by assetUid
|
||||
*
|
||||
* @param $assetUid
|
||||
* @return FileInterface[]
|
||||
*/
|
||||
public function getPreviousCurrentAndNext($assetUid)
|
||||
{
|
||||
$previous = $last = $current = $next = null;
|
||||
|
||||
foreach ($assets = $this->getAssets() as $asset) {
|
||||
if ($current !== null) {
|
||||
$next = $asset;
|
||||
break;
|
||||
}
|
||||
$previous = $last;
|
||||
$last = $asset;
|
||||
/** @var $asset File|FileReference */
|
||||
if ((int)$assetUid === (int)$asset->getUid()) {
|
||||
$current = $asset;
|
||||
}
|
||||
}
|
||||
|
||||
return [$previous, $current, $next];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @deprecated Will be removed in next major version 2.*
|
||||
*/
|
||||
public function getAssetsUids()
|
||||
{
|
||||
trigger_error('MediaAlbum::getAssetsUid is deprecated and will be removed with next major version 2.*. Use getAssets() as this method can not handle static file collections', E_USER_DEPRECATED);
|
||||
$assetsUids = [];
|
||||
foreach ($assets = $this->getAssets() as $asset) {
|
||||
/** @var $asset FileInterface */
|
||||
$assetsUids[] = $asset->getUid();
|
||||
}
|
||||
return $assetsUids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assetsCount
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getAssetsCount()
|
||||
{
|
||||
if ($this->assetCache === null) {
|
||||
return count($this->getAssets());
|
||||
}
|
||||
return count($this->assetCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child albums
|
||||
*
|
||||
* @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum>>
|
||||
*/
|
||||
public function getAlbums()
|
||||
{
|
||||
if ($this->albumCache === null) {
|
||||
$this->albumCache = $this->mediaAlbumRepository->findByParentalbum($this, $this->excludeEmptyAlbums);
|
||||
}
|
||||
return $this->albumCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get random child album
|
||||
*
|
||||
* @return MediaAlbum
|
||||
*/
|
||||
public function getRandomAlbum()
|
||||
{
|
||||
$albums = $this->getAlbums();
|
||||
return $albums[rand(0, count($albums) - 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File|FileReference
|
||||
*/
|
||||
public function getMainAsset()
|
||||
{
|
||||
$mainAsset = null;
|
||||
if ($this->mainAsset) {
|
||||
$mainAsset = $this->mainAsset->getOriginalResource();
|
||||
} else {
|
||||
$assets = $this->getAssets();
|
||||
$mainAsset = $assets !== [] ? $assets[0] : null;
|
||||
}
|
||||
return $mainAsset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File|FileReference
|
||||
*/
|
||||
public function getRandomAsset()
|
||||
{
|
||||
$assets = $this->getAssets();
|
||||
|
||||
// if there is an asset, return it
|
||||
if (count($assets)) {
|
||||
return $assets[rand(1, count($assets)) - 1];
|
||||
} else {
|
||||
// try to fetch it from child album
|
||||
$randomAlbum = $this->getRandomAlbum();
|
||||
if ($randomAlbum) {
|
||||
return $randomAlbum->getRandomAsset();
|
||||
}
|
||||
// album and child album are empty
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get datetime
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getDatetime()
|
||||
{
|
||||
return $this->datetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date time
|
||||
*
|
||||
* @param \DateTime $datetime datetime
|
||||
* @return void
|
||||
*/
|
||||
public function setDatetime($datetime)
|
||||
{
|
||||
$this->datetime = $datetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FileInterface[] $files
|
||||
* @param string $orderBy
|
||||
* @param string $direction
|
||||
* @return FileInterface[]
|
||||
*/
|
||||
protected function orderAssets($files, $orderBy, $direction)
|
||||
{
|
||||
usort($files, function ($a, $b) use ($orderBy, $direction) {
|
||||
if ($orderBy === 'crdate') {
|
||||
$compare = $a->getCreationTime() > $b->getCreationTime();
|
||||
} elseif (in_array($orderBy, ['content_creation_date', 'content_modification_date'], true)) {
|
||||
$compare = $a->getProperty($orderBy) > $b->getProperty($orderBy);
|
||||
} else {
|
||||
$compare = strnatcasecmp($a->getProperty($orderBy), $b->getProperty($orderBy));
|
||||
}
|
||||
return $direction === 'desc' ? -1 * $compare : $compare;
|
||||
});
|
||||
|
||||
return $files;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Domain\Repository;
|
||||
|
||||
/***************************************************************
|
||||
* 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 3 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\Extbase\Persistence\Repository;
|
||||
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
|
||||
use MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum;
|
||||
|
||||
/**
|
||||
* MediaAlbumRepository
|
||||
*/
|
||||
class MediaAlbumRepository extends Repository
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array default ordering
|
||||
*/
|
||||
protected $defaultOrderings = [
|
||||
'sorting' => QueryInterface::ORDER_ASCENDING,
|
||||
'crdate' => QueryInterface::ORDER_DESCENDING,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedAssetMimeTypes = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $albumUids = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $useAlbumUidsAsExclude = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $assetsOrderBy = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $assetsOrderDirection = 'asc';
|
||||
|
||||
/**
|
||||
* Set allowedAssetMimeTypes
|
||||
*
|
||||
* @param array $allowedAssetMimeTypes
|
||||
*/
|
||||
public function setAllowedAssetMimeTypes($allowedAssetMimeTypes)
|
||||
{
|
||||
$this->allowedAssetMimeTypes = $allowedAssetMimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowedAssetMimeTypes
|
||||
*
|
||||
* @return array $allowedAssetMimeTypes
|
||||
*/
|
||||
public function getAllowedAssetMimeTypes()
|
||||
{
|
||||
return $this->allowedAssetMimeTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowedAlbumUids
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAlbumUids()
|
||||
{
|
||||
return $this->albumUids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allowedAlbumUids
|
||||
*
|
||||
* @param array $albumUids
|
||||
*/
|
||||
public function setAlbumUids($albumUids)
|
||||
{
|
||||
$this->albumUids = $albumUids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get useAlbumUidsAsExclude
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getUseAlbumUidsAsExclude()
|
||||
{
|
||||
return $this->useAlbumUidsAsExclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set useAlbumUidsAsExclude
|
||||
*
|
||||
* @param boolean $useAlbumUidsAsExclude
|
||||
*/
|
||||
public function setUseAlbumUidsAsExclude($useAlbumUidsAsExclude)
|
||||
{
|
||||
$this->useAlbumUidsAsExclude = $useAlbumUidsAsExclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assetsOrderBy
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAssetsOrderBy()
|
||||
{
|
||||
return $this->assetsOrderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assetsOrderBy
|
||||
*
|
||||
* @param string $assetsOrderBy
|
||||
*/
|
||||
public function setAssetsOrderBy($assetsOrderBy)
|
||||
{
|
||||
$this->assetsOrderBy = $assetsOrderBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assetsOrderDirection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAssetsOrderDirection()
|
||||
{
|
||||
return $this->assetsOrderDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set assetsOrderDirection
|
||||
*
|
||||
* @param string $assetsOrderDirection
|
||||
*/
|
||||
public function setAssetsOrderDirection($assetsOrderDirection)
|
||||
{
|
||||
$this->assetsOrderDirection = $assetsOrderDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get random sub album
|
||||
*
|
||||
* @param MediaAlbum|bool $parent parent MediaAlbum, FALSE for parent = 0 or NULL for no restriction by parent
|
||||
* @return \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum|NULL
|
||||
*/
|
||||
public function findRandom($parent = null)
|
||||
{
|
||||
|
||||
/** @var \TYPO3\CMS\Extbase\Persistence\Generic\Query $query */
|
||||
$query = $this->createQuery();
|
||||
$constraints = [];
|
||||
|
||||
// restrict by parent album
|
||||
if ($parent !== null) {
|
||||
$constraints[] = $query->equals('parentalbum', $parent ? $parent->getUid() : 0);
|
||||
}
|
||||
|
||||
// restrict by given uids
|
||||
if ($this->albumUids !== []) {
|
||||
if ($this->useAlbumUidsAsExclude) {
|
||||
$constraints[] = $query->logicalNot($query->in('uid', $this->albumUids));
|
||||
} else {
|
||||
$constraints[] = $query->in('uid', $this->albumUids);
|
||||
}
|
||||
}
|
||||
$query->matching($query->logicalAnd($constraints));
|
||||
$mediaAlbums = $query->execute()->toArray();
|
||||
|
||||
/** @var \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum $mediaAlbum */
|
||||
$mediaAlbum = null;
|
||||
|
||||
if ($mediaAlbums) {
|
||||
$mediaAlbum = $mediaAlbums[array_rand($mediaAlbums, 1)];
|
||||
|
||||
// set allowed asset mime types
|
||||
$mediaAlbum->setAllowedMimeTypes($this->allowedAssetMimeTypes);
|
||||
// set assets order
|
||||
$mediaAlbum->setAssetsOrderBy($this->assetsOrderBy);
|
||||
$mediaAlbum->setAssetsOrderDirection($this->assetsOrderDirection);
|
||||
}
|
||||
|
||||
return $mediaAlbum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find albums by parent album
|
||||
*
|
||||
* @param MediaAlbum $parentAlbum
|
||||
* @param boolean $excludeEmptyAlbums
|
||||
* @param string $orderBy Sort albums by: datetime|crdate|sorting
|
||||
* @param string $orderDirection Sort order: asc|desc
|
||||
* @return MediaAlbum[]
|
||||
*/
|
||||
public function findByParentAlbum(
|
||||
MediaAlbum $parentAlbum = null,
|
||||
$excludeEmptyAlbums = true,
|
||||
$orderBy = 'sorting',
|
||||
$orderDirection = 'desc'
|
||||
) {
|
||||
$excludeEmptyAlbums = filter_var($excludeEmptyAlbums, FILTER_VALIDATE_BOOLEAN);
|
||||
$query = $this->createQuery();
|
||||
$constraints = [];
|
||||
$constraints[] = $query->equals('parentalbum', $parentAlbum ?: 0);
|
||||
|
||||
if ($this->albumUids !== []) {
|
||||
if ($this->useAlbumUidsAsExclude) {
|
||||
$constraints[] = $query->logicalNot($query->in('uid', $this->albumUids));
|
||||
} else {
|
||||
$constraints[] = $query->in('uid', $this->albumUids);
|
||||
}
|
||||
}
|
||||
|
||||
$query->matching($query->logicalAnd($constraints));
|
||||
$query->setOrderings($this->getOrderingsSettings($orderBy, $orderDirection));
|
||||
$mediaAlbums = $query->execute()->toArray();
|
||||
|
||||
foreach ($mediaAlbums as $key => $mediaAlbum) {
|
||||
/** @var $mediaAlbum \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum */
|
||||
// set allowed asset mime types
|
||||
$mediaAlbum->setAllowedMimeTypes($this->allowedAssetMimeTypes);
|
||||
// set assets order
|
||||
$mediaAlbum->setAssetsOrderBy($this->assetsOrderBy);
|
||||
$mediaAlbum->setAssetsOrderDirection($this->assetsOrderDirection);
|
||||
$mediaAlbum->setExcludeEmptyAlbums($excludeEmptyAlbums);
|
||||
|
||||
// exclude if album is empty
|
||||
if (
|
||||
$excludeEmptyAlbums
|
||||
&&
|
||||
$mediaAlbum->getAssetsCount() === 0
|
||||
&&
|
||||
count($mediaAlbum->getAlbums()) === 0
|
||||
) {
|
||||
unset($mediaAlbums[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset array keys and return albums
|
||||
return array_values($mediaAlbums);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find album by Uid
|
||||
*
|
||||
* @param integer $uid The identifier of the MediaAlbum to find
|
||||
* @param bool $respectStorage possibility to disable storage restriction
|
||||
* @return MediaAlbum|NULL The matching media album if found, otherwise NULL
|
||||
*/
|
||||
public function findByUid($uid, $respectStorage = true)
|
||||
{
|
||||
|
||||
$query = $this->createQuery();
|
||||
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||
|
||||
if (!$respectStorage) {
|
||||
$query->getQuerySettings()->setRespectStoragePage(false);
|
||||
}
|
||||
|
||||
$constraints = [$query->equals('uid', (int)$uid)];
|
||||
|
||||
if ($this->albumUids !== []) {
|
||||
if ($this->useAlbumUidsAsExclude) {
|
||||
$constraints[] = $query->logicalNot($query->in('uid', $this->albumUids));
|
||||
} else {
|
||||
$constraints[] = $query->in('uid', $this->albumUids);
|
||||
}
|
||||
}
|
||||
|
||||
/** @var $mediaAlbum \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum */
|
||||
$mediaAlbum = $query->matching($query->logicalAnd($constraints))->execute()->getFirst();
|
||||
|
||||
if ($mediaAlbum) {
|
||||
// set allowed asset mime types
|
||||
$mediaAlbum->setAllowedMimeTypes($this->allowedAssetMimeTypes);
|
||||
// set assets order
|
||||
$mediaAlbum->setAssetsOrderBy($this->assetsOrderBy);
|
||||
$mediaAlbum->setAssetsOrderDirection($this->assetsOrderDirection);
|
||||
}
|
||||
|
||||
return $mediaAlbum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all albums
|
||||
*
|
||||
* @param boolean $excludeEmptyAlbums
|
||||
* @param string $orderBy Sort albums by: datetime|crdate|sorting
|
||||
* @param string $orderDirection Sort order: asc|desc
|
||||
* @return MediaAlbum[]
|
||||
*/
|
||||
public function findAll($excludeEmptyAlbums = true, $orderBy = 'datetime', $orderDirection = 'desc')
|
||||
{
|
||||
$excludeEmptyAlbums = filter_var($excludeEmptyAlbums, FILTER_VALIDATE_BOOLEAN);
|
||||
$query = $this->createQuery();
|
||||
$query->setOrderings($this->getOrderingsSettings($orderBy, $orderDirection));
|
||||
$query->getQuerySettings()->setRespectSysLanguage(false);
|
||||
|
||||
if ($this->albumUids !== []) {
|
||||
if ($this->useAlbumUidsAsExclude) {
|
||||
$query->matching($query->logicalNot($query->in('uid', $this->albumUids)));
|
||||
} else {
|
||||
$query->matching($query->in('uid', $this->albumUids));
|
||||
}
|
||||
}
|
||||
|
||||
$mediaAlbums = $query->execute()->toArray();
|
||||
|
||||
foreach ($mediaAlbums as $key => $mediaAlbum) {
|
||||
/** @var $mediaAlbum \MiniFranske\FsMediaGallery\Domain\Model\MediaAlbum */
|
||||
// set allowed asset mime types
|
||||
$mediaAlbum->setAllowedMimeTypes($this->allowedAssetMimeTypes);
|
||||
// set assets order
|
||||
$mediaAlbum->setAssetsOrderBy($this->assetsOrderBy);
|
||||
$mediaAlbum->setAssetsOrderDirection($this->assetsOrderDirection);
|
||||
$mediaAlbum->setExcludeEmptyAlbums($excludeEmptyAlbums);
|
||||
|
||||
// exclude if album is empty
|
||||
if (
|
||||
$excludeEmptyAlbums
|
||||
&&
|
||||
$mediaAlbum->getAssetsCount() === 0
|
||||
&&
|
||||
count($mediaAlbum->getAlbums()) === 0
|
||||
) {
|
||||
unset($mediaAlbums[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset array keys and return albums
|
||||
return array_values($mediaAlbums);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get orderings settings. Returns an array like:
|
||||
* array(
|
||||
* 'foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
|
||||
* 'bar' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
|
||||
* )
|
||||
*
|
||||
* @param string $orderBy Sort albums by: datetime|crdate|sorting
|
||||
* @param string $orderDirection Sort order: asc|desc
|
||||
* @return array Orderings settings used by \TYPO3\CMS\Extbase\Persistence\QueryInterface->setOrderings()
|
||||
*/
|
||||
protected function getOrderingsSettings($orderBy = 'sorting', $orderDirection = 'asc')
|
||||
{
|
||||
|
||||
// check orderDirection
|
||||
if ($orderDirection === 'asc') {
|
||||
$orderDirection = QueryInterface::ORDER_ASCENDING;
|
||||
} else {
|
||||
$orderDirection = QueryInterface::ORDER_DESCENDING;
|
||||
}
|
||||
|
||||
// set $orderingsSettings by orderBy and orderDirection
|
||||
switch ($orderBy) {
|
||||
case 'datetime':
|
||||
$orderingsSettings = [
|
||||
'datetime' => $orderDirection,
|
||||
'crdate' => $orderDirection
|
||||
];
|
||||
break;
|
||||
case 'crdate':
|
||||
$orderingsSettings = ['crdate' => $orderDirection];
|
||||
break;
|
||||
default:
|
||||
// sorting
|
||||
$orderingsSettings = [
|
||||
'sorting' => $orderDirection,
|
||||
'crdate' => $orderDirection
|
||||
];
|
||||
}
|
||||
|
||||
return $orderingsSettings;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Hooks;
|
||||
|
||||
/***************************************************************
|
||||
* 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\Backend\Routing\UriBuilder;
|
||||
use TYPO3\CMS\Backend\Controller\BackendController;
|
||||
use TYPO3\CMS\Core\Page\PageRenderer;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* This class adds Filelist related JavaScript to the backend
|
||||
*/
|
||||
class BackendControllerHook
|
||||
{
|
||||
/**
|
||||
* Adds Filelist JavaScript used e.g. by context menu
|
||||
*
|
||||
* @param array $configuration
|
||||
* @param BackendController $backendController
|
||||
*/
|
||||
public function addJavaScript(array $configuration, BackendController $backendController)
|
||||
{
|
||||
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
|
||||
/** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
|
||||
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
|
||||
$pageRenderer->addInlineSetting('FileEdit', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('file_edit'));
|
||||
$pageRenderer->addInlineSetting('FileCreate', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('file_upload'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Hooks;
|
||||
|
||||
/***************************************************************
|
||||
* 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 MiniFranske\FsMediaGallery\Service\AbstractBeAlbumButtons;
|
||||
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
|
||||
use TYPO3\CMS\Core\Imaging\Icon;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Hook to add extra button to DocHeaderButtons in file list
|
||||
*/
|
||||
class DocHeaderButtonsHook extends AbstractBeAlbumButtons
|
||||
{
|
||||
protected function createLink(string $title, string $shortTitle, Icon $icon, string $url, bool $addReturnUrl = true): array
|
||||
{
|
||||
return [
|
||||
'title' => $title,
|
||||
'icon' => $icon,
|
||||
'url' => $url . ($addReturnUrl ? '&returnUrl=' . rawurlencode($_SERVER['REQUEST_URI']) : '')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add media album buttons to file list
|
||||
*/
|
||||
public function moduleTemplateDocHeaderGetButtons(array $params, ButtonBar $buttonBar): array
|
||||
{
|
||||
$buttons = $params['buttons'];
|
||||
if (GeneralUtility::_GP('M') === 'file_FilelistList'
|
||||
|| GeneralUtility::_GP('route') === '/file/FilelistList/'
|
||||
|| GeneralUtility::_GP('route') === '/module/file/FilelistList'
|
||||
) {
|
||||
foreach ($this->generateButtons((string)GeneralUtility::_GP('id')) as $buttonInfo) {
|
||||
$button = $buttonBar->makeLinkButton();
|
||||
$button->setShowLabelText(true);
|
||||
$button->setIcon($buttonInfo['icon']);
|
||||
$button->setTitle($buttonInfo['title']);
|
||||
if (strpos($buttonInfo['url'], 'alert') === 0) {
|
||||
// using CSS class to trigger confirmation in modal box
|
||||
$button->setClasses('t3js-modal-trigger')
|
||||
->setDataAttributes([
|
||||
'severity' => 'warning',
|
||||
'title' => $buttonInfo['title'],
|
||||
'bs-content' => htmlspecialchars(substr($buttonInfo['url'], 6)),
|
||||
]);
|
||||
} else {
|
||||
$button->setHref($buttonInfo['url']);
|
||||
}
|
||||
$buttons['left'][2][] = $button;
|
||||
}
|
||||
}
|
||||
|
||||
return $buttons;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Hooks;
|
||||
|
||||
/* *
|
||||
* This script is part of the TYPO3 project. *
|
||||
* *
|
||||
* It is free software; you can redistribute it and/or modify it under *
|
||||
* the terms of the GNU Lesser General Public License, either version 3 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* The TYPO3 project - inspiring people to share! *
|
||||
* */
|
||||
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* ItemsProcFuncHook
|
||||
*/
|
||||
class ItemsProcFuncHook
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets the available actions for settings.switchableControllerActions
|
||||
*
|
||||
* @param array &$config
|
||||
* @return void
|
||||
*/
|
||||
public function getItemsForSwitchableControllerActions(array &$config)
|
||||
{
|
||||
$availableActions = [
|
||||
'nestedList' => 'MediaAlbum->nestedList;MediaAlbum->showAsset',
|
||||
'flatList' => 'MediaAlbum->flatList;MediaAlbum->showAlbum;MediaAlbum->showAsset',
|
||||
'showAlbumByParam' => 'MediaAlbum->showAlbum;MediaAlbum->showAsset',
|
||||
'showAlbumByConfig' => 'MediaAlbum->showAlbumByConfig;MediaAlbum->showAsset',
|
||||
'randomAsset' => 'MediaAlbum->randomAsset',
|
||||
];
|
||||
$extConf = $this->getExtensionConfiguration();;
|
||||
$allowedActions = [
|
||||
// index action is always allowed
|
||||
// this is needed to make sure the correct tabs/fields are shown in
|
||||
// flexform when a new plugin is added
|
||||
'index' => 'MediaAlbum->index',
|
||||
];
|
||||
$allowedActionsFromExtConf = [];
|
||||
if (!empty($extConf['allowedActionsInFlexforms'])) {
|
||||
$allowedActionsFromExtConf = GeneralUtility::trimExplode(',', $extConf['allowedActionsInFlexforms']);
|
||||
}
|
||||
foreach ($allowedActionsFromExtConf as $allowedActionFromExtConf) {
|
||||
if (!empty($availableActions[$allowedActionFromExtConf])) {
|
||||
$allowedActions[$allowedActionFromExtConf] = $availableActions[$allowedActionFromExtConf];
|
||||
}
|
||||
}
|
||||
// check items; allow all actions if something went wrong (no action except of "indexAction" is allowed)
|
||||
if (count($allowedActions) > 1) {
|
||||
foreach ($config['items'] as $key => $item) {
|
||||
if (!in_array($item[1], $allowedActions)) {
|
||||
unset($config['items'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the available options for settings.list.orderBy
|
||||
*
|
||||
* @param array &$config
|
||||
* @return void
|
||||
*/
|
||||
public function getItemsForListOrderBy(array &$config)
|
||||
{
|
||||
$availableOptions = ['datetime', 'crdate', 'sorting'];
|
||||
$extConf = $this->getExtensionConfiguration();;
|
||||
$allowedOptions = [];
|
||||
$allowedOptionsFromExtConf = [];
|
||||
if (!empty($extConf['list']['orderOptions'])) {
|
||||
$allowedOptionsFromExtConf = GeneralUtility::trimExplode(',', $extConf['list']['orderOptions']);
|
||||
}
|
||||
foreach ($allowedOptionsFromExtConf as $allowedOptionFromExtConf) {
|
||||
if (in_array($allowedOptionFromExtConf, $availableOptions)) {
|
||||
$allowedOptions[] = $allowedOptionFromExtConf;
|
||||
}
|
||||
}
|
||||
foreach ($config['items'] as $key => $item) {
|
||||
// check items; empty value (inherit from TS) is always allowed
|
||||
if (!empty($item[1]) && !in_array($item[1], $allowedOptions)) {
|
||||
unset($config['items'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the available options for settings.album.assets.orderBy
|
||||
*
|
||||
* @param array &$config
|
||||
* @return void
|
||||
*/
|
||||
public function getItemsForAssetsOrderBy(array &$config)
|
||||
{
|
||||
// default set
|
||||
$allowedOptions = ['name', 'crdate', 'title', 'content_creation_date', 'content_modification_date'];
|
||||
$availableOptions = [];
|
||||
$extConf = $this->getExtensionConfiguration();;
|
||||
|
||||
if (!empty($extConf['asset']['orderOptions'])) {
|
||||
$allowedOptions = GeneralUtility::trimExplode(',', $extConf['asset']['orderOptions']);
|
||||
}
|
||||
// check if field exists in TCA of sys_file or sys_file_metadata
|
||||
foreach ($allowedOptions as $key => $option) {
|
||||
if (
|
||||
$option === 'crdate'
|
||||
||
|
||||
!empty($GLOBALS['TCA']['sys_file']['columns'][$option])
|
||||
||
|
||||
!empty($GLOBALS['TCA']['sys_file_metadata']['columns'][$option])
|
||||
) {
|
||||
$availableOptions[] = $option;
|
||||
}
|
||||
}
|
||||
// @todo: add option to add custom options to the item list
|
||||
// use label from TCA
|
||||
foreach ($config['items'] as $key => $item) {
|
||||
// check items; empty value (inherit from TS) is always allowed
|
||||
if (!empty($item[1]) && !in_array($item[1], $availableOptions)) {
|
||||
unset($config['items'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension configuration
|
||||
*/
|
||||
protected function getExtensionConfiguration() {
|
||||
return GeneralUtility::makeInstance(
|
||||
ExtensionConfiguration::class
|
||||
)->get('fs_media_gallery');
|
||||
}
|
||||
}
|
||||
250
typo3conf/ext/fs_media_gallery/Classes/Hooks/PageLayoutView.php
Normal file
250
typo3conf/ext/fs_media_gallery/Classes/Hooks/PageLayoutView.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Hooks;
|
||||
|
||||
/*
|
||||
* This source file is proprietary property of Beech Applications B.V.
|
||||
* Date: 28-09-2016
|
||||
* All code (c) Beech Applications B.V. all rights reserved
|
||||
*/
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility as BackendUtilityCore;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
|
||||
/**
|
||||
* Class PageLayoutView
|
||||
*/
|
||||
class PageLayoutView
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const LLPATH = 'LLL:EXT:fs_media_gallery/Resources/Private/Language/locallang_be.xlf:';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $summaryData = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $flexFormData = [];
|
||||
|
||||
public function getExtensionSummary(array $params): string
|
||||
{
|
||||
/** @var \TYPO3\CMS\Backend\View\PageLayoutView $pageLayoutView */
|
||||
$pageLayoutView = $params['pObj'];
|
||||
$row = $params['row'];
|
||||
$this->flexFormData = GeneralUtility::xml2array($row['pi_flexform']);
|
||||
$action = $this->getAction();
|
||||
|
||||
$result = '<strong>' . $pageLayoutView->linkEditContent($this->getLanguageService()->sL(self::LLPATH . 'mediagallery.title'), $row) . '</strong><br>';
|
||||
$result .= $this->getDisplayMode($action);
|
||||
|
||||
$result .= '<hr>';
|
||||
|
||||
if (in_array($action, ['showAlbum', 'showAlbumByConfig'], true)) {
|
||||
$this->addSelectedAlbumToSettingsSummary();
|
||||
} else {
|
||||
$this->addSelectedAlbumsToSettingsSummary();
|
||||
}
|
||||
$this->addStartingPointToSettingsSummary();
|
||||
|
||||
$result .= $this->renderSettingsAsTable();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getAction(): string
|
||||
{
|
||||
// if flexForm data is found
|
||||
$actions = $this->getFieldFromFlexform('switchableControllerActions');
|
||||
$action = '';
|
||||
|
||||
if (!empty($actions)) {
|
||||
$actionList = GeneralUtility::trimExplode(';', $actions);
|
||||
|
||||
// translate the first action into its translation
|
||||
$action = str_replace('MediaAlbum->', '', $actionList[0]);
|
||||
}
|
||||
return $action;
|
||||
}
|
||||
|
||||
private function getDisplayMode(string $action): string
|
||||
{
|
||||
switch ($action) {
|
||||
case 'showalbum';
|
||||
$actionTranslationKey = 'showAlbumByParam';
|
||||
break;
|
||||
default:
|
||||
$actionTranslationKey = $action;
|
||||
}
|
||||
return $this->getLanguageService()->sL(self::LLPATH . 'flexforms.mediagallery.switchableControllerActions.I.' . $actionTranslationKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field value from flexform configuration,
|
||||
* including checks if flexform configuration is available
|
||||
*
|
||||
* @param string $key name of the key
|
||||
* @param string $sheet name of the sheet
|
||||
* @return string|NULL if nothing found, value if found
|
||||
*/
|
||||
private function getFieldFromFlexform(string $key, string $sheet = 'general'): ?string
|
||||
{
|
||||
$flexform = $this->flexFormData;
|
||||
if (isset($flexform['data'])) {
|
||||
$flexform = $flexform['data'];
|
||||
if (is_array($flexform) && is_array($flexform[$sheet]) && is_array($flexform[$sheet]['lDEF'])
|
||||
&& is_array($flexform[$sheet]['lDEF'][$key]) && isset($flexform[$sheet]['lDEF'][$key]['vDEF'])
|
||||
) {
|
||||
return $flexform[$sheet]['lDEF'][$key]['vDEF'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function addSelectedAlbumToSettingsSummary(): void
|
||||
{
|
||||
$albumUid = (int)$this->getFieldFromFlexform('settings.mediaAlbum');
|
||||
if ((int)$albumUid > 0) {
|
||||
// Album record
|
||||
$rowSysFileCollectionRecords = $this->getDatabaseConnection()->select(['*'], 'sys_file_collection', [
|
||||
'uid' => (int)$albumUid,
|
||||
'deleted' => 0,
|
||||
])->fetchAllAssociative();
|
||||
|
||||
$albums = [];
|
||||
foreach ($rowSysFileCollectionRecords as $record) {
|
||||
$albums[] = htmlspecialchars(BackendUtilityCore::getRecordTitle('sys_file_collection', $record));
|
||||
}
|
||||
|
||||
$this->summaryData[] = [
|
||||
$this->getLanguageService()->sL(self::LLPATH . 'flexforms.mediagallery.mediaAlbum') .
|
||||
'<br />',
|
||||
implode(', ', $albums)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function addSelectedAlbumsToSettingsSummary(): void
|
||||
{
|
||||
$filterMode = '';
|
||||
$albums = [];
|
||||
|
||||
$albumUids = GeneralUtility::intExplode(',', $this->getFieldFromFlexform('settings.mediaAlbumsUids'), true);
|
||||
if (count($albumUids) > 0) {
|
||||
|
||||
// Filter mode
|
||||
$selectedFilerMode = $this->getFieldFromFlexform('settings.useAlbumFilterAsExclude');
|
||||
|
||||
if ($selectedFilerMode !== '') {
|
||||
$filterMode = $this->getLanguageService()->sL(self::LLPATH . 'flexforms.general.I.inherit');
|
||||
$filterMode = '<span style="font-weight:normal;font-style:italic">(' . htmlspecialchars($filterMode) . ')</span>';
|
||||
}
|
||||
|
||||
// Album records
|
||||
$q = $this->getDatabaseConnection()->createQueryBuilder();
|
||||
|
||||
$q->getRestrictions()
|
||||
->removeAll()
|
||||
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
|
||||
|
||||
$quotedIdentifiers = $q->createNamedParameter($albumUids, Connection::PARAM_INT_ARRAY);
|
||||
$q->select('*')
|
||||
->from('sys_file_collection')
|
||||
->where(
|
||||
$q->expr()->in('uid', $quotedIdentifiers)
|
||||
);
|
||||
|
||||
$rowSysFileCollectionRecords = $q->execute()->fetchAllAssociative();
|
||||
|
||||
foreach ((array)$rowSysFileCollectionRecords as $record) {
|
||||
$albums[] = htmlspecialchars(BackendUtilityCore::getRecordTitle('sys_file_collection', $record));
|
||||
}
|
||||
|
||||
$this->summaryData[] = [
|
||||
$this->getLanguageService()->sL(self::LLPATH . 'flexforms.mediagallery.mediaAlbumsUids') .
|
||||
'<br />' . $filterMode,
|
||||
implode(', ', $albums)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
private function addStartingPointToSettingsSummary(): void
|
||||
{
|
||||
$value = $this->getFieldFromFlexform('settings.startingpoint');
|
||||
|
||||
if (!empty($value)) {
|
||||
$pagesOut = [];
|
||||
|
||||
$q = $this->getDatabaseConnection('pages')->createQueryBuilder();
|
||||
$quotedIdentifiers = $q->createNamedParameter(GeneralUtility::intExplode(',', $value, true), Connection::PARAM_INT_ARRAY);
|
||||
|
||||
$q->select('*')
|
||||
->from('pages')
|
||||
->where(
|
||||
$q->expr()->in('uid', $quotedIdentifiers)
|
||||
);
|
||||
|
||||
$rawPagesRecords = $q->execute()->fetchAllAssociative();
|
||||
|
||||
foreach ((array)$rawPagesRecords as $page) {
|
||||
$pagesOut[] = htmlspecialchars(BackendUtilityCore::getRecordTitle('pages',
|
||||
$page)) . ' (' . $page['uid'] . ')';
|
||||
}
|
||||
|
||||
$recursiveLevel = (int)$this->getFieldFromFlexform('settings.recursive');
|
||||
$recursiveLevelText = '';
|
||||
if ($recursiveLevel === 250) {
|
||||
$recursiveLevelText = $this->getLanguageService()->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:recursive.I.5');
|
||||
} elseif ($recursiveLevel > 0) {
|
||||
$recursiveLevelText = $this->getLanguageService()->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:recursive.I.' . $recursiveLevel);
|
||||
}
|
||||
|
||||
if (!empty($recursiveLevelText)) {
|
||||
$recursiveLevelText = '<br />' .
|
||||
$this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.recursive') . ' ' .
|
||||
$recursiveLevelText;
|
||||
}
|
||||
|
||||
$this->summaryData[] = [
|
||||
$this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.startingpoint'),
|
||||
implode(', ', $pagesOut) . $recursiveLevelText
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the settings as table for Web>Page module
|
||||
*
|
||||
* System settings are displayed in mono font
|
||||
*/
|
||||
private function renderSettingsAsTable(): string
|
||||
{
|
||||
if (count($this->summaryData) == 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = '';
|
||||
foreach ($this->summaryData as $line) {
|
||||
$content .= '<strong>' . $line[0] . '</strong>' . ' ' . $line[1] . '<br />';
|
||||
}
|
||||
|
||||
return '<pre style="white-space:normal">' . $content . '</pre>';
|
||||
}
|
||||
|
||||
private function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
|
||||
private function getDatabaseConnection(string $table = 'sys_file_collection'): Connection
|
||||
{
|
||||
return GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Hooks;
|
||||
|
||||
/***************************************************************
|
||||
* 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\DataHandling\DataHandler;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
|
||||
/**
|
||||
* Hooks called after sys_file_collection is added/updated/deleted
|
||||
*/
|
||||
class ProcessDatamapHook
|
||||
{
|
||||
|
||||
/**
|
||||
* Trigger updateFolderTree after change in sys_file_collection
|
||||
*
|
||||
* @param string $status
|
||||
* @param string $table
|
||||
* @param $id
|
||||
* @param array $fieldArray
|
||||
* @param \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler
|
||||
*/
|
||||
public function processDatamap_afterDatabaseOperations(
|
||||
$status,
|
||||
$table,
|
||||
$id,
|
||||
array $fieldArray,
|
||||
DataHandler $dataHandler
|
||||
) {
|
||||
if ($table === 'sys_file_collection') {
|
||||
BackendUtility::setUpdateSignal('updateFolderTree');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger updateFolderTree after a sys_file_collection record is deleted
|
||||
*
|
||||
* @param string $command
|
||||
* @param string $table
|
||||
* @param int $id
|
||||
* @param mixed $value
|
||||
* @param \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler
|
||||
* @param mixed $pasteUpdate
|
||||
* @param array $pasteDatamap
|
||||
*/
|
||||
public function processCmdmap_postProcess(
|
||||
$command,
|
||||
$table,
|
||||
$id,
|
||||
$value,
|
||||
DataHandler $dataHandler,
|
||||
$pasteUpdate,
|
||||
array $pasteDatamap
|
||||
) {
|
||||
if ($table === 'sys_file_collection') {
|
||||
BackendUtility::setUpdateSignal('updateFolderTree');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Listeners;
|
||||
|
||||
/***************************************************************
|
||||
* 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\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileAddedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileCopiedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileCreatedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileDeletedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileMovedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileRenamedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFileReplacedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFolderAddedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFolderDeletedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\AfterFolderMovedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\BeforeFolderDeletedEvent;
|
||||
use TYPO3\CMS\Core\Resource\Event\BeforeFolderMovedEvent;
|
||||
use MiniFranske\FsMediaGallery\Service\Utility;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
use TYPO3\CMS\Core\Resource\FolderInterface;
|
||||
|
||||
/**
|
||||
* Slots that pick up signals after (re)moving folders to update mediagallery record (sys_file_collection)
|
||||
*/
|
||||
final class FolderChangedListener
|
||||
{
|
||||
protected $folderMapping = [];
|
||||
|
||||
/**
|
||||
* @var Utility
|
||||
*/
|
||||
private $utilityService;
|
||||
|
||||
/**
|
||||
* @var ExtensionConfiguration
|
||||
*/
|
||||
private $extensionConfiguration;
|
||||
|
||||
public function __construct(Utility $utilityService, ExtensionConfiguration $extensionConfiguration)
|
||||
{
|
||||
$this->utilityService = $utilityService;
|
||||
$this->extensionConfiguration = $extensionConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sub folder structure of folder before is gets moved
|
||||
* Is needed to update sys_file_collection records when move was successful
|
||||
*/
|
||||
public function preFolderMove(BeforeFolderMovedEvent $event): void
|
||||
{
|
||||
$this->folderMapping[$event->getFolder()->getCombinedIdentifier()] = $this->getSubFolderIdentifiers($event->getFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sys_file_collection records when folder is moved
|
||||
*/
|
||||
public function postFolderMove(AfterFolderMovedEvent $event): void
|
||||
{
|
||||
if (!$event->getTargetFolder()) {
|
||||
return;
|
||||
}
|
||||
$newFolder = $event->getTargetFolder();
|
||||
$oldStorageUid = $event->getFolder()->getStorage()->getUid();
|
||||
$newStorageUid = $newFolder->getStorage()->getUid();
|
||||
|
||||
$newParentId = null;
|
||||
// If this is a subFolder find new parent album
|
||||
if ($newFolder->getParentFolder() !== $newFolder) {
|
||||
$newParentId = $this->utilityService->findFileCollectionRecordsForFolder(
|
||||
$newStorageUid,
|
||||
$event->getFolder()->getParentFolder()->getIdentifier()
|
||||
)[0]['parentalbum'] ?? null;
|
||||
}
|
||||
|
||||
$this->utilityService->updateFolderRecord(
|
||||
$oldStorageUid,
|
||||
$event->getFolder()->getIdentifier(),
|
||||
$newStorageUid,
|
||||
$newFolder->getIdentifier(),
|
||||
$newParentId
|
||||
);
|
||||
|
||||
if (!empty($this->folderMapping[$event->getFolder()->getCombinedIdentifier()])) {
|
||||
$newMapping = $this->getSubFolderIdentifiers($newFolder);
|
||||
foreach ($this->folderMapping[$event->getFolder()->getCombinedIdentifier()] as $key => $folderInfo) {
|
||||
$this->utilityService->updateFolderRecord(
|
||||
$oldStorageUid,
|
||||
$folderInfo[1],
|
||||
$newStorageUid,
|
||||
$newMapping[$key][1]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sub folder structure of folder before is gets deleted
|
||||
* Is needed to update sys_file_collection records when delete was successful
|
||||
*/
|
||||
public function preFolderDelete(BeforeFolderDeletedEvent $event): void
|
||||
{
|
||||
$this->folderMapping[$event->getFolder()->getCombinedIdentifier()] = $this->getSubFolderIdentifiers($event->getFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sys_file_collection records when folder is deleted
|
||||
*/
|
||||
public function postFolderDelete(AfterFolderDeletedEvent $event): void
|
||||
{
|
||||
$folder = $event->getFolder();
|
||||
$storageUid = $folder->getStorage()->getUid();
|
||||
$this->utilityService->deleteFolderRecord($storageUid, $folder->getIdentifier());
|
||||
foreach ($this->folderMapping[$folder->getCombinedIdentifier()] as $folderInfo) {
|
||||
$this->utilityService->deleteFolderRecord($storageUid, $folderInfo[1]);
|
||||
}
|
||||
$this->clearMediaGalleryPageCache($folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto creates a file collection to the first parentCollection found of the current folder,
|
||||
* when no collection is found nothing is created
|
||||
*/
|
||||
public function postFolderAdd(AfterFolderAddedEvent $event): void
|
||||
{
|
||||
if (!$this->getConfigFlag('enableAutoCreateFileCollection')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$folder = $event->getFolder();
|
||||
$mediaFolders = $this->utilityService->getStorageFolders();
|
||||
if (count($mediaFolders) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($mediaFolders as $uid => $title) {
|
||||
$parents = $this->utilityService->getFirstParentCollections($folder, $uid);
|
||||
if (count($parents) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take the first parent found
|
||||
$parentUid = $parents[0]['uid'];
|
||||
$this->utilityService->createFolderRecord(
|
||||
ucfirst(trim(str_replace('_', ' ', $folder->getName()))),
|
||||
$uid,
|
||||
$folder->getStorage()->getUid(),
|
||||
$folder->getIdentifier(),
|
||||
$parentUid
|
||||
);
|
||||
$this->clearMediaGalleryPageCache($folder);
|
||||
}
|
||||
}
|
||||
|
||||
public function postFileAdd(AfterFileAddedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFolder());
|
||||
}
|
||||
|
||||
public function postFileCreate(AfterFileCreatedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFolder());
|
||||
}
|
||||
|
||||
public function postFileCopy(AfterFileCopiedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFolder());
|
||||
}
|
||||
|
||||
public function postFileMove(AfterFileMovedEvent $event)
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getOriginalFolder());
|
||||
$this->clearMediaGalleryPageCache($event->getFolder());
|
||||
}
|
||||
|
||||
public function postFileDelete(AfterFileDeletedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFile()->getParentFolder());
|
||||
}
|
||||
|
||||
public function postFileRename(AfterFileRenamedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFile()->getParentFolder());
|
||||
}
|
||||
|
||||
public function postFileReplace(AfterFileReplacedEvent $event): void
|
||||
{
|
||||
$this->clearMediaGalleryPageCache($event->getFile()->getParentFolder());
|
||||
}
|
||||
|
||||
private function clearMediaGalleryPageCache(FolderInterface $folder): void
|
||||
{
|
||||
if ($this->getBackendUser() && $this->getConfigFlag('clearCacheAfterFileChange')) {
|
||||
$this->utilityService->clearMediaGalleryPageCache($folder);
|
||||
}
|
||||
}
|
||||
|
||||
private function getSubFolderIdentifiers(Folder $folder): array
|
||||
{
|
||||
$folderIdentifiers = [];
|
||||
foreach ($folder->getSubfolders() as $subFolder) {
|
||||
$folderIdentifiers[] = [$subFolder->getHashedIdentifier(), $subFolder->getIdentifier()];
|
||||
$folderIdentifiers = array_merge($folderIdentifiers, $this->getSubFolderIdentifiers($subFolder));
|
||||
}
|
||||
|
||||
return $folderIdentifiers;
|
||||
}
|
||||
|
||||
private function getConfigFlag(string $flag): bool
|
||||
{
|
||||
return (bool)($this->extensionConfiguration->get('fs_media_gallery')[$flag] ?? false);
|
||||
}
|
||||
|
||||
private function getBackendUser(): ?BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'] ?? null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Listeners;
|
||||
|
||||
/***************************************************************
|
||||
* Copyright notice
|
||||
*
|
||||
* (c) 2016 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 MiniFranske\FsMediaGallery\Service\Utility;
|
||||
use TYPO3\CMS\Core\Imaging\Event\ModifyIconForResourcePropertiesEvent;
|
||||
use TYPO3\CMS\Core\Resource\FolderInterface;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
|
||||
/**
|
||||
* Class IconFactory
|
||||
*/
|
||||
class IconFactoryListener
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
static private $mediaFolders;
|
||||
|
||||
/**
|
||||
* @var Utility
|
||||
*/
|
||||
private $utilityService;
|
||||
|
||||
public function __construct(Utility $utilityService)
|
||||
{
|
||||
$this->utilityService = $utilityService;
|
||||
}
|
||||
|
||||
public function buildIconForResource(
|
||||
ModifyIconForResourcePropertiesEvent $event
|
||||
): void
|
||||
{
|
||||
$folderObject = $event->getResource();
|
||||
|
||||
if (!($folderObject instanceof Folder)
|
||||
|| !in_array($folderObject->getRole(), [FolderInterface::ROLE_DEFAULT, FolderInterface::ROLE_USERUPLOAD])
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mediaFolders = $this->getMediaFolders();
|
||||
if ($mediaFolders === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$collections = $this->utilityService->findFileCollectionRecordsForFolder(
|
||||
$folderObject->getStorage()->getUid(),
|
||||
$folderObject->getIdentifier(),
|
||||
array_keys($mediaFolders)
|
||||
);
|
||||
|
||||
if (!$collections) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->setIconIdentifier('tcarecords-sys_file_collection-folder');
|
||||
$hidden = true;
|
||||
foreach ($collections as $collection) {
|
||||
if ((int)$collection['hidden'] === 0) {
|
||||
$hidden = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hidden) {
|
||||
$event->setOverlayIdentifier('overlay-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
private function getMediaFolders(): array
|
||||
{
|
||||
if (self::$mediaFolders === null) {
|
||||
self::$mediaFolders = $this->utilityService->getStorageFolders();
|
||||
}
|
||||
return self::$mediaFolders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Pagination;
|
||||
|
||||
use TYPO3\CMS\Core\Pagination\AbstractPaginator;
|
||||
|
||||
class ExtendedArrayPaginator extends AbstractPaginator
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $items;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $paginatedItems = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $itemsBefore = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $itemsAfter = [];
|
||||
|
||||
public function __construct(
|
||||
array $items,
|
||||
int $currentPageNumber = 1,
|
||||
int $itemsPerPage = 10
|
||||
)
|
||||
{
|
||||
$this->items = $items;
|
||||
$this->setCurrentPageNumber($currentPageNumber);
|
||||
$this->setItemsPerPage($itemsPerPage);
|
||||
|
||||
$this->updateInternalState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable|array
|
||||
*/
|
||||
public function getPaginatedItems(): iterable
|
||||
{
|
||||
return $this->paginatedItems;
|
||||
}
|
||||
|
||||
protected function updatePaginatedItems(int $itemsPerPage, int $offset): void
|
||||
{
|
||||
$this->itemsBefore = array_slice($this->items, 0, $offset);
|
||||
$this->paginatedItems = array_slice($this->items, $offset, $itemsPerPage);
|
||||
$this->itemsAfter = array_slice($this->items, $offset + $itemsPerPage);
|
||||
}
|
||||
|
||||
protected function getTotalAmountOfItems(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
protected function getAmountOfItemsOnCurrentPage(): int
|
||||
{
|
||||
return count($this->paginatedItems);
|
||||
}
|
||||
|
||||
public function getItemsBefore(): iterable
|
||||
{
|
||||
return $this->itemsBefore;
|
||||
}
|
||||
|
||||
public function getItemsAfter(): iterable
|
||||
{
|
||||
return $this->itemsAfter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
258
typo3conf/ext/fs_media_gallery/Classes/Service/SlugService.php
Normal file
258
typo3conf/ext/fs_media_gallery/Classes/Service/SlugService.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
259
typo3conf/ext/fs_media_gallery/Classes/Service/Utility.php
Normal file
259
typo3conf/ext/fs_media_gallery/Classes/Service/Utility.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Updates;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use MiniFranske\FsMediaGallery\Service\SlugService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Install\Updates\AbstractUpdate;
|
||||
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
|
||||
/**
|
||||
* Migrate EXT:realurl unique alias into album slugs
|
||||
*
|
||||
* If a lot of similar titles are used it might be a good a idea
|
||||
* to migrate the unique aliases from realurl to be sure that the same alias is used
|
||||
*
|
||||
* Requires existence of DB table tx_realurl_uniqalias, but EXT:realurl requires not to be installed
|
||||
* Will only appear if missing slugs found between realurl and fs_media_gallery, respecting language and expire date from realurl
|
||||
* Converts title into slug
|
||||
*/
|
||||
class PopulateMedialAlbumsSlug implements UpgradeWizardInterface
|
||||
{
|
||||
|
||||
/** @var SlugService */
|
||||
protected $slugService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->slugService = GeneralUtility::makeInstance(SlugService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Fill empty field "slug" of EXT:fs_media_gallery records';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description
|
||||
*
|
||||
* @return string Longer description of this updater
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Fill empty field "slug" of EXT:fs_media_gallery records';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Unique identifier of this updater
|
||||
*/
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return 'populateMedialAlbumsSlug';
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [
|
||||
DatabaseUpdatedPrerequisite::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an update is needed
|
||||
*
|
||||
* @return bool Whether an update is needed (TRUE) or not (FALSE)
|
||||
*/
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
if (!$this->slugService->typo3SupportsSlugs()) {
|
||||
return false;
|
||||
}
|
||||
$elementCount = $this->slugService->countOfSlugUpdates();
|
||||
return (bool)$elementCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the database update
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$queries = $this->slugService->performUpdateSlugs();
|
||||
if (!empty($queries)) {
|
||||
foreach ($queries as $query) {
|
||||
$databaseQueries[] = $query;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\Updates;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use MiniFranske\FsMediaGallery\Service\SlugService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Install\Updates\AbstractUpdate;
|
||||
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
|
||||
/**
|
||||
* Migrate EXT:realurl unique alias into album slugs
|
||||
*
|
||||
* If a lot of similar titles are used it might be a good a idea
|
||||
* to migrate the unique aliases from realurl to be sure that the same alias is used
|
||||
*
|
||||
* Requires existence of DB table tx_realurl_uniqalias, but EXT:realurl requires not to be installed
|
||||
* Will only appear if missing slugs found between realurl and fs_media_gallery, respecting language and expire date from realurl
|
||||
* Converts title into slug
|
||||
*/
|
||||
class RealurlAliasMediaAlbumsSlug implements UpgradeWizardInterface
|
||||
{
|
||||
/** @var SlugService */
|
||||
protected $slugService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->slugService = GeneralUtility::makeInstance(SlugService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Migrate realurl alias to slug field "slug" of EXT:fs_media_gallery records';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description
|
||||
*
|
||||
* @return string Longer description of this updater
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Migrates EXT:realurl unique alias values into empty slug field "slug" of EXT:fs_media_gallery records.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Unique identifier of this updater
|
||||
*/
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return 'realurlAliasMediaAlbumsSlug';
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [
|
||||
DatabaseUpdatedPrerequisite::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an update is needed
|
||||
*
|
||||
* @return bool Whether an update is needed (TRUE) or not (FALSE)
|
||||
*/
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
if (!$this->slugService->typo3SupportsSlugs()) {
|
||||
return false;
|
||||
}
|
||||
$elementCount = $this->slugService->countOfRealurlAliasMigrations();
|
||||
|
||||
return (bool)$elementCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the database update
|
||||
* @return bool
|
||||
*/
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$queries = $this->slugService->performRealurlAliasMigration();
|
||||
if (!empty($queries)) {
|
||||
foreach ($queries as $query) {
|
||||
$databaseQueries[] = $query;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\Utility;
|
||||
|
||||
/* *
|
||||
* Inspired by Tx_News_Utility_TypoScript *
|
||||
* *
|
||||
* This script is part of the TYPO3 project. *
|
||||
* *
|
||||
* It is free software; you can redistribute it and/or modify it under *
|
||||
* the terms of the GNU Lesser General Public License, either version 3 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* The TYPO3 project - inspiring people to share! *
|
||||
* */
|
||||
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* TypoScript Utility class
|
||||
*/
|
||||
class TypoScriptUtility implements SingletonInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $base
|
||||
* @param array $overload
|
||||
* @return array
|
||||
*/
|
||||
public function override(array $base, array $overload)
|
||||
{
|
||||
$validFields = GeneralUtility::trimExplode(',', $overload['settings']['overrideFlexformSettingsIfEmpty'], true);
|
||||
foreach ($validFields as $fieldName) {
|
||||
|
||||
// Multilevel field
|
||||
if (strpos($fieldName, '.') !== false) {
|
||||
$keyAsArray = explode('.', $fieldName);
|
||||
|
||||
$foundInCurrentTs = $this->getValue($base, $keyAsArray);
|
||||
|
||||
if (is_string($foundInCurrentTs) && strlen($foundInCurrentTs) === 0) {
|
||||
$foundInOriginal = $this->getValue($overload['settings'], $keyAsArray);
|
||||
if ($foundInOriginal) {
|
||||
$base = $this->setValue($base, $keyAsArray, $foundInOriginal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if flexform setting is empty and value is available in TS
|
||||
if ((!isset($base[$fieldName]) || (strlen($base[$fieldName]) === 0))
|
||||
&& isset($overload['settings'][$fieldName])
|
||||
) {
|
||||
$base[$fieldName] = $overload['settings'][$fieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from array by path
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $path
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getValue(array $data, array $path)
|
||||
{
|
||||
$found = true;
|
||||
|
||||
for ($x = 0; ($x < count($path) && $found); $x++) {
|
||||
$key = $path[$x];
|
||||
|
||||
if (isset($data[$key])) {
|
||||
$data = $data[$key];
|
||||
} else {
|
||||
$found = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
return $data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value in array by path
|
||||
*
|
||||
* @param array $array
|
||||
* @param $path
|
||||
* @param $value
|
||||
* @return array
|
||||
*/
|
||||
protected function setValue(array $array, $path, $value)
|
||||
{
|
||||
$this->setValueByReference($array, $path, $value);
|
||||
|
||||
$final = array_merge_recursive([], $array);
|
||||
return $final;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value by reference
|
||||
*
|
||||
* @param array $array
|
||||
* @param array $path
|
||||
* @param $value
|
||||
*/
|
||||
private function setValueByReference(array &$array, array $path, $value)
|
||||
{
|
||||
while (count($path) > 1) {
|
||||
$key = array_shift($path);
|
||||
if (!isset($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
$array = &$array[$key];
|
||||
}
|
||||
|
||||
$key = reset($path);
|
||||
$array[$key] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\ViewHelpers\Embed;
|
||||
|
||||
/* *
|
||||
* This script is part of the TYPO3 project. *
|
||||
* *
|
||||
* It is free software; you can redistribute it and/or modify it under *
|
||||
* the terms of the GNU Lesser General Public License, either version 3 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* The TYPO3 project - inspiring people to share! *
|
||||
* */
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Core\Http\ApplicationType;
|
||||
use TYPO3\CMS\Core\Page\PageRenderer;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
|
||||
/**
|
||||
* Embed JavaScript view helper.
|
||||
*/
|
||||
class JavaScriptViewHelper extends AbstractViewHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize arguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
$this->registerArgument('name', 'string',
|
||||
'If empty, a combination of plugin name and the uid of the cObj is used.');
|
||||
$this->registerArgument('moveToFooter', 'boolean',
|
||||
'If TRUE, adds the script to the document footer by PageRenderer->addJsFooterInlineCode().');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders child nodes as inline JavaScript content or adds it to page footer
|
||||
*
|
||||
* @return string The rendered script content; if moveToFooter is TRUE the script content is added by PageRenderer->addJsFooterInlineCode() and an empty string is returned
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$content = $this->renderChildren();
|
||||
|
||||
if (!is_string($content)) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if (empty($this->arguments['name'])) {
|
||||
$blockName = 'tx_fsmediagallery';
|
||||
if ($cObj = $this->configurationManager->getContentObject()) {
|
||||
$blockName .= '.' . $cObj->data['uid'];
|
||||
}
|
||||
} else {
|
||||
$blockName = (string)$this->arguments['name'];
|
||||
}
|
||||
|
||||
if (!empty($this->arguments['moveToFooter']) && $this->getApplicationType() === 'FE') {
|
||||
// add JS inline code to footer
|
||||
$this->getPageRenderer()->addJsFooterInlineCode(
|
||||
$blockName,
|
||||
$content,
|
||||
$GLOBALS['TSFE']->config['config']['compressJs']
|
||||
);
|
||||
return '';
|
||||
} else {
|
||||
$lb = "\n";
|
||||
return '<script type="text/javascript">' . $lb . '/*<![CDATA[*/' . $lb .
|
||||
'/*' . $blockName . '*/' . $lb . $content . $lb . '/*]]>*/' . $lb . '</script>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PageRenderer
|
||||
*/
|
||||
protected function getPageRenderer() {
|
||||
if(class_exists(\TYPO3\CMS\Core\Page\PageRenderer::class)) {
|
||||
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
|
||||
} elseif (method_exists($GLOBALS['TSFE'], 'getPageRenderer')) {
|
||||
$pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
|
||||
} else {
|
||||
$pageRenderer = null;
|
||||
}
|
||||
return $pageRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* String 'FE' if in FrontendApplication, 'BE' otherwise (also in CLI without request object)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function getApplicationType(): string
|
||||
{
|
||||
if (
|
||||
($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface &&
|
||||
ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()
|
||||
) {
|
||||
return 'FE';
|
||||
}
|
||||
|
||||
return 'BE';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
namespace MiniFranske\FsMediaGallery\ViewHelpers;
|
||||
|
||||
/***************************************************************
|
||||
* 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 3 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\Resource\File;
|
||||
use TYPO3\CMS\Core\Resource\FileInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
|
||||
/**
|
||||
* File title viewHelper
|
||||
*/
|
||||
class FileDescriptionViewHelper extends AbstractViewHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Initialize arguments.
|
||||
*
|
||||
* @api
|
||||
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('file', File::class, 'File', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title of a File
|
||||
*
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
* @return string
|
||||
*/
|
||||
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
|
||||
{
|
||||
$file = $arguments['file'];
|
||||
|
||||
if (is_callable([$file, 'getOriginalResource'])) {
|
||||
// Get the original file from the Extbase model
|
||||
$file = $file->getOriginalResource();
|
||||
}
|
||||
|
||||
if (!$file instanceof FileInterface) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($file->getProperty('description')) {
|
||||
return $file->getProperty('description');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace MiniFranske\FsMediaGallery\ViewHelpers;
|
||||
|
||||
/***************************************************************
|
||||
* 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 3 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\Resource\FileInterface;
|
||||
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
||||
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
||||
|
||||
/**
|
||||
* File title viewHelper
|
||||
*/
|
||||
class FileTitleViewHelper extends AbstractViewHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Initialize arguments.
|
||||
*
|
||||
* @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
|
||||
*/
|
||||
public function initializeArguments()
|
||||
{
|
||||
parent::initializeArguments();
|
||||
$this->registerArgument('file', FileInterface::class, 'File', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title of a File
|
||||
*
|
||||
* @param array $arguments
|
||||
* @param \Closure $renderChildrenClosure
|
||||
* @param RenderingContextInterface $renderingContext
|
||||
* @return string
|
||||
*/
|
||||
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
|
||||
{
|
||||
$file = $arguments['file'];
|
||||
|
||||
if (is_callable([$file, 'getOriginalResource'])) {
|
||||
// Get the original file from the Extbase model
|
||||
$file = $file->getOriginalResource();
|
||||
}
|
||||
|
||||
if (!$file instanceof FileInterface) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($file->getProperty('title')) {
|
||||
return $file->getProperty('title');
|
||||
} else {
|
||||
return str_ireplace('_', ' ', $file->getNameWithoutExtension());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user