diff --git a/Classes/Controller/YoutubeController.php b/Classes/Controller/YoutubeController.php index c521d0c23bf019ffc356ceb7dc0d9ddf1eca2dbd..513de3a052fc4b8eb770a3f8e1075aba1d6dc543 100644 --- a/Classes/Controller/YoutubeController.php +++ b/Classes/Controller/YoutubeController.php @@ -60,7 +60,7 @@ class YoutubeController extends ActionController { $apiKey = $this->settings['apiKey']; $thumbnailType = $this->settings['thumbnailType']; $aspectRatio = $this->settings['aspectRatio']; - $showApiResult = (boolean) $this->settings['showApiResult']; + $showApiResult = (bool) $this->settings['showApiResult']; $debugOutput = ''; try { @@ -71,7 +71,11 @@ class YoutubeController extends ActionController { } $jsonArray['items'] = $this->youtubeService->mapArray( - $jsonArray['items'], $id, $aspectRatio, $thumbnailType, $apiKey + $jsonArray['items'], + $id, + $aspectRatio, + $thumbnailType, + $apiKey ); $jsonArray['items'] = $this->mapJsonArrayWithPossibleCustomThumbnails($jsonArray['items']); @@ -113,7 +117,9 @@ class YoutubeController extends ActionController { $fileRepository = GeneralUtility::makeInstance(FileRepository::class); $fileObjects = $fileRepository->findByRelation( - 'tt_content', 'tx_sgyoutube_thumbnail_image', $contentElementUid + 'tt_content', + 'tx_sgyoutube_thumbnail_image', + $contentElementUid ); if (count($fileObjects) <= 0) { return $jsonArray; diff --git a/Classes/Hooks/PageLayoutView/PluginRenderer.php b/Classes/Hooks/PageLayoutView/PluginRenderer.php index 9b7e3da292dd8980d501b03e07feb11724450f91..6780e1878bf8c25f4d094c6c4b26755ca101e683 100644 --- a/Classes/Hooks/PageLayoutView/PluginRenderer.php +++ b/Classes/Hooks/PageLayoutView/PluginRenderer.php @@ -20,20 +20,28 @@ namespace SGalinski\SgYoutube\Hooks\PageLayoutView; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use SGalinski\SgYoutube\Preview\PreviewService; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\View\PageLayoutView; use TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface; +use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; -use \TYPO3\CMS\Core\Localization\LanguageService; /** * Class PluginRenderer * Renders back-end preview for the SG YouTube Videos plugin * * @package SGalinski\SgYoutube\Hooks + * @deprecated All of this class will be removed when TYPO3 10 support is dropped */ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { + protected PreviewService $previewService; + + public function init() { + $this->previewService = GeneralUtility::makeInstance(PreviewService::class); + } + /** * Preprocesses the preview rendering of a content element of type "sg_youtube" * @@ -44,41 +52,27 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { * @param array $row Record row of tt_content * @return void * @noinspection ReferencingObjectsInspection + * @deprecated All of this class will be removed when TYPO3 10 support is dropped */ public function preProcess( - PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row + PageLayoutView &$parentObject, + &$drawItem, + &$headerContent, + &$itemContent, + array &$row ): void { + $this->init(); + trigger_error( + 'Using the old style of rendering backend previews is deprecated and will not longer work when TYPO3 10' + . ' support is dropped! Please switch to using the Fluid Based Page Module instead!', + E_USER_DEPRECATED + ); if ($row['list_type'] === 'sgyoutube_youtube') { $drawItem = FALSE; $this->adaptPluginHeaderContent($headerContent, $row); - $view = GeneralUtility::makeInstance(StandaloneView::class); - $view->setPartialRootPaths(['EXT:sg_youtube/Resources/Private/Partials/Backend']); - $view->setTemplateRootPaths(['EXT:sg_youtube/Resources/Private/Templates/Youtube']); - $view->setTemplate('Backend.html'); - $view->assign('uid', $row['uid']); - - // Get available plugin settings and their values from flexform - $pluginConfiguration = GeneralUtility::xml2array( - $row['pi_flexform'], 'T3DataStructure' - )['data']['sDEF']['lDEF']; - - $templateData = [ - 'youtubeId' => $pluginConfiguration['settings.id']['vDEF'], - 'maxResults' => $pluginConfiguration['settings.maxResults']['vDEF'], - 'showTitle' => (int) ($pluginConfiguration['settings.showTitle']['vDEF'] ?? 1), - 'showDescription' => (int) ($pluginConfiguration['settings.showDescription']['vDEF'] ?? 1), - 'disableLightbox' => $pluginConfiguration['settings.disableLightbox']['vDEF'], - 'disableLightboxMobile' => $pluginConfiguration['settings.disableLightboxMobile']['vDEF'], - 'aspectRatio' => $pluginConfiguration['settings.aspectRatio']['vDEF'], - 'thumbnailType' => $pluginConfiguration['settings.thumbnailType']['vDEF'], - 'thumbnailImagesCount' => $pluginConfiguration['settings.thumbnailImages']['vDEF'], - 'showApiResult' => $pluginConfiguration['settings.showApiResult']['vDEF'], - ]; - - $view->assign('data', $templateData); - + $view = $this->previewService->getPluginPreview($row); $itemContent .= $view->render(); } } @@ -87,13 +81,14 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { * Adapts the given $headerContent. * To be used in all plugin previews so the Header Contents appear similarly. * - * @param $headerContent - * @param $row + * @param string $headerContent + * @param array $row */ protected function adaptPluginHeaderContent(&$headerContent, $row): void { $headerContent = '<h4>' . $this->getPluginNameForHeaderContent( - (int) $row['pid'], $row['list_type'] - ) . $headerContent . '</h4>'; + (int) $row['pid'], + $row['list_type'] + ) . $headerContent . '</h4>'; } /** @@ -109,7 +104,10 @@ class PluginRenderer implements PageLayoutViewDrawItemHookInterface { $pluginName = $languageService->sL( BackendUtility::getLabelFromItemListMerged( - $pid, 'tt_content', 'list_type', $listType + $pid, + 'tt_content', + 'list_type', + $listType ) ); return '<span class="label label-primary">' . $pluginName . '</span> '; diff --git a/Classes/Preview/PreviewRenderer.php b/Classes/Preview/PreviewRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..73e7b165cd453ce2d6a6dfd5c713838ae2a38180 --- /dev/null +++ b/Classes/Preview/PreviewRenderer.php @@ -0,0 +1,95 @@ +<?php + +/*************************************************************** + * Copyright notice + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * 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! + ***************************************************************/ + +namespace SGalinski\SgYoutube\Preview; + +use TYPO3\CMS\Backend\Preview\PreviewRendererInterface; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; + +class PreviewRenderer implements PreviewRendererInterface { + /** + * @var LanguageService $languageService + */ + protected LanguageService $languageService; + + protected PreviewService $previewService; + + public function __construct(LanguageService $languageService, PreviewService $previewService) { + $this->languageService = $languageService; + $this->previewService = $previewService; + } + + /** + * Dedicated method for rendering preview header HTML for + * the page module only. Receives $item which is an instance of + * GridColumnItem which has a getter method to return the record. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewHeader(GridColumnItem $item): string { + $label = BackendUtility::getLabelFromItemListMerged( + $item->getRecord()['pid'], + 'tt_content', + 'list_type', + $item->getRecord()['list_type'] + ); + return '<h4><span class="label label-primary">' . $this->languageService->sL($label) . '</span></h4>'; + } + + /** + * Dedicated method for rendering preview body HTML for + * the page module only. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewContent(GridColumnItem $item): string { + $view = $this->previewService->getPluginPreview($item->getRecord()); + return $view->render(); + } + + /** + * Render a footer for the record to display in page module below + * the body of the item's preview. + * + * @param GridColumnItem $item + * @return string + */ + public function renderPageModulePreviewFooter(GridColumnItem $item): string { + return ''; + } + + /** + * Dedicated method for wrapping a preview header and body HTML. + * + * @param string $previewHeader + * @param string $previewContent + * @param GridColumnItem $item + * @return string + */ + public function wrapPageModulePreview(string $previewHeader, string $previewContent, GridColumnItem $item): string { + return $previewHeader . $previewContent; + } +} diff --git a/Classes/Preview/PreviewService.php b/Classes/Preview/PreviewService.php new file mode 100644 index 0000000000000000000000000000000000000000..1d88d9fba92d615e731b993714117f4ae9ba35b6 --- /dev/null +++ b/Classes/Preview/PreviewService.php @@ -0,0 +1,85 @@ +<?php + +/*************************************************************** + * Copyright notice + * (c) sgalinski Internet Services (https://www.sgalinski.de) + * 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! + ***************************************************************/ +namespace SGalinski\SgYoutube\Preview; + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; + +/** + * PreviewService, to get Views while we have to duplicate previewCode + */ +class PreviewService { + public const RETURNTYPE_ARR = 'array'; + + /** + * returns the usable PluginView + * + * @param array $row + * @return StandaloneView + */ + public function getPluginPreview(array $row): StandaloneView { + $view = GeneralUtility::makeInstance(StandaloneView::class); + $view->setPartialRootPaths(['EXT:sg_youtube/Resources/Private/Partials/Backend']); + $view->setTemplateRootPaths(['EXT:sg_youtube/Resources/Private/Templates/Youtube']); + $view->setTemplate('Backend.html'); + $view->assign('uid', $row['uid']); + + // Get available plugin settings and their values from flexform + $pluginConfiguration = GeneralUtility::xml2array( + $row['pi_flexform'], + 'T3DataStructure' + )['data']['sDEF']['lDEF']; + + $templateData = [ + 'youtubeId' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.id'), + 'maxResults' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.maxResults'), + 'showTitle' => (int) ($this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.showTitle') ?? 1), + 'showDescription' => (int) ($this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.showDescription') ?? 1), + 'disableLightbox' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.disableLightbox'), + 'disableLightboxMobile' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.disableLightboxMobile'), + 'aspectRatio' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.aspectRatio'), + 'thumbnailType' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.thumbnailType'), + 'thumbnailImagesCount' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.thumbnailImages'), + 'showApiResult' => $this->passVDefOnKeyToTemplate($pluginConfiguration, 'settings.showApiResult'), + ]; + + $view->assign('data', $templateData); + return $view; + } + + /** + * @param array $conf + * @param string $key + * @param string $returnType + * @return array|mixed|string + */ + private function passVDefOnKeyToTemplate(array $conf, string $key, string $returnType = '') { + if (isset($conf[$key])) { + return $conf[$key]['vDEF']; + } + + // check if we got a possible returntype: + if ($returnType === self::RETURNTYPE_ARR) { + return []; + } + + return ''; + } +} diff --git a/Classes/Service/CachedImageService.php b/Classes/Service/CachedImageService.php index b45774f9ab6eae136308ea1828f1fb200b7371cc..b6e7470da1547cd0e6a38d51d3939ecac1296ca7 100644 --- a/Classes/Service/CachedImageService.php +++ b/Classes/Service/CachedImageService.php @@ -74,7 +74,7 @@ class CachedImageService { * * @param string $cacheDirectory */ - public function __construct($cacheDirectory) { + public function __construct(string $cacheDirectory = '') { $this->cacheDirectory = ltrim($cacheDirectory, '/'); } diff --git a/Classes/Service/YoutubeService.php b/Classes/Service/YoutubeService.php index b406514cc9fc1b8b00eb511de07fe96a8b21f376..c21799b4ccc895349929dc54534a99aae480ce2b 100644 --- a/Classes/Service/YoutubeService.php +++ b/Classes/Service/YoutubeService.php @@ -26,27 +26,29 @@ namespace SGalinski\SgYoutube\Service; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use Exception; +use GuzzleHttp\Exception\ClientException; use InvalidArgumentException; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException; use TYPO3\CMS\Core\Context\LanguageAspect; +use TYPO3\CMS\Core\Http\RequestFactory; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Registry; use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\VersionNumberUtility; /** * YouTube Helper Service */ class YoutubeService { - const API_URL = 'https://www.googleapis.com/youtube/v3/'; - const API_CHANNEL = 'search'; - const API_PLAYLIST = 'playlistItems'; - const API_VIDEO = 'videos'; - const API_PART = 'snippet'; - const API_PART_LOCALIZATIONS = 'localizations'; - const API_ORDER_BY = 'date'; + public const API_URL = 'https://www.googleapis.com/youtube/v3/'; + public const API_CHANNEL = 'search'; + public const API_PLAYLIST = 'playlistItems'; + public const API_VIDEO = 'videos'; + public const API_PART = 'snippet'; + public const API_PART_LOCALIZATIONS = 'localizations'; + public const API_ORDER_BY = 'date'; /** * Maps the json array from the YouTube call to return some unified value. The output from YouTube is pretty @@ -60,7 +62,11 @@ class YoutubeService { * @return array */ public function mapArray( - $jsonArray = [], $youtubeId = '', $aspectRatio = '16:9', $thumbnailType = 'byAspectRatio', $apiKey = '' + $jsonArray = [], + $youtubeId = '', + $aspectRatio = '16:9', + $thumbnailType = 'byAspectRatio', + $apiKey = '' ): array { if (count($jsonArray) <= 0) { return $jsonArray; @@ -84,22 +90,18 @@ class YoutubeService { $aspectRatio = '16:9'; } - // Localization is just available from TYPO3 9.X.X - if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '9.0.0', '>=')) { - $context = GeneralUtility::makeInstance(Context::class); - - try { - /** @var LanguageAspect $languageAspect */ - $languageAspect = $context->getAspect('language'); - $currentLanguageUid = $languageAspect->getId(); - } catch (AspectNotFoundException $e) { - // Can't be possible to land here, otherwise the whole frontend would be weird as hell.. - $currentLanguageUid = 0; - } + $context = GeneralUtility::makeInstance(Context::class); + try { + /** @var LanguageAspect $languageAspect */ + $languageAspect = $context->getAspect('language'); + $currentLanguageUid = $languageAspect->getId(); + } catch (AspectNotFoundException $e) { + // Can't be possible to land here, otherwise the whole frontend would be weird as hell.. + $currentLanguageUid = 0; + } - if ($currentLanguageUid > 0 && $youtubeId && $apiKey) { - $jsonArray = $this->addLocalizationData($jsonArray, $apiKey, $currentLanguageUid); - } + if ($currentLanguageUid > 0 && $youtubeId && $apiKey) { + $jsonArray = $this->addLocalizationData($jsonArray, $apiKey, $currentLanguageUid); } $result = []; @@ -156,21 +158,19 @@ class YoutubeService { } $localizationData = $this->getDetailedVideoInformationForJsonArray( - $jsonArray, $apiKey, self::API_PART_LOCALIZATIONS + $jsonArray, + $apiKey, + self::API_PART_LOCALIZATIONS ); - if (!isset($localizationData['items']) || count($localizationData['items']) <= 0) { + if (!isset($localizationData['items']) || (is_countable($localizationData['items']) ? count($localizationData['items']) : 0) <= 0) { return $jsonArray; } - /** @var ServerRequest $request */ - $request = $GLOBALS['TYPO3_REQUEST']; - $attributes = $request->getAttributes(); - if (!isset($attributes['site'])) { + $site = $this->getSite(); + if ($site === NULL) { return $jsonArray; } - /** @var Site $site */ - $site = $attributes['site']; $languages = $site->getLanguages(); $currentSiteLanguage = $languages[$currentLanguageUid]; if (!$currentSiteLanguage) { @@ -190,7 +190,7 @@ class YoutubeService { } foreach ($localizationData['items'] as $index => $localizationEntry) { - if (!isset($localizationEntry['localizations']) || count($localizationEntry['localizations']) <= 0) { + if (!isset($localizationEntry['localizations']) || (is_countable($localizationEntry['localizations']) ? count($localizationEntry['localizations']) : 0) <= 0) { continue; } @@ -202,11 +202,11 @@ class YoutubeService { break; } - if (!$title && isset($localizations[$languageIsoCode]['title'])) { + if (!$title && isset($localizations[$languageIsoCode]['title'])) { $title = $localizations[$languageIsoCode]['title']; } - if (!$description && isset($localizations[$languageIsoCode]['description'])) { + if (!$description && isset($localizations[$languageIsoCode]['description'])) { $description = $localizations[$languageIsoCode]['description']; } } @@ -266,7 +266,7 @@ class YoutubeService { } $result = $this->getJsonAsArray('', '10', $apiKey, $apiUrl . '?' . $query); - if (!isset($result['items']) || count($result['items']) <= 0) { + if (!isset($result['items']) || (is_countable($result['items']) ? count($result['items']) : 0) <= 0) { return $jsonArray; } @@ -302,26 +302,27 @@ class YoutubeService { } } - if (function_exists('curl_init')) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_URL, $url); - $jsonString = curl_exec($ch); - curl_close($ch); - - } elseif (ini_get('allow_url_fopen')) { - $jsonString = file_get_contents($url); - } else { - throw new InvalidArgumentException( - 'The system doesn\'t have CURL enabled and "allow_url_fopen" is disabled.', 403 - ); + $requestFactory = GeneralUtility::makeInstance(RequestFactory::class); + try { + $site = $this->getSite(); + if ($site === NULL) { + throw new Exception('No site object found!'); + } + $response = $requestFactory->request($url, 'GET', [ + 'headers' => [ + 'Referer' => $site->getBase()->getHost() + ] + ]); + $jsonString = (string) $response->getBody(); + } catch (ClientException $exception) { + $jsonString = (string) $exception->getResponse()->getBody(); } - + $jsonArray = ($jsonString !== '' ? json_decode($jsonString, TRUE) : []); if ($jsonArray === NULL) { throw new InvalidArgumentException( - 'There is something wrong with loaded JSON or encoded data is deeper than the recursion limit.', 403 + 'There is something wrong with loaded JSON or encoded data is deeper than the recursion limit.', + 403 ); } @@ -339,7 +340,7 @@ class YoutubeService { throw new InvalidArgumentException('No items array.', 403); } - if (count($jsonArray['items']) < 1) { + if ((is_countable($jsonArray['items']) ? count($jsonArray['items']) : 0) < 1) { throw new InvalidArgumentException('No items found.', 403); } @@ -396,4 +397,20 @@ class YoutubeService { return $youtubeId; } + + /** + * Get the current site of the request + * + * @return Site|null + */ + protected function getSite(): ?Site { + /** @var ServerRequest $request */ + $request = $GLOBALS['TYPO3_REQUEST']; + $attributes = $request->getAttributes(); + if (!isset($attributes['site'])) { + return NULL; + } + + return $attributes['site']; + } } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000000000000000000000000000000000000..53ba19598e5d49e5db0e15371b80e19bcdd768cb --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: true + + SGalinski\SgYoutube\: + resource: '../Classes/*' + + SGalinski\SgYoutube\Preview\PreviewRenderer: + public: true + + SGalinski\SgYoutube\Service\YoutubeService: + public: true + autowire: false diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index 2940744c5dd5ec35a4bf5e362bb6580ecca53546..3749ff006deafa710c4b986ce2fcac6b8d193758 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,5 +1,6 @@ <?php +defined('TYPO3') or die(); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile( 'sg_youtube', 'Configuration/TypoScript', diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index c12eb263102d20dd0b4d942104183164def494d9..76259ba94cea5f2a45349c09555f58e5a777f89a 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -1,12 +1,18 @@ <?php +defined('TYPO3') or die(); $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgyoutube_youtube'] = 'pi_flexform'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( - 'sgyoutube_youtube', 'FILE:EXT:sg_youtube/Configuration/FlexForms/flexform_sgyoutube_youtube.xml' + 'sgyoutube_youtube', + 'FILE:EXT:sg_youtube/Configuration/FlexForms/flexform_sgyoutube_youtube.xml' ); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( - 'SGalinski.sg_youtube', + 'SgYoutube', 'Youtube', 'YouTube Videos' ); + +// add the backend preview for the youtube plugin +$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgyoutube_youtube'] = + \SGalinski\SgYoutube\Preview\PreviewRenderer::class; diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript index 32b5bbdb22e78bb405f50a00053754b718cfa3f4..381ab31b1763fcb6ee4c405353b143e65e247a3f 100644 --- a/Configuration/TypoScript/setup.typoscript +++ b/Configuration/TypoScript/setup.typoscript @@ -20,3 +20,4 @@ plugin.tx_sgyoutube { } } } +plugin.tx_sgyoutube_youtube < plugin.tx_sgyoutube diff --git a/README.md b/README.md index 9d28075c3cecfa432364106f0d31073351340201..fcedb8308d1f36c392f87e0a48db6176d12f243e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Repository: https://gitlab.sgalinski.de/typo3/sg_youtube Please report bugs here: https://gitlab.sgalinski.de/typo3/sg_youtube -TYPO3 version: >9.5 +TYPO3 version: >10.4 ## Installation / Integration diff --git a/Resources/Public/Icons/Extension.png b/Resources/Public/Icons/Extension.png new file mode 100644 index 0000000000000000000000000000000000000000..67fda8fec210ccf660363ff30c10f19513b4bfb2 Binary files /dev/null and b/Resources/Public/Icons/Extension.png differ diff --git a/Resources/Public/JavaScript/youtubeLightbox.js b/Resources/Public/JavaScript/youtubeLightbox.js deleted file mode 100644 index 92d787888b5470574da929c2a0dbd678c49c46c4..0000000000000000000000000000000000000000 --- a/Resources/Public/JavaScript/youtubeLightbox.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * JavaScript module for the sg-youtube plugin - * - * @deprecated since version 4.4.0 and will be removed in 5.0.0 - */ -module.exports = function() { - 'use strict'; - - const $ = require('jquery'); - require('magnific-popup'); - - /** - * Initialize the whole Popup setup - */ - function init(section) { - $(`${section || ''} .sg-youtube-item`).each(function (index, item) { - let $youtubeItem = $(item), - viewportWidth = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); - if (($youtubeItem.data('disable-lightbox') && viewportWidth >= 680) || - ($youtubeItem.data('disable-lightbox-mobile') && viewportWidth < 680) - ) { - $youtubeItem.on('click', replaceThumbnailWithVideo); - } else { - $youtubeItem.magnificPopup({ - type: 'iframe', - iframe: { - patterns: { - youtube: { - index: 'youtube.com/', - id: function(url) { - return prepareVideoUrl(url); - }, - src: '//www.youtube-nocookie.com/embed/%id%' - } - } - } - }); - } - }); - } - - /** - * Replaces the given element behind the event with a youtube video. - * - * @param {Event} event - */ - function replaceThumbnailWithVideo(event) { - event.preventDefault(); - let $youtubeItem = $(event.currentTarget); - - // This needs to be done, because the height of inline elements is always 0, if on auto... - $youtubeItem.css('display', 'block'); - - let queryString = prepareVideoUrl($youtubeItem.attr('href')), - $thumbnailElement = $youtubeItem.find('.sg-youtube-image'), - width = $thumbnailElement.outerWidth() + 'px', - height = $thumbnailElement.outerHeight() + 'px'; - $thumbnailElement.replaceWith('<div class="sg-youtube-item sg-card-shadow" ' + - 'style="height: ' + height + '; width: ' + width + ';"><iframe ' + - 'width="' + width + '" height="' + height + '" ' + - 'src="https://www.youtube-nocookie.com/embed/' + queryString + '" frameborder="0" ' + - 'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" ' + - 'allowfullscreen></iframe></div>'); - } - - /** - * Prepares the given url, or returns null. - * - * @param {string} url - * @return {string|null} - */ - function prepareVideoUrl(url) { - let matches = url.match(/watch\?v=(.*)&list=(.*)/); - if (!matches) { - // check if the list parameter is missing - matches = url.match(/watch\?v=([^?&]*)/); - if (!matches) { - return null; - } - } - let [, videoString] = matches, - queryParameterSeparator = '?'; - if (matches[2]) { - videoString += '?list=' + matches[2]; - queryParameterSeparator = '&'; - - } - - return videoString + queryParameterSeparator + 'autoplay=1&rel=0'; - } - - init(); -}; diff --git a/UPGRADE.md b/UPGRADE.md index b669916711875659dfae2452deea0f1370fed234..ac1134cf4f91ab17e002eaa8d3974f0609c590c2 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,6 +1,8 @@ ## Version 5 - `youtubeLightbox.js` (deprecated since 4.4.0) using magnific-popup and jQuery removed in favor of `sgYoutubeLightbox.js` (vanilla JS). - Extension `project_theme_lightbox` required starting with version 5.0.0. +- Dropped TYPO3 9 Support +- Dropped php 7.3 Support ## Version 4.4 ```project_theme_lightbox``` integration - The magnific popup integration is deprecated and will be removed in later versions. diff --git a/composer.json b/composer.json index a8f158fc97026517545bd7e81ddc2f0073215945..2e912f6999f570efe4fc84e2f41632974cd151cd 100644 --- a/composer.json +++ b/composer.json @@ -6,11 +6,8 @@ "license": "GPL-2.0-or-later", "version": "4.8.2", "require": { - "typo3/cms-core": "^9.5.4 || ^10.4.0", - "sgalinski/project-theme-lightbox": "^1.0.0" - }, - "require-dev": { - "roave/security-advisories": "dev-master" + "typo3/cms-core": "^10.4.0 || ^11.5.0", + "sgalinski/project-theme-lightbox": "^2.0.0" }, "replace": { "sgalinski/sg_youtube": "self.version" diff --git a/ext_emconf.php b/ext_emconf.php index ddcd5dd44b820af3c672dbc560e79f69320c1d71..d89aa145ba4ad079705b5f938efee7b68d246793 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -39,8 +39,9 @@ $EM_CONF['sg_youtube'] = [ 'version' => '4.8.2', 'constraints' => [ 'depends' => [ - 'typo3' => '9.5.0-10.4.99', - 'project_theme_lightbox' => '^1.0.0', + 'typo3' => '10.4.0-11.5.99', + 'project_theme_lightbox' => '1.0.0-2.9.99', + 'php' => '7.4.0-8.1.99', ], 'conflicts' => [], 'suggests' => [], diff --git a/ext_localconf.php b/ext_localconf.php index 71c8207270ad838aef688283229dc4721620aaaf..d4fb86d3af8cb75c487226f2eb1f4fdbdda9098e 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -24,15 +24,13 @@ * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -if (!defined('TYPO3_MODE')) { - die('Access denied.'); -} +defined('TYPO3') or die(); \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'SGalinski.sg_youtube', + 'SgYoutube', 'Youtube', [ - 'Youtube' => 'index', + \SGalinski\SgYoutube\Controller\YoutubeController::class => 'index', ], // non-cacheable actions