Skip to content

Commit

Permalink
Add autowiring for actions and views
Browse files Browse the repository at this point in the history
  • Loading branch information
digedag committed Oct 6, 2024
1 parent d25df61 commit 4089bc4
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Changelog
v1.19.0 (??.10.2024)
* Use Doctrine and QueryBuilder for insert, update and delete statements
* new delete()-method for PersistanceRepository
* Possible BC: moved tx_rnbase_controller to PSR-4 and declared some underscore-methods private
* Action and View-classes based on AbstractAction and AbstractView can use autowiring from TYPO3 10 and higher

v1.18.2 (11.07.2024)
* Fix PHP warnings
Expand Down
39 changes: 39 additions & 0 deletions Classes/DependencyInjection/FrontendServicePass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Sys25\RnBase\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Sys25\RnBase\Frontend\Controller\AbstractAction;
use Sys25\RnBase\Frontend\Service\FrontendServiceProvider;
use Sys25\RnBase\Frontend\View\AbstractView;

class FrontendServicePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
// always first check if the primary service is defined
if (!$container->has(FrontendServiceProvider::class)) {
return;
}

$definition = $container->findDefinition(FrontendServiceProvider::class);

// find all tagged service IDs
$taggedServices = $container->findTaggedServiceIds(AbstractAction::SERVICE_TAG);

foreach ($taggedServices as $id => $tags) {
// add the service to the ServiceProvider service
$definition->addMethodCall('addFrontendAction', [new Reference($id)]);
}

// find all tagged service IDs
$taggedServices = $container->findTaggedServiceIds(AbstractView::SERVICE_TAG);

