Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config/services/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ services:
_defaults:
public: true

OpenConext\EngineBlockBundle\Bridge\EngineBlockBootstrapper:
autowire: true
autoconfigure: true
tags:
- { name: kernel.event_subscriber }

OpenConext\EngineBlock\Xml\:
resource: '../../src/OpenConext/EngineBlock/Xml'
exclude: '../../src/OpenConext/EngineBlock/Xml/ValueObjects'
Expand Down
14 changes: 5 additions & 9 deletions library/EngineBlock/Application/DiContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@
use OpenConext\EngineBlock\Validator\AllowedSchemeValidator;
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Twig\Environment;

/**
* This DiContainer relies on fetching services from the Symfony service container. This is no longer the way to go.
* Instead, going forward, inject new dependencies into \OpenConext\EngineBlockBundle\Bridge\DiContainerRuntime
* This way we no longer need to worry about Symfony purging services and Symfony can properly optimize it's service container.
*/
class EngineBlock_Application_DiContainer extends \Pimple\Container
{
const ATTRIBUTE_METADATA = 'attributeMetadata';
Expand Down Expand Up @@ -405,14 +409,6 @@ public function getEncryptionKeysConfiguration()
return $this->container->getParameter('encryption_keys');
}

/**
* @return Environment
*/
public function getTwigEnvironment()
{
return $this->container->get('twig');
}

/**
* @return array
*/
Expand Down
19 changes: 17 additions & 2 deletions library/EngineBlock/ApplicationSingleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
*/

use OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy;
use OpenConext\EngineBlock\Metadata\Entity\IdentityProvider;
use OpenConext\EngineBlock\Metadata\MetadataRepository\EntityNotFoundException;
use OpenConext\EngineBlock\Request\RequestId;
use OpenConext\EngineBlockBundle\Bridge\DiContainerRuntime;
use OpenConext\EngineBlockBundle\Exception\Art;
use Psr\Log\LoggerInterface;
use SAML2\XML\saml\Issuer;
use Symfony\Component\DependencyInjection\ContainerInterface;

define('ENGINEBLOCK_FOLDER_ROOT' , realpath(__DIR__ . '/../../') . '/');
Expand Down Expand Up @@ -80,6 +79,8 @@ class EngineBlock_ApplicationSingleton
*/
protected $_diContainer;

protected ?DiContainerRuntime $_diContainerRuntime = null;

/**
* @var ManualOrDecoratedActivationStrategy
*/
Expand Down Expand Up @@ -109,6 +110,20 @@ public static function getInstance()
return self::$s_instance;
}

public function setDiContainerRuntime(DiContainerRuntime $diContainerRuntime): void
{
$this->_diContainerRuntime = $diContainerRuntime;
}

public function getDiContainerRuntime(): DiContainerRuntime
{
if ($this->_diContainerRuntime === null) {
throw new RuntimeException('The DiContainerRuntime is not ready yet!');
}

return $this->_diContainerRuntime;
}

