Zwischenstand
This commit is contained in:
53
Classes/Service/AbstractExtensionService.php
Normal file
53
Classes/Service/AbstractExtensionService.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
|
||||
/**
|
||||
* An access control service
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class AbstractExtensionService implements SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||
*/
|
||||
protected $objectManager;
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||
*/
|
||||
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
|
||||
{
|
||||
$this->objectManager = $objectManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Service\LoggingService
|
||||
*/
|
||||
protected $loggingService;
|
||||
/**
|
||||
* @var \TYPO3\CMS\Core\Log\Logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Service\LoggingService $loggingService
|
||||
*/
|
||||
public function __construct(LoggingService $loggingService)
|
||||
{
|
||||
$this->loggingService = $loggingService;
|
||||
$this->logger = $loggingService->getLogger(get_class($this));
|
||||
}
|
||||
}
|
187
Classes/Service/AccessControlService.php
Normal file
187
Classes/Service/AccessControlService.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter;
|
||||
use WapplerSystems\BookmarksLikesRatings\Exception\FeUserNotFoundException;
|
||||
use TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
|
||||
/**
|
||||
* An access control service
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class AccessControlService extends AbstractExtensionService
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
|
||||
*/
|
||||
protected $frontendUserRepository;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository $frontendUserRepository
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function injectFrontendUserRepository(FrontendUserRepository $frontendUserRepository): void
|
||||
{
|
||||
$this->frontendUserRepository = $frontendUserRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository
|
||||
*/
|
||||
protected $voterRepository;
|
||||
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository
|
||||
*/
|
||||
public function injectVoterRepository(\WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoterRepository $voterRepository): void
|
||||
{
|
||||
$this->voterRepository = $voterRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Core\Context\Context $context
|
||||
*/
|
||||
protected $context;
|
||||
/**
|
||||
* @param \TYPO3\CMS\Core\Context\Context $context
|
||||
*/
|
||||
public function injectContext(\TYPO3\CMS\Core\Context\Context $context): void
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests, if the given person is logged into the frontend
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\Domain\Model\FrontendUser|null $person The person
|
||||
* @return bool The result; true if the given person is logged in; otherwise false
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function isLoggedIn(\TYPO3\CMS\Extbase\Domain\Model\FrontendUser $person = null): bool
|
||||
{
|
||||
if (is_object($person)) {
|
||||
if ($person->getUid() &&
|
||||
($person->getUid() === $this->getFrontendUserUid())) {
|
||||
return true; //treat anonymous user also as logged in
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function backendAdminIsLoggedIn(): bool
|
||||
{
|
||||
return $this->context->getPropertyFromAspect('backend.user', 'isLoggedIn');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function hasLoggedInFrontendUser(): bool
|
||||
{
|
||||
return $this->context->getPropertyFromAspect('frontend.user', 'isLoggedIn');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function getFrontendUserGroups(): array
|
||||
{
|
||||
if ($this->hasLoggedInFrontendUser()) {
|
||||
return $this->context->getPropertyFromAspect('frontend.user', 'groupIds');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function getFrontendUserUid(): ?int
|
||||
{
|
||||
if ($this->hasLoggedInFrontendUser()) {
|
||||
return $this->context->getPropertyFromAspect('frontend.user', 'id');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads objects from repositories
|
||||
*
|
||||
* @param mixed $voter
|
||||
* @return \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function getFrontendUser($voter = null): ?\TYPO3\CMS\Extbase\Domain\Model\FrontendUser
|
||||
{
|
||||
//set userobject
|
||||
if (!$voter instanceof \TYPO3\CMS\Extbase\Domain\Model\FrontendUser) {
|
||||
//TODO Errorhandling if no user is logged in
|
||||
if ((int)$voter === 0) {
|
||||
//get logged in fe-user
|
||||
$voter = $this->frontendUserRepository->findByUid($this->getFrontendUserUid());
|
||||
} else {
|
||||
$voter = $this->frontendUserRepository->findByUid((int)$voter);
|
||||
}
|
||||
}
|
||||
return $voter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads objects from repositories
|
||||
*
|
||||
* @param int|null $voter
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter
|
||||
* @throws FeUserNotFoundException
|
||||
* @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
|
||||
*/
|
||||
public function getFrontendVoter(?int $voter = 0): Voter
|
||||
{
|
||||
$exceptionMessageArray = [];
|
||||
|
||||
/** @var Voter $voterObject */
|
||||
$voterObject = null;
|
||||
|
||||
//TODO Errorhandling if no user is logged in
|
||||
if ((int)$voter === 0) {
|
||||
//get logged in fe-user
|
||||
$voterObject = $this->voterRepository->findByUid($this->getFrontendUserUid());
|
||||
$exceptionMessageArray = [$this->getFrontendUserUid()];
|
||||
$exceptionMessageType = 'feUser';
|
||||
} else {
|
||||
$voterObject = $this->voterRepository->findByUid((int)$voter);
|
||||
$exceptionMessageArray = [(int)$voter];
|
||||
$exceptionMessageType = 'anonymousUser';
|
||||
}
|
||||
|
||||
if (empty($voterObject)) {
|
||||
throw new FeUserNotFoundException(
|
||||
LocalizationUtility::translate(
|
||||
'flash.pluginConfiguration.missing.' . $exceptionMessageType,
|
||||
'ThRating',
|
||||
$exceptionMessageArray
|
||||
),
|
||||
1602095329
|
||||
);
|
||||
}
|
||||
|
||||
return $voterObject;
|
||||
}
|
||||
}
|
21
Classes/Service/AccessException.php
Normal file
21
Classes/Service/AccessException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Extbase\Exception;
|
||||
|
||||
/**
|
||||
* An access exception
|
||||
*
|
||||
* @version $ID: $
|
||||
*/
|
||||
class AccessException extends Exception
|
||||
{
|
||||
}
|
139
Classes/Service/CookieService.php
Normal file
139
Classes/Service/CookieService.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Service for setting cookies like Typo3 does
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class CookieService extends AbstractExtensionService
|
||||
{
|
||||
/**
|
||||
* Indicator for cookieProtection has been set
|
||||
* @var bool
|
||||
*/
|
||||
protected $cookieProtection = false;
|
||||
|
||||
/**
|
||||
* Gets the domain to be used on setting cookies.
|
||||
* The information is taken from the value in $GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieDomain'].
|
||||
* Protected function taken from t3lib_userAuth (t3 4.7.7)
|
||||
*
|
||||
* @return string The domain to be used on setting cookies
|
||||
*/
|
||||
protected function getCookieDomain()
|
||||
{
|
||||
$result = '';
|
||||
$cookieDomain = $GLOBALS['TYPO3_CONF_VARS']['SYS']['cookieDomain'];
|
||||
// If a specific cookie domain is defined for a given TYPO3_MODE,
|
||||
// use that domain
|
||||
if (!empty($GLOBALS['TYPO3_CONF_VARS']['FE']['cookieDomain'])) {
|
||||
$cookieDomain = $GLOBALS['TYPO3_CONF_VARS']['FE']['cookieDomain'];
|
||||
}
|
||||
if ($cookieDomain) {
|
||||
if ($cookieDomain[0] === '/') {
|
||||
$match = [];
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
$matchCnt = @preg_match(
|
||||
$cookieDomain,
|
||||
GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'),
|
||||
$match
|
||||
);
|
||||
if ($matchCnt === false) {
|
||||
$this->logger->log(
|
||||
LogLevel::ERROR,
|
||||
'getCookieDomain: The regular expression for the cookie domain contains errors.' .
|
||||
'The session is not shared across sub-domains.',
|
||||
['cookieDomain' => $cookieDomain, 'errorCode' => 1399137882]
|
||||
);
|
||||
} elseif ($matchCnt) {
|
||||
$result = $match[0];
|
||||
}
|
||||
} else {
|
||||
$result = $cookieDomain;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cookie
|
||||
* Protected function taken from t3lib_userAuth (t3 4.7.7)
|
||||
*
|
||||
* @param string $cookieName identifier for the cookie
|
||||
* @param string $cookieValue cookie value
|
||||
* @param int $cookieExpire expire time for the cookie (UNIX timestamp)
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setVoteCookie($cookieName, $cookieValue, $cookieExpire = 0): void
|
||||
{
|
||||
// do not set session cookies
|
||||
if (!empty($cookieExpire)) {
|
||||
$settings = $GLOBALS['TYPO3_CONF_VARS']['SYS'];
|
||||
// Get the domain to be used for the cookie (if any):
|
||||
$cookieDomain = $this->getCookieDomain();
|
||||
// If no cookie domain is set, use the base path:
|
||||
$cookiePath = ($cookieDomain ? '/' : GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'));
|
||||
// Use the secure option when the current request is served by a secure connection:
|
||||
$cookieSecure = (bool)$settings['cookieSecure'] && GeneralUtility::getIndpEnv('TYPO3_SSL');
|
||||
// Deliver cookies only via HTTP and prevent possible XSS by JavaScript:
|
||||
$cookieHttpOnly = (bool)$settings['cookieHttpOnly'];
|
||||
|
||||
// Do not set cookie if cookieSecure is set to "1" (force HTTPS) and no secure channel is used:
|
||||
if ((int)$settings['cookieSecure'] !== 1 || GeneralUtility::getIndpEnv('TYPO3_SSL')) {
|
||||
setcookie(
|
||||
$cookieName,
|
||||
$cookieValue,
|
||||
(int)$cookieExpire,
|
||||
$cookiePath,
|
||||
$cookieDomain,
|
||||
$cookieSecure,
|
||||
$cookieHttpOnly
|
||||
);
|
||||
$this->cookieProtection = true;
|
||||
$this->logger->log(
|
||||
LogLevel::INFO,
|
||||
'setVoteCookie: Cookie set',
|
||||
[
|
||||
'cookieName' => $cookieName,
|
||||
'cookieValue' => $cookieValue,
|
||||
'cookieExpire' => $cookieExpire,
|
||||
'cookiePath' => $cookiePath,
|
||||
'cookieDomain' => $cookieDomain,
|
||||
'cookieSecure' => $cookieSecure,
|
||||
'cookieHttpOnly' => $cookieHttpOnly,
|
||||
]
|
||||
);
|
||||
} else {
|
||||
throw new Exception(
|
||||
"Cookie was not set since HTTPS was forced in \$GLOBALS['TYPO3_CONF_VARS'][SYS][cookieSecure].",
|
||||
1254325546
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if cookie protection has been set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isProtected()
|
||||
{
|
||||
return $this->cookieProtection;
|
||||
}
|
||||
}
|
19
Classes/Service/Exception.php
Normal file
19
Classes/Service/Exception.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
/**
|
||||
* A ViewHelper Exception
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Exception extends \TYPO3Fluid\Fluid\Core\Exception
|
||||
{
|
||||
}
|
233
Classes/Service/ExtensionConfigurationService.php
Normal file
233
Classes/Service/ExtensionConfigurationService.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use WapplerSystems\BookmarksLikesRatings\Exception\FeUserStoragePageException;
|
||||
use WapplerSystems\BookmarksLikesRatings\Exception\InvalidStoragePageException;
|
||||
use TYPO3\CMS\Core\Log\Logger;
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
|
||||
/**
|
||||
* Factory for model objects
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class ExtensionConfigurationService extends AbstractExtensionService
|
||||
{
|
||||
/**
|
||||
* Contains configuration of the calling extension
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $originalConfiguration;
|
||||
|
||||
/**
|
||||
* Calling extension query settings
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
|
||||
*/
|
||||
protected $originalTypo3QuerySettings;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $cookieLifetime;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* @var QuerySettingsInterface
|
||||
*/
|
||||
private $extDefaultQuerySettings;
|
||||
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
*/
|
||||
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the settings of the current extension
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Contains configuration of th_rating
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $thRatingConfiguration;
|
||||
|
||||
/**
|
||||
* Contains configuration of the current extension
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $frameworkConfiguration;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function initializeObject(): void
|
||||
{
|
||||
// store calling extension configuration
|
||||
$this->originalConfiguration = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
|
||||
);
|
||||
|
||||
$this->thRatingConfiguration = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
|
||||
'thrating',
|
||||
'pi1'
|
||||
);
|
||||
if (!empty($this->thRatingConfiguration['ratings'])) {
|
||||
//Merge extension ratingConfigurations with customer added ones
|
||||
ArrayUtility::mergeRecursiveWithOverrule(
|
||||
$this->thRatingConfiguration['settings']['ratingConfigurations'],
|
||||
$this->thRatingConfiguration['ratings']
|
||||
);
|
||||
}
|
||||
|
||||
$this->frameworkConfiguration = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
|
||||
'thrating',
|
||||
'pi1'
|
||||
);
|
||||
|
||||
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->frameworkConfiguration,get_class($this).' frameworkConfiguration');
|
||||
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->thRatingConfiguration,get_class($this).' thRatingConfiguration');
|
||||
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($this->originalConfiguration,get_class($this).' originalConfiguration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance
|
||||
* The configuration of the logger is modified by extension typoscript config
|
||||
*
|
||||
* @param string|null $name the class name which this logger is for
|
||||
* @return \TYPO3\CMS\Core\Log\Logger
|
||||
*/
|
||||
public function getLogger(string $name = null): Logger
|
||||
{
|
||||
if (empty($name)) {
|
||||
return $this->loggingService->getLogger(__CLASS__);
|
||||
}
|
||||
|
||||
return $this->loggingService->getLogger($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default query settings to those of th_rating
|
||||
* (could be different if services are called from other extensions
|
||||
* @throws FeUserStoragePageException
|
||||
* @throws InvalidStoragePageException
|
||||
*/
|
||||
public function setExtDefaultQuerySettings(): void
|
||||
{
|
||||
$this->mergeStoragePids();
|
||||
$this->extDefaultQuerySettings = $this->objectManager->get(QuerySettingsInterface::class);
|
||||
$this->extDefaultQuerySettings->setStoragePageIds(
|
||||
explode(',', $this->thRatingConfiguration['persistence']['storagePid'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function getCookieProtection(): bool
|
||||
{
|
||||
$this->cookieLifetime = abs((int)$this->thRatingConfiguration['settings']['cookieLifetime']);
|
||||
$this->logger->log(
|
||||
LogLevel::DEBUG,
|
||||
'Cookielifetime set to ' . $this->cookieLifetime . ' days',
|
||||
['errorCode' => 1465728751]
|
||||
);
|
||||
return empty($this->cookieLifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks storagePid settings of th_rating and tx_felogin_pi1 and
|
||||
* concatenates them to the new storagePid setting
|
||||
*
|
||||
* @throws InvalidStoragePageException if plugin.tx_thrating.storagePid has not been set
|
||||
* @throws FeUserStoragePageException if plugin.tx_felogin_pi1.storagePid has not been set
|
||||
*/
|
||||
private function mergeStoragePids(): void
|
||||
{
|
||||
$storagePids = GeneralUtility::intExplode(',', $this->thRatingConfiguration['storagePid'], true);
|
||||
if (empty($storagePids[0])) {
|
||||
throw new InvalidStoragePageException(
|
||||
LocalizationUtility::translate('flash.vote.general.invalidStoragePid', 'ThRating'),
|
||||
1403203519
|
||||
);
|
||||
}
|
||||
|
||||
$storagePids[] = $this->getFeUserStoragePage();
|
||||
$this->thRatingConfiguration['persistence.']['storagePid'] = implode(',', $storagePids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and return the first configured storage page for website users
|
||||
* @return int
|
||||
* @throws FeUserStoragePageException
|
||||
*/
|
||||
private function getFeUserStoragePage(): int
|
||||
{
|
||||
$feUserStoragePid = array_merge(
|
||||
GeneralUtility::intExplode(
|
||||
',',
|
||||
$this->frameworkConfiguration['plugin.']['tx_felogin_pi1.']['storagePid'],
|
||||
true
|
||||
),
|
||||
GeneralUtility::intExplode(',', $this->thRatingConfiguration['feUsersStoragePid'], true)
|
||||
);
|
||||
if (empty($feUserStoragePid[0])) {
|
||||
throw new FeUserStoragePageException(
|
||||
LocalizationUtility::translate('flash.pluginConfiguration.missing.feUserStoragePid', 'ThRating'),
|
||||
1403190539
|
||||
);
|
||||
}
|
||||
return $feUserStoragePid[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current extbase configuration to the one of th_rating
|
||||
*/
|
||||
public function prepareExtensionConfiguration(): void
|
||||
{
|
||||
if ($this->originalConfiguration['extensionName'] !== 'ThRating') {
|
||||
//Set default storage pids
|
||||
$this->setExtDefaultQuerySettings();
|
||||
}
|
||||
$this->configurationManager->setConfiguration($this->thRatingConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current extbase configuration to the one of th_rating
|
||||
*/
|
||||
public function restoreCallingExtensionConfiguration(): void
|
||||
{
|
||||
if ($this->originalConfiguration['extensionName'] !== 'ThRating') {
|
||||
$this->configurationManager->setConfiguration($this->originalConfiguration);
|
||||
}
|
||||
}
|
||||
}
|
720
Classes/Service/ExtensionHelperService.php
Normal file
720
Classes/Service/ExtensionHelperService.php
Normal file
@@ -0,0 +1,720 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpFullyQualifiedNameUsageInspection */
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\RatingImage;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingobjectValidator;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\RatingValidator;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Validator\VoteValidator;
|
||||
use WapplerSystems\BookmarksLikesRatings\Evaluation\DynamicCssEvaluator;
|
||||
use WapplerSystems\BookmarksLikesRatings\Exception\LanguageNotFoundException;
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Log\Logger;
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Site\Entity\Site;
|
||||
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
|
||||
use TYPO3\CMS\Core\Site\SiteFinder;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
|
||||
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
|
||||
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
|
||||
|
||||
/**
|
||||
* Factory for model objects
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class ExtensionHelperService extends AbstractExtensionService
|
||||
{
|
||||
protected const DYN_CSS_FILENAME = 'typo3temp/thratingDyn.css';
|
||||
|
||||
/**
|
||||
* The current request.
|
||||
*
|
||||
* @var \TYPO3\CMS\Extbase\Mvc\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository
|
||||
*/
|
||||
protected $ratingobjectRepository;
|
||||
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingobjectRepository $ratingobjectRepository
|
||||
*/
|
||||
public function injectRatingobjectRepository(RatingobjectRepository $ratingobjectRepository): void
|
||||
{
|
||||
$this->ratingobjectRepository = $ratingobjectRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository
|
||||
*/
|
||||
protected $ratingRepository;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\RatingRepository $ratingRepository
|
||||
*/
|
||||
public function injectRatingRepository(RatingRepository $ratingRepository): void
|
||||
{
|
||||
$this->ratingRepository = $ratingRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository
|
||||
*/
|
||||
protected $stepnameRepository;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\StepnameRepository $stepnameRepository
|
||||
*/
|
||||
public function injectStepnameRepository(StepnameRepository $stepnameRepository): void
|
||||
{
|
||||
$this->stepnameRepository = $stepnameRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository
|
||||
*/
|
||||
protected $voteRepository;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Repository\VoteRepository $voteRepository
|
||||
*/
|
||||
public function injectVoteRepository(VoteRepository $voteRepository): void
|
||||
{
|
||||
$this->voteRepository = $voteRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Service\AccessControlService
|
||||
*/
|
||||
protected $accessControllService;
|
||||
/**
|
||||
* @param AccessControlService $accessControllService
|
||||
*/
|
||||
public function injectAccessControlService(AccessControlService $accessControllService): void
|
||||
{
|
||||
$this->accessControllService = $accessControllService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator
|
||||
*/
|
||||
protected $stepconfValidator;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Validator\StepconfValidator $stepconfValidator
|
||||
*/
|
||||
public function injectStepconfValidator(StepconfValidator $stepconfValidator): void
|
||||
{
|
||||
$this->stepconfValidator = $stepconfValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
/**
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||
*/
|
||||
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager): void
|
||||
{
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the settings of the current extension
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\RatingImage
|
||||
*/
|
||||
protected $ratingImage;
|
||||
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
|
||||
*/
|
||||
protected $extDefaultQuerySettings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function initializeObject(): void
|
||||
{
|
||||
$this->settings = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||
'thrating',
|
||||
'pi1'
|
||||
);
|
||||
|
||||
$frameworkConfiguration = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
|
||||
'thrating',
|
||||
'pi1'
|
||||
);
|
||||
if (!empty($frameworkConfiguration['ratings'])) {
|
||||
//Merge extension ratingConfigurations with customer added ones
|
||||
ArrayUtility::mergeRecursiveWithOverrule(
|
||||
$this->settings['ratingConfigurations'],
|
||||
$frameworkConfiguration['ratings']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
|
||||
*/
|
||||
protected function getTypoScriptFrontendController(): TypoScriptFrontendController
|
||||
{
|
||||
global $TSFE;
|
||||
|
||||
return $TSFE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the completed settings array
|
||||
*
|
||||
* @param array $settings
|
||||
* @return array
|
||||
*/
|
||||
private function completeConfigurationSettings(array $settings): array
|
||||
{
|
||||
$cObj = $this->configurationManager->getContentObject();
|
||||
|
||||
if (!empty($cObj->currentRecord)) {
|
||||
/* build array [0=>cObj tablename, 1=> cObj uid] - initialize with content information
|
||||
(usage as normal content) */
|
||||
$currentRecord = explode(':', $cObj->currentRecord);
|
||||
} else {
|
||||
//build array [0=>cObj tablename, 1=> cObj uid] - initialize with page info if used by typoscript
|
||||
$currentRecord = ['pages', $GLOBALS['TSFE']->page['uid']];
|
||||
}
|
||||
|
||||
if (empty($settings['ratetable'])) {
|
||||
$settings['ratetable'] = $currentRecord[0];
|
||||
}
|
||||
if (empty($settings['ratefield'])) {
|
||||
$settings['ratefield'] = 'uid';
|
||||
}
|
||||
if (empty($settings['ratedobjectuid'])) {
|
||||
$settings['ratedobjectuid'] = $currentRecord[1];
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new or existing ratingobject
|
||||
*
|
||||
* @param array $settings
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\RecordNotFoundException
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||
*/
|
||||
public function getRatingobject(array $settings): Ratingobject
|
||||
{
|
||||
$ratingobject = null;
|
||||
|
||||
//check whether a dedicated ratingobject is configured
|
||||
if (!empty($settings['ratingobject'])) {
|
||||
$ratingobject = $this->ratingobjectRepository->findByUid($settings['ratingobject']);
|
||||
} else {
|
||||
if (empty($settings['ratetable']) || empty($settings['ratefield'])) {
|
||||
//fallback to default configuration
|
||||
$settings = $settings['defaultObject'] + $settings;
|
||||
}
|
||||
$settings = $this->completeConfigurationSettings($settings);
|
||||
$ratingobject = $this->ratingobjectRepository->findMatchingTableAndField(
|
||||
$settings['ratetable'],
|
||||
$settings['ratefield'],
|
||||
RatingobjectRepository::ADD_IF_NOT_FOUND
|
||||
);
|
||||
}
|
||||
return $ratingobject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new or existing ratingobject
|
||||
*
|
||||
* @param array $stepconfArray
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf
|
||||
*/
|
||||
public function createStepconf(array $stepconfArray): Stepconf
|
||||
{
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf */
|
||||
$stepconf = $this->objectManager->get(Stepconf::class);
|
||||
$stepconf->setRatingobject($stepconfArray['ratingobject']);
|
||||
$stepconf->setSteporder($stepconfArray['steporder']);
|
||||
$stepconf->setStepweight($stepconfArray['stepweight']);
|
||||
|
||||
return $stepconf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new or existing ratingobject
|
||||
*
|
||||
* @param Stepconf $stepconf
|
||||
* @param array $stepnameArray
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname
|
||||
* @throws LanguageNotFoundException
|
||||
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||
*/
|
||||
public function createStepname(Stepconf $stepconf, array $stepnameArray): Stepname
|
||||
{
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname */
|
||||
$stepname = $this->objectManager->get(Stepname::class);
|
||||
$stepname->setStepconf($stepconf);
|
||||
$stepname->setStepname($stepnameArray['stepname']);
|
||||
$stepname->setPid($stepnameArray['pid']);
|
||||
$stepname->setSysLanguageUid(
|
||||
$this->getStaticLanguageByIsoCode(
|
||||
$stepname->getPid(),
|
||||
$stepnameArray['twoLetterIsoCode'] ?: null
|
||||
)->getLanguageId()
|
||||
);
|
||||
|
||||
$defaultStepname = $this->stepnameRepository->findDefaultStepname($stepname);
|
||||
$l18nParent = is_null($defaultStepname) ? 0 : $defaultStepname->getUid();
|
||||
$stepname->setL18nParent($l18nParent);
|
||||
return $stepname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new or existing rating
|
||||
*
|
||||
* @param array $settings
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject|null $ratingobject
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Service\Exception
|
||||
*/
|
||||
public function getRating(array $settings, ?Ratingobject $ratingobject): Rating
|
||||
{
|
||||
$settings = $this->completeConfigurationSettings($settings);
|
||||
if (!empty($settings['rating'])) {
|
||||
//fetch rating when it is configured
|
||||
$rating = $this->ratingRepository->findByUid($settings['rating']);
|
||||
} elseif ($settings['ratedobjectuid'] && !$this->objectManager->get(RatingobjectValidator::class)
|
||||
->validate($ratingobject)->hasErrors()) {
|
||||
//get rating according to given row
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
$rating = $this->ratingRepository->findMatchingObjectAndUid(
|
||||
$ratingobject,
|
||||
$settings['ratedobjectuid'],
|
||||
RatingRepository::ADD_IF_NOT_FOUND
|
||||
);
|
||||
} else {
|
||||
throw new \WapplerSystems\BookmarksLikesRatings\Service\Exception(
|
||||
'Incomplete configuration setting. Either \'rating\' or \'ratedobjectuid\' are missing.',
|
||||
1398351336
|
||||
);
|
||||
}
|
||||
return $rating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new or existing vote
|
||||
*
|
||||
* @param string $prefixId
|
||||
* @param array $settings
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Rating $rating
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\FeUserNotFoundException
|
||||
*/
|
||||
public function getVote(string $prefixId, array $settings, Rating $rating): Vote
|
||||
{
|
||||
// initialize variables
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Vote $vote */
|
||||
$vote = null;
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter $voter */
|
||||
$voter = null;
|
||||
|
||||
//first fetch real voter or anonymous
|
||||
/** @var int $frontendUserUid */
|
||||
$frontendUserUid = $this->accessControllService->getFrontendUserUid();
|
||||
if (!$frontendUserUid && !empty($settings['mapAnonymous'])) {
|
||||
//set anonymous vote
|
||||
$voter = $this->accessControllService->getFrontendVoter($settings['mapAnonymous']);
|
||||
$anonymousRating = GeneralUtility::makeInstance(\WapplerSystems\BookmarksLikesRatings\Service\JsonService::class)
|
||||
->decodeJsonToArray($_COOKIE[$prefixId . '_AnonymousRating_' . $rating->getUid()]);
|
||||
if (!empty($anonymousRating['voteUid'])) {
|
||||
$vote = $this->voteRepository->findByUid($anonymousRating['voteUid']);
|
||||
}
|
||||
} elseif ($frontendUserUid) {
|
||||
//set FEUser if one is logged on
|
||||
$voter = $this->accessControllService->getFrontendVoter($frontendUserUid);
|
||||
if ($voter instanceof \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter) {
|
||||
$vote = $this->voteRepository->findMatchingRatingAndVoter($rating, $voter);
|
||||
}
|
||||
}
|
||||
//voting not found in database or anonymous vote? - create new one
|
||||
$voteValidator = $this->objectManager->get(VoteValidator::class);
|
||||
if ($voteValidator->validate($vote)->hasErrors()) {
|
||||
$vote = $this->objectManager->get(Vote::class);
|
||||
$ratingValidator = $this->objectManager->get(RatingValidator::class);
|
||||
if (!$ratingValidator->validate($rating)->hasErrors()) {
|
||||
$vote->setRating($rating);
|
||||
}
|
||||
if ($voter instanceof \WapplerSystems\BookmarksLikesRatings\Domain\Model\Voter) {
|
||||
$vote->setVoter($voter);
|
||||
}
|
||||
}
|
||||
|
||||
return $vote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance
|
||||
* The configuration of the logger is modified by extension typoscript config
|
||||
*
|
||||
* @param string|null $name the class name which this logger is for
|
||||
* @return \TYPO3\CMS\Core\Log\Logger
|
||||
*/
|
||||
public function getLogger(?string $name): Logger
|
||||
{
|
||||
if (empty($name)) {
|
||||
return $this->loggingService->getLogger(__CLASS__);
|
||||
}
|
||||
|
||||
return $this->loggingService->getLogger($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update and persist attached objects to the repository
|
||||
*
|
||||
* @param string $repository
|
||||
* @param \TYPO3\CMS\Extbase\DomainObject\AbstractEntity $objectToPersist
|
||||
*/
|
||||
public function persistRepository(string $repository, AbstractEntity $objectToPersist): void
|
||||
{
|
||||
$objectUid = $objectToPersist->getUid();
|
||||
if (!is_int($objectUid)) {
|
||||
$this->objectManager->get($repository)->add($objectToPersist);
|
||||
} else {
|
||||
$this->objectManager->get($repository)->update($objectToPersist);
|
||||
}
|
||||
$this->objectManager->get(PersistenceManager::class)->persistAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the dynamic CSS file for recreation
|
||||
*/
|
||||
public function clearDynamicCssFile(): void
|
||||
{
|
||||
$this->objectManager->get(DynamicCssEvaluator::class)->clearCachePostProc([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render CSS-styles for ratings and ratingsteps
|
||||
* Only called by singeltonAction to render styles once per page.
|
||||
* The file self::DYN_CSS_FILENAME will be created if it doesn<73>t exist
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function renderDynCSS(): array
|
||||
{
|
||||
$messageArray = [];
|
||||
$cssFile = '';
|
||||
|
||||
//create file if it does not exist
|
||||
if (file_exists(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME)) {
|
||||
$fstat = stat(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME);
|
||||
//do not recreate file if it has greater than zero length
|
||||
if ($fstat[7] !== 0) {
|
||||
$this->logger->log(LogLevel::DEBUG, 'Dynamic CSS file exists - exiting');
|
||||
return $messageArray;
|
||||
}
|
||||
}
|
||||
|
||||
//now walk through all ratingobjects to calculate stepwidths
|
||||
$allRatingobjects = $this->ratingobjectRepository->findAll(true);
|
||||
|
||||
foreach ($allRatingobjects as $ratingobject) {
|
||||
$ratingobjectUid = $ratingobject->getUid();
|
||||
/** @var ObjectStorage<\WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf> $stepconfObjects */
|
||||
$stepconfObjects = $ratingobject->getStepconfs();
|
||||
$stepcount = count($stepconfObjects);
|
||||
if (!$stepcount) {
|
||||
if ($this->settings['showMissingStepconfError']) {
|
||||
//show error message in GUI
|
||||
$messageArray[] = [
|
||||
'messageText' => LocalizationUtility::translate(
|
||||
'flash.renderCSS.noStepconf',
|
||||
'ThRating',
|
||||
[
|
||||
1 => $ratingobject->getUid(),
|
||||
2 => $ratingobject->getPid()
|
||||
]
|
||||
),
|
||||
'messageTitle' => LocalizationUtility::translate(
|
||||
'flash.configuration.error',
|
||||
'ThRating'
|
||||
),
|
||||
'severity' => 'ERROR',
|
||||
'additionalInfo' => [
|
||||
'errorCode' => 1384705470,
|
||||
'ratingobject UID' => $ratingobject->getUid(),
|
||||
'ratingobject PID' => $ratingobject->getPid(),
|
||||
],
|
||||
];
|
||||
} else {
|
||||
//only log message
|
||||
$this->logger->log(
|
||||
LogLevel::ERROR,
|
||||
LocalizationUtility::translate(
|
||||
'flash.renderCSS.noStepconf',
|
||||
'ThRating',
|
||||
[
|
||||
1 => $ratingobject->getUid(),
|
||||
2 => $ratingobject->getPid()
|
||||
]
|
||||
),
|
||||
[
|
||||
'errorCode' => 1384705470,
|
||||
'ratingobject UID' => $ratingobject->getUid(),
|
||||
'ratingobject PID' => $ratingobject->getPid(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$stepWeights = [];
|
||||
$sumStepWeights = 0;
|
||||
|
||||
$stepconfs = $stepconfObjects->toArray();
|
||||
foreach ($stepconfs as $stepconf) { //stepconfs are already sorted by steporder
|
||||
//just do checks here that all steps are OK
|
||||
if (!$this->stepconfValidator->validate($stepconf)->hasErrors()) {
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf */
|
||||
$stepWeights[] = $stepconf->getStepweight();
|
||||
$sumStepWeights += $stepconf->getStepweight();
|
||||
} else {
|
||||
foreach ($this->stepconfValidator->validate($stepconf)->getErrors() as $errorMessage) {
|
||||
$messageArray[] = [
|
||||
'messageText' => $errorMessage->getMessage(),
|
||||
'messageTitle' => LocalizationUtility::translate('flash.configuration.error', 'ThRating'),
|
||||
'severity' => 'ERROR',
|
||||
'additionalInfo' => ['errorCode' => $errorMessage->getCode(),
|
||||
'errorMessage' => $errorMessage->getMessage(), ], ];
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->logger->log(
|
||||
LogLevel::INFO,
|
||||
'Ratingobject data',
|
||||
[
|
||||
'ratingobject UID' => $ratingobject->getUid(),
|
||||
'ratingobject PID' => $ratingobject->getPid(),
|
||||
'stepcount' => $stepcount,
|
||||
'stepWeights' => $stepWeights,
|
||||
'sumStepWeights' => $sumStepWeights,
|
||||
'messageCount' => count($messageArray)
|
||||
]
|
||||
);
|
||||
|
||||
//generate CSS for all ratings out of TSConfig
|
||||
foreach ($this->settings['ratingConfigurations'] as $ratingName => $ratingConfig) {
|
||||
if ($ratingName === 'default') {
|
||||
continue;
|
||||
}
|
||||
$subURI = substr(Environment::getPublicPath() . '/', strlen($_SERVER['DOCUMENT_ROOT']) + 1);
|
||||
$basePath = $this->getTypoScriptFrontendController()->baseUrl ?: '//' .
|
||||
$_SERVER['HTTP_HOST'] . '/' . $subURI;
|
||||
|
||||
$this->ratingImage = $this->objectManager->get(RatingImage::class);
|
||||
$this->ratingImage->setConf($ratingConfig['imagefile']);
|
||||
$filename = $this->ratingImage->getImageFile();
|
||||
if (empty($filename)) {
|
||||
$messageArray[] = [
|
||||
'messageText' => LocalizationUtility::translate(
|
||||
'flash.vote.renderCSS.defaultImage',
|
||||
'ThRating'
|
||||
),
|
||||
'messageTitle' => LocalizationUtility::translate(
|
||||
'flash.heading.warning',
|
||||
'ThRating'
|
||||
),
|
||||
'severity' => 'WARNING',
|
||||
'additionalInfo' => ['errorCode' => 1403192702,
|
||||
'ratingName' => $ratingName,
|
||||
'ratingConfig' => $ratingConfig, ], ];
|
||||
$defaultRatingName = $this->settings['ratingConfigurations']['default'];
|
||||
$ratingConfig = $this->settings['ratingConfigurations'][$defaultRatingName];
|
||||
$this->ratingImage->setConf($ratingConfig['imagefile']);
|
||||
$filename = $this->ratingImage->getImageFile();
|
||||
}
|
||||
$filenameUri = $basePath . '/' . $filename; //prepend host basepath if no URL is given
|
||||
|
||||
$imageDimensions = $this->ratingImage->getImageDimensions();
|
||||
$height = $imageDimensions['height'];
|
||||
$width = $imageDimensions['width'];
|
||||
$mainId = '.thRating-RObj' . $ratingobjectUid . '-' . $ratingName;
|
||||
$this->logger->log(
|
||||
LogLevel::DEBUG,
|
||||
'Main CSS info',
|
||||
[
|
||||
'mainId' => $mainId,
|
||||
'filenameUri' => $filenameUri,
|
||||
'image width' => $width,
|
||||
'image height' => $height, ]
|
||||
);
|
||||
|
||||
//calculate overall rating size depending on rating direction
|
||||
if ($ratingConfig['tilt']) {
|
||||
$width = round($width / 3, 1);
|
||||
if (!$ratingConfig['barimage']) {
|
||||
$height *= $sumStepWeights;
|
||||
}
|
||||
$cssFile .= $mainId . ' { width:' . $width . 'px; height:' . $height . 'px; }' . chr(10);
|
||||
$cssFile .= $mainId . ', ' . $mainId . ' span:hover, ' . $mainId . ' span:active, ' . $mainId .
|
||||
' span:focus, ' . $mainId . ' .current-rating { background:url(' . $filenameUri .
|
||||
') right bottom repeat-y; }' . chr(10);
|
||||
$cssFile .= $mainId . ' span, ' . $mainId . ' .current-rating { width:' . $width . 'px; }' .
|
||||
chr(10);
|
||||
} else {
|
||||
$height = round($height / 3, 1);
|
||||
if (!$ratingConfig['barimage']) {
|
||||
$width *= $sumStepWeights;
|
||||
}
|
||||
$cssFile .= $mainId . ' { width:' . $width . 'px; height:' . $height . 'px; }' . chr(10);
|
||||
$cssFile .= $mainId . ', ' . $mainId . ' span:hover, ' . $mainId . ' span:active, ' . $mainId .
|
||||
' span:focus, ' . $mainId . ' .current-rating { background:url(' . $filenameUri .
|
||||
') 0 0 repeat-x; }' . chr(10);
|
||||
$cssFile .= $mainId . ' span, ' . $mainId . ' .current-rating { height:' . $height .
|
||||
'px; line-height:' . $height . 'px; }' . chr(10);
|
||||
//calculate widths/heights related to stepweights
|
||||
}
|
||||
$cssFile .= $mainId . ' .current-poll { background:url(' . $filenameUri . '); }' . chr(10);
|
||||
}
|
||||
|
||||
//calculate widths/heights related to stepweights
|
||||
$i = 1;
|
||||
$stepPart = 0;
|
||||
$sumWeights = 0;
|
||||
foreach ($stepWeights as $stepWeight) {
|
||||
$sumWeights += $stepWeight;
|
||||
$zIndex = $stepcount - $i + 2; //add 2 to override .current-poll and .currentPollText
|
||||
//configure rating and polling styles for steps
|
||||
$oneStepPart = round($stepWeight * 100 / $sumStepWeights, 1); //calculate single width of ratingstep
|
||||
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingpoll-normal { width:' .
|
||||
$oneStepPart . '%; z-index:' . $zIndex . '; margin-left:' . $stepPart . '%;}' . chr(10);
|
||||
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingpoll-tilt { height:' .
|
||||
$oneStepPart . '%; z-index:' . $zIndex . '; margin-bottom:' . $stepPart . '%; }' . chr(10);
|
||||
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-normal { width:' .
|
||||
$oneStepPart . '%; margin-left:' . $stepPart . '%; }' . chr(10);
|
||||
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-normal span { width:100%; }' .
|
||||
chr(10);
|
||||
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-tilt { height:' .
|
||||
$oneStepPart . '%; margin-bottom:' . $stepPart . '%; }' . chr(10);
|
||||
$cssFile .= 'li.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-currentpoll-tilt span { height:100%; }' .
|
||||
chr(10);
|
||||
$stepPart = round($sumWeights * 100 / $sumStepWeights, 1); //calculate sum of widths to this ratingstep
|
||||
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingstep-normal { width:' .
|
||||
$stepPart . '%; z-index:' . $zIndex . '; }' . chr(10);
|
||||
$cssFile .= 'span.RObj' . $ratingobjectUid . '-StpOdr' . $i . '-ratingstep-tilt { height:' .
|
||||
$stepPart . '%; z-index:' . $zIndex . '; }' . chr(10);
|
||||
$i++;
|
||||
}
|
||||
//reset variables for next iteration
|
||||
unset($stepWeights, $sumWeights, $sumStepWeights);
|
||||
$this->logger->log(LogLevel::DEBUG, 'CSS finished for ratingobject');
|
||||
}
|
||||
|
||||
$this->logger->log(LogLevel::DEBUG, 'Saving CSS file', ['cssFile' => $cssFile]);
|
||||
$fp = fopen(Environment::getPublicPath() . '/' . self::DYN_CSS_FILENAME, 'wb');
|
||||
fwrite($fp, $cssFile);
|
||||
fclose($fp);
|
||||
|
||||
return $messageArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language object
|
||||
* If not ISO code is provided the default language is returned
|
||||
*
|
||||
* @param int $pid page id to which is part of the site
|
||||
* @param string|null $twoLetterIsoCode iso-639-1 string (e.g. en, de, us)
|
||||
* @return \TYPO3\CMS\Core\Site\Entity\SiteLanguage
|
||||
* @throws LanguageNotFoundException
|
||||
*/
|
||||
public function getStaticLanguageByIsoCode(int $pid, string $twoLetterIsoCode = null): SiteLanguage
|
||||
{
|
||||
/** @var Site $site */
|
||||
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pid);
|
||||
|
||||
if (!is_null($twoLetterIsoCode)) {
|
||||
foreach ($site->getAllLanguages() as $language) {
|
||||
if ($language->getTwoLetterIsoCode() === $twoLetterIsoCode) {
|
||||
return $language;
|
||||
}
|
||||
}
|
||||
throw new LanguageNotFoundException(LocalizationUtility::translate(
|
||||
'flash.general.languageNotFound',
|
||||
'ThRating'
|
||||
), 1582980369);
|
||||
}
|
||||
return $site->getDefaultLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the language object
|
||||
* If not ISO code is provided the default language is returned
|
||||
*
|
||||
* @param int $pid page id to which is part of the site
|
||||
* @param int|null $languageId iso-639-1 string (e.g. en, de, us)
|
||||
* @return \TYPO3\CMS\Core\Site\Entity\SiteLanguage
|
||||
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||
*/
|
||||
public function getStaticLanguageById(int $pid, int $languageId = null): ?SiteLanguage
|
||||
{
|
||||
/** @var Site $site */
|
||||
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pid);
|
||||
|
||||
if ($languageId) {
|
||||
return $site->getLanguageById($languageId);
|
||||
}
|
||||
return $site->getDefaultLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public function getRequest(): ServerRequestInterface
|
||||
{
|
||||
return $GLOBALS['TYPO3_REQUEST'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current request object
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Request $request
|
||||
*/
|
||||
public function setRequest(\TYPO3\CMS\Extbase\Mvc\Request $request): void
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
185
Classes/Service/ExtensionManagementService.php
Normal file
185
Classes/Service/ExtensionManagementService.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject;
|
||||
use WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf;
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Factory for model objects
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class ExtensionManagementService extends AbstractExtensionService
|
||||
{
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionConfigurationService
|
||||
*/
|
||||
protected $extensionConfigurationService;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionConfigurationService $extensionConfigurationService
|
||||
*/
|
||||
public function injectExtensionConfigurationService(ExtensionConfigurationService $extensionConfigurationService): void
|
||||
{
|
||||
$this->extensionConfigurationService = $extensionConfigurationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
|
||||
*/
|
||||
protected $extensionHelperService;
|
||||
/**
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService $extensionHelperService
|
||||
*/
|
||||
public function injectExtensionHelperService(ExtensionHelperService $extensionHelperService)
|
||||
{
|
||||
$this->extensionHelperService = $extensionHelperService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an object for ratings
|
||||
*
|
||||
* @api
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @param int $stepcount
|
||||
* @return \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\RecordNotFoundException
|
||||
*/
|
||||
public function makeRatable(string $tablename, string $fieldname, int $stepcount): Ratingobject
|
||||
{
|
||||
$this->logger->log(
|
||||
LogLevel::INFO,
|
||||
'makeRatable called',
|
||||
['tablename' => $tablename, 'fieldname' => $fieldname, 'stepcount' => $stepcount]
|
||||
);
|
||||
$this->extensionConfigurationService->prepareExtensionConfiguration();
|
||||
|
||||
$ratingobject = $this->extensionHelperService->getRatingobject(
|
||||
['ratetable' => $tablename, 'ratefield' => $fieldname]
|
||||
);
|
||||
|
||||
//create a new default stepconf having stepweight 1 for each step
|
||||
for ($i = 1; $i <= $stepcount; $i++) {
|
||||
$stepconfArray = ['ratingobject' => $ratingobject, 'steporder' => $i, 'stepweight' => 1];
|
||||
$stepconf = $this->extensionHelperService->createStepconf($stepconfArray);
|
||||
$ratingobject->addStepconf($stepconf);
|
||||
}
|
||||
|
||||
//Full reload of newly created object
|
||||
$ratingobject = $this->extensionHelperService->getRatingobject(
|
||||
['ratetable' => $tablename, 'ratefield' => $fieldname]
|
||||
);
|
||||
|
||||
// CREATE NEW DYNCSS FILE
|
||||
$this->extensionHelperService->clearDynamicCssFile();
|
||||
$this->extensionHelperService->renderDynCSS();
|
||||
$this->extensionConfigurationService->restoreCallingExtensionConfiguration();
|
||||
return $ratingobject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an object for ratings
|
||||
*
|
||||
* @api
|
||||
* @param \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepconf $stepconf
|
||||
* @param string $stepname
|
||||
* @param string|null $twoLetterIsoCode
|
||||
* @param bool $allStepconfs Take stepname for all steps and add steporder number at the end
|
||||
* @return bool
|
||||
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
|
||||
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\Exception
|
||||
*/
|
||||
public function setStepname(
|
||||
Stepconf $stepconf,
|
||||
string $stepname,
|
||||
string $twoLetterIsoCode=null,
|
||||
bool $allStepconfs = false
|
||||
): bool {
|
||||
$this->logger->log(
|
||||
LogLevel::INFO,
|
||||
'setStepname called',
|
||||
[
|
||||
'stepconf' => $stepconf->getUid(),
|
||||
'steporder' => $stepconf->getSteporder(),
|
||||
'stepname' => $stepname,
|
||||
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||
'allStepconfs' => $allStepconfs
|
||||
]
|
||||
);
|
||||
|
||||
$this->extensionConfigurationService->prepareExtensionConfiguration();
|
||||
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Ratingobject $ratingobject */
|
||||
$ratingobject = $stepconf->getRatingobject();
|
||||
|
||||
$success = true;
|
||||
if (!$allStepconfs) {
|
||||
//only add the one specific stepname
|
||||
$stepnameArray = [
|
||||
'stepname' => $stepname,
|
||||
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||
'pid' => $stepconf->getPid()
|
||||
];
|
||||
/** @var \WapplerSystems\BookmarksLikesRatings\Domain\Model\Stepname $stepname */
|
||||
$stepnameObject = $this->extensionHelperService->createStepname($stepconf, $stepnameArray);
|
||||
|
||||
if (!$stepconf->addStepname($stepnameObject)) {
|
||||
$this->logger->log(
|
||||
LogLevel::WARNING,
|
||||
'Stepname entry for language already exists',
|
||||
[
|
||||
'stepconf' => $stepconf->getUid(),
|
||||
'steporder' => $stepconf->getSteporder(),
|
||||
'stepname' => $stepnameObject,
|
||||
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||
'errorCode' => 1398972827
|
||||
]
|
||||
);
|
||||
$success = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
//add stepnames to every stepconf
|
||||
foreach ($ratingobject->getStepconfs() as $loopStepConf) {
|
||||
$stepnameArray = [
|
||||
'stepname' => $stepname . $loopStepConf->getSteporder(),
|
||||
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||
'pid' => $ratingobject->getPid()
|
||||
];
|
||||
|
||||
$stepnameObject = $this->extensionHelperService->createStepname($loopStepConf, $stepnameArray);
|
||||
if ($success && !$loopStepConf->addStepname($stepnameObject)) {
|
||||
$this->logger->log(
|
||||
LogLevel::WARNING,
|
||||
'Stepname entry for language already exists',
|
||||
[
|
||||
'stepconf' => $stepconf->getUid(),
|
||||
'steporder' => $stepconf->getSteporder(),
|
||||
'stepname' => $stepname,
|
||||
'twoLetterIsoCode' => $twoLetterIsoCode,
|
||||
'errorCode' => 1398972331
|
||||
]
|
||||
);
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->extensionConfigurationService->restoreCallingExtensionConfiguration();
|
||||
return $success;
|
||||
}
|
||||
}
|
81
Classes/Service/JsonService.php
Normal file
81
Classes/Service/JsonService.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
|
||||
/**
|
||||
* Service for setting cookies like Typo3 does
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class JsonService extends AbstractExtensionService
|
||||
{
|
||||
|
||||
/**
|
||||
* Encode a string to JSON
|
||||
* Log a warning on error
|
||||
*
|
||||
* @param mixed $content
|
||||
* @return string|false The domain to be used on setting cookies
|
||||
*/
|
||||
public function encodeToJson($content)
|
||||
{
|
||||
if (!empty($content)) {
|
||||
try {
|
||||
return json_encode($content, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
$this->logger->log(
|
||||
LogLevel::WARNING,
|
||||
LocalizationUtility::translate('system.warning.json.encode', 'ThRating', [
|
||||
1 => $content,
|
||||
]),
|
||||
[
|
||||
'errorCode' => 1615051494,
|
||||
'JSON' => $content,
|
||||
'Exception' => $e,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a string to JSON
|
||||
* Log a warning on error
|
||||
*
|
||||
* @param string|null $content
|
||||
* @return array|false The domain to be used on setting cookies
|
||||
*/
|
||||
public function decodeJsonToArray(string $content=null)
|
||||
{
|
||||
if (!empty($content)) {
|
||||
try {
|
||||
return json_decode($content, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
$this->logger->log(
|
||||
LogLevel::WARNING,
|
||||
LocalizationUtility::translate('system.warning.json.encode', 'ThRating', [
|
||||
1 => $content,
|
||||
]),
|
||||
[
|
||||
'errorCode' => 1615051494,
|
||||
'JSON' => $content,
|
||||
'Exception' => $e,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
83
Classes/Service/LoggingService.php
Normal file
83
Classes/Service/LoggingService.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Log\Logger;
|
||||
use TYPO3\CMS\Core\Log\LogManager;
|
||||
use TYPO3\CMS\Core\Log\Writer\DatabaseWriter;
|
||||
use TYPO3\CMS\Core\Log\Writer\FileWriter;
|
||||
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||
|
||||
/**
|
||||
* Factory for model objects
|
||||
*
|
||||
* @version $Id:$
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU protected License, version 2
|
||||
*/
|
||||
class LoggingService
|
||||
{
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
|
||||
*/
|
||||
protected $objectManager;
|
||||
/**
|
||||
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
|
||||
*/
|
||||
protected $configurationManager;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Must overrule the abstract class method to avoid self referencing
|
||||
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
|
||||
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager,
|
||||
*/
|
||||
public function __construct(
|
||||
ObjectManagerInterface $objectManager,
|
||||
ConfigurationManagerInterface $configurationManager
|
||||
) {
|
||||
$this->objectManager = $objectManager;
|
||||
$this->configurationManager = $configurationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance
|
||||
* The configuration of the logger is modified by extension typoscript config
|
||||
*
|
||||
* @param string $name the class name which this logger is for
|
||||
* @return \TYPO3\CMS\Core\Log\Logger
|
||||
*/
|
||||
public function getLogger(string $name): Logger
|
||||
{
|
||||
/** @var array $writerConfiguration */
|
||||
$writerConfiguration = $GLOBALS['TYPO3_CONF_VARS']['LOG']['Thucke']['ThRating']['writerConfiguration'];
|
||||
$settings = $this->configurationManager->getConfiguration(
|
||||
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||
'thRating',
|
||||
'pi1'
|
||||
);
|
||||
if (is_array($settings['logging'])) {
|
||||
foreach ($settings['logging'] as $logLevel => $logConfig) {
|
||||
$levelUppercase = strtoupper($logLevel);
|
||||
if (!empty($logConfig['file'])) {
|
||||
$writerConfiguration[constant('\TYPO3\CMS\Core\Log\LogLevel::' . $levelUppercase)][FileWriter::class] = ['logFile' => $logConfig['file']];
|
||||
}
|
||||
if (!empty($logConfig['database'])) {
|
||||
$writerConfiguration[constant('\TYPO3\CMS\Core\Log\LogLevel::' . $levelUppercase)][DatabaseWriter::class] = ['table' => $logConfig['table']];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($writerConfiguration)) {
|
||||
$GLOBALS['TYPO3_CONF_VARS']['LOG']['Thucke']['ThRating']['writerConfiguration'] = $writerConfiguration;
|
||||
}
|
||||
|
||||
return $this->objectManager->get(LogManager::class)->getLogger($name);
|
||||
}
|
||||
}
|
442
Classes/Service/RichSnippetService.php
Normal file
442
Classes/Service/RichSnippetService.php
Normal file
@@ -0,0 +1,442 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the package thucke/th-rating.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace WapplerSystems\BookmarksLikesRatings\Service;
|
||||
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\Log\LogLevel;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
|
||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||
|
||||
/**
|
||||
* The voter
|
||||
*/
|
||||
class RichSnippetService extends AbstractExtensionService
|
||||
{
|
||||
/**
|
||||
* Instances of AggregateRating may appear as properties of the following types
|
||||
* This list derives from Google's information about supported types in aggregateRating (20 May 2021)
|
||||
* (see https://developers.google.com/search/docs/data-types/review-snippet#aggregated-rating-type-definition)
|
||||
* @const array
|
||||
*/
|
||||
protected const VALID_AGGREGATE_RATING_SCHEMA_TYPES = [
|
||||
'Book',
|
||||
'Audiobook',
|
||||
'Course',
|
||||
'CreativeWorkSeason',
|
||||
'PodcastSeason',
|
||||
'RadioSeason',
|
||||
'TVSeason',
|
||||
'CreativeWorkSeries',
|
||||
'BookSeries',
|
||||
'MovieSeries',
|
||||
'Periodical',
|
||||
'ComicSeries',
|
||||
'Newspaper',
|
||||
'PodcastSeries',
|
||||
'RadioSeries',
|
||||
'TVSeries',
|
||||
'VideoGameSeries',
|
||||
'Episode',
|
||||
'PodcastEpisode',
|
||||
'RadioEpisode',
|
||||
'TVEpisode',
|
||||
'Event',
|
||||
'BusinessEvent',
|
||||
'ChildrensEvent',
|
||||
'ComedyEvent',
|
||||
'CourseInstance',
|
||||
'DanceEvent',
|
||||
'DeliveryEvent',
|
||||
'EducationEvent',
|
||||
'EventSeries',
|
||||
'ExhibitionEvent',
|
||||
'Festival',
|
||||
'FoodEvent',
|
||||
'Hackathon',
|
||||
'LiteraryEvent',
|
||||
'MusicEvent',
|
||||
'PublicationEvent',
|
||||
'BroadcastEvent',
|
||||
'OnDemandEvent',
|
||||
'SaleEvent',
|
||||
'ScreeningEvent',
|
||||
'SocialEvent',
|
||||
'SportsEvent',
|
||||
'TheaterEvent',
|
||||
'VisualArtsEvent',
|
||||
'Game',
|
||||
'VideoGame',
|
||||
'HowTo',
|
||||
'Recipe',
|
||||
'AnimalShelter',
|
||||
'ArchiveOrganization',
|
||||
'AutomotiveBusiness',
|
||||
'AutoBodyShop',
|
||||
'AutoDealer',
|
||||
'AutoRental',
|
||||
'AutoRepair',
|
||||
'AutoWash',
|
||||
'GasStation',
|
||||
'MotorcycleDealer',
|
||||
'MotorcycleRepair',
|
||||
'ChildCare',
|
||||
'DryCleaningOrLaundry',
|
||||
'EmergencyService',
|
||||
'FireStation',
|
||||
'Hospital',
|
||||
'PoliceStation',
|
||||
'EmploymentAgency',
|
||||
'EntertainmentBusiness',
|
||||
'AdultEntertainment',
|
||||
'AmusementPark',
|
||||
'ArtGallery',
|
||||
'Casino',
|
||||
'ComedyClub',
|
||||
'MovieTheater',
|
||||
'NightClub',
|
||||
'FinancialService',
|
||||
'AccountingService',
|
||||
'AutomatedTeller',
|
||||
'BankOrCreditUnion',
|
||||
'InsuranceAgency',
|
||||
'FoodEstablishment',
|
||||
'Bakery',
|
||||
'BarOrPub',
|
||||
'Brewery',
|
||||
'CafeOrCoffeeShop',
|
||||
'Distillery',
|
||||
'FastFoodRestaurant',
|
||||
'IceCreamShop',
|
||||
'Restaurant',
|
||||
'Winery',
|
||||
'GovernmentOffice',
|
||||
'PostOffice',
|
||||
'HealthAndBeautyBusiness',
|
||||
'BeautySalon',
|
||||
'DaySpa',
|
||||
'HairSalon',
|
||||
'NailSalon',
|
||||
'TattooParlor',
|
||||
'HomeAndConstructionBusiness',
|
||||
'Electrician',
|
||||
'GeneralContractor',
|
||||
'HVACBusiness',
|
||||
'HousePainter',
|
||||
'Locksmith',
|
||||
'MovingCompany',
|
||||
'Plumber',
|
||||
'RoofingContractor',
|
||||
'InternetCafe',
|
||||
'LegalService',
|
||||
'Attorney',
|
||||
'Notary',
|
||||
'Library',
|
||||
'LodgingBusiness',
|
||||
'BedAndBreakfast',
|
||||
'Campground',
|
||||
'Hostel',
|
||||
'Hotel',
|
||||
'Motel',
|
||||
'Resort',
|
||||
'MedicalBusiness',
|
||||
'CovidTestingFacility',
|
||||
'Optician',
|
||||
'Pharmacy',
|
||||
'Physician',
|
||||
'ProfessionalService',
|
||||
'RadioStation',
|
||||
'RealEstateAgent',
|
||||
'RecyclingCenter',
|
||||
'SelfStorage',
|
||||
'ShoppingCenter',
|
||||
'SportsActivityLocation',
|
||||
'BowlingAlley',
|
||||
'ExerciseGym',
|
||||
'GolfCourse',
|
||||
'HealthClub',
|
||||
'PublicSwimmingPool',
|
||||
'SkiResort',
|
||||
'SportsClub',
|
||||
'StadiumOrArena',
|
||||
'TennisComplex',
|
||||
'Store',
|
||||
'AutoPartsStore',
|
||||
'BikeStore',
|
||||
'BookStore',
|
||||
'ClothingStore',
|
||||
'ComputerStore',
|
||||
'ConvenienceStore',
|
||||
'DepartmentStore',
|
||||
'ElectronicsStore',
|
||||
'Florist',
|
||||
'FurnitureStore',
|
||||
'GardenStore',
|
||||
'GroceryStore',
|
||||
'HardwareStore',
|
||||
'HobbyShop',
|
||||
'HomeGoodsStore',
|
||||
'JewelryStore',
|
||||
'LiquorStore',
|
||||
'MensClothingStore',
|
||||
'MobilePhoneStore',
|
||||
'MovieRentalStore',
|
||||
'MusicStore',
|
||||
'OfficeEquipmentStore',
|
||||
'OutletStore',
|
||||
'PawnShop',
|
||||
'PetStore',
|
||||
'ShoeStore',
|
||||
'SportingGoodsStore',
|
||||
'TireShop',
|
||||
'ToyStore',
|
||||
'WholesaleStore',
|
||||
'TelevisionStation',
|
||||
'TouristInformationCenter',
|
||||
'TravelAgency',
|
||||
'MediaObject',
|
||||
'3DModel',
|
||||
'AudioObject',
|
||||
'DataDownload',
|
||||
'ImageObject',
|
||||
'Barcode',
|
||||
'LegislationObject',
|
||||
'MusicVideoObject',
|
||||
'VideoObject',
|
||||
'Movie',
|
||||
'MusicPlaylist',
|
||||
'MusicAlbum',
|
||||
'MusicRelease',
|
||||
'MusicRecording',
|
||||
'Organization',
|
||||
'Airline',
|
||||
'Consortium',
|
||||
'Corporation',
|
||||
'EducationalOrganization',
|
||||
'CollegeOrUniversity',
|
||||
'ElementarySchool',
|
||||
'HighSchool',
|
||||
'MiddleSchool',
|
||||
'Preschool',
|
||||
'School',
|
||||
'FundingScheme',
|
||||
'GovernmentOrganization',
|
||||
'LibrarySystem',
|
||||
'LocalBusiness',
|
||||
'MedicalOrganization',
|
||||
'NGO',
|
||||
'NewsMediaOrganization',
|
||||
'Dentist',
|
||||
'DiagnosticLab',
|
||||
'MedicalClinic',
|
||||
'VeterinaryCare',
|
||||
'PerformingGroup',
|
||||
'DanceGroup',
|
||||
'MusicGroup',
|
||||
'TheaterGroup',
|
||||
'Project',
|
||||
'FundingAgency',
|
||||
'ResearchProject',
|
||||
'SportsOrganization',
|
||||
'SportsTeam',
|
||||
'WorkersUnion',
|
||||
'Product',
|
||||
'IndividualProduct',
|
||||
'ProductCollection',
|
||||
'ProductGroup',
|
||||
'ProductModel',
|
||||
'SomeProducts',
|
||||
'Vehicle',
|
||||
'BusOrCoach',
|
||||
'Car',
|
||||
'Motorcycle',
|
||||
'MotorizedBicycle',
|
||||
'SoftwareApplication',
|
||||
'MobileApplication',
|
||||
'WebApplication'
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $schema = 'Product';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $anchor;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $richSnippetConfig;
|
||||
|
||||
/**
|
||||
* @param array $settings
|
||||
* @return bool
|
||||
*/
|
||||
public function setRichSnippetConfig(array $settings): bool
|
||||
{
|
||||
$this->logger->log(LogLevel::DEBUG, 'setRichSnippetConfig Entry point', $settings);
|
||||
$this->richSnippetConfig['tablename'] = $settings['ratetable'];
|
||||
$this->richSnippetConfig['richSnippetFields'] = $settings['richSnippetFields'];
|
||||
|
||||
if (is_array($this->richSnippetConfig['richSnippetFields'])) {
|
||||
$this->logger->log(
|
||||
LogLevel::DEBUG,
|
||||
'setRichSnippetConfig Exit point',
|
||||
$this->richSnippetConfig['richSnippetFields']
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->logger->log(LogLevel::DEBUG, 'setRichSnippetConfig Exit point');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|false
|
||||
*/
|
||||
public function getRichSnippetConfig()
|
||||
{
|
||||
return GeneralUtility::makeInstance(\WapplerSystems\BookmarksLikesRatings\Service\JsonService::class)
|
||||
->encodeToJson($this->richSnippetConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSchema(): string
|
||||
{
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $schema
|
||||
* @throws \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException if parameter is invalid
|
||||
*/
|
||||
public function setSchema(?string $schema): void
|
||||
{
|
||||
if (!empty($schema)) {
|
||||
if (in_array($schema, self::VALID_AGGREGATE_RATING_SCHEMA_TYPES, true)) {
|
||||
$this->schema = $schema;
|
||||
} else {
|
||||
throw new \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException(
|
||||
LocalizationUtility::translate(
|
||||
'error.richSnippetConfiguration.AggregateRatingPropertySchema',
|
||||
'ThRating'
|
||||
),
|
||||
1521487362
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAnchor(): string
|
||||
{
|
||||
return $this->anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $anchor
|
||||
*/
|
||||
public function setAnchor(string $anchor): void
|
||||
{
|
||||
$this->anchor = $anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
*/
|
||||
public function setName(?string $name): void
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $description
|
||||
*/
|
||||
public function setDescription(?string $description): void
|
||||
{
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @return RichSnippetService
|
||||
*@throws \WapplerSystems\BookmarksLikesRatings\Exception\InvalidAggregateRatingSchemaTypeException
|
||||
*/
|
||||
public function getRichSnippetObject(int $uid): self
|
||||
{
|
||||
$this->logger->log(LogLevel::DEBUG, 'getRichSnippetObject Entry point');
|
||||
$this->setSchema($this->richSnippetConfig['richSnippetFields']['aggregateRatingSchemaType']);
|
||||
if (empty($this->richSnippetConfig['richSnippetFields']['name'])) {
|
||||
$this->logger->log(LogLevel::INFO, 'No name field defined - skipping database access');
|
||||
unset($this->name, $this->description);
|
||||
throw new \TYPO3\CMS\Core\Exception();
|
||||
} else {
|
||||
/** @var QueryBuilder $queryBuilder */
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable($this->richSnippetConfig['tablename']);
|
||||
|
||||
//fetch whole row from database
|
||||
/** @var array $row */
|
||||
$row = $queryBuilder
|
||||
->select('*')
|
||||
->from($this->richSnippetConfig['tablename'])
|
||||
->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid)))
|
||||
->execute()
|
||||
->fetch();
|
||||
|
||||
$this->logger->log(LogLevel::DEBUG, 'Data fetched', $row);
|
||||
$this->setName($row[$this->richSnippetConfig['richSnippetFields']['name']]);
|
||||
|
||||
$contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
||||
$this->setDescription($row[$this->richSnippetConfig['richSnippetFields']['description']]);
|
||||
//$this->setDescription($contentObjectRenderer->cObjGetSingle('TEXT', $this->richSnippetConfig['richSnippetFields']['description']));
|
||||
//$this->setDescription($contentObjectRenderer->render($this->richSnippetConfig['richSnippetFields']['description']));
|
||||
}
|
||||
$this->logger->log(LogLevel::DEBUG, 'getRichSnippetObject Exit point', (array)$this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user