Skip to content

Commit

Permalink
OXDEV-8716 Controller as a service
Browse files Browse the repository at this point in the history
  • Loading branch information
godefroy-le-hardi committed Dec 11, 2024
1 parent 52c50ba commit ad26582
Show file tree
Hide file tree
Showing 19 changed files with 428 additions and 18 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG-7.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Added
- PHPUnit v11 support
- Category detail page codeception test
- Controllers can be registered as DI services

### Fixed
- Shop ID resolution considers SSL language URLs
Expand All @@ -18,7 +18,7 @@
- PHPUnit v10 support

### Deprecated
- Config parameters from [config.inc.php](https://docs.oxid-esales.com/developer/en/latest/development/modules_components_themes/project/configincphp.html) will be moved to env or container parameters
- Config parameters from [config.inc.php](https://docs.oxid-esales.com/developer/en/latest/development/modules_components_themes/project/configincphp.html) will be moved to env variables and container parameters
- Global functions `warningHandler(), dumpVar(), debug()`
- `ConnectionProviderInterface` will be superseded by `ConnectionFactory` in next version
- Redundant interfaces `TransactionServiceInterface, FinderFactoryInterface`
Expand Down
3 changes: 2 additions & 1 deletion source/Core/Controller/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Core\ShopVersion;
use OxidEsales\EshopCommunity\Internal\Framework\Controller\ControllerInterface;
use OxidEsales\EshopCommunity\Internal\Transition\ShopEvents\AfterRequestProcessedEvent;
use OxidEsales\Facts\Facts;
use Psr\Container\ContainerInterface;
Expand All @@ -17,7 +18,7 @@
* Base view class. Collects and passes data to template engine, sets some global
* configuration parameters.
*/
class BaseController extends \OxidEsales\Eshop\Core\Base
class BaseController extends \OxidEsales\Eshop\Core\Base implements ControllerInterface
{
/**
* Array of data that is passed to template engine - array( "varName" => "varValue").
Expand Down
10 changes: 10 additions & 0 deletions source/Core/Routing/ControllerClassNameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public function __construct(
*/
public function getClassNameById($classId)
{
$controllers = ContainerFacade::getParameter('oxid.controllers_map');
if (array_key_exists($classId, $controllers)) {
return $controllers[$classId];
}

$className = $this->getClassNameFromShopMap($classId);

if (empty($className)) {
Expand All @@ -52,6 +57,11 @@ public function getClassNameById($classId)
*/
public function getIdByClassName($className)
{
$controllers = ContainerFacade::getParameter('oxid.controllers_map');
if (in_array($className, $controllers)) {
return array_search($className, $controllers, true);
}

$classId = $this->getClassIdFromShopMap($className);

if (empty($classId)) {
Expand Down
6 changes: 4 additions & 2 deletions source/Core/ShopControl.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use OxidEsales\Eshop\Core\Exception\StandardException;
use OxidEsales\Eshop\Core\Exception\SystemComponentException;
use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Core\Di\ContainerFacade;
use OxidEsales\EshopCommunity\Internal\Framework\Controller\ControllerInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Templating\TemplateRendererBridgeInterface;
use OxidEsales\EshopCommunity\Internal\Framework\Templating\TemplateRendererInterface;
use PHPMailer\PHPMailer\PHPMailer;
Expand Down Expand Up @@ -341,7 +343,7 @@ protected function initializeViewObject($class, $function, $parameters = null, $
$classKey = !is_null($classKey) ? $classKey : $class; //fallback

/** @var FrontendController $view */
$view = oxNew($class);
$view = ContainerFacade::has($class) ? ContainerFacade::get($class) : oxNew($class);

$view->setClassKey($classKey);
$view->setFncName($function);
Expand Down Expand Up @@ -879,7 +881,7 @@ private function processTemplateRenderError(string $templateName, \Throwable $re
Registry::getLogger()->error($displayedException->getMessage(), [$rendererError]);
}

private function passSessionErrorsToViewData(BaseController $view, array $viewData): array
private function passSessionErrorsToViewData(ControllerInterface $view, array $viewData): array
{
$errors = $this->getErrors($view->getClassKey());
if (\is_array($errors) && count($errors)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Internal\Framework\Controller;

abstract class AbstractControllerDecorator implements ControllerInterface
{
public function __construct(
protected readonly ControllerInterface $controller,
) {
}

public function init()
{
$this->controller->init();
}

public function render()
{
return $this->controller->render();
}

public function getFncName()
{
return $this->controller->getFncName();
}

public function executeFunction($function)
{
$this->controller->executeFunction($function);
}

public function getIsCallForCache()
{
return $this->controller->getIsCallForCache();
}

public function getClassKey()
{
return $this->controller->getClassKey();
}

public function getViewData()
{
return $this->controller->getViewData();
}

public function setViewData($viewData = null)
{
$this->controller->setViewData($viewData);
}

public function getViewId()
{
return $this->controller->getViewId();
}

public function getCharSet()
{
return $this->controller->getCharSet();
}

public function setClassKey($classKey)
{
$this->controller->setClassKey($classKey);
}

public function setFncName($fncName)
{
$this->controller->setFncName($fncName);
}

public function setViewParameters($params = null)
{
$this->controller->setViewParameters($params);
}

public function getViewParameter($key)
{
return $this->controller->getViewParameter($key);
}
}
41 changes: 41 additions & 0 deletions source/Internal/Framework/Controller/ControllerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Internal\Framework\Controller;

interface ControllerInterface
{
public function init();

public function render();

public function executeFunction($function);

public function setClassKey($classKey);

public function getClassKey();

public function setFncName($fncName);

public function getFncName();

public function setViewParameters($params = null);

public function getViewParameter($key);

public function setViewData($viewData = null);

public function getViewData();

public function getViewId();

public function getCharSet();

public function getIsCallForCache();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Internal\Framework\DIContainer\CompilerPass;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ControllerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
$taggedServices = $container->findTaggedServiceIds('oxid.controller');
$controllersMap = [];

foreach ($taggedServices as $id => $tags) {
foreach ($tags as $attributes) {
$controllersMap[$attributes['controller_key']] = $id;
}
}

$container->setParameter('oxid.controllers_map', $controllersMap);
}
}
2 changes: 2 additions & 0 deletions source/Internal/Framework/DIContainer/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace OxidEsales\EshopCommunity\Internal\Framework\DIContainer;

use OxidEsales\EshopCommunity\Internal\Framework\DIContainer\CompilerPass\ControllerPass;
use OxidEsales\EshopCommunity\Internal\Framework\DIContainer\Dao\ProjectYamlDao;
use OxidEsales\EshopCommunity\Internal\Framework\DIContainer\Service\ProjectYamlImportService;
use OxidEsales\EshopCommunity\Internal\Framework\Logger\LoggerServiceFactory;
Expand Down Expand Up @@ -42,6 +43,7 @@ public function getContainer(): SymfonyContainerBuilder
$symfonyContainer = new SymfonyContainerBuilder();
$symfonyContainer->addCompilerPass(new RegisterListenersPass());
$symfonyContainer->addCompilerPass(new AddConsoleCommandPass());
$symfonyContainer->addCompilerPass(new ControllerPass());
$this->loadEditionServices($symfonyContainer);
$this->loadModuleServices($symfonyContainer);
$this->loadProjectServices($symfonyContainer);
Expand Down
15 changes: 3 additions & 12 deletions source/Internal/Transition/ShopEvents/BeforeHeadersSendEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,23 @@

use OxidEsales\Eshop\Core\Controller\BaseController;
use OxidEsales\Eshop\Core\ShopControl;
use OxidEsales\EshopCommunity\Internal\Framework\Controller\ControllerInterface;
use Symfony\Contracts\EventDispatcher\Event;

class BeforeHeadersSendEvent extends Event
{
public function __construct(
private ShopControl $shopControl,
private BaseController $controller
private ControllerInterface $controller
) {
}

/**
* Getter for ShopControl object.
*
* @return ShopControl
*/
public function getShopControl(): ShopControl
{
return $this->shopControl;
}

/**
* Getter for controller object.
*
* @return BaseController
*/
public function getController(): BaseController
public function getController(): ControllerInterface
{
return $this->controller;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "oxid-esales/module1",
"description": "",
"type": "oxideshop-module",
"license": [
"GPL-3.0"
],
"autoload": {
"psr-4": {
"OxidEsales\\Module1\\": "src/"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

use OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller\ModuleController;
use OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller\ModuleControllerMissingTemplate;

$sMetadataVersion = '2.1';

$aModule = [
'id' => 'module1',
'controllers' => [
'module1_controller' => ModuleController::class,
],
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
services:
_defaults:
autowire: true

OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller\ModuleControllerAsService:
tags:
- { name: 'oxid.controller', controller_key: 'test_module_controller_as_service' }
public: true

OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller\ModuleControllerDecorator:
decorates: OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller\ModuleControllerAsService
arguments: [ '@.inner' ]
public: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller;

use OxidEsales\Eshop\Application\Controller\FrontendController;

class ModuleController extends FrontendController
{
protected $_sThisTemplate = '@module1/module_controller';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Module\Controller\Fixtures\module1\src\Controller;

use OxidEsales\EshopCommunity\Core\Controller\BaseController;

class ModuleControllerAsService extends BaseController
{
protected $_sThisTemplate = '@module1/module_controller_as_service';

public function testFunction(): void
{
echo 'Function output';
}
}
Loading

0 comments on commit ad26582

Please sign in to comment.