foreach ($taggedServices as $id => $tags) {
// add the service to the ServiceProvider service
$definition->addMethodCall('addFrontendView', [new Reference($id)]);
}
}
}
2 changes: 2 additions & 0 deletions Classes/Frontend/Controller/AbstractAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
*/
abstract class AbstractAction
{
public const SERVICE_TAG = 'sys25.frontend.action';

/**
* This method is called by base controller.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
<?php

namespace Sys25\RnBase\Frontend\Controller;

use Sys25\RnBase\Configuration\ConfigurationInterface;
use Sys25\RnBase\Configuration\Processor;
use Sys25\RnBase\Exception\ExceptionHandler;
use Sys25\RnBase\Exception\ExceptionHandlerInterface;
use Sys25\RnBase\Exception\PageNotFound404;
use Sys25\RnBase\Exception\SkipActionException;
use Sys25\RnBase\Frontend\Request\Parameters;
use Sys25\RnBase\Frontend\Request\ParametersInterface;
use Sys25\RnBase\Frontend\Service\FrontendServiceProvider;
use Sys25\RnBase\Utility\Arrays;
use Sys25\RnBase\Utility\Logger;
use Sys25\RnBase\Utility\Misc;
use Sys25\RnBase\Utility\Strings;
use Sys25\RnBase\Utility\TYPO3;
use Throwable;
use tx_rnbase;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;

/***************************************************************
* Copyright notice
*
* (c) 2007-2013 René Nitzsche
* (c) 2007-2024 René Nitzsche
* All rights reserved
*
* Based on code by Elmar Hinz Contact: elmar.hinz@team-red.net
Expand Down Expand Up @@ -112,7 +118,7 @@
* FIXME: move to PSR-4
*/

class tx_rnbase_controller
class MainController
{
public $configurationsClassName = Processor::class; // You may overwrite this in your subclass with an own configurations class.

Expand All @@ -130,6 +136,13 @@ class tx_rnbase_controller

private $errors = [];

private $frontendServiceProvider;

public function __construct(?FrontendServiceProvider $frontendServiceProvider = null)
{
$this->frontendServiceProvider = $frontendServiceProvider ?: null;
}

public function setContentObjectRenderer(ContentObjectRenderer $cObj): void
{
$this->cObj = $cObj;
Expand Down Expand Up @@ -212,7 +225,7 @@ public function main($out, $configurationArray)

// Making the configurations object
Misc::pushTT('init configuration', '');
/** @var $configurations Processor */
/** @var Processor $configurations */
$configurations = $this->_makeConfigurationsObject($configurationArray);
Misc::pullTT();

Expand Down Expand Up @@ -260,22 +273,42 @@ public function main($out, $configurationArray)
return $out;
}

/**
* @param mixed $actionName
* @return AbstractAction
*/
private function lookupActionService($actionName)
{
// Zuerst im DI-Container suchen
$action = null;
if ($this->frontendServiceProvider) {
$action = $this->frontendServiceProvider->getActionForClass($actionName);
}

if (!$action) {
// Fallback auf alte Services. In T3 8 und 9 müssen sich die Extension ggf. selber kümmern.
$action = tx_rnbase::makeInstance($actionName);
}

return $action;
}

/**
* Call a single action.
*
* @param string $actionName class name
* @param tx_rnbase_IParams $parameters
* @param Tx_Rnbase_Configuration_ProcessorInterface $configurations
* @param string $actionName class name
* @param ParametersInterface $parameters
* @param ConfigurationInterface $configurations
*
* @return string
*/
public function doAction($actionName, &$parameters, &$configurations)
public function doAction(string $actionName, ParametersInterface $parameters, ConfigurationInterface $configurations)
{
$ret = '';

try {
// Creating the responsible Action
$action = tx_rnbase::makeInstance($actionName);
$action = $this->lookupActionService($actionName);
if (is_object($action)) {
$ret = $action->execute($parameters, $configurations);
}
Expand Down Expand Up @@ -433,7 +466,7 @@ protected function _findAction($parameters, $configurations)
*
* @return string the action value
*/
public function _getParameterAction($parameters)
private function _getParameterAction($parameters)
{
$action = $parameters->offsetExists('action') ? $parameters->offsetGet('action') : '';
if (!is_array($action)) {
Expand All @@ -450,9 +483,9 @@ public function _getParameterAction($parameters)
*
* @param array $configurationArray the local configuration array
*
* @return Tx_Rnbase_Configuration_ProcessorInterface the configurations
* @return ConfigurationInterface the configurations
*/
public function _makeConfigurationsObject($configurationArray)
private function _makeConfigurationsObject($configurationArray)
{
// TODO, die Configklasse sollte über TS variabel gehalten werden
// Make configurations object
Expand Down
2 changes: 1 addition & 1 deletion Classes/Frontend/Filter/BaseFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/***************************************************************
* Copyright notice
*
* (c) 2009-2023 Rene Nitzsche
* (c) 2009-2024 Rene Nitzsche
* Contact: rene@system25.de
* All rights reserved
*
Expand Down
2 changes: 1 addition & 1 deletion Classes/Frontend/Filter/FilterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/***************************************************************
* Copyright notice
*
* (c) 2009 Rene Nitzsche
* (c) 2009-2024 Rene Nitzsche
* Contact: rene@system25.de
* All rights reserved
*
Expand Down
64 changes: 64 additions & 0 deletions Classes/Frontend/Service/FrontendServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Sys25\RnBase\Frontend\Service;

use ReflectionClass;
use Sys25\RnBase\Frontend\Controller\AbstractAction;
use Sys25\RnBase\Frontend\View\AbstractView;

/***************************************************************
* Copyright notice
*
* (c) 2007-2024 Rene Nitzsche <rene@system25.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

class FrontendServiceProvider
{
private $actions = [];
private $views = [];
private $filters = [];

public function addFrontendAction(AbstractAction $action): void
{
$this->actions[get_class($action)] = $action;
}

public function getActionForClass(string $actionClass): ?AbstractAction
{
if (!array_key_exists($actionClass, $this->actions) && class_exists($actionClass)) {
// Hier werden häufig aliases verwendet.
$reflection = new ReflectionClass($actionClass);
$action = $reflection->getName();
$this->actions[$actionClass] = $this->actions[$action] ?? null;
}

return $this->actions[$actionClass] ?? null;
}

public function addFrontendView(AbstractView $view): void
{
$this->views[get_class($view)] = $view;
}

public function getViewForClass(string $viewClass): ?AbstractView
{
return $this->views[$viewClass] ?? null;
}
}
4 changes: 3 additions & 1 deletion Classes/Frontend/View/AbstractView.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/***************************************************************
* Copyright notice
*
* (c) 2007-2019 René Nitzsche <rene@system25.de>
* (c) 2007-2024 René Nitzsche <rene@system25.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
Expand All @@ -29,6 +29,8 @@

abstract class AbstractView
{
public const SERVICE_TAG = 'sys25.frontend.view';

protected $pathToTemplates;

protected $templateFile;
Expand Down
16 changes: 15 additions & 1 deletion Classes/Frontend/View/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Sys25\RnBase\Frontend\View;

use Sys25\RnBase\Frontend\Request\RequestInterface;
use Sys25\RnBase\Frontend\Service\FrontendServiceProvider;
use tx_rnbase;

/***************************************************************
Expand Down Expand Up @@ -30,13 +31,26 @@

class Factory
{
private $frontendServiceProvider;

public function __construct(?FrontendServiceProvider $frontendServiceProvider = null)
{
$this->frontendServiceProvider = $frontendServiceProvider ?: null;
}

public function createView(RequestInterface $context, $fallbackViewClassName, $templateFile)
{
$configurations = $context->getConfigurations();
// It is possible to set another view via typoscript
$viewClassName = $configurations->get($context->getConfId().'viewClassName');
$viewClassName = strlen($viewClassName) > 0 ? $viewClassName : $fallbackViewClassName;
$view = tx_rnbase::makeInstance($viewClassName);

$view = null;
if ($this->frontendServiceProvider) {
$view = $this->frontendServiceProvider->getViewForClass($viewClassName);
}

$view = $view ?? tx_rnbase::makeInstance($viewClassName);
$view->setTemplatePath($configurations->getTemplatePath());
$view->setTemplateFile($templateFile);

Expand Down
6 changes: 6 additions & 0 deletions Configuration/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Sys25\RnBase\Domain\Repository\AbstractRepository;
use Sys25\RnBase\Frontend\Controller\AbstractAction;
use Sys25\RnBase\Frontend\View\AbstractView;

return function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) {
$containerBuilder->registerForAutoconfiguration(AbstractRepository::class)->addTag(AbstractRepository::SERVICE_TAG);
$containerBuilder->addCompilerPass(new DependencyInjection\DomainRepositoryPass());

$containerBuilder->registerForAutoconfiguration(AbstractAction::class)->addTag(AbstractAction::SERVICE_TAG);
$containerBuilder->registerForAutoconfiguration(AbstractView::class)->addTag(AbstractView::SERVICE_TAG);
$containerBuilder->addCompilerPass(new DependencyInjection\FrontendServicePass());
};
10 changes: 10 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ services:
'../Classes/Testing/*'
]

Sys25\RnBase\Frontend\Controller\MainController:
public: true

tx_rnbase_controller:
alias: Sys25\RnBase\Frontend\Controller\MainController
public: true

Sys25\RnBase\Frontend\View\Factory:
public: true

Sys25\RnBase\Backend\Module\ModFuncFrame:
public: true

Expand Down
1 change: 1 addition & 0 deletions Migrations/Code/ClassAliasMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
'tx_rnbase_cache_Manager' => Sys25\RnBase\Cache\CacheManager::class,
'tx_rnbase_cache_TYPO3Cache62' => Sys25\RnBase\Cache\TYPO3Cache62::class,
'tx_rnbase_configurations' => Sys25\RnBase\Configuration\Processor::class,
'tx_rnbase_controller' => Sys25\RnBase\Frontend\Controller\MainController::class,
'tx_rnbase_exception_Handler' => Sys25\RnBase\Exception\ExceptionHandler::class,
'tx_rnbase_exception_IHandler' => Sys25\RnBase\Exception\ExceptionHandlerInterface::class,
'tx_rnbase_exception_ItemNotFound404' => Sys25\RnBase\Exception\PageNotFound404::class,
Expand Down

0 comments on commit 4089bc4

Please sign in to comment.