/**
* Get THE Log instance.
*
Expand Down
2 changes: 1 addition & 1 deletion library/EngineBlock/Corto/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ protected function _processProxyServerResponseBody(EngineBlock_Http_Response $re

protected function _getCoreProxy()
{
$twig = EngineBlock_ApplicationSingleton::getInstance()->getDiContainer()->getTwigEnvironment();
$twig = EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->twig;
return new EngineBlock_Corto_ProxyServer($twig);
}

Expand Down
2 changes: 1 addition & 1 deletion library/EngineBlock/Corto/Module/Bindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public function __construct(EngineBlock_Corto_ProxyServer $server)
$diContainer = EngineBlock_ApplicationSingleton::getInstance()->getDiContainer();
$this->_featureConfiguration = $diContainer->getFeatureConfiguration();
$this->_logger = EngineBlock_ApplicationSingleton::getLog();
$this->twig = $diContainer->getTwigEnvironment();
$this->twig = EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->twig;
$this->acsLocationSchemeValidator = $diContainer->getAcsLocationSchemeValidator();
$this->stepupIdentityProvider = $diContainer->getStepupIdentityProvider($this->_server);
}
Expand Down
9 changes: 5 additions & 4 deletions library/EngineBlock/Corto/Module/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public function serve($serviceName)
private function factoryService($className, EngineBlock_Corto_ProxyServer $server)
{
$diContainer = EngineBlock_ApplicationSingleton::getInstance()->getDiContainer();
$diContainerRuntime = EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime();

switch($className) {
case EngineBlock_Corto_Module_Service_ProvideConsent::class :
Expand All @@ -84,7 +85,7 @@ private function factoryService($className, EngineBlock_Corto_ProxyServer $serve
$diContainer->getConsentFactory(),
$diContainer->getConsentService(),
$diContainer->getAuthenticationStateHelper(),
$diContainer->getTwigEnvironment(),
$diContainerRuntime->twig,
$diContainer->getProcessingStateHelper(),
$diContainer->getDiscoverySelectionService()
);
Expand Down Expand Up @@ -122,19 +123,19 @@ private function factoryService($className, EngineBlock_Corto_ProxyServer $serve
return new EngineBlock_Corto_Module_Service_SingleSignOn(
$server,
$diContainer->getXmlConverter(),
$diContainer->getTwigEnvironment(),
$diContainerRuntime->twig,
$diContainer->getServiceProviderFactory(),
$diContainer->getDiscoverySelectionService()
);
case EngineBlock_Corto_Module_Service_ContinueToIdp::class :
return new EngineBlock_Corto_Module_Service_ContinueToIdp(
$server,
$diContainer->getXmlConverter(),
$diContainer->getTwigEnvironment(),
$diContainerRuntime->twig,
$diContainer->getServiceProviderFactory()
);
default :
return new $className($server, $diContainer->getXmlConverter(), $diContainer->getTwigEnvironment());
return new $className($server, $diContainer->getXmlConverter(), $diContainerRuntime->twig);
}
}
}
35 changes: 35 additions & 0 deletions src/OpenConext/EngineBlockBundle/Bridge/DiContainerRuntime.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/**
* Copyright 2025 SURFnet B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace OpenConext\EngineBlockBundle\Bridge;

use Twig\Environment;

/**
* In contrast to DiContainer, this provider is constructed 'runtime'.
* As in, the current DiContainer is needed very early in the bootstrapping process, so it's not possible to inject dependencies into it.
*
* This provider should be used for all new dependencies.
*/
final readonly class DiContainerRuntime
{

public function __construct(public Environment $twig)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/**
* Copyright 2025 SURFnet B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace OpenConext\EngineBlockBundle\Bridge;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

class EngineBlockBootstrapper implements EventSubscriberInterface
{
private readonly DiContainerRuntime $diContainerRuntime;

public function __construct(
Environment $twig,
) {
$this->diContainerRuntime = new DiContainerRuntime($twig);
}

public function onKernelRequest(): void
{
$engineBlock = \EngineBlock_ApplicationSingleton::getInstance();
$engineBlock->setDiContainerRuntime($this->diContainerRuntime);
}

public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 100],
];
}
}
5 changes: 5 additions & 0 deletions tests/library/EngineBlock/Test/Corto/Module/BindingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Mockery as m;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider;
use OpenConext\EngineBlockBundle\Bridge\DiContainerRuntime;
use PHPUnit\Framework\TestCase;
use SAML2\Assertion;
use SAML2\Assertion\Validation\ConstraintValidator\NotBefore;
Expand Down Expand Up @@ -48,6 +49,10 @@ public function setUp(): void
new EngineBlock_X509_PrivateKey(__DIR__.'/test.pem.key')
)
);

$engineBlock = \EngineBlock_ApplicationSingleton::getInstance();
$engineBlock->setDiContainerRuntime(new DiContainerRuntime(Phake::mock(Twig\Environment::class)));

$this->bindings = new EngineBlock_Corto_Module_Bindings($proxyServer);
}

Expand Down