meilisearch/Classes/Widget/AbstractWidgetViewHelper.php
2021-04-17 21:20:54 +02:00

248 lines
8.4 KiB
PHP

<?php
namespace WapplerSystems\Meilisearch\Widget;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use WapplerSystems\Meilisearch\Mvc\Controller\MeilisearchControllerContext;
use WapplerSystems\Meilisearch\Widget\WidgetRequest as MeilisearchFluidWidgetRequest;
use TYPO3\CMS\Extbase\Mvc\Web\Response;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\RootNode;
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperInterface;
use TYPO3\CMS\Fluid\Core\Widget\AbstractWidgetViewHelper as AbstractCoreWidgetViewHelper;
use TYPO3\CMS\Fluid\Core\Widget\AjaxWidgetContextHolder;
use TYPO3\CMS\Fluid\Core\Widget\Exception\MissingControllerException;
use TYPO3\CMS\Fluid\Core\Widget\WidgetRequest as CoreWidgetRequest;
use TYPO3\CMS\Fluid\Core\Widget\WidgetContext;
use TYPO3\CMS\Extbase\Service\ExtensionService;
/**
* Class AbstractWidgetViewHelper
*
* This is almost a exact copy of \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper
* because we need to switch the request object to overrule the widget prefix for url params
* todo: find cleaner way to let widget listen to tx_meilisearch[] instead of tx_meilisearch[@widget]
*
* @author Frans Saris <frans@beech.it>
* @author Timo Hund <timo.hund@dkd.de>
*/
abstract class AbstractWidgetViewHelper extends AbstractCoreWidgetViewHelper implements ViewHelperInterface
{
/**
* The Controller associated to this widget.
* This needs to be filled by the individual subclass by di
* annotation.
*
* @var AbstractWidgetController
* @api
*/
protected $controller;
/**
* If set to TRUE, it is an AJAX widget.
*
* @var boolean
* @api
*/
protected $ajaxWidget = false;
/**
* @var AjaxWidgetContextHolder
*/
private $ajaxWidgetContextHolder;
/**
* @var ObjectManagerInterface
*/
protected $objectManager;
/**
* @var ExtensionService
*/
protected $extensionService;
/**
* @var \TYPO3\CMS\Fluid\Core\Widget\WidgetContext
*/
private $widgetContext;
/**
* @param ExtensionService $extensionService
*/
public function injectExtensionService(ExtensionService $extensionService)
{
$this->extensionService = $extensionService;
}
/**
* @param AjaxWidgetContextHolder $ajaxWidgetContextHolder
* @return void
*/
public function injectAjaxWidgetContextHolder(AjaxWidgetContextHolder $ajaxWidgetContextHolder)
{
$this->ajaxWidgetContextHolder = $ajaxWidgetContextHolder;
}
/**
* @param ObjectManagerInterface $objectManager
* @return void
*/
public function injectObjectManager(ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
$this->widgetContext = $this->objectManager->get(WidgetContext::class);
}
/**
* Initialize the arguments of the ViewHelper, and call the render() method of the ViewHelper.
*
* @return string the rendered ViewHelper.
*/
public function initializeArgumentsAndRender()
{
$this->validateArguments();
$this->initialize();
$this->initializeWidgetContext();
return $this->callRenderMethod();
}
/**
* @return MeilisearchControllerContext
* @throws \InvalidArgumentException
*/
protected function getControllerContext()
{
$controllerContext = null;
if (method_exists($this->renderingContext, 'getControllerContext')) {
$controllerContext = $this->renderingContext->getControllerContext();
}
if (!$controllerContext instanceof MeilisearchControllerContext) {
throw new \InvalidArgumentException('No valid MeilisearchControllerContext found', 1512998673);
}
return $controllerContext;
}
/**
* Initialize the Widget Context, before the Render method is called.
*
* @return void
*/
private function initializeWidgetContext()
{
$this->widgetContext->setWidgetConfiguration($this->getWidgetConfiguration());
$this->initializeWidgetIdentifier();
$this->widgetContext->setControllerObjectName(get_class($this->controller));
$extensionName = $this->getControllerContext()->getRequest()->getControllerExtensionName();
$pluginName = $this->getControllerContext()->getRequest()->getPluginName();
$this->widgetContext->setParentExtensionName($extensionName);
$this->widgetContext->setParentPluginName($pluginName);
$pluginNamespace = $this->extensionService->getPluginNamespace($extensionName, $pluginName);
$this->widgetContext->setParentPluginNamespace($pluginNamespace);
$this->widgetContext->setWidgetViewHelperClassName(get_class($this));
if ($this->ajaxWidget === true) {
$this->ajaxWidgetContextHolder->store($this->widgetContext);
}
}
/**
* Stores the syntax tree child nodes in the Widget Context, so they can be
* rendered with <f:widget.renderChildren> lateron.
*
* @param array $childNodes The SyntaxTree Child nodes of this ViewHelper.
* @return void
*/
public function setChildNodes(array $childNodes)
{
$rootNode = $this->objectManager->get(RootNode::class);
foreach ($childNodes as $childNode) {
$rootNode->addChildNode($childNode);
}
$this->widgetContext->setViewHelperChildNodes($rootNode, $this->renderingContext);
}
/**
* Generate the configuration for this widget. Override to adjust.
*
* @return array
* @api
*/
protected function getWidgetConfiguration()
{
return $this->arguments;
}
/**
* Initiate a sub request to $this->controller. Make sure to fill $this->controller
* via Dependency Injection.
*
* @return \TYPO3\CMS\Extbase\Mvc\ResponseInterface the response of this request.
* @throws MissingControllerException
*/
protected function initiateSubRequest()
{
if (!$this->controller instanceof AbstractWidgetController) {
if (isset($this->controller)) {
throw new MissingControllerException('initiateSubRequest() can not be called if there is no valid controller extending TYPO3\\CMS\\Fluid\\Core\\Widget\\AbstractWidgetController. Got "' . get_class($this->controller) . '" in class "' . get_class($this) . '".', 1289422564);
}
throw new MissingControllerException('initiateSubRequest() can not be called if there is no controller inside $this->controller. Make sure to add a corresponding injectController method to your WidgetViewHelper class "' . get_class($this) . '".', 1284401632);
}
/** @var $subRequest \WapplerSystems\Meilisearch\Widget\WidgetRequest */
$subRequest = $this->objectManager->get(MeilisearchFluidWidgetRequest::class);
$subRequest->setWidgetContext($this->widgetContext);
$this->passArgumentsToSubRequest($subRequest);
$subResponse = $this->objectManager->get(Response::class);
$this->controller->processRequest($subRequest, $subResponse);
return $subResponse;
}
/**
* Pass the arguments of the widget to the subrequest.
*
* @param CoreWidgetRequest $subRequest
* @return void
*/
private function passArgumentsToSubRequest(CoreWidgetRequest $subRequest)
{
$arguments = $this->getControllerContext()->getRequest()->getArguments();
if (isset($arguments)) {
if (isset($arguments['action'])) {
$subRequest->setControllerActionName($arguments['action']);
unset($arguments['action']);
}
$subRequest->setArguments($arguments);
}
}
/**
* The widget identifier is unique on the current page, and is used
* in the URI as a namespace for the widget's arguments.
*
* @return string the widget identifier for this widget
* @return void
* @todo clean up, and make it somehow more routing compatible.
*/
private function initializeWidgetIdentifier()
{
$this->widgetContext->setWidgetIdentifier('');
}
}