From b2b67f31f892136c87f95570722fa326f708aa70 Mon Sep 17 00:00:00 2001 From: "Landolsi, Abdellatif" Date: Thu, 15 Aug 2024 16:17:14 +0200 Subject: [PATCH] make extension compatible to TYPO3 v12 --- .../Controller/AdministrationController.php | 236 +++++--- Classes/Controller/EidController.php | 2 +- Classes/Controller/FeedsController.php | 9 +- .../Restriction/BackendGroupRestriction.php | 2 +- Classes/Domain/Model/BackendUserGroup.php | 526 +++++++++++++++++ Classes/Domain/Model/Configuration.php | 17 +- Classes/Domain/Model/Feed.php | 12 +- Classes/Domain/Model/Token.php | 33 +- .../Repository/AbstractBackendRepository.php | 4 +- Classes/Domain/Repository/FeedRepository.php | 25 +- Classes/Domain/Repository/TokenRepository.php | 18 +- .../Validator/ConfigurationValidator.php | 6 +- .../Validation/Validator/TokenValidator.php | 10 +- .../BeforeReturnTwitterQueryFieldsEvent.php | 25 + .../Event/BeforeUpdateFacebookFeedEvent.php | 49 ++ .../Event/BeforeUpdateInstagramFeedEvent.php | 49 ++ .../Event/BeforeUpdateTwitterFeedEvent.php | 49 ++ .../Event/BeforeUpdateTwitterV2FeedEvent.php | 59 ++ .../Event/BeforeUpdateYoutubeFeedEvent.php | 49 ++ Classes/Event/ChangedFeedItemEvent.php | 24 + Classes/Event/FacebookEndPointEvent.php | 33 ++ .../FacebookEndPointRequestFieldsEvent.php | 25 + Classes/Event/RemovedFeedItemEvent.php | 27 + .../YoutubeEndPointRequestFieldsEvent.php | 25 + Classes/Exception/BadResponseException.php | 4 +- .../FailedExecutingImportException.php | 4 +- Classes/Exception/InvalidFeedSourceData.php | 4 +- Classes/Exception/UnsupportedTokenType.php | 4 +- Classes/Feed/Source/BaseFacebookSource.php | 31 +- Classes/Feed/Source/BaseSource.php | 3 - Classes/Feed/Source/InstagramSource.php | 2 +- Classes/Feed/Source/TwitterSource.php | 18 +- Classes/Feed/Source/TwitterV2Source.php | 10 +- Classes/Feed/Source/YoutubeSource.php | 11 +- Classes/Feed/Update/BaseUpdater.php | 22 +- Classes/Feed/Update/FacebookFeedUpdater.php | 13 +- Classes/Feed/Update/InstagramFeedUpdater.php | 9 +- Classes/Feed/Update/TwitterFeedUpdater.php | 16 +- Classes/Feed/Update/TwitterV2FeedUpdater.php | 7 +- Classes/Feed/Update/YoutubeFeedUpdater.php | 9 +- Classes/Hooks/PageLayoutView.php | 14 +- Classes/Task/AdditionalFieldProviderTrait.php | 24 +- .../ImportTaskAdditionalFieldProvider.php | 15 +- Classes/Utility/ConfigurationUtility.php | 6 +- Classes/Utility/LoggerUtility.php | 4 +- Classes/Utility/SchedulerUtility.php | 8 +- .../FacebookLoginUrlViewHelper.php | 2 +- Configuration/Backend/Modules.php | 43 ++ Configuration/Extbase/Persistence/Classes.php | 3 + Configuration/Icons.php | 32 + Configuration/JavaScriptModules.php | 8 + Configuration/Services.yaml | 4 +- Configuration/TCA/Overrides/sys_template.php | 2 +- Configuration/TCA/Overrides/tt_content.php | 2 +- ...asocialfeed_domain_model_configuration.php | 22 +- .../tx_pxasocialfeed_domain_model_feed.php | 51 +- .../tx_pxasocialfeed_domain_model_token.php | 42 +- .../Partials/Backend/ListConfigurations.html | 6 +- .../Private/Partials/Backend/ListTokens.html | 4 +- .../Backend/TokenInfo/FacebookInstagram.html | 6 +- .../Templates/Administration/EditToken.html | 4 +- Resources/Public/Icons/Extension.gif | Bin 0 -> 831882 bytes Resources/Public/Icons/Extension.svg | 47 ++ Resources/Public/Icons/ext_icon.svg | 47 ++ .../JavaScript/Backend/SocialFeedModule.js | 545 +++++++++--------- .../social-feed-administration-module.js | 218 +++++++ composer.json | 6 +- ext_emconf.php | 9 +- ext_localconf.php | 32 +- ext_tables.php | 32 +- ext_tables.sql | 2 +- ext_typoscript_setup.typoscript | 1 + 72 files changed, 2032 insertions(+), 690 deletions(-) create mode 100644 Classes/Domain/Model/BackendUserGroup.php create mode 100644 Classes/Event/BeforeReturnTwitterQueryFieldsEvent.php create mode 100644 Classes/Event/BeforeUpdateFacebookFeedEvent.php create mode 100644 Classes/Event/BeforeUpdateInstagramFeedEvent.php create mode 100644 Classes/Event/BeforeUpdateTwitterFeedEvent.php create mode 100644 Classes/Event/BeforeUpdateTwitterV2FeedEvent.php create mode 100644 Classes/Event/BeforeUpdateYoutubeFeedEvent.php create mode 100644 Classes/Event/ChangedFeedItemEvent.php create mode 100644 Classes/Event/FacebookEndPointEvent.php create mode 100644 Classes/Event/FacebookEndPointRequestFieldsEvent.php create mode 100644 Classes/Event/RemovedFeedItemEvent.php create mode 100644 Classes/Event/YoutubeEndPointRequestFieldsEvent.php create mode 100644 Configuration/Backend/Modules.php create mode 100644 Configuration/Icons.php create mode 100644 Configuration/JavaScriptModules.php create mode 100644 Resources/Public/Icons/Extension.gif create mode 100644 Resources/Public/Icons/Extension.svg create mode 100644 Resources/Public/Icons/ext_icon.svg create mode 100644 Resources/Public/JavaScript/Backend/social-feed-administration-module.js diff --git a/Classes/Controller/AdministrationController.php b/Classes/Controller/AdministrationController.php index d66ffc5e..ac6c9e51 100644 --- a/Classes/Controller/AdministrationController.php +++ b/Classes/Controller/AdministrationController.php @@ -12,18 +12,22 @@ use Pixelant\PxaSocialFeed\Domain\Repository\ConfigurationRepository; use Pixelant\PxaSocialFeed\Domain\Repository\FeedRepository; use Pixelant\PxaSocialFeed\Domain\Repository\TokenRepository; +use Pixelant\PxaSocialFeed\Domain\Validation\Validator\ConfigurationValidator; +use Pixelant\PxaSocialFeed\Domain\Validation\Validator\TokenValidator; use Pixelant\PxaSocialFeed\Service\Task\ImportFeedsTaskService; use Pixelant\PxaSocialFeed\Utility\ConfigurationUtility; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Backend\Routing\UriBuilder as BackendUriBuilder; -use TYPO3\CMS\Backend\View\BackendTemplateView; +use TYPO3\CMS\Backend\Template\ModuleTemplate; +use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Core\Http\RedirectResponse; use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; use TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; @@ -78,29 +82,30 @@ class AdministrationController extends ActionController * @var BackendUserGroupRepository */ protected $backendUserGroupRepository; - /** - * BackendTemplateContainer - * - * @var BackendTemplateView + * Summary of moduleTemplateFactory + * @var ModuleTemplateFactory */ - protected $view; + protected ModuleTemplateFactory $moduleTemplateFactory; /** - * Backend Template Container - * - * @var BackendTemplateView + * @var ModuleTemplate */ - protected $defaultViewObjectName = BackendTemplateView::class; + protected ModuleTemplate $moduleTemplate; /** * @param BackendUserGroupRepository $backendUserGroupRepository */ - public function __construct(BackendUserGroupRepository $backendUserGroupRepository) + public function __construct(BackendUserGroupRepository $backendUserGroupRepository, private ModuleTemplateFactory $moduleTemplateFactor, private readonly PageRenderer $pageRenderer) { $this->backendUserGroupRepository = $backendUserGroupRepository; } + public function injectModuleTemplateFactory(ModuleTemplateFactory $moduleTemplateFactory): void + { + $this->moduleTemplateFactory = $moduleTemplateFactory; + } + /** * @param ConfigurationRepository $configurationRepository */ @@ -125,24 +130,12 @@ public function injectFeedRepository(FeedRepository $feedRepository): void $this->feedRepository = $feedRepository; } - /** - * Set up the doc header properly here - * - * @param ViewInterface $view - */ - protected function initializeView(ViewInterface $view): void + protected function initializeView() { - /** @var BackendTemplateView $view */ - parent::initializeView($view); - - // create select box menu - $this->createMenu(); - - $pageRenderer = $this->view->getModuleTemplate() - ? $this->view->getModuleTemplate()->getPageRenderer() - : GeneralUtility::makeInstance(PageRenderer::class); + // $this->pageRenderer->addCssFile ( 'EXT:pxa_social_feed/Resources/Public/Css/Backend/SocialFeedModule.css' ); + // $this->pageRenderer->loadJavaScriptModule ( '@pixelant/pxa-social-feed/social-feed-administration-module.js' ); - $pageRenderer->addRequireJsConfiguration( + $this->pageRenderer->addRequireJsConfiguration( [ 'paths' => [ 'clipboard' => PathUtility::getAbsoluteWebPath( @@ -158,38 +151,47 @@ protected function initializeView(ViewInterface $view): void ] ); - $pageRenderer->loadRequireJsModule( + $this->pageRenderer->loadRequireJsModule( 'TYPO3/CMS/PxaSocialFeed/Backend/SocialFeedModule', "function(socialFeedModule) { socialFeedModule.getInstance({$this->getInlineSettings()}).run() }" ); } + public function initializeAction() + { + $this->moduleTemplate = $this->moduleTemplateFactory->create($this->request); + $this->createMenu(); + } + /** * Index action to show all configurations and tokens * * @param bool $activeTokenTab */ - public function indexAction($activeTokenTab = false): void + public function indexAction($activeTokenTab = false): ResponseInterface { $tokens = $this->findAllByRepository($this->tokenRepository); - $this->view->assignMultiple([ - 'tokens' => $tokens, + 'tokens' => $tokens, 'configurations' => $this->findAllByRepository($this->configurationRepository), 'activeTokenTab' => $activeTokenTab, 'isTokensValid' => $this->isTokensValid($tokens), 'isAdmin' => $GLOBALS['BE_USER']->isAdmin(), ]); + + $this->moduleTemplate->setContent ( $this->view->render () ); + return $this->htmlResponse($this->moduleTemplate->renderContent()); } /** * Edit token form * - * @param Token $token + * @param Token|null $tokenToEdit * @param int $type */ - public function editTokenAction(Token $token = null, int $type = Token::FACEBOOK): void + public function editTokenAction(Token $tokenToEdit = null, int $type = Token::FACEBOOK): ResponseInterface { + $token = $tokenToEdit; $isNew = $token === null; if (!$isNew) { @@ -205,21 +207,30 @@ public function editTokenAction(Token $token = null, int $type = Token::FACEBOOK $this->view->assignMultiple(compact('token', 'type', 'isNew', 'availableTypes')); $this->assignBEGroups(); + + $this->moduleTemplate->setContent ( $this->view->render () ); + return $this->htmlResponse ( $this->moduleTemplate->renderContent () ); } /** * Save token changes * - * @param Token $token - * @Extbase\Validate("\Pixelant\PxaSocialFeed\Domain\Validation\Validator\TokenValidator", param="token") + * @param Token $tokenToEdit */ - public function updateTokenAction(Token $token): void + #[Extbase\Validate(['validator' => TokenValidator::class, 'param' => 'tokenToEdit'])] + public function updateTokenAction(Token $tokenToEdit): RedirectResponse { - $isNew = $token->getUid() === null; + $isNew = $tokenToEdit->getUid() === null; - $this->tokenRepository->{$isNew ? 'add' : 'update'}($token); + $this->tokenRepository->{$isNew ? 'add' : 'update'}($tokenToEdit); + + $this->addFlashMessage( + $this->translate('action_changes_saved'), + '', + ContextualFeedbackSeverity::INFO, + ); - $this->redirectToIndexTokenTab($this->translate('action_changes_saved')); + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed') . '&activeTokenTab=1'); } /** @@ -227,40 +238,59 @@ public function updateTokenAction(Token $token): void * * @param Token $token */ - public function resetAccessTokenAction(Token $token): void + public function resetAccessTokenAction ( Token $resetToken ) : RedirectResponse { - $token->setAccessToken(''); - $this->tokenRepository->update($token); + $resetToken->setAccessToken ( '' ); + $this->tokenRepository->update ( $resetToken ); - $this->redirectToIndexTokenTab(); + $this->addFlashMessage( + 'Access token was reset', + '', + ContextualFeedbackSeverity::INFO, + ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed') . '&activeTokenTab=1'); } /** * Delete token * - * @param Token $token + * @param Token $tokenToDelete */ - public function deleteTokenAction(Token $token): void + public function deleteTokenAction ( Token $tokenToDelete ) : RedirectResponse { - $tokenConfigurations = $this->configurationRepository->findConfigurationByToken($token); + $tokenConfigurations = $this->configurationRepository->findConfigurationByToken ( $tokenToDelete ); if ($tokenConfigurations->count() === 0) { - $this->tokenRepository->remove($token); + $this->tokenRepository->remove ( $tokenToDelete ); - if ($token->getType() === Token::FACEBOOK) { + if ( $tokenToDelete->getType () === Token::FACEBOOK ) + { // Remove all page access tokens created by this token $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getConnectionForTable('tx_pxasocialfeed_domain_model_token'); - $queryBuilder->delete('tx_pxasocialfeed_domain_model_token', ['parent_token' => $token->getUid()]); + $queryBuilder->delete ( 'tx_pxasocialfeed_domain_model_token', [ 'parent_token' => $tokenToDelete->getUid () ] ); } - $this->redirectToIndexTokenTab($this->translate('action_delete')); + $this->addFlashMessage( + $this->translate('action_delete'), + '', + ContextualFeedbackSeverity::INFO, + ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed') . '&activeTokenTab=1'); } - $this->redirectToIndexTokenTab( - $this->translate('error_token_configuration_exist', [$tokenConfigurations->getFirst()->getName()]), - FlashMessage::ERROR + $this->addFlashMessage( + $this->translate( + 'error_token_configuration_exist', + [ $tokenConfigurations->getFirst()->getName() ], + ), + '', + ContextualFeedbackSeverity::ERROR, ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed') . '&activeTokenTab=1'); } /** @@ -268,21 +298,25 @@ public function deleteTokenAction(Token $token): void * * @param Configuration $configuration */ - public function editConfigurationAction(Configuration $configuration = null): void + public function editConfigurationAction(Configuration $configuration = null): ResponseInterface { $tokens = $this->findAllByRepository($this->tokenRepository); $this->view->assignMultiple(compact('configuration', 'tokens')); $this->assignBEGroups(); + + + $this->moduleTemplate->setContent ( $this->view->render () ); + return $this->htmlResponse ( $this->moduleTemplate->renderContent () ); } /** * Update configuration * * @param Configuration $configuration - * @Extbase\Validate("\Pixelant\PxaSocialFeed\Domain\Validation\Validator\ConfigurationValidator", param="configuration") */ - public function updateConfigurationAction(Configuration $configuration): void + #[Extbase\Validate(['validator' => ConfigurationValidator::class, 'param' => 'configuration'])] + public function updateConfigurationAction(Configuration $configuration): RedirectResponse { $isNew = $configuration->getUid() === null; @@ -298,10 +332,16 @@ public function updateConfigurationAction(Configuration $configuration): void GeneralUtility::makeInstance(PersistenceManagerInterface::class)->persistAll(); // Redirect back to edit view, so user can now provide social ID according to selected token - $this->redirect('editConfiguration', null, null, ['configuration' => $configuration]); + return new RedirectResponse($this->uriBuilder->reset()->uriFor('editConfiguration', [ 'configuration' => $configuration ], 'Administration', 'PxaSocialFeed')); } - $this->redirectToIndex($this->translate('action_changes_saved')); + $this->addFlashMessage( + $this->translate('action_changes_saved'), + '', + ContextualFeedbackSeverity::OK, + ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed')); } /** @@ -309,7 +349,7 @@ public function updateConfigurationAction(Configuration $configuration): void * * @param Configuration $configuration */ - public function deleteConfigurationAction(Configuration $configuration): void + public function deleteConfigurationAction(Configuration $configuration): RedirectResponse { // Remove all feeds $feeds = $this->feedRepository->findByConfiguration($configuration); @@ -320,7 +360,13 @@ public function deleteConfigurationAction(Configuration $configuration): void $this->configurationRepository->remove($configuration); - $this->redirectToIndex($this->translate('action_delete')); + $this->addFlashMessage( + $this->translate('action_delete'), + '', + ContextualFeedbackSeverity::WARNING, + ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed')); } /** @@ -328,16 +374,26 @@ public function deleteConfigurationAction(Configuration $configuration): void * * @param Configuration $configuration */ - public function runConfigurationAction(Configuration $configuration) + public function runConfigurationAction(Configuration $configuration): RedirectResponse { $importService = GeneralUtility::makeInstance(ImportFeedsTaskService::class); try { $importService->import([ $configuration->getUid() ]); } catch (\Exception $e) { - $this->redirectToIndex($e->getMessage(), FlashMessage::ERROR); + $this->addFlashMessage( + $e->getMessage(), + '', + ContextualFeedbackSeverity::ERROR, + ); } - $this->redirectToIndex($this->translate('single_import_end')); + $this->addFlashMessage( + $this->translate('single_import_end'), + '', + ContextualFeedbackSeverity::WARNING, + ); + + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed')); } /** @@ -366,7 +422,7 @@ protected function assignBEGroups() $excludeGroups = $this->getExcludeGroups(); - if ($GLOBALS['BE_USER']->isAdmin()) { + if ($GLOBALS[ 'BE_USER' ]->isAdmin()) { $groups = $this->backendUserGroupRepository->findAll($excludeGroups); } else { $groups = array_filter($GLOBALS['BE_USER']->userGroups, function ($group) use ($excludeGroups) { @@ -396,32 +452,23 @@ protected function translate(string $key, array $arguments = null): ?string */ protected function createMenu(): void { - // if view was found - if ($this->view->getModuleTemplate() !== null) { - /** @var UriBuilder $uriBuilder */ - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $uriBuilder->setRequest($this->request); - - $menu = $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); - $menu->setIdentifier('pxa_social_feed'); - - $actions = [ - 'index', - 'editConfiguration', - 'editToken', - ]; - - foreach ($actions as $action) { - $item = $menu->makeMenuItem() - ->setTitle($this->translate($action . 'Action')) - ->setHref($uriBuilder->reset()->uriFor($action, [], 'Administration')) - ->setActive($this->request->getControllerActionName() === $action); - - $menu->addMenuItem($item); - } + /** @var UriBuilder $uriBuilder */ + $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); + $uriBuilder->setRequest($this->request); + + $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); + $menu->setIdentifier('pxa_social_feed'); - $this->view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu); + $actions = [ 'index', 'editConfiguration', 'editToken' ]; + + foreach ($actions as $action) { + $item = $menu->makeMenuItem() + ->setTitle($this->translate($action . 'Action')) + ->setHref($uriBuilder->reset()->uriFor($action, [], 'Administration')) + ->setActive($this->request->getControllerActionName() === $action); + $menu->addMenuItem($item); } + $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu); } /** @@ -479,7 +526,7 @@ protected function getInlineSettings(): string * @param string|null $message * @param int $severity */ - protected function redirectToIndexTokenTab(string $message = null, int $severity = FlashMessage::OK) + protected function redirectToIndexTokenTab(string $message = null, int $severity = ContextualFeedbackSeverity::OK): RedirectResponse { if (!empty($message)) { $this->addFlashMessage( @@ -489,7 +536,7 @@ protected function redirectToIndexTokenTab(string $message = null, int $severity ); } - $this->redirect('index', null, null, ['activeTokenTab' => true]); + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed') . '&activeTokenTab=1'); } /** @@ -498,7 +545,7 @@ protected function redirectToIndexTokenTab(string $message = null, int $severity * @param string|null $message * @param int $severity */ - protected function redirectToIndex(string $message = null, int $severity = FlashMessage::OK) + protected function redirectToIndex(string $message = null, int $severity = ContextualFeedbackSeverity::OK): RedirectResponse { if (!empty($message)) { $this->addFlashMessage( @@ -508,7 +555,7 @@ protected function redirectToIndex(string $message = null, int $severity = Flash ); } - $this->redirect('index'); + return new RedirectResponse($this->uriBuilder->reset()->uriFor('index', [], 'Administration', 'PxaSocialFeed')); } /** @@ -522,7 +569,6 @@ protected function getExcludeGroups() if (isset($configuration['excludeBackendUserGroups'])) { return GeneralUtility::intExplode(',', $configuration['excludeBackendUserGroups'], true); } - return []; } } diff --git a/Classes/Controller/EidController.php b/Classes/Controller/EidController.php index cb2bcb9e..a1272ca3 100644 --- a/Classes/Controller/EidController.php +++ b/Classes/Controller/EidController.php @@ -21,7 +21,7 @@ */ class EidController { - const IDENTIFIER = 'pxa_social_feed_fb_access_token'; + public const IDENTIFIER = 'pxa_social_feed_fb_access_token'; /** * @var TokenRepository diff --git a/Classes/Controller/FeedsController.php b/Classes/Controller/FeedsController.php index a2f9cca9..3ed0f64f 100644 --- a/Classes/Controller/FeedsController.php +++ b/Classes/Controller/FeedsController.php @@ -3,6 +3,7 @@ namespace Pixelant\PxaSocialFeed\Controller; use Pixelant\PxaSocialFeed\Domain\Repository\FeedRepository; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; @@ -49,10 +50,12 @@ public function injectFeedRepository(FeedRepository $feedRepository): void $this->feedRepository = $feedRepository; } + protected function initializeView($view) {} + /** * List action */ - public function listAction() + public function listAction(): ResponseInterface { $limit = $this->settings['feedsLimit'] ? (int)($this->settings['feedsLimit']) : 10; $configurations = GeneralUtility::intExplode(',', $this->settings['configuration'], true); @@ -60,14 +63,16 @@ public function listAction() $feeds = $this->feedRepository->findByConfigurations($configurations, $limit); $this->view->assign('feeds', $feeds); + return $this->htmlResponse(); } /** * List ajax action * Prepare view for later ajax request */ - public function listAjaxAction() + public function listAjaxAction(): ResponseInterface { + return $this->htmlResponse(); } /** diff --git a/Classes/Database/Query/Restriction/BackendGroupRestriction.php b/Classes/Database/Query/Restriction/BackendGroupRestriction.php index 26e88807..5dbafdba 100644 --- a/Classes/Database/Query/Restriction/BackendGroupRestriction.php +++ b/Classes/Database/Query/Restriction/BackendGroupRestriction.php @@ -61,6 +61,6 @@ public function buildExpression(array $queriedTables, ExpressionBuilder $express } } - return $expressionBuilder->orX(...$constraints); + return $expressionBuilder->or(...$constraints); } } diff --git a/Classes/Domain/Model/BackendUserGroup.php b/Classes/Domain/Model/BackendUserGroup.php new file mode 100644 index 00000000..710a28a1 --- /dev/null +++ b/Classes/Domain/Model/BackendUserGroup.php @@ -0,0 +1,526 @@ + + */ + protected $subGroups; + + /** + * @var string + */ + protected $modules = ''; + + /** + * @var string + */ + protected $tablesListening = ''; + + /** + * @var string + */ + protected $tablesModify = ''; + + /** + * @var string + */ + protected $pageTypes = ''; + + /** + * @var string + */ + protected $allowedExcludeFields = ''; + + /** + * @var string + */ + protected $explicitlyAllowAndDeny = ''; + + /** + * @var string + */ + protected $allowedLanguages = ''; + + /** + * @var bool + */ + protected $workspacePermission = false; + + /** + * @var string + */ + protected $databaseMounts = ''; + + /** + * @var int + */ + protected $fileOperationPermissions = 0; + + /** + * @var string + */ + protected $tsConfig = ''; + + /** + * Constructs this backend usergroup + */ + public function __construct() + { + $this->subGroups = new ObjectStorage(); + } + + /** + * Setter for title + * + * @param string $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * Getter for title + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Setter for description + * + * @param string $description + */ + public function setDescription($description) + { + $this->description = $description; + } + + /** + * Getter for description + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Setter for the sub groups + * + * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $subGroups + */ + public function setSubGroups(ObjectStorage $subGroups) + { + $this->subGroups = $subGroups; + } + + /** + * Adds a sub group to this backend user group + * + * @param \Pixelant\PxaSocialFeed\Domain\Model\BackendUserGroup $beGroup + */ + public function addSubGroup(\Pixelant\PxaSocialFeed\Domain\Model\BackendUserGroup $beGroup) + { + $this->subGroups->attach($beGroup); + } + + /** + * Removes sub group from this backend user group + * + * @param \Pixelant\PxaSocialFeed\Domain\Model\BackendUserGroup $groupToDelete + */ + public function removeSubGroup(\Pixelant\PxaSocialFeed\Domain\Model\BackendUserGroup $groupToDelete) + { + $this->subGroups->detach($groupToDelete); + } + + /** + * Remove all sub groups from this backend user group + */ + public function removeAllSubGroups() + { + $subGroups = clone $this->subGroups; + $this->subGroups->removeAll($subGroups); + } + + /** + * Getter of sub groups + * + * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage + */ + public function getSubGroups() + { + return $this->subGroups; + } + + /** + * Setter for modules + * + * @param string $modules + */ + public function setModules($modules) + { + $this->modules = $modules; + } + + /** + * Getter for modules + * + * @return string + */ + public function getModules() + { + return $this->modules; + } + + /** + * Setter for tables listening + * + * @param string $tablesListening + */ + public function setTablesListening($tablesListening) + { + $this->tablesListening = $tablesListening; + } + + /** + * Getter for tables listening + * + * @return string + */ + public function getTablesListening() + { + return $this->tablesListening; + } + + /** + * Setter for tables modify + * + * @param string $tablesModify + */ + public function setTablesModify($tablesModify) + { + $this->tablesModify = $tablesModify; + } + + /** + * Getter for tables modify + * + * @return string + */ + public function getTablesModify() + { + return $this->tablesModify; + } + + /** + * Setter for page types + * + * @param string $pageTypes + */ + public function setPageTypes($pageTypes) + { + $this->pageTypes = $pageTypes; + } + + /** + * Getter for page types + * + * @return string + */ + public function getPageTypes() + { + return $this->pageTypes; + } + + /** + * Setter for allowed exclude fields + * + * @param string $allowedExcludeFields + */ + public function setAllowedExcludeFields($allowedExcludeFields) + { + $this->allowedExcludeFields = $allowedExcludeFields; + } + + /** + * Getter for allowed exclude fields + * + * @return string + */ + public function getAllowedExcludeFields() + { + return $this->allowedExcludeFields; + } + + /** + * Setter for explicitly allow and deny + * + * @param string $explicitlyAllowAndDeny + */ + public function setExplicitlyAllowAndDeny($explicitlyAllowAndDeny) + { + $this->explicitlyAllowAndDeny = $explicitlyAllowAndDeny; + } + + /** + * Getter for explicitly allow and deny + * + * @return string + */ + public function getExplicitlyAllowAndDeny() + { + return $this->explicitlyAllowAndDeny; + } + + /** + * Setter for allowed languages + * + * @param string $allowedLanguages + */ + public function setAllowedLanguages($allowedLanguages) + { + $this->allowedLanguages = $allowedLanguages; + } + + /** + * Getter for allowed languages + * + * @return string + */ + public function getAllowedLanguages() + { + return $this->allowedLanguages; + } + + /** + * Setter for workspace permission + * + * @param bool $workspacePermission + */ + public function setWorkspacePermissions($workspacePermission) + { + $this->workspacePermission = $workspacePermission; + } + + /** + * Getter for workspace permission + * + * @return bool + */ + public function getWorkspacePermission() + { + return $this->workspacePermission; + } + + /** + * Setter for database mounts + * + * @param string $databaseMounts + */ + public function setDatabaseMounts($databaseMounts) + { + $this->databaseMounts = $databaseMounts; + } + + /** + * Getter for database mounts + * + * @return string + */ + public function getDatabaseMounts() + { + return $this->databaseMounts; + } + + /** + * Getter for file operation permissions + * + * @param int $fileOperationPermissions + */ + public function setFileOperationPermissions($fileOperationPermissions) + { + $this->fileOperationPermissions = $fileOperationPermissions; + } + + /** + * Getter for file operation permissions + * + * @return int + */ + public function getFileOperationPermissions() + { + return $this->fileOperationPermissions; + } + + /** + * Check if file operations like upload, copy, move, delete, rename, new and + * edit files is allowed. + * + * @return bool + */ + public function isFileOperationAllowed() + { + return $this->isPermissionSet(self::FILE_OPPERATIONS); + } + + /** + * Set the the bit for file operations are allowed. + * + * @param bool $value + */ + public function setFileOperationAllowed($value) + { + $this->setPermission(self::FILE_OPPERATIONS, $value); + } + + /** + * Check if folder operations like move, delete, rename, and new are allowed. + * + * @return bool + */ + public function isDirectoryOperationAllowed() + { + return $this->isPermissionSet(self::DIRECTORY_OPPERATIONS); + } + + /** + * Set the the bit for directory operations are allowed. + * + * @param bool $value + */ + public function setDirectoryOperationAllowed($value) + { + $this->setPermission(self::DIRECTORY_OPPERATIONS, $value); + } + + /** + * Check if it is allowed to copy folders. + * + * @return bool + */ + public function isDirectoryCopyAllowed() + { + return $this->isPermissionSet(self::DIRECTORY_COPY); + } + + /** + * Set the the bit for copy directories. + * + * @param bool $value + */ + public function setDirectoryCopyAllowed($value) + { + $this->setPermission(self::DIRECTORY_COPY, $value); + } + + /** + * Check if it is allowed to remove folders recursively. + * + * @return bool + */ + public function isDirectoryRemoveRecursivelyAllowed() + { + return $this->isPermissionSet(self::DIRECTORY_REMOVE_RECURSIVELY); + } + + /** + * Set the the bit for remove directories recursively. + * + * @param bool $value + */ + public function setDirectoryRemoveRecursivelyAllowed($value) + { + $this->setPermission(self::DIRECTORY_REMOVE_RECURSIVELY, $value); + } + + /** + * Setter for ts config + * + * @param string $tsConfig + */ + public function setTsConfig($tsConfig) + { + $this->tsConfig = $tsConfig; + } + + /** + * Getter for ts config + * + * @return string + */ + public function getTsConfig() + { + return $this->tsConfig; + } + + /** + * Helper method for checking the permissions bitwise. + * + * @param int $permission + * @return bool + */ + protected function isPermissionSet($permission) + { + return ($this->fileOperationPermissions & $permission) == $permission; + } + + /** + * Helper method for setting permissions bitwise. + * + * @param int $permission + * @param bool $value + */ + protected function setPermission($permission, $value) + { + if ($value) { + $this->fileOperationPermissions |= $permission; + } else { + $this->fileOperationPermissions &= ~$permission; + } + } +} diff --git a/Classes/Domain/Model/Configuration.php b/Classes/Domain/Model/Configuration.php index 549e7315..1a6791df 100644 --- a/Classes/Domain/Model/Configuration.php +++ b/Classes/Domain/Model/Configuration.php @@ -28,9 +28,8 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Extbase\Domain\Model\BackendUserGroup; +use TYPO3\CMS\Extbase\Annotation\ORM\Lazy; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; @@ -97,14 +96,14 @@ class Configuration extends AbstractEntity /** * @var Token - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy */ + #[Lazy] protected $token; /** - * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy + * @var ObjectStorage */ + #[Lazy] protected $beGroup; /** @@ -283,8 +282,8 @@ public function setPerformCleanUp(bool $performCleanUp): void /** * @return bool */ - public function getPerformCleanUp(): bool - { - return $this->performCleanUp; - } + public function getPerformCleanUp(): bool + { + return $this->performCleanUp; + } } diff --git a/Classes/Domain/Model/Feed.php b/Classes/Domain/Model/Feed.php index 2e33c67e..870d7d14 100644 --- a/Classes/Domain/Model/Feed.php +++ b/Classes/Domain/Model/Feed.php @@ -28,7 +28,7 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - +use TYPO3\CMS\Extbase\Annotation\ORM\Lazy; use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; @@ -42,12 +42,12 @@ class Feed extends AbstractEntity /** * image media type */ - const IMAGE = 1; + public const IMAGE = 1; /** * video media type */ - const VIDEO = 2; + public const VIDEO = 2; /** * pid @@ -131,17 +131,17 @@ class Feed extends AbstractEntity /** * token * - * @var \Pixelant\PxaSocialFeed\Domain\Model\Configuration - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy + * @var Configuration */ + #[Lazy] protected $configuration; /** * Fal media items * * @var ObjectStorage<\Pixelant\PxaSocialFeed\Domain\Model\FileReference> - * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy */ + #[Lazy] protected $falMedia; /** diff --git a/Classes/Domain/Model/Token.php b/Classes/Domain/Model/Token.php index 1d7c6c91..3c6f3991 100644 --- a/Classes/Domain/Model/Token.php +++ b/Classes/Domain/Model/Token.php @@ -28,7 +28,6 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use League\OAuth2\Client\Provider\Exception\FacebookProviderException; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use League\OAuth2\Client\Token\AccessToken; @@ -44,37 +43,37 @@ */ class Token extends AbstractEntity { - use EmitSignalTrait; + // use EmitSignalTrait; /** * facebook user token */ - const FACEBOOK = 1; + public const FACEBOOK = 1; /** * instagram_oauth2 */ - const INSTAGRAM = 2; + public const INSTAGRAM = 2; /** * twitter token */ - const TWITTER = 3; + public const TWITTER = 3; /** * youtube token */ - const YOUTUBE = 4; + public const YOUTUBE = 4; /** * facebook page token */ - const FACEBOOK_PAGE = 5; + public const FACEBOOK_PAGE = 5; /** * twitter token v2 API */ - const TWITTER_V2 = 6; + public const TWITTER_V2 = 6; /** * Default PID @@ -84,7 +83,7 @@ class Token extends AbstractEntity protected $pid = 0; /** - * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\BackendUserGroup> + * @var ObjectStorage|null * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy */ protected $beGroup; @@ -145,7 +144,7 @@ class Token extends AbstractEntity protected string $fbSocialId = ''; /** - * @var Token|null + * @var Token */ protected $parentToken; @@ -310,9 +309,9 @@ public function setBearerToken(string $bearerToken): void } /** - * @return ObjectStorage + * @return ObjectStorage|null */ - public function getBeGroup(): ObjectStorage + public function getBeGroup(): ?ObjectStorage { return $this->beGroup; } @@ -320,7 +319,7 @@ public function getBeGroup(): ObjectStorage /** * @param ObjectStorage $beGroup */ - public function setBeGroup(ObjectStorage $beGroup): void + public function setBeGroup($beGroup): void { $this->beGroup = $beGroup; } @@ -448,11 +447,11 @@ public function getFacebookPagesIds(): array */ public function getParentToken(): ?Token { - if ($this->parentToken instanceof Token) { + if ( $this->parentToken instanceof Token ) + { return $this->parentToken; - } - - return null; + } + return NULL; } /** diff --git a/Classes/Domain/Repository/AbstractBackendRepository.php b/Classes/Domain/Repository/AbstractBackendRepository.php index 3f511d78..69e73552 100644 --- a/Classes/Domain/Repository/AbstractBackendRepository.php +++ b/Classes/Domain/Repository/AbstractBackendRepository.php @@ -26,11 +26,11 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use Pixelant\PxaSocialFeed\Database\Query\Restriction\BackendGroupRestriction; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\Repository; /** @@ -57,7 +57,7 @@ public function initializeObject() /** * Find all records with backend user group restriction * - * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return QueryResultInterface */ public function findAllBackendGroupRestriction() { diff --git a/Classes/Domain/Repository/FeedRepository.php b/Classes/Domain/Repository/FeedRepository.php index 577eb48a..73b80dc4 100644 --- a/Classes/Domain/Repository/FeedRepository.php +++ b/Classes/Domain/Repository/FeedRepository.php @@ -4,11 +4,14 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; +use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use TYPO3\CMS\Extbase\Persistence\QueryInterface; +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\Repository; /*************************************************************** @@ -58,10 +61,10 @@ public function initializeObject() // Don't respect storage $defaultQuerySettings->setRespectStoragePage(false); - if (TYPO3_MODE === 'BE' || TYPO3_MODE === 'CLI') { + if (ApplicationType::fromRequest($GLOBALS[ 'TYPO3_REQUEST' ])->isBackend() || Environment::isCli()) { // don't add fields from enable columns constraint $defaultQuerySettings->setIgnoreEnableFields(true); - $defaultQuerySettings->setEnableFieldsToBeIgnored(['disabled']); + $defaultQuerySettings->setEnableFieldsToBeIgnored([ 'disabled' ]); } $this->setDefaultQuerySettings($defaultQuerySettings); @@ -72,17 +75,17 @@ public function initializeObject() * * @param ObjectStorage $storage * @param Configuration $configuration - * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return QueryResultInterface */ public function findNotInStorage(ObjectStorage $storage, Configuration $configuration) { $query = $this->createQuery(); $query->matching( - $query->logicalAnd([ + $query->logicalAnd( $query->logicalNot($query->in('uid', $storage)), $query->equals('configuration', $configuration), - ]) + ) ); return $query->execute(); @@ -126,12 +129,12 @@ public function findOneByExternalIdentifier(string $externalIdentifier, int $pid { $query = $this->createQuery(); - $logicalAnd = [ - $query->equals('pid', $pid), - $query->equals('externalIdentifier', $externalIdentifier), - ]; - - $query->matching($query->logicalAnd($logicalAnd)); + $query->matching( + $query->logicalAnd( + $query->equals('pid', $pid), + $query->equals('externalIdentifier', $externalIdentifier), + ), + ); return $query->execute()->getFirst(); } diff --git a/Classes/Domain/Repository/TokenRepository.php b/Classes/Domain/Repository/TokenRepository.php index b03abb49..06deae77 100644 --- a/Classes/Domain/Repository/TokenRepository.php +++ b/Classes/Domain/Repository/TokenRepository.php @@ -26,12 +26,12 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use Pixelant\PxaSocialFeed\Domain\Model\Token; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult; use TYPO3\CMS\Extbase\Persistence\QueryInterface; +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; /** * The repository for Feeds @@ -51,18 +51,20 @@ class TokenRepository extends AbstractBackendRepository * @param Token $token * @param string $fbSocialId * - * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface + * @return QueryResultInterface */ public function findFacebookPageToken(Token $token, string $fbSocialId) { $query = $this->createQuery(); - $query->getQuerySettings()->setIgnoreEnableFields(true); - + $query->getQuerySettings ()->setIgnoreEnableFields ( TRUE ); + //TODO: handle Facebook Social ID and parent token + // $query->equals('parentToken', $token->getParentToken()), + // $query->equals('fbSocialId', $fbSocialId), $query->matching( - $query->logicalAnd([ - $query->equals('parentToken', $token->getParentToken()), - $query->equals('fbSocialId', $fbSocialId), - ]) + $query->logicalAnd( + $query->equals ( 'parentToken', 0 ), + $query->equals ( 'fbSocialId', '' ), + ) ); $query->setLimit(1); diff --git a/Classes/Domain/Validation/Validator/ConfigurationValidator.php b/Classes/Domain/Validation/Validator/ConfigurationValidator.php index 76c64f5b..e6560412 100644 --- a/Classes/Domain/Validation/Validator/ConfigurationValidator.php +++ b/Classes/Domain/Validation/Validator/ConfigurationValidator.php @@ -38,7 +38,7 @@ class ConfigurationValidator extends AbstractValidator * * @return bool */ - public function isValid($configuration) + public function isValid($configuration): void { // do trim $this->trimObjectProperties($configuration); @@ -62,10 +62,6 @@ public function isValid($configuration) $this->translateErrorMessage('validator.error.' . $errorCode, 'PxaSocialFeed'), $errorCode ); - - return false; } - - return true; } } diff --git a/Classes/Domain/Validation/Validator/TokenValidator.php b/Classes/Domain/Validation/Validator/TokenValidator.php index 4600df77..71842e62 100644 --- a/Classes/Domain/Validation/Validator/TokenValidator.php +++ b/Classes/Domain/Validation/Validator/TokenValidator.php @@ -36,10 +36,8 @@ class TokenValidator extends AbstractValidator * Validates tokens * * @param Token $token - * - * @return bool */ - protected function isValid($token) + protected function isValid($token): void { if (!in_array($token->getType(), Token::getAvailableTokensTypes())) { $this->addError( @@ -49,8 +47,6 @@ protected function isValid($token) ), 1562851281828 ); - - return false; } switch (true) { @@ -84,11 +80,7 @@ protected function isValid($token) ), 1221559976 ); - - return false; } } - - return true; } } diff --git a/Classes/Event/BeforeReturnTwitterQueryFieldsEvent.php b/Classes/Event/BeforeReturnTwitterQueryFieldsEvent.php new file mode 100644 index 00000000..f6c9e6ec --- /dev/null +++ b/Classes/Event/BeforeReturnTwitterQueryFieldsEvent.php @@ -0,0 +1,25 @@ +fields = $fields; + } + + public function getFields() + { + return $this->fields; + } + + public function setFields($fields): void + { + $this->fields = $fields; + } +} diff --git a/Classes/Event/BeforeUpdateFacebookFeedEvent.php b/Classes/Event/BeforeUpdateFacebookFeedEvent.php new file mode 100644 index 00000000..8116a2ad --- /dev/null +++ b/Classes/Event/BeforeUpdateFacebookFeedEvent.php @@ -0,0 +1,49 @@ +feedItem = $feedItem; + $this->rawData = $rawData; + $this->configuration = $configuration; + } + + public function getFeedItem() + { + return $this->feedItem; + } + + public function getRawData() + { + return $this->rawData; + } + + public function getConfiguration() + { + return $this->configuration; + } + + public function setFeedItem($feedItem): void + { + $this->feedItem = $feedItem; + } + + public function setRawData($rawData): void + { + $this->rawData = $rawData; + } + + public function setConfiguration($configuration): void + { + $this->configuration = $configuration; + } +} diff --git a/Classes/Event/BeforeUpdateInstagramFeedEvent.php b/Classes/Event/BeforeUpdateInstagramFeedEvent.php new file mode 100644 index 00000000..3900d6f4 --- /dev/null +++ b/Classes/Event/BeforeUpdateInstagramFeedEvent.php @@ -0,0 +1,49 @@ +feedItem = $feedItem; + $this->rawData = $rawData; + $this->configuration = $configuration; + } + + public function getFeedItem() + { + return $this->feedItem; + } + + public function getRawData() + { + return $this->rawData; + } + + public function getConfiguration() + { + return $this->configuration; + } + + public function setFeedItem($feedItem): void + { + $this->feedItem = $feedItem; + } + + public function setRawData($rawData): void + { + $this->rawData = $rawData; + } + + public function setConfiguration($configuration): void + { + $this->configuration = $configuration; + } +} diff --git a/Classes/Event/BeforeUpdateTwitterFeedEvent.php b/Classes/Event/BeforeUpdateTwitterFeedEvent.php new file mode 100644 index 00000000..475a155f --- /dev/null +++ b/Classes/Event/BeforeUpdateTwitterFeedEvent.php @@ -0,0 +1,49 @@ +feedItem = $feedItem; + $this->rawData = $rawData; + $this->configuration = $configuration; + } + + public function getFeedItem() + { + return $this->feedItem; + } + + public function getRawData() + { + return $this->rawData; + } + + public function getConfiguration() + { + return $this->configuration; + } + + public function setFeedItem($feedItem): void + { + $this->feedItem = $feedItem; + } + + public function setRawData($rawData): void + { + $this->rawData = $rawData; + } + + public function setConfiguration($configuration): void + { + $this->configuration = $configuration; + } +} diff --git a/Classes/Event/BeforeUpdateTwitterV2FeedEvent.php b/Classes/Event/BeforeUpdateTwitterV2FeedEvent.php new file mode 100644 index 00000000..45eeb085 --- /dev/null +++ b/Classes/Event/BeforeUpdateTwitterV2FeedEvent.php @@ -0,0 +1,59 @@ +feedItem = $feedItem; + $this->rawData = $rawData; + $this->configuration = $configuration; + $this->includes = $includes; + } + + public function getFeedItem() + { + return $this->feedItem; + } + + public function getRawData() + { + return $this->rawData; + } + + public function getConfiguration() + { + return $this->configuration; + } + public function getIncludes() + { + return $this->includes; + } + + public function setFeedItem($feedItem): void + { + $this->feedItem = $feedItem; + } + + public function setRawData($rawData): void + { + $this->rawData = $rawData; + } + + public function setConfiguration($configuration): void + { + $this->configuration = $configuration; + } + public function setIncludes($includes): void + { + $this->includes = $includes; + } +} diff --git a/Classes/Event/BeforeUpdateYoutubeFeedEvent.php b/Classes/Event/BeforeUpdateYoutubeFeedEvent.php new file mode 100644 index 00000000..8f804e16 --- /dev/null +++ b/Classes/Event/BeforeUpdateYoutubeFeedEvent.php @@ -0,0 +1,49 @@ +feedItem = $feedItem; + $this->rawData = $rawData; + $this->configuration = $configuration; + } + + public function getFeedItem() + { + return $this->feedItem; + } + + public function getRawData() + { + return $this->rawData; + } + + public function getConfiguration() + { + return $this->configuration; + } + + public function setFeedItem($feedItem): void + { + $this->feedItem = $feedItem; + } + + public function setRawData($rawData): void + { + $this->rawData = $rawData; + } + + public function setConfiguration($configuration): void + { + $this->configuration = $configuration; + } +} diff --git a/Classes/Event/ChangedFeedItemEvent.php b/Classes/Event/ChangedFeedItemEvent.php new file mode 100644 index 00000000..7ff60df0 --- /dev/null +++ b/Classes/Event/ChangedFeedItemEvent.php @@ -0,0 +1,24 @@ +feed = $feed; + } + public function getFeed() + { + return $this->feed; + } + + public function setFeed($feed): void + { + $this->feed = $feed; + } +} diff --git a/Classes/Event/FacebookEndPointEvent.php b/Classes/Event/FacebookEndPointEvent.php new file mode 100644 index 00000000..8a29c12f --- /dev/null +++ b/Classes/Event/FacebookEndPointEvent.php @@ -0,0 +1,33 @@ +endPoint = $endPoint; + } + + /** + * @return mixed + */ + public function getEndPoint() + { + return $this->endPoint; + } + + /** + * @param mixed $endPoint + * @return self + */ + public function setEndPoint($endPoint): self + { + $this->endPoint = $endPoint; + return $this; + } +} diff --git a/Classes/Event/FacebookEndPointRequestFieldsEvent.php b/Classes/Event/FacebookEndPointRequestFieldsEvent.php new file mode 100644 index 00000000..92c36c51 --- /dev/null +++ b/Classes/Event/FacebookEndPointRequestFieldsEvent.php @@ -0,0 +1,25 @@ +fields = $fields; + } + + public function getFields() + { + return $this->fields; + } + + public function setFields($fields): void + { + $this->fields = $fields; + } +} diff --git a/Classes/Event/RemovedFeedItemEvent.php b/Classes/Event/RemovedFeedItemEvent.php new file mode 100644 index 00000000..3e8d4f2b --- /dev/null +++ b/Classes/Event/RemovedFeedItemEvent.php @@ -0,0 +1,27 @@ +feed = $feed; + } + + public function getFeed(): Feed + { + return $this->feed; + } + + public function setFeed(Feed $feed): void + { + $this->feed = $feed; + } +} diff --git a/Classes/Event/YoutubeEndPointRequestFieldsEvent.php b/Classes/Event/YoutubeEndPointRequestFieldsEvent.php new file mode 100644 index 00000000..5682dfaf --- /dev/null +++ b/Classes/Event/YoutubeEndPointRequestFieldsEvent.php @@ -0,0 +1,25 @@ +fields = $fields; + } + + public function getFields() + { + return $this->fields; + } + + public function setFields($fields): void + { + $this->fields = $fields; + } +} diff --git a/Classes/Exception/BadResponseException.php b/Classes/Exception/BadResponseException.php index 25e4171e..4a4f496c 100644 --- a/Classes/Exception/BadResponseException.php +++ b/Classes/Exception/BadResponseException.php @@ -7,6 +7,4 @@ /** * Class BadResponseException */ -class BadResponseException extends \Exception -{ -} +class BadResponseException extends \Exception {} diff --git a/Classes/Exception/FailedExecutingImportException.php b/Classes/Exception/FailedExecutingImportException.php index ef38261e..3ed4b359 100644 --- a/Classes/Exception/FailedExecutingImportException.php +++ b/Classes/Exception/FailedExecutingImportException.php @@ -4,6 +4,4 @@ namespace Pixelant\PxaSocialFeed\Exception; -class FailedExecutingImportException extends \Exception -{ -} +class FailedExecutingImportException extends \Exception {} diff --git a/Classes/Exception/InvalidFeedSourceData.php b/Classes/Exception/InvalidFeedSourceData.php index 9a1cbe58..f1b1965a 100644 --- a/Classes/Exception/InvalidFeedSourceData.php +++ b/Classes/Exception/InvalidFeedSourceData.php @@ -7,6 +7,4 @@ /** * Class InvalidFeedSourceData */ -class InvalidFeedSourceData extends \Exception -{ -} +class InvalidFeedSourceData extends \Exception {} diff --git a/Classes/Exception/UnsupportedTokenType.php b/Classes/Exception/UnsupportedTokenType.php index 1a94802a..c008b5cc 100644 --- a/Classes/Exception/UnsupportedTokenType.php +++ b/Classes/Exception/UnsupportedTokenType.php @@ -7,6 +7,4 @@ /** * Class UnsupportedTokenType */ -class UnsupportedTokenType extends \Exception -{ -} +class UnsupportedTokenType extends \Exception {} diff --git a/Classes/Feed/Source/BaseFacebookSource.php b/Classes/Feed/Source/BaseFacebookSource.php index 2ecb4df2..5d400d1a 100644 --- a/Classes/Feed/Source/BaseFacebookSource.php +++ b/Classes/Feed/Source/BaseFacebookSource.php @@ -4,14 +4,18 @@ namespace Pixelant\PxaSocialFeed\Feed\Source; +use Pixelant\PxaSocialFeed\Event\FacebookEndPointEvent; +use Pixelant\PxaSocialFeed\Event\FacebookEndPointRequestFieldsEvent; use Pixelant\PxaSocialFeed\Exception\InvalidFeedSourceData; +use Psr\EventDispatcher\EventDispatcherInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class BaseFacebookSource */ abstract class BaseFacebookSource extends BaseSource { - const GRAPH_VERSION = 'v12.0'; + public const GRAPH_VERSION = 'v12.0'; /** * Generate facebook endpoint @@ -22,18 +26,17 @@ abstract class BaseFacebookSource extends BaseSource */ protected function generateEndPoint(string $id, string $endPointEntry): string { - $limit = $this->getConfiguration()->getMaxItems(); - - $fields = $this->getEndPointFields(); - - list($fields) = $this->emitSignal('facebookEndPointRequestFields', [$fields]); - + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); + $limit = $this->getConfiguration()->getMaxItems(); + $fields = $this->getEndPointFields(); + $event = $eventDispatcher->dispatch(new FacebookEndPointRequestFieldsEvent($fields)); + $fieldsArray = $event->getFields(); $url = $id . '/' . $endPointEntry; $queryParams = [ - 'fields' => implode(',', $fields), - 'limit' => $limit, - 'access_token' => $this->getConfiguration()->getToken()->getAccessToken(), + 'fields' => implode(',', $fieldsArray), + 'limit' => $limit, + 'access_token' => $this->getConfiguration()->getToken()->getAccessToken(), 'appsecret_proof' => hash_hmac( 'sha256', $this->getConfiguration()->getToken()->getAccessToken(), @@ -42,10 +45,14 @@ protected function generateEndPoint(string $id, string $endPointEntry): string ]; $endPoint = $this->addFieldsAsGetParametersToUrl($url, $queryParams); + $event = $eventDispatcher->dispatch(new FacebookEndPointEvent($endPoint)); + + // dd ( $event->getEndPoint () ); + // $endPointArray = $event->getEndPoint (); - list($endPoint) = $this->emitSignal('faceBookEndPoint', [$endPoint]); + // list( $endPoint ) = $endPointArray; - return $endPoint; + return $event->getEndPoint(); } /** diff --git a/Classes/Feed/Source/BaseSource.php b/Classes/Feed/Source/BaseSource.php index 6490be44..cfcf88f0 100644 --- a/Classes/Feed/Source/BaseSource.php +++ b/Classes/Feed/Source/BaseSource.php @@ -6,7 +6,6 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Exception\BadResponseException; -use Pixelant\PxaSocialFeed\SignalSlot\EmitSignalTrait; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Http\RequestFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -16,8 +15,6 @@ */ abstract class BaseSource implements FeedSourceInterface { - use EmitSignalTrait; - /** * @var Configuration */ diff --git a/Classes/Feed/Source/InstagramSource.php b/Classes/Feed/Source/InstagramSource.php index 310204ae..bf01899f 100644 --- a/Classes/Feed/Source/InstagramSource.php +++ b/Classes/Feed/Source/InstagramSource.php @@ -9,7 +9,7 @@ */ class InstagramSource extends BaseFacebookSource { - const BASE_INSTAGRAM_GRAPH_URL = 'https://graph.facebook.com/'; + public const BASE_INSTAGRAM_GRAPH_URL = 'https://graph.facebook.com/'; /** * Load feed source diff --git a/Classes/Feed/Source/TwitterSource.php b/Classes/Feed/Source/TwitterSource.php index e10af4fb..2fc398df 100644 --- a/Classes/Feed/Source/TwitterSource.php +++ b/Classes/Feed/Source/TwitterSource.php @@ -4,9 +4,12 @@ namespace Pixelant\PxaSocialFeed\Feed\Source; +use Pixelant\PxaSocialFeed\Event\BeforeReturnTwitterQueryFieldsEvent; use Pixelant\PxaSocialFeed\Exception\BadResponseException; use Pixelant\PxaSocialFeed\Exception\InvalidFeedSourceData; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ResponseInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class TwitterSource @@ -16,7 +19,7 @@ class TwitterSource extends BaseSource /** * Twitter api */ - const API_URL = 'https://api.twitter.com/1.1/'; + public const API_URL = 'https://api.twitter.com/1.1/'; /** * Load feed source @@ -99,16 +102,17 @@ protected function getFields(): array // Important to pass field value as string, because it's encoded with rawurlencode $fields = [ - 'screen_name' => $configuration->getSocialId(), - 'count' => (string)$configuration->getMaxItems(), - 'tweet_mode' => 'extended', + 'screen_name' => $configuration->getSocialId(), + 'count' => (string)$configuration->getMaxItems(), + 'tweet_mode' => 'extended', 'exclude_replies' => '1', - 'include_rts' => '1', + 'include_rts' => '1', ]; - list($fields) = $this->emitSignal('beforeReturnTwitterQueryFields', [$fields]); + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); + $event = $eventDispatcher->dispatch(new BeforeReturnTwitterQueryFieldsEvent($fields)); - return $fields; + return $event->getFields(); } /** diff --git a/Classes/Feed/Source/TwitterV2Source.php b/Classes/Feed/Source/TwitterV2Source.php index 8b5648e4..035dcc00 100644 --- a/Classes/Feed/Source/TwitterV2Source.php +++ b/Classes/Feed/Source/TwitterV2Source.php @@ -4,8 +4,10 @@ namespace Pixelant\PxaSocialFeed\Feed\Source; +use Pixelant\PxaSocialFeed\Event\BeforeReturnTwitterQueryFieldsEvent; use Pixelant\PxaSocialFeed\Exception\BadResponseException; use Pixelant\PxaSocialFeed\Exception\InvalidFeedSourceData; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ResponseInterface; /** @@ -16,7 +18,11 @@ class TwitterV2Source extends BaseSource /** * Twitter api */ - const API_URL = 'https://api.twitter.com/2/'; + public const API_URL = 'https://api.twitter.com/2/'; + + public function __construct( + private readonly EventDispatcherInterface $eventDispatcher, + ) {} /** * Load feed source @@ -117,7 +123,7 @@ protected function getFields(): array 'exclude' => 'replies', ]; - [$fields] = $this->emitSignal('beforeReturnTwitterQueryFields', [$fields]); + [ $fields ] = $this->eventDispatcher->dispatch(new BeforeReturnTwitterQueryFieldsEvent($fields)); return $fields; } diff --git a/Classes/Feed/Source/YoutubeSource.php b/Classes/Feed/Source/YoutubeSource.php index 78a7ad2b..1da3b467 100644 --- a/Classes/Feed/Source/YoutubeSource.php +++ b/Classes/Feed/Source/YoutubeSource.php @@ -5,16 +5,19 @@ namespace Pixelant\PxaSocialFeed\Feed\Source; use Pixelant\PxaSocialFeed\Domain\Model\Configuration; +use Pixelant\PxaSocialFeed\Event\YoutubeEndPointRequestFieldsEvent; use Pixelant\PxaSocialFeed\Exception\BadResponseException; use Pixelant\PxaSocialFeed\Exception\InvalidFeedSourceData; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Http\Message\ResponseInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class YoutubeSource */ class YoutubeSource extends BaseSource { - const API_URL = 'https://www.googleapis.com/youtube/v3/'; + public const API_URL = 'https://www.googleapis.com/youtube/v3/'; /** * Load feed source @@ -94,8 +97,10 @@ protected function getFields(Configuration $configuration): array 'key' => $configuration->getToken()->getApiKey(), ]; - list($fields) = $this->emitSignal('youtubeEndPointRequestFields', [$fields]); + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); + $event = $eventDispatcher->dispatch(new YoutubeEndPointRequestFieldsEvent($fields)); + $fieldsArray = $event->getFields(); - return $fields; + return $fieldsArray; } } diff --git a/Classes/Feed/Update/BaseUpdater.php b/Classes/Feed/Update/BaseUpdater.php index 3f78da1e..5d4f4116 100644 --- a/Classes/Feed/Update/BaseUpdater.php +++ b/Classes/Feed/Update/BaseUpdater.php @@ -4,9 +4,8 @@ namespace Pixelant\PxaSocialFeed\Feed\Update; -use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Exception as DriverException; -use Exception; +use Doctrine\DBAL\Exception; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use InvalidArgumentException; @@ -14,7 +13,9 @@ use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\FileReference; use Pixelant\PxaSocialFeed\Domain\Repository\FeedRepository; -use Pixelant\PxaSocialFeed\SignalSlot\EmitSignalTrait; +use Pixelant\PxaSocialFeed\Event\ChangedFeedItemEvent; +use Pixelant\PxaSocialFeed\Event\RemovedFeedItemEvent; +use Psr\EventDispatcher\EventDispatcherInterface; use RuntimeException; use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException; use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException; @@ -37,8 +38,6 @@ */ abstract class BaseUpdater implements FeedUpdaterInterface { - use EmitSignalTrait; - /** * @var FeedRepository */ @@ -81,14 +80,12 @@ public function persist(): void */ public function cleanUp(Configuration $configuration): void { + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); if (count($this->feeds) > 0) { /** @var Feed $feedToRemove */ foreach ($this->feedRepository->findNotInStorage($this->feeds, $configuration) as $feedToRemove) { - // todo: remove in next major version - /** @deprecated The call to changedFeedItem is deprecated and will be removed in version 4 */ - $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'changedFeedItem', [$feedToRemove]); - - $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'removedFeedItem', [$feedToRemove]); + $eventDispatcher->dispatch(new ChangedFeedItemEvent($feedToRemove)); + $eventDispatcher->dispatch(new RemovedFeedItemEvent($feedToRemove)); $this->feedRepository->remove($feedToRemove); } } @@ -102,9 +99,10 @@ public function cleanUp(Configuration $configuration): void */ protected function addOrUpdateFeedItem(Feed $feed): void { + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); // Check if $feed is new or modified and emit change event if ($feed->_isDirty() || $feed->_isNew()) { - $this->getSignalSlotDispatcher()->dispatch(__CLASS__, 'changedFeedItem', [$feed]); + $eventDispatcher->dispatch(new ChangedFeedItemEvent($feed)); } $this->feeds->attach($feed); @@ -182,7 +180,7 @@ protected function storeImg(string $url, Feed $feed): ?FileReference * @param Configuration $configuration * @return File|null * @throws InvalidArgumentException - * @throws DBALException + * @throws Exception * @throws DriverException * @throws InsufficientFolderAccessPermissionsException * @throws ExistingTargetFolderException diff --git a/Classes/Feed/Update/FacebookFeedUpdater.php b/Classes/Feed/Update/FacebookFeedUpdater.php index 39fc2a65..72897d01 100644 --- a/Classes/Feed/Update/FacebookFeedUpdater.php +++ b/Classes/Feed/Update/FacebookFeedUpdater.php @@ -7,14 +7,16 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\Token; +use Pixelant\PxaSocialFeed\Event\BeforeUpdateFacebookFeedEvent; use Pixelant\PxaSocialFeed\Feed\Source\FeedSourceInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Class FacebookFeedUpdater */ class FacebookFeedUpdater extends BaseUpdater -{ + { /** * Create/Update feed items * @@ -56,11 +58,10 @@ protected function updateFeedItem(Feed $feedItem, array $rawData): void $feedItem->setUpdateDate((new \DateTime())->setTimestamp($updated)); } - $feedItem->setLikes((int)($rawData['reactions']['summary']['total_count'])); - - // Call hook - $this->emitSignal('beforeUpdateFacebookFeed', [$feedItem, $rawData, $feedItem->getConfiguration()]); - + $feedItem->setLikes((int)($rawData[ 'reactions' ][ 'summary' ][ 'total_count' ])); + // dispatch event + $eventDispatcher = GeneralUtility::makeInstance ( EventDispatcherInterface::class); + $eventDispatcher->dispatch ( new BeforeUpdateFacebookFeedEvent ( $feedItem, $rawData, $feedItem->getConfiguration () ) ); $this->addOrUpdateFeedItem($feedItem); } diff --git a/Classes/Feed/Update/InstagramFeedUpdater.php b/Classes/Feed/Update/InstagramFeedUpdater.php index f94d25ae..e8a77939 100644 --- a/Classes/Feed/Update/InstagramFeedUpdater.php +++ b/Classes/Feed/Update/InstagramFeedUpdater.php @@ -7,7 +7,9 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\Token; +use Pixelant\PxaSocialFeed\Event\BeforeUpdateInstagramFeedEvent; use Pixelant\PxaSocialFeed\Feed\Source\FeedSourceInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -38,10 +40,9 @@ public function update(FeedSourceInterface $source): void // Add/update instagram feed data gotten from facebook $this->populateGraphInstagramFeed($feedItem, $rawData); - - // Call hook - $this->emitSignal('beforeUpdateInstagramFeed', [$feedItem, $rawData, $source->getConfiguration()]); - + // dispatch event + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); + $eventDispatcher->dispatch(new BeforeUpdateInstagramFeedEvent($feedItem, $rawData, $source->getConfiguration())); // Add/update $this->addOrUpdateFeedItem($feedItem); } diff --git a/Classes/Feed/Update/TwitterFeedUpdater.php b/Classes/Feed/Update/TwitterFeedUpdater.php index f54fa140..81b2cfb4 100644 --- a/Classes/Feed/Update/TwitterFeedUpdater.php +++ b/Classes/Feed/Update/TwitterFeedUpdater.php @@ -7,7 +7,9 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\Token; +use Pixelant\PxaSocialFeed\Event\BeforeUpdateTwitterFeedEvent; use Pixelant\PxaSocialFeed\Feed\Source\FeedSourceInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -15,6 +17,15 @@ */ class TwitterFeedUpdater extends BaseUpdater { + /** + * @var EventDispatcherInterface + */ + private EventDispatcherInterface $eventDispatcher; + + public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher): void + { + $this->eventDispatcher = $eventDispatcher; + } /** * Create/Update feed items * @@ -35,10 +46,7 @@ public function update(FeedSourceInterface $source): void } $this->updateFeedItem($feedItem, $rawData); - - // Call hook - $this->emitSignal('beforeUpdateTwitterFeed', [$feedItem, $rawData, $source->getConfiguration()]); - + $this->eventDispatcher->dispatch(new BeforeUpdateTwitterFeedEvent($feedItem, $rawData, $source->getConfiguration())); $this->addOrUpdateFeedItem($feedItem); } } diff --git a/Classes/Feed/Update/TwitterV2FeedUpdater.php b/Classes/Feed/Update/TwitterV2FeedUpdater.php index b2d45f52..220594d3 100644 --- a/Classes/Feed/Update/TwitterV2FeedUpdater.php +++ b/Classes/Feed/Update/TwitterV2FeedUpdater.php @@ -7,6 +7,7 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\Token; +use Pixelant\PxaSocialFeed\Event\BeforeUpdateTwitterV2FeedEvent; use Pixelant\PxaSocialFeed\Feed\Source\FeedSourceInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -38,10 +39,8 @@ public function update(FeedSourceInterface $source): void } $this->updateFeedItem($feedItem, $rawData, $includes); - - // Call hook - $this->emitSignal('beforeUpdateTwitterFeed', [$feedItem, $rawData, $source->getConfiguration(), $includes]); - + // dispatch event + $this->eventDispatcher->dispatch(new BeforeUpdateTwitterV2FeedEvent($feedItem, $rawData, $source->getConfiguration(), $includes)); $this->addOrUpdateFeedItem($feedItem); } } diff --git a/Classes/Feed/Update/YoutubeFeedUpdater.php b/Classes/Feed/Update/YoutubeFeedUpdater.php index 8e933344..8dc4f1e8 100644 --- a/Classes/Feed/Update/YoutubeFeedUpdater.php +++ b/Classes/Feed/Update/YoutubeFeedUpdater.php @@ -7,7 +7,9 @@ use Pixelant\PxaSocialFeed\Domain\Model\Configuration; use Pixelant\PxaSocialFeed\Domain\Model\Feed; use Pixelant\PxaSocialFeed\Domain\Model\Token; +use Pixelant\PxaSocialFeed\Event\BeforeUpdateYoutubeFeedEvent; use Pixelant\PxaSocialFeed\Feed\Source\FeedSourceInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -35,10 +37,9 @@ public function update(FeedSourceInterface $source): void } $this->updateFeedItem($feedItem, $rawData); - - // Call hook - $this->emitSignal('beforeUpdateYoutubeFeed', [$feedItem, $rawData, $source->getConfiguration()]); - + // dispatch event + $eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class); + $eventDispatcher->dispatch(new BeforeUpdateYoutubeFeedEvent($feedItem, $rawData, $source->getConfiguration())); $this->addOrUpdateFeedItem($feedItem); } } diff --git a/Classes/Hooks/PageLayoutView.php b/Classes/Hooks/PageLayoutView.php index 09821472..bb2954e3 100644 --- a/Classes/Hooks/PageLayoutView.php +++ b/Classes/Hooks/PageLayoutView.php @@ -26,9 +26,9 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Service\FlexFormService; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -70,8 +70,7 @@ public function getExtensionInformation($params): string $configurations = $queryBuilder ->select('name') - ->from('tx_pxasocialfeed_domain_model_configuration') - ->where( + ->from('tx_pxasocialfeed_domain_model_configuration')->where( $queryBuilder->expr()->in( 'uid', $queryBuilder->createNamedParameter( @@ -79,9 +78,8 @@ public function getExtensionInformation($params): string Connection::PARAM_INT_ARRAY ) ) - ) - ->execute() - ->fetchAll(\PDO::FETCH_COLUMN); + )->executeQuery() + ->fetchAllAssociative(); if (is_array($configurations)) { $configurations = implode(', ', $configurations); @@ -112,10 +110,10 @@ protected function getView(): StandaloneView } /** - * @return \TYPO3\CMS\Core\Service\FlexFormService + * @return FlexFormService */ protected function getFlexFormService() { - return GeneralUtility::makeInstance(\TYPO3\CMS\Core\Service\FlexFormService::class); + return GeneralUtility::makeInstance(FlexFormService::class); } } diff --git a/Classes/Task/AdditionalFieldProviderTrait.php b/Classes/Task/AdditionalFieldProviderTrait.php index eed16c69..956bcb8e 100644 --- a/Classes/Task/AdditionalFieldProviderTrait.php +++ b/Classes/Task/AdditionalFieldProviderTrait.php @@ -4,9 +4,10 @@ namespace Pixelant\PxaSocialFeed\Task; -use TYPO3\CMS\Core\Messaging\AbstractMessage; +use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Messaging\FlashMessageService; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; @@ -30,29 +31,30 @@ protected function getAction(SchedulerModuleController $schedulerModuleControlle { return method_exists($schedulerModuleController, 'getCurrentAction') ? (string)$schedulerModuleController->getCurrentAction() - : $schedulerModuleController->CMD; + : (string)$schedulerModuleController->getCurrentAction(); } /** - * Creates a Message object and adds it to the FlashMessageQueue. + * Add a flash message * - * @param string $messageBody The message - * @param int $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\FlashMessage constants - * @throws \InvalidArgumentException if the message body is no string + * @param string $message the flash message content + * @param value-of|ContextualFeedbackSeverity $severity the flash message severity + * + * @todo: Change $severity to allow ContextualFeedbackSeverity only in v13 */ - protected function addMessage(string $messageBody, int $severity = AbstractMessage::OK): void + protected function addMessage(string $message, int|ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::OK): void { - if (!is_string($messageBody)) { + if (!is_string($message)) { throw new \InvalidArgumentException( - 'The message body must be of type string, "' . gettype($messageBody) . '" given.', + 'The message body must be of type string, "' . gettype($message) . '" given.', 1548921638461 ); } /* @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Messaging\FlashMessage::class, - $messageBody, + FlashMessage::class, + $message, '', $severity, true diff --git a/Classes/Task/ImportTaskAdditionalFieldProvider.php b/Classes/Task/ImportTaskAdditionalFieldProvider.php index 33e6a004..8a76826c 100644 --- a/Classes/Task/ImportTaskAdditionalFieldProvider.php +++ b/Classes/Task/ImportTaskAdditionalFieldProvider.php @@ -5,9 +5,9 @@ namespace Pixelant\PxaSocialFeed\Task; use Pixelant\PxaSocialFeed\Utility\SchedulerUtility; -use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Scheduler\AdditionalFieldProviderInterface; +use TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider; use TYPO3\CMS\Scheduler\Controller\SchedulerModuleController; use TYPO3\CMS\Scheduler\Task\AbstractTask; @@ -35,10 +35,9 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -class ImportTaskAdditionalFieldProvider implements AdditionalFieldProviderInterface +class ImportTaskAdditionalFieldProvider extends AbstractAdditionalFieldProvider { use AdditionalFieldProviderTrait; - /** * @param array $taskInfo * @param ImportTask $task @@ -97,7 +96,6 @@ public function getAdditionalFields( return $additionalFields; } - /** * @param array $submittedData * @param SchedulerModuleController $parentObject @@ -113,18 +111,17 @@ public function validateAdditionalFields( if (!isset($submittedData['pxasocialfeed_run_all_configs']) && !isset($submittedData['pxasocialfeed_configs']) ) { - $this->addMessage('Wrong configurations select', FlashMessage::ERROR); + $this->addMessage('Wrong configurations select', AbstractMessage::ERROR); } elseif (!$this->isValidEmail($submittedData['pxasocialfeed_sender_email']) || !$this->isValidEmail($submittedData['pxasocialfeed_receiver_email']) ) { - $this->addMessage('Please provide a valid email address.', FlashMessage::ERROR); + $this->addMessage('Please provide a valid email address.', AbstractMessage::ERROR); } else { $valid = true; } return $valid; } - /** * @param array $submittedData * @param ImportTask $task @@ -136,7 +133,6 @@ public function saveAdditionalFields(array $submittedData, AbstractTask $task) $task->setSenderEmail($submittedData['pxasocialfeed_sender_email']); $task->setRunAllConfigurations((bool)($submittedData['pxasocialfeed_run_all_configs'] ?? false)); } - /** * Input field code * @@ -153,7 +149,6 @@ protected function getInputField(string $fieldName, string $value): string htmlspecialchars($value) ); } - /** * Validate email * diff --git a/Classes/Utility/ConfigurationUtility.php b/Classes/Utility/ConfigurationUtility.php index d838a1ec..c9baf50a 100644 --- a/Classes/Utility/ConfigurationUtility.php +++ b/Classes/Utility/ConfigurationUtility.php @@ -4,6 +4,8 @@ namespace Pixelant\PxaSocialFeed\Utility; +use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; +use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -16,8 +18,8 @@ class ConfigurationUtility * Get extension configuration * * @return array - * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException - * @throws \TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException + * @throws ExtensionConfigurationExtensionNotConfiguredException + * @throws ExtensionConfigurationPathDoesNotExistException */ public static function getExtensionConfiguration(): array { diff --git a/Classes/Utility/LoggerUtility.php b/Classes/Utility/LoggerUtility.php index 51247713..d5cf4469 100644 --- a/Classes/Utility/LoggerUtility.php +++ b/Classes/Utility/LoggerUtility.php @@ -14,8 +14,8 @@ class LoggerUtility /** * Message type */ - const INFO = 0; - const ERROR = 1; + public const INFO = 0; + public const ERROR = 1; /** * Log error diff --git a/Classes/Utility/SchedulerUtility.php b/Classes/Utility/SchedulerUtility.php index e7b4f7c6..81437e0d 100644 --- a/Classes/Utility/SchedulerUtility.php +++ b/Classes/Utility/SchedulerUtility.php @@ -87,8 +87,7 @@ public static function getSelectedConfigurationsInfo(array $configurations, bool $statement = $queryBuilder ->select('uid', 'name') - ->from('tx_pxasocialfeed_domain_model_configuration') - ->where( + ->from('tx_pxasocialfeed_domain_model_configuration')->where( $queryBuilder->expr()->in( 'uid', $queryBuilder->createNamedParameter( @@ -96,12 +95,11 @@ public static function getSelectedConfigurationsInfo(array $configurations, bool Connection::PARAM_INT_ARRAY ) ) - ) - ->execute(); + )->executeQuery(); $info = 'Feeds: '; - while ($config = $statement->fetch()) { + while ($config = $statement->fetchAssociative()) { $info .= $config['name'] . ' [UID: ' . $config['uid'] . ']; '; } diff --git a/Classes/ViewHelpers/FacebookLoginUrlViewHelper.php b/Classes/ViewHelpers/FacebookLoginUrlViewHelper.php index aabd5c77..213c367f 100644 --- a/Classes/ViewHelpers/FacebookLoginUrlViewHelper.php +++ b/Classes/ViewHelpers/FacebookLoginUrlViewHelper.php @@ -103,7 +103,7 @@ public static function renderStatic( $variableProvider->add($redirectUrlAs, $redirectUrl); - if (strpos($url, 'redirect_uri=&') !== false) { + if (str_contains($url, 'redirect_uri=&')) { $urlStructure = explode('redirect_uri=&', $url); $url = sprintf( '%sredirect_uri=%s&%s', diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php new file mode 100644 index 00000000..2e9f49a9 --- /dev/null +++ b/Configuration/Backend/Modules.php @@ -0,0 +1,43 @@ + [ + 'parent' => 'tools', + 'position' => [ 'after' => 'extensions' ], + 'access' => 'user,group', + 'workspaces' => '*', + 'path' => '/module/tools/PxaSocialFeedPxasocialfeed', + 'iconIdentifier' => 'ext-pxasocialfeed-wizard-icon', + 'labels' => 'LLL:EXT:pxa_social_feed/Resources/Private/Language/locallang_be.xlf', + 'extensionName' => 'PxaSocialFeed', + 'controllerActions' => [ + AdministrationController::class => [ + 'index', + 'editToken', + 'updateToken', + 'resetAccess', + 'deleteToken', + 'editConfiguration', + 'updateConfiguration', + 'deleteConfiguration', + 'runConfiguration', + ], + ], + 'routes' => [ + '_default' => [ + 'target' => AdministrationController::class . '::index', + ], + 'editConfiguration' => [ + 'path' => '/Administration/editConfiguration', + 'target' => AdministrationController::class . '::editConfiguration', + ], + 'editToken' => [ + 'path' => '/Administration/editToken', + 'target' => AdministrationController::class . '::editToken', + ], + ], + ], +]; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index ec122d5b..2c576c6a 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -6,4 +6,7 @@ \Pixelant\PxaSocialFeed\Domain\Model\FileReference::class => [ 'tableName' => 'sys_file_reference', ], + \Pixelant\PxaSocialFeed\Domain\Model\BackendUserGroup::class => [ + 'tableName' => 'be_groups', + ], ]; diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 00000000..3b0eba25 --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,32 @@ + [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/feed.svg', + ], + 'ext-pxasocialfeed-model-icon' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/feed.svg', + ], + 'ext-pxasocialfeed-model-icon-facebook' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/facebook.svg', + ], + 'ext-pxasocialfeed-model-icon-instagram' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/instagram.svg', + ], + 'ext-pxasocialfeed-model-icon-twitter' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/twitter.svg', + ], + 'ext-pxasocialfeed-model-icon-youtube' => [ + 'provider' => SvgIconProvider::class, + 'source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/youtube.svg', + ], +]; diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 00000000..ef525ad2 --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,8 @@ + [ 'backend' ], + 'imports' => [ + '@pixelant/pxa-social-feed/' => 'EXT:pxa_social_feed/Resources/Public/JavaScript/Backend/', + ], +]; diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 6bbcde3f..ca66c4c1 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,4 +1,3 @@ -# Configuration/Services.yaml services: _defaults: autowire: true @@ -9,4 +8,5 @@ services: resource: '../Classes/*' exclude: - '../Classes/Domain/Model/*' - - '../Classes/Controller/AdministrationController.php' + Pixelant\PxaSocialFeed\Controller\AdministrationController: + tags: ['backend.controller'] diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index e3c525b1..e36bf3ab 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,6 +1,6 @@ 'name', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'default_sortby' => 'crdate DESC', 'delete' => 'deleted', @@ -27,9 +26,6 @@ 'rootLevel' => 1, ], - 'interface' => [ - 'showRecordFieldList' => 'hidden, name, social_id, end_point_entry, token, max_items, storage, be_group', - ], 'types' => [ '1' => ['showitem' => '--palette--;;1, name, social_id, end_point_entry, max_items, storage' . $accessTab], ], @@ -50,7 +46,8 @@ 'config' => [ 'type' => 'input', 'size' => 30, - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'image_size' => [ @@ -59,7 +56,8 @@ 'config' => [ 'type' => 'input', 'size' => 30, - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'social_id' => [ @@ -68,7 +66,8 @@ 'config' => [ 'type' => 'input', 'size' => 30, - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'end_point_entry' => [ @@ -101,7 +100,8 @@ 'label' => $ll . '.storage', 'config' => [ 'type' => 'input', - 'eval' => 'int,required', + 'eval' => 'int', + 'required' => true, ], ], 'token' => [ @@ -126,9 +126,11 @@ 'maxitems' => 20, 'foreign_table' => 'be_groups', 'foreign_table_where' => 'ORDER BY be_groups.title', - 'enableMultiSelectFilterTextfield' => true, ], ], ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ]; })(); diff --git a/Configuration/TCA/tx_pxasocialfeed_domain_model_feed.php b/Configuration/TCA/tx_pxasocialfeed_domain_model_feed.php index 37f6c9cf..4382d926 100644 --- a/Configuration/TCA/tx_pxasocialfeed_domain_model_feed.php +++ b/Configuration/TCA/tx_pxasocialfeed_domain_model_feed.php @@ -1,6 +1,6 @@ 'message,post_url', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'default_sortby' => 'crdate DESC', 'type' => 'type', @@ -31,10 +30,6 @@ ], 'searchFields' => 'post_url,message,image,title,config,', ], - // @codingStandardsIgnoreStart - 'interface' => [ - 'showRecordFieldList' => 'hidden, post_date, post_url, message, media_type, likes, title, configuration, update_date, external_identifier, type', - ], 'types' => [ '0' => ['showitem' => '--palette--;;core, --palette--;;main,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.media, fal_media,fal_related_files'], '1' => ['showitem' => '--palette--;;core, --palette--;;main,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.media, fal_media,fal_related_files'], @@ -62,10 +57,10 @@ 'type' => 'select', 'renderType' => 'selectSingle', 'items' => [ - [$ll . 'tx_pxasocialfeed_domain_model_feeds.type.1', 1, 'ext-pxasocialfeed-model-icon-facebook'], - [$ll . 'tx_pxasocialfeed_domain_model_feeds.type.2', 2, 'ext-pxasocialfeed-model-icon-instagram'], - [$ll . 'tx_pxasocialfeed_domain_model_feeds.type.3', 3, 'ext-pxasocialfeed-model-icon-twitter'], - [$ll . 'tx_pxasocialfeed_domain_model_feeds.type.4', 4, 'ext-pxasocialfeed-model-icon-youtube'], + ['label' => $ll . 'tx_pxasocialfeed_domain_model_feeds.type.1', 'value' => 1, 'icon' => 'ext-pxasocialfeed-model-icon-facebook'], + ['label' => $ll . 'tx_pxasocialfeed_domain_model_feeds.type.2', 'value' => 2, 'icon' => 'ext-pxasocialfeed-model-icon-instagram'], + ['label' => $ll . 'tx_pxasocialfeed_domain_model_feeds.type.3', 'value' => 3, 'icon' => 'ext-pxasocialfeed-model-icon-twitter'], + ['label' => $ll . 'tx_pxasocialfeed_domain_model_feeds.type.4', 'value' => 4, 'icon' => 'ext-pxasocialfeed-model-icon-youtube'], ], 'fieldWizard' => [ 'selectIcons' => [ @@ -128,28 +123,27 @@ 'exclude' => true, 'label' => $ll . 'tx_pxasocialfeed_domain_model_feeds.fal_media', 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( - 'fal_media', - [ - 'appearance' => [ - 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference', - ], - 'foreign_match_fields' => [ - 'fieldname' => 'fal_media', - 'tablenames' => 'tx_pxasocialfeed_domain_model_feed', - 'table_local' => 'sys_file', - ], - 'overrideChildTca' => [ - 'types' => [ - \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ - 'showitem' => ' - --palette--;LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, + 'fal_media', + [ + 'appearance' => [ + 'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference', + ], + 'foreign_match_fields' => [ + 'fieldname' => 'fal_media', + 'tablenames' => 'tx_pxasocialfeed_domain_model_feed', + ], + 'overrideChildTca' => [ + 'types' => [ + \TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ + 'showitem' => ' + --palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;filePalette ', + ], ], ], ], - ], - 'jpg,jpeg,png,gif,svg' + 'jpg,jpeg,png,gif,svg' ), ], 'likes' => [ @@ -216,5 +210,8 @@ ], ], ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ]; })(); diff --git a/Configuration/TCA/tx_pxasocialfeed_domain_model_token.php b/Configuration/TCA/tx_pxasocialfeed_domain_model_token.php index 1d9b5850..4a51ba14 100644 --- a/Configuration/TCA/tx_pxasocialfeed_domain_model_token.php +++ b/Configuration/TCA/tx_pxasocialfeed_domain_model_token.php @@ -1,6 +1,6 @@ 'uid', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'default_sortby' => 'crdate DESC', 'delete' => 'deleted', @@ -29,9 +28,6 @@ 'type' => 'type', 'rootLevel' => 1, ], - 'interface' => [ - 'showRecordFieldList' => 'hidden, name, type, app_id, app_secret, be_group', - ], 'types' => [ \Pixelant\PxaSocialFeed\Domain\Model\Token::FACEBOOK => ['showitem' => 'name, type, --palette--;;paletteGraphApi' . $accessTab], \Pixelant\PxaSocialFeed\Domain\Model\Token::INSTAGRAM => ['showitem' => 'name, type, --palette--;;paletteGraphApi' . $accessTab], @@ -80,11 +76,11 @@ 'type' => 'select', 'renderType' => 'selectSingle', 'items' => [ - [$ll . '.type.type.1', \Pixelant\PxaSocialFeed\Domain\Model\Token::FACEBOOK], - [$ll . '.type.type.2', \Pixelant\PxaSocialFeed\Domain\Model\Token::INSTAGRAM], - [$ll . '.type.type.3', \Pixelant\PxaSocialFeed\Domain\Model\Token::TWITTER], - [$ll . '.type.type.6', \Pixelant\PxaSocialFeed\Domain\Model\Token::TWITTER_V2], - [$ll . '.type.type.4', \Pixelant\PxaSocialFeed\Domain\Model\Token::YOUTUBE], + ['label' => $ll . '.type.type.1', 'value' => \Pixelant\PxaSocialFeed\Domain\Model\Token::FACEBOOK], + ['label' => $ll . '.type.type.2', 'value' => \Pixelant\PxaSocialFeed\Domain\Model\Token::INSTAGRAM], + ['label' => $ll . '.type.type.3', 'value' => \Pixelant\PxaSocialFeed\Domain\Model\Token::TWITTER], + ['label' => $ll . '.type.type.6', 'value' => \Pixelant\PxaSocialFeed\Domain\Model\Token::TWITTER_V2], + ['label' => $ll . '.type.type.4', 'value' => \Pixelant\PxaSocialFeed\Domain\Model\Token::YOUTUBE], ], ], ], @@ -105,7 +101,7 @@ 'renderType' => 'selectSingle', 'default' => 0, 'items' => [ - ['', 0], + ['label' => '', 'value' => 0], ], 'foreign_table' => 'tx_pxasocialfeed_domain_model_token', 'foreign_table_where' => 'AND {#tx_pxasocialfeed_domain_model_token}.{#pid}=###CURRENT_PID### AND {#tx_pxasocialfeed_domain_model_token}.{#sys_language_uid} IN (-1,0)', @@ -124,7 +120,8 @@ 'label' => $ll . '.app_id', 'config' => [ 'type' => 'input', - 'eval' => 'required,trim', + 'eval' => 'trim', + 'required' => true, ], ], 'app_secret' => [ @@ -132,7 +129,8 @@ 'label' => $ll . '.app_secret', 'config' => [ 'type' => 'input', - 'eval' => 'required,trim', + 'eval' => 'trim', + 'required' => true, ], ], 'access_token' => [ @@ -148,7 +146,8 @@ 'label' => $ll . '.api_key', 'config' => [ 'type' => 'input', - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'api_secret_key' => [ @@ -156,7 +155,8 @@ 'label' => $ll . '.api_secret_key', 'config' => [ 'type' => 'input', - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'access_token_secret' => [ @@ -164,7 +164,8 @@ 'label' => $ll . '.access_token_secret', 'config' => [ 'type' => 'input', - 'eval' => 'trim,required', + 'eval' => 'trim', + 'required' => true, ], ], 'bearer_token' => [ @@ -172,8 +173,9 @@ 'label' => $ll . '.bearer_token', 'config' => [ 'type' => 'input', - 'eval' => 'trim,required' - ] + 'eval' => 'trim', + 'required' => true, + ], ], 'be_group' => [ 'exclude' => true, @@ -186,9 +188,11 @@ 'maxitems' => 20, 'foreign_table' => 'be_groups', 'foreign_table_where' => 'ORDER BY be_groups.title', - 'enableMultiSelectFilterTextfield' => true, ], ], ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ]; })(); diff --git a/Resources/Private/Partials/Backend/ListConfigurations.html b/Resources/Private/Partials/Backend/ListConfigurations.html index 5b6a5a25..d8b61896 100644 --- a/Resources/Private/Partials/Backend/ListConfigurations.html +++ b/Resources/Private/Partials/Backend/ListConfigurations.html @@ -33,7 +33,7 @@ - + @@ -45,10 +45,10 @@ - + - + diff --git a/Resources/Private/Partials/Backend/ListTokens.html b/Resources/Private/Partials/Backend/ListTokens.html index 28e78914..5c766a9d 100644 --- a/Resources/Private/Partials/Backend/ListTokens.html +++ b/Resources/Private/Partials/Backend/ListTokens.html @@ -20,11 +20,11 @@
- + - +
diff --git a/Resources/Private/Partials/Backend/TokenInfo/FacebookInstagram.html b/Resources/Private/Partials/Backend/TokenInfo/FacebookInstagram.html index 4dff0ac5..d83e09c3 100644 --- a/Resources/Private/Partials/Backend/TokenInfo/FacebookInstagram.html +++ b/Resources/Private/Partials/Backend/TokenInfo/FacebookInstagram.html @@ -13,10 +13,12 @@

- +

diff --git a/Resources/Private/Templates/Administration/EditToken.html b/Resources/Private/Templates/Administration/EditToken.html index 43f04464..7e15d774 100644 --- a/Resources/Private/Templates/Administration/EditToken.html +++ b/Resources/Private/Templates/Administration/EditToken.html @@ -13,7 +13,7 @@

- + @@ -52,4 +52,4 @@

- \ No newline at end of file + diff --git a/Resources/Public/Icons/Extension.gif b/Resources/Public/Icons/Extension.gif new file mode 100644 index 0000000000000000000000000000000000000000..a555b3ecefacbe652b658e7898a8cd3faf37ccce GIT binary patch literal 831882 zcmeI5`L|s~wePv(z2DyZ>HPt3yzw-&0hLZb8U-$>AQwatR21(O6j4#}!j-F6Dr>XU||Nm_NFZrk3|9?8||D5*U^oD)^fBlcsTK?;4u9?$L%l*?+ zbM^J#ecT-=00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS z00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H z24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H24DaN zU;qYS00v+H24DaNU;qYS00v+H24DaNU;qYS00v+H20~`wf&mHh{jo`N|Fo2Ocvi~v zo}V^D-btHhm!!?e#c4C}?X-DpZo1{YUrkAwo1RUYbNj+f$jor<@DBqp;2Q&%Jee@R zvwm>Wii}yYBWn(wY&Mm)Jx80(qRrVBKl<|*ljgi9;KesyxE`2>0T}R=fiFJRWbPQB zG~<_L%%=U7`@&LuXeMjSO6zlnElitlKAkYW$~4Z`HEnIitlgCj_J7|u(#~=B^ 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Public/Icons/ext_icon.svg b/Resources/Public/Icons/ext_icon.svg new file mode 100644 index 00000000..554d6822 --- /dev/null +++ b/Resources/Public/Icons/ext_icon.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Public/JavaScript/Backend/SocialFeedModule.js b/Resources/Public/JavaScript/Backend/SocialFeedModule.js index 7ad5dc6c..5ba7c6cb 100644 --- a/Resources/Public/JavaScript/Backend/SocialFeedModule.js +++ b/Resources/Public/JavaScript/Backend/SocialFeedModule.js @@ -8,277 +8,276 @@ define([ 'clipboard', ], function ($, bootstrap, Modal, Severity, Notification, MessageUtility, clipboard) { return (function ($, bootstrap, Modal, Severity, Notification, MessageUtility, clipboard) { - /** - * @private - * - * Hold the instance (Singleton Pattern) - */ - var _socialFeedModuleInstance = null; - - /** - * Main module JavaScript - * - * @return {{init: init}} - * @constructor - */ - function SocialFeedModule(settings) { - - /** - * If was initialized - * - * @type {boolean} - * @private - */ - var _isRunning = false; - - /** - * HTML Identifiers - * @type {{}} - * @private - */ - var _domElementsSelectors = { - confirmationButton: '.delete-action,.confirmation-action', - selectSocialType: '#select-type', - socialTypeUrlKeep: '#type-url-', - winStorageBrowser: '[data-identifier="browse-feeds-storage"]', - feedsStorageInput: '[data-identifier="feeds-storage-input"]', - feedsStorageTitle: '[data-identifier="feed-storage-title"]', - copyRedirectUriButton: '.copy-redirect-uri-button', - facebookLoginButton: '.facebook-login-link' - }; - - /** - * run if not running yet - * - * @public - */ - function run() { - if (_isRunning === false) { - _bootstrap(); - } - - _isRunning = true; - } - - /** - * Init - * @private - */ - function _bootstrap() { - _deleteConfirmation(); - _facebookLoginWindow(); - _changeSocialType(); - _winStorageBrowser(); - _getRedirectUriButtonClick(); - _initToolTip(); - _activateTabs(); - } - - /** - * Activate the tabs for the backend module - * - * @private - */ - function _activateTabs() { - let triggerTabList = [].slice.call(document.querySelectorAll('#tabs a')) - triggerTabList.forEach(function (triggerEl) { - let tabTrigger = new bootstrap.Tab(triggerEl) - - triggerEl.addEventListener('click', function (event) { - event.preventDefault() - tabTrigger.show() - }) - }); - } - - /** - * If user try to delete something - * - * @private - */ - function _deleteConfirmation() { - $(_getDomElementIdentifier('confirmationButton')).on('click', function (e) { - e.preventDefault(); - - var $this = $(this); - var title = $this.data('confirmation-title') || 'Delete'; - var message = $this.data('confirmation-message') || 'Are you sure you want to delete this record ?'; - - var url = $this.attr('href'), - modal = Modal.confirm(title, message, Severity.warning); - - modal.on('confirm.button.cancel', function () { - Modal.dismiss(modal); - }); - - modal.on('confirm.button.ok', function () { - Modal.dismiss(modal); - window.location.href = url; - }); - }) - } - - /** - * Show window with facebook login - * - * @private - */ - function _facebookLoginWindow() { - $(_getDomElementIdentifier('facebookLoginButton')).on('click', function (e) { - e.preventDefault(); - - var $this = $(this); - var w = 800; - var h = 800; - - var y = window.top.outerHeight / 2 + window.top.screenY - (h / 2); - var x = window.top.outerWidth / 2 + window.top.screenX - (w / 2); - - window.open($this.attr('href'), 'Facebook login', 'height=' + h + ',width=' + w + 'top=' + y + ', left=' + x); - }); - } - - /** - * Switch to different social type - * - * @private - */ - function _changeSocialType() { - $(_getDomElementIdentifier('selectSocialType')).on('change', function () { - var selectSocialType = $(this).find(':selected').val(); - - window.location.href = $(_getDomElementIdentifier('socialTypeUrlKeep') + selectSocialType).val(); - }); - } - - /** - * Copy redirect uri to clipboard - * @private - */ - function _getRedirectUriButtonClick() { - new clipboard(_getDomElementIdentifier('copyRedirectUriButton')); - } - - /** - * Load browser pages window - * - * @private - */ - function _winStorageBrowser() { - window.addEventListener('message', function (e) { - if (!MessageUtility.MessageUtility.verifyOrigin(e.origin)) { - throw 'Denied message sent by ' + e.origin; - } - - if (typeof e.data.fieldName === 'undefined') { - throw 'fieldName not defined in message'; - } - - if (typeof e.data.value === 'undefined') { - throw 'value not defined in message'; - } - - const fieldElement = _getInsertTarget(e.data.fieldName); - if (fieldElement) { - fieldElement.value = e.data.value; - } - - const storageTitleElement = document.querySelector(_getDomElementIdentifier('feedsStorageTitle')); - if (storageTitleElement) { - storageTitleElement.innerHTML = e.data.label; - } - }); - - $(_getDomElementIdentifier('winStorageBrowser')).on('click', function () { - var insertTarget = $(_getDomElementIdentifier('feedsStorageInput')), - randomIdentifier = Math.floor(Math.random() * 100000 + 1); - - insertTarget.attr('data-insert-target', randomIdentifier); - _openTypo3WinBrowser('db', randomIdentifier + '|||pages'); - }); - } - - /** - * @private - * - * opens a popup window with the element browser - * - * @param mode - * @param params - */ - function _openTypo3WinBrowser(mode, params) { - const url = _getSetting('browserUrl') + '&mode=' + mode + '&bparams=' + params; - Modal.advanced({ - type: Modal.types.iframe, - content: url, - size: Modal.sizes.large, - }); - } - - /** - * Get selector - * @param elementIdentifier - * @return {*|undefined} - * @private - */ - function _getDomElementIdentifier(elementIdentifier) { - return _domElementsSelectors[elementIdentifier] || undefined; - } - - /** - * Get insert target - * @param reference - * @return {HTMLElement|null} - * @private - */ - function _getInsertTarget(reference) { - return document.querySelector('[data-insert-target="' + reference + '"]'); - } - - /** - * Get settings - * @param key - * @return {*|undefined} - * @private - */ - function _getSetting(key) { - return settings[key] || undefined; - } - - /** - * Tool tip - * @private - */ - function _initToolTip() { - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - }); - } - - /** - * return public methods - */ - return { - run: run - } - } - - return { - /** - * @public - * @static - * - * Implement the "Singleton Pattern". - * - * @return object - */ - getInstance: function (settings) { - if (_socialFeedModuleInstance === null) { - _socialFeedModuleInstance = new SocialFeedModule(settings); - } - - return _socialFeedModuleInstance; - }, - }; - })($, bootstrap, Modal, Severity, Notification, MessageUtility, clipboard); + /** + * @private + * + * Hold the instance (Singleton Pattern) + */ + var _socialFeedModuleInstance = null; + + /** + * Main module JavaScript + * + * @return {{init: init}} + * @constructor + */ + function SocialFeedModule(settings) { + /** + * If was initialized + * + * @type {boolean} + * @private + */ + var _isRunning = false; + + /** + * HTML Identifiers + * @type {{}} + * @private + */ + var _domElementsSelectors = { + confirmationButton: '.delete-action,.confirmation-action', + selectSocialType: '#select-type', + socialTypeUrlKeep: '#type-url-', + winStorageBrowser: '[data-identifier="browse-feeds-storage"]', + feedsStorageInput: '[data-identifier="feeds-storage-input"]', + feedsStorageTitle: '[data-identifier="feed-storage-title"]', + copyRedirectUriButton: '.copy-redirect-uri-button', + facebookLoginButton: '.facebook-login-link', + }; + + /** + * run if not running yet + * + * @public + */ + function run() { + if (_isRunning === false) { + _bootstrap(); + } + + _isRunning = true; + } + + /** + * Init + * @private + */ + function _bootstrap() { + _deleteConfirmation(); + _facebookLoginWindow(); + _changeSocialType(); + _winStorageBrowser(); + _getRedirectUriButtonClick(); + _initToolTip(); + _activateTabs(); + } + + /** + * Activate the tabs for the backend module + * + * @private + */ + function _activateTabs() { + let triggerTabList = [].slice.call(document.querySelectorAll('#tabs a')); + triggerTabList.forEach(function (triggerEl) { + let tabTrigger = new bootstrap.Tab(triggerEl); + + triggerEl.addEventListener('click', function (event) { + event.preventDefault(); + tabTrigger.show(); + }); + }); + } + + /** + * If user try to delete something + * + * @private + */ + function _deleteConfirmation() { + $(_getDomElementIdentifier('confirmationButton')).on('click', function (e) { + e.preventDefault(); + + var $this = $(this); + var title = $this.data('confirmation-title') || 'Delete'; + var message = $this.data('confirmation-message') || 'Are you sure you want to delete this record ?'; + + var url = $this.attr('href'), + modal = Modal.confirm(title, message, Severity.warning); + + modal.addEventListener('confirm.button.cancel', function () { + Modal.dismiss(modal); + }); + + modal.addEventListener('confirm.button.ok', function () { + Modal.dismiss(modal); + window.location.href = url; + }); + }); + } + + /** + * Show window with facebook login + * + * @private + */ + function _facebookLoginWindow() { + $(_getDomElementIdentifier('facebookLoginButton')).on('click', function (e) { + e.preventDefault(); + + var $this = $(this); + var w = 800; + var h = 800; + + var y = window.top.outerHeight / 2 + window.top.screenY - h / 2; + var x = window.top.outerWidth / 2 + window.top.screenX - w / 2; + + window.open($this.attr('href'), 'Facebook login', 'height=' + h + ',width=' + w + 'top=' + y + ', left=' + x); + }); + } + + /** + * Switch to different social type + * + * @private + */ + function _changeSocialType() { + $(_getDomElementIdentifier('selectSocialType')).on('change', function () { + var selectSocialType = $(this).find(':selected').val(); + + window.location.href = $(_getDomElementIdentifier('socialTypeUrlKeep') + selectSocialType).val(); + }); + } + + /** + * Copy redirect uri to clipboard + * @private + */ + function _getRedirectUriButtonClick() { + new clipboard(_getDomElementIdentifier('copyRedirectUriButton')); + } + + /** + * Load browser pages window + * + * @private + */ + function _winStorageBrowser() { + window.addEventListener('message', function (e) { + if (!MessageUtility.MessageUtility.verifyOrigin(e.origin)) { + throw 'Denied message sent by ' + e.origin; + } + + if (typeof e.data.fieldName === 'undefined') { + throw 'fieldName not defined in message'; + } + + if (typeof e.data.value === 'undefined') { + throw 'value not defined in message'; + } + + const fieldElement = _getInsertTarget(e.data.fieldName); + if (fieldElement) { + fieldElement.value = e.data.value.split('_').pop(); + } + + const storageTitleElement = document.querySelector(_getDomElementIdentifier('feedsStorageTitle')); + if (storageTitleElement) { + storageTitleElement.innerHTML = e.data.label; + } + }); + + $(_getDomElementIdentifier('winStorageBrowser')).on('click', function () { + var insertTarget = $(_getDomElementIdentifier('feedsStorageInput')), + randomIdentifier = Math.floor(Math.random() * 100000 + 1); + + insertTarget.attr('data-insert-target', randomIdentifier); + _openTypo3WinBrowser('db', randomIdentifier + '|||pages'); + }); + } + + /** + * @private + * + * opens a popup window with the element browser + * + * @param mode + * @param params + */ + function _openTypo3WinBrowser(mode, params) { + const url = _getSetting('browserUrl') + '&mode=' + mode + '&bparams=' + params; + Modal.advanced({ + type: Modal.types.iframe, + content: url, + size: Modal.sizes.large, + }); + } + + /** + * Get selector + * @param elementIdentifier + * @return {*|undefined} + * @private + */ + function _getDomElementIdentifier(elementIdentifier) { + return _domElementsSelectors[elementIdentifier] || undefined; + } + + /** + * Get insert target + * @param reference + * @return {HTMLElement|null} + * @private + */ + function _getInsertTarget(reference) { + return document.querySelector('[data-insert-target="' + reference + '"]'); + } + + /** + * Get settings + * @param key + * @return {*|undefined} + * @private + */ + function _getSetting(key) { + return settings[key] || undefined; + } + + /** + * Tool tip + * @private + */ + function _initToolTip() { + $(function () { + $('[data-toggle="tooltip"]').tooltip(); + }); + } + + /** + * return public methods + */ + return { + run: run, + }; + } + + return { + /** + * @public + * @static + * + * Implement the "Singleton Pattern". + * + * @return object + */ + getInstance: function (settings) { + if (_socialFeedModuleInstance === null) { + _socialFeedModuleInstance = new SocialFeedModule(settings); + } + + return _socialFeedModuleInstance; + }, + }; + })($, bootstrap, Modal, Severity, Notification, MessageUtility, clipboard); }); diff --git a/Resources/Public/JavaScript/Backend/social-feed-administration-module.js b/Resources/Public/JavaScript/Backend/social-feed-administration-module.js new file mode 100644 index 00000000..1c5c335a --- /dev/null +++ b/Resources/Public/JavaScript/Backend/social-feed-administration-module.js @@ -0,0 +1,218 @@ +import DocumentService from '@typo3/core/document-service.js'; +import Notification from '@typo3/backend/notification.js'; +import Modal from '@typo3/backend/modal.js'; +import $ from 'jquery'; +import Severity from '@typo3/backend/severity.js'; +import bootstrap from '@typo3/backend/bootstrap'; +/* + * file created by Abdellatif Landolsi for TYPO3 v12.4 + * Date: 2023-10-19 + */ + +class SocialFeedAdministrationModule { + constructor() { + this._isRunning = false; + this._domElementsSelectors = { + confirmationButton: '.delete-action,.confirmation-action', + selectSocialType: '#select-type', + socialTypeUrlKeep: '#type-url-', + winStorageBrowser: '[data-identifier="browse-feeds-storage"]', + feedsStorageInput: '[data-identifier="feeds-storage-input"]', + feedsStorageTitle: '[data-identifier="feed-storage-title"]', + copyRedirectUriButton: '.copy-redirect-uri-button', + facebookLoginButton: '.facebook-login-link', + }; + DocumentService.ready().then(() => { + this.initialize(); + }); + } + initialize() { + if (this._isRunning === false) { + this._bootstrap(); + } + _isRunning = true; + } + + _bootstrap() { + this._deleteConfirmation(); + this._facebookLoginWindow(); + this._changeSocialType(); + this._winStorageBrowser(); + this._getRedirectUriButtonClick(); + this._initToolTip(); + this._activateTabs(); + } + + /** + * Activate the tabs for the backend module + * + * @private + */ + _activateTabs() { + let triggerTabList = [].slice.call(document.querySelectorAll('#tabs a')); + triggerTabList.forEach(function (triggerEl) { + let tabTrigger = new bootstrap.Tab(triggerEl); + + triggerEl.addEventListener('click', function (event) { + event.preventDefault(); + tabTrigger.show(); + }); + }); + } + + /** + * If user try to delete something + * + * @private + */ + _deleteConfirmation() { + this._getDomElementIdentifier('confirmationButton').on('click', function (e) { + e.preventDefault(); + + var $this = $(this); + var title = $this.data('confirmation-title') || 'Delete'; + var message = $this.data('confirmation-message') || 'Are you sure you want to delete this record ?'; + + var url = $this.attr('href'), + modal = Modal.confirm(title, message, Severity.warning); + + modal.on('confirm.button.cancel', function () { + Modal.dismiss(modal); + }); + + modal.on('confirm.button.ok', function () { + Modal.dismiss(modal); + window.location.href = url; + }); + }); + } + + /** + * Show window with facebook login + * + * @private + */ + _facebookLoginWindow() { + this._getDomElementIdentifier('facebookLoginButton').on('click', function (e) { + e.preventDefault(); + + var $this = $(this); + var w = 800; + var h = 800; + + var y = window.top.outerHeight / 2 + window.top.screenY - h / 2; + var x = window.top.outerWidth / 2 + window.top.screenX - w / 2; + + window.open($this.attr('href'), 'Facebook login', 'height=' + h + ',width=' + w + 'top=' + y + ', left=' + x); + }); + } + + /** + * Switch to different social type + * + * @private + */ + _changeSocialType() { + this._getDomElementIdentifier('selectSocialType').on('change', function () { + var selectSocialType = $(this).find(':selected').val(); + + window.location.href = $(_getDomElementIdentifier('socialTypeUrlKeep') + selectSocialType).val(); + }); + } + + /** + * Copy redirect uri to clipboard + * @private + */ + _getRedirectUriButtonClick() { + new clipboard(this._getDomElementIdentifier('copyRedirectUriButton')); + } + + /** + * Load browser pages window + * + * @private + */ + _winStorageBrowser() { + window.addEventListener('message', function (e) { + if (!MessageUtility.MessageUtility.verifyOrigin(e.origin)) { + throw 'Denied message sent by ' + e.origin; + } + + if (typeof e.data.fieldName === 'undefined') { + throw 'fieldName not defined in message'; + } + + if (typeof e.data.value === 'undefined') { + throw 'value not defined in message'; + } + + const fieldElement = this._getInsertTarget(e.data.fieldName); + if (fieldElement) { + fieldElement.value = e.data.value; + } + + const storageTitleElement = document.querySelector(this._getDomElementIdentifier('feedsStorageTitle')); + if (storageTitleElement) { + storageTitleElement.innerHTML = e.data.label; + } + }); + + this._getDomElementIdentifier('winStorageBrowser').on('click', function () { + var insertTarget = this._getDomElementIdentifier('feedsStorageInput'), + randomIdentifier = Math.floor(Math.random() * 100000 + 1); + + insertTarget.attr('data-insert-target', randomIdentifier); + this._openTypo3WinBrowser('db', randomIdentifier + '|||pages'); + }); + } + + /** + * @private + * + * opens a popup window with the element browser + * + * @param mode + * @param params + */ + _openTypo3WinBrowser(mode, params) { + const url = _getSetting('browserUrl') + '&mode=' + mode + '&bparams=' + params; + Modal.advanced({ + type: Modal.types.iframe, + content: url, + size: Modal.sizes.large, + }); + } + + /** + * Get selector + * @param elementIdentifier + * @return {*|undefined} + * @private + */ + _getDomElementIdentifier(elementIdentifier) { + return _domElementsSelectors[elementIdentifier] || undefined; + } + + /** + * Get insert target + * @param reference + * @return {HTMLElement|null} + * @private + */ + _getInsertTarget(reference) { + return document.querySelector('[data-insert-target="' + reference + '"]'); + } + + /** + * Get settings + * @param key + * @return {*|undefined} + * @private + */ + _getSetting(key) { + return settings[key] || undefined; + } +} + +export default new SocialFeedAdministrationModule(); diff --git a/composer.json b/composer.json index 7e40ab7f..b6738136 100644 --- a/composer.json +++ b/composer.json @@ -17,9 +17,9 @@ } ], "require": { - "php": ">=7.4", - "typo3/cms-core": "^10.3 || ^11.5", - "typo3/cms-scheduler": "^10.3 || ^11.5", + "php": ">=8.1", + "typo3/cms-core": "^11.5 || ^12.4", + "typo3/cms-scheduler": "^11.5 || ^12.4", "league/oauth2-facebook": "2.0.5" }, "require-dev": { diff --git a/ext_emconf.php b/ext_emconf.php index 5c88356c..8539667f 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -12,17 +12,14 @@ 'author_email' => 'info@pixelant.net', 'author_company' => 'Pixelant', 'state' => 'stable', - 'uploadfolder' => '0', - 'createDirs' => '', - 'clearCacheOnLoad' => 0, - 'version' => '3.7.1', + 'version' => '4.0.0', 'constraints' => [ 'depends' => [ - 'typo3' => '10.3.0-11.5.99', + 'typo3' => '11.5.0-12.4.99', ], 'conflicts' => [ ], 'suggests' => [ ], ], -]; +]; \ No newline at end of file diff --git a/ext_localconf.php b/ext_localconf.php index d41b46ba..f295d417 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,10 +1,8 @@ $_EXTKEY, + 'extension' => 'pxa_social_feed', 'title' => $ll . 'task.import.name', 'description' => $ll . 'task.import.description', 'additionalFields' => \Pixelant\PxaSocialFeed\Task\ImportTaskAdditionalFieldProvider::class, ]; // hook for extension BE view - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['pxasocialfeed_showfeed'][$_EXTKEY] = + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['pxasocialfeed_showfeed']['pxa_social_feed'] = \Pixelant\PxaSocialFeed\Hooks\PageLayoutView::class . '->getExtensionInformation'; // @codingStandardsIgnoreEnd @@ -37,28 +35,6 @@ "@import 'EXT:pxa_social_feed/Configuration/TSconfig/ContentElementWizard.tsconfig'" ); - // Register icons - $icons = [ - 'ext-pxasocialfeed-wizard-icon' => 'feed.svg', - 'ext-pxasocialfeed-model-icon' => 'feed.svg', - 'ext-pxasocialfeed-model-icon-facebook' => 'facebook.svg', - 'ext-pxasocialfeed-model-icon-instagram' => 'instagram.svg', - 'ext-pxasocialfeed-model-icon-twitter' => 'twitter.svg', - 'ext-pxasocialfeed-model-icon-youtube' => 'youtube.svg', - ]; - /** @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */ - $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( - \TYPO3\CMS\Core\Imaging\IconRegistry::class - ); - - foreach ($icons as $identifier => $path) { - $iconRegistry->registerIcon( - $identifier, - \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, - ['source' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/' . $path] - ); - } - // Register eID to obtain access token $eID = \Pixelant\PxaSocialFeed\Controller\EidController::IDENTIFIER; $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$eID] = diff --git a/ext_tables.php b/ext_tables.php index 8ad0e219..871e1f78 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -1,33 +1,3 @@ - 'index, editToken, updateToken, deleteToken, editConfiguration, ' . - 'updateConfiguration, deleteConfiguration, resetAccessToken, runConfiguration', - ], - [ - 'access' => 'user,group', - 'icon' => 'EXT:pxa_social_feed/Resources/Public/Icons/BE/feed.svg', - 'labels' => 'LLL:EXT:pxa_social_feed/Resources/Private/Language/locallang_be.xlf', - ] - ); - } - - foreach (['feed', 'token', 'configuration'] as $table) { - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages( - 'tx_pxasocialfeed_domain_model_' . $table - ); - } -})(); +defined('TYPO3') or die(); diff --git a/ext_tables.sql b/ext_tables.sql index 7519abb7..8b6db7b4 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -50,7 +50,7 @@ CREATE TABLE tx_pxasocialfeed_domain_model_token app_secret varchar(255) DEFAULT '' NOT NULL, access_token text, fb_social_id varchar(255) DEFAULT '' NOT NULL, - parent_token int(11), + parent_token int(11) DEFAULT '0' NOT NULL, # Twitter, access_token already exist api_key varchar(255) DEFAULT '' NOT NULL, diff --git a/ext_typoscript_setup.typoscript b/ext_typoscript_setup.typoscript index f84d7d4b..6fc4ae38 100644 --- a/ext_typoscript_setup.typoscript +++ b/ext_typoscript_setup.typoscript @@ -4,3 +4,4 @@ plugin.tx_pxasocialfeed { } } module.tx_pxasocialfeed < plugin.tx_pxasocialfeed +