258 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?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\ViewHelpers;
 | 
						|
 | 
						|
use TYPO3\CMS\Core\Log\LogLevel;
 | 
						|
use TYPO3\CMS\Core\Utility\GeneralUtility;
 | 
						|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
 | 
						|
use TYPO3\CMS\Extbase\Object\ObjectManager;
 | 
						|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 | 
						|
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 | 
						|
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 | 
						|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
 | 
						|
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
 | 
						|
 | 
						|
/**
 | 
						|
 * The Rating Viewhelper
 | 
						|
 *
 | 
						|
 * Renders the rating view based upon plugin.tx_thrating
 | 
						|
 * Only the argument ratedobjectuid is required.
 | 
						|
 * Others could be used to configure the output
 | 
						|
 *
 | 
						|
 * = Example =
 | 
						|
 *
 | 
						|
 * <code title="Render rating view">
 | 
						|
 * <thr:rating ratetable="some_tablename" ratefield="one_field_of_the_table" ratedobjectuid="UID integer" ></thr:rating>
 | 
						|
 * </code>
 | 
						|
 * <output>
 | 
						|
 * rendered rating
 | 
						|
 * </output>
 | 
						|
 */
 | 
						|
class RatingViewHelper extends AbstractViewHelper
 | 
						|
{
 | 
						|
    use CompileWithRenderStatic;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Disable escaping of this node's output
 | 
						|
     *
 | 
						|
     * @var bool
 | 
						|
     */
 | 
						|
    protected $escapeOutput = false;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @noinspection PhpUnnecessaryFullyQualifiedNameInspection
 | 
						|
     * @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
 | 
						|
     *      contains a backup of the current['TSFE'] if used in BE mode
 | 
						|
     */
 | 
						|
    protected static $tsfeBackup;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @noinspection PhpFullyQualifiedNameUsageInspection
 | 
						|
     * @var \TYPO3\CMS\Core\Log\Logger $logger
 | 
						|
     */
 | 
						|
    protected $logger;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var array
 | 
						|
     */
 | 
						|
    protected $typoScriptSetup;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @noinspection PhpUnnecessaryFullyQualifiedNameInspection
 | 
						|
     * @var \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
 | 
						|
     */
 | 
						|
    protected $extensionHelperService;
 | 
						|
 | 
						|
    public function initializeArguments(): void
 | 
						|
    {
 | 
						|
        $this->registerArgument('action', 'string', 'The rating action');
 | 
						|
        $this->registerArgument('ratetable', 'string', 'The rating tablename');
 | 
						|
        $this->registerArgument('ratefield', 'string', 'The rating fieldname');
 | 
						|
        $this->registerArgument('ratedobjectuid', 'integer', 'The ratingobject uid', true);
 | 
						|
        $this->registerArgument('ratingobject', 'integer', 'The ratingobject');
 | 
						|
        $this->registerArgument('display', 'string', 'The display configuration');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Renders the ratingView
 | 
						|
     *
 | 
						|
     * @param array $arguments
 | 
						|
     * @param \Closure $renderChildrenClosure
 | 
						|
     * @param RenderingContextInterface $renderingContext
 | 
						|
     * @return mixed
 | 
						|
     * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
 | 
						|
     * @noinspection PhpFullyQualifiedNameUsageInspection
 | 
						|
     */
 | 
						|
    public static function renderStatic(
 | 
						|
        array $arguments,
 | 
						|
        \Closure $renderChildrenClosure,
 | 
						|
        RenderingContextInterface $renderingContext
 | 
						|
    ) {
 | 
						|
        $typoscriptObjectPath = 'plugin.tx_thrating';
 | 
						|
        $ratedobjectuid = $arguments['ratedobjectuid'];
 | 
						|
        $action = $arguments['action'];
 | 
						|
        $ratingobject = $arguments['ratingobject'];
 | 
						|
        $ratetable = $arguments['ratetable'];
 | 
						|
        $ratefield = $arguments['ratefield'];
 | 
						|
        $display = $arguments['display'];
 | 
						|
        $extensionHelperService = static::getExtensionHelperService();
 | 
						|
        $contentObjectRenderer = static::getContentObjectRenderer();
 | 
						|
 | 
						|
        //instantiate the logger
 | 
						|
        $logger = $extensionHelperService->getLogger(__CLASS__);
 | 
						|
        $logger->log(
 | 
						|
            LogLevel::DEBUG,
 | 
						|
            'Entry point',
 | 
						|
            [
 | 
						|
                'Viewhelper parameters' => [
 | 
						|
                    'action' => $action,
 | 
						|
                    'ratingobject' => $ratingobject,
 | 
						|
                    'ratetable' => $ratetable,
 | 
						|
                    'ratefield' => $ratefield,
 | 
						|
                    'ratedobjectuid' => $ratedobjectuid,
 | 
						|
                    'display' => $display, ],
 | 
						|
                    'typoscript' => static::getConfigurationManager()
 | 
						|
                        ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT),
 | 
						|
            ]
 | 
						|
        );
 | 
						|
 | 
						|
        if (TYPO3_MODE === 'BE') {
 | 
						|
            static::simulateFrontendEnvironment();
 | 
						|
        }
 | 
						|
        $contentObjectRenderer->start([]);
 | 
						|
 | 
						|
        $pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
 | 
						|
        $lastSegment = array_pop($pathSegments);
 | 
						|
        $setup = static::getConfigurationManager()
 | 
						|
            ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
 | 
						|
        foreach ($pathSegments as $segment) {
 | 
						|
            if (!array_key_exists($segment . '.', $setup)) {
 | 
						|
                $logger->log(
 | 
						|
                    LogLevel::CRITICAL,
 | 
						|
                    'TypoScript object path does not exist',
 | 
						|
                    [
 | 
						|
                        'Typoscript object path' => htmlspecialchars($typoscriptObjectPath),
 | 
						|
                        'Setup' => $setup,
 | 
						|
                        'errorCode' => 1253191023, ]
 | 
						|
                );
 | 
						|
 | 
						|
                throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
 | 
						|
                    'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
 | 
						|
                    1549388144
 | 
						|
                );
 | 
						|
            }
 | 
						|
            $setup = $setup[$segment . '.'];
 | 
						|
        }
 | 
						|
 | 
						|
        if (!isset($setup[$lastSegment])) {
 | 
						|
            throw new \TYPO3Fluid\Fluid\Core\ViewHelper\Exception(
 | 
						|
                'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
 | 
						|
                1549388123
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        if (!empty($action)) {
 | 
						|
            $setup[$lastSegment . '.']['action'] = $action;
 | 
						|
            $setup[$lastSegment . '.']['switchableControllerActions.']['Vote.']['1'] = $action;
 | 
						|
        }
 | 
						|
        if (!empty($ratingobject)) {
 | 
						|
            $setup[$lastSegment . '.']['settings.']['ratingobject'] = $ratingobject;
 | 
						|
        } elseif (!empty($ratetable) && !empty($ratefield)) {
 | 
						|
            $setup[$lastSegment . '.']['settings.']['ratetable'] = $ratetable;
 | 
						|
            $setup[$lastSegment . '.']['settings.']['ratefield'] = $ratefield;
 | 
						|
        } else {
 | 
						|
            $logger->log(
 | 
						|
                LogLevel::CRITICAL,
 | 
						|
                'ratingobject not specified or ratetable/ratfield not set',
 | 
						|
                ['errorCode' => 1399727698]
 | 
						|
            );
 | 
						|
            throw new Exception('ratingobject not specified or ratetable/ratfield not set', 1399727698);
 | 
						|
        }
 | 
						|
        if (!empty($ratedobjectuid)) {
 | 
						|
            $setup[$lastSegment . '.']['settings.']['ratedobjectuid'] = $ratedobjectuid;
 | 
						|
        } else {
 | 
						|
            $logger->log(LogLevel::CRITICAL, 'ratedobjectuid not set', ['errorCode' => 1304624408]);
 | 
						|
            throw new Exception('ratedobjectuid not set', 1304624408);
 | 
						|
        }
 | 
						|
        if (!empty($display)) {
 | 
						|
            $setup[$lastSegment . '.']['settings.']['display'] = $display;
 | 
						|
        }
 | 
						|
 | 
						|
        $logger->log(
 | 
						|
            LogLevel::DEBUG,
 | 
						|
            'Single contentObjectRenderer to get',
 | 
						|
            [
 | 
						|
                'contentObjectRenderer type' => $setup[$lastSegment],
 | 
						|
                'cOjb config' => $setup[$lastSegment . '.'], ]
 | 
						|
        );
 | 
						|
 | 
						|
        $content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ?? []);
 | 
						|
        if (TYPO3_MODE === 'BE') {
 | 
						|
            static::resetFrontendEnvironment();
 | 
						|
        }
 | 
						|
 | 
						|
        $logger->log(LogLevel::INFO, 'Generated content', ['content' => $content]);
 | 
						|
        $logger->log(LogLevel::DEBUG, 'Exit point');
 | 
						|
 | 
						|
        return $content;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return \WapplerSystems\BookmarksLikesRatings\Service\ExtensionHelperService
 | 
						|
     */
 | 
						|
    protected static function getExtensionHelperService(): ExtensionHelperService
 | 
						|
    {
 | 
						|
        return GeneralUtility::makeInstance(ObjectManager::class)->get(ExtensionHelperService::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return object|\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
 | 
						|
     */
 | 
						|
    protected static function getConfigurationManager()
 | 
						|
    {
 | 
						|
        return GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationManagerInterface::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
 | 
						|
     */
 | 
						|
    protected static function getContentObjectRenderer(): ContentObjectRenderer
 | 
						|
    {
 | 
						|
        return GeneralUtility::makeInstance(
 | 
						|
            ContentObjectRenderer::class,
 | 
						|
            $GLOBALS['TSFE'] ?? GeneralUtility::makeInstance(TypoScriptFrontendController::class, null, 0, 0)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Sets the $TSFE->cObjectDepthCounter in Backend mode
 | 
						|
     * This somewhat hacky work around is currently needed because the cObjGetSingle() function
 | 
						|
     * of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on this setting
 | 
						|
     */
 | 
						|
    protected static function simulateFrontendEnvironment(): void
 | 
						|
    {
 | 
						|
        static::$tsfeBackup = $GLOBALS['TSFE'] ?? null;
 | 
						|
        /** @noinspection PhpFullyQualifiedNameUsageInspection */
 | 
						|
        $GLOBALS['TSFE'] = new \stdClass();
 | 
						|
        $GLOBALS['TSFE']->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
 | 
						|
        $GLOBALS['TSFE']->cObjectDepthCounter = 100;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment()
 | 
						|
     *
 | 
						|
     * @see simulateFrontendEnvironment()
 | 
						|
     */
 | 
						|
    protected static function resetFrontendEnvironment(): void
 | 
						|
    {
 | 
						|
        $GLOBALS['TSFE'] = static::$tsfeBackup;
 | 
						|
    }
 | 
						|
}
 |