From 5d986dab9380c6297572b86b18c3d414e4d64e9f Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Fri, 31 Oct 2025 10:07:58 +0100 Subject: [PATCH 1/3] IBX-10764: Remove dependencies to Platform.sh --- .../IbexaCoreExtension.php | 184 ------------------ .../TrustedHeaderClientIpEventSubscriber.php | 10 - .../IbexaCoreExtensionTest.php | 45 ----- ...ustedHeaderClientIpEventSubscriberTest.php | 55 +----- 4 files changed, 5 insertions(+), 289 deletions(-) diff --git a/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php b/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php index 854d1d057d..ae9624e320 100644 --- a/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php +++ b/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php @@ -19,7 +19,6 @@ use Ibexa\Bundle\Core\DependencyInjection\Configuration\Suggestion\Formatter\YamlSuggestionFormatter; use Ibexa\Bundle\Core\DependencyInjection\Security\PolicyProvider\PoliciesConfigBuilder; use Ibexa\Bundle\Core\DependencyInjection\Security\PolicyProvider\PolicyProviderInterface; -use Ibexa\Bundle\Core\Session\Handler\NativeSessionHandler; use Ibexa\Bundle\Core\SiteAccess\SiteAccessConfigurationFilter; use Ibexa\Contracts\Core\MVC\EventSubscriber\ConfigScopeChangeSubscriber; use Ibexa\Contracts\Core\Repository\Values\Filter\CriterionQueryBuilder as FilteringCriterionQueryBuilder; @@ -194,7 +193,6 @@ public function prepend(ContainerBuilder $container): void $this->handleDefaultSettingsLoading($container); $this->configureGenericSetup($container); - $this->configurePlatformShSetup($container); } /** @@ -803,188 +801,6 @@ private function configureGenericSetup(ContainerBuilder $container): void } } - /** - * @throws \Exception - */ - private function configurePlatformShSetup(ContainerBuilder $container): void - { - $projectDir = $container->getParameter('kernel.project_dir'); - - // Will not be executed on build step - $relationships = $_SERVER['PLATFORM_RELATIONSHIPS'] ?? false; - if (!$relationships) { - return; - } - $routes = $_SERVER['PLATFORM_ROUTES']; - - $relationships = json_decode(base64_decode($relationships), true); - $routes = json_decode(base64_decode($routes), true); - - // PLATFORMSH_DFS_NFS_PATH is different compared to DFS_NFS_PATH in the sense that it is relative to ezplatform dir - // DFS_NFS_PATH is an absolute path - if ($dfsNfsPath = $_SERVER['PLATFORMSH_DFS_NFS_PATH'] ?? false) { - $container->setParameter('dfs_nfs_path', sprintf('%s/%s', $projectDir, $dfsNfsPath)); - - // Map common parameters - $container->setParameter('dfs_database_charset', $container->getParameter('database_charset')); - $container->setParameter( - 'dfs_database_collation', - $container->getParameter('database_collation') - ); - if (\array_key_exists('dfs_database', $relationships)) { - // process dedicated P.sh dedicated config - foreach ($relationships['dfs_database'] as $endpoint) { - if (empty($endpoint['query']['is_master'])) { - continue; - } - $container->setParameter('dfs_database_driver', 'pdo_' . $endpoint['scheme']); - $container->setParameter( - 'dfs_database_url', - sprintf( - '%s://%s:%s@%s:%d/%s', - $endpoint['scheme'], - $endpoint['username'], - $endpoint['password'], - $endpoint['host'], - $endpoint['port'], - $endpoint['path'] - ) - ); - } - } else { - // or set fallback from the Repository database, if not configured - $container->setParameter('dfs_database_driver', $container->getParameter('database_driver')); - } - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/dfs')); - $loader->load('dfs.yaml'); - } - - // Use Redis-based caching if possible. - if (isset($relationships['rediscache'])) { - foreach ($relationships['rediscache'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/cache_pool')); - $loader->load('cache.redis.yaml'); - - $container->setParameter('cache_pool', 'cache.redis'); - $container->setParameter('cache_dsn', sprintf('%s:%d', $endpoint['host'], $endpoint['port']) . '?retry_interval=3'); - } - } elseif (isset($relationships['cache'])) { - // Fallback to memcached if here (deprecated, we will only handle redis here in the future) - foreach ($relationships['cache'] as $endpoint) { - if ($endpoint['scheme'] !== 'memcached') { - continue; - } - - @trigger_error('Usage of Memcached is deprecated, redis is recommended', E_USER_DEPRECATED); - - $container->setParameter('cache_pool', 'cache.memcached'); - $container->setParameter('cache_dsn', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/cache_pool')); - $loader->load('cache.memcached.yaml'); - } - } - - // Use Redis-based sessions if possible. If a separate Redis instance - // is available, use that. If not, share a Redis instance with the - // Cache. (That should be safe to do except on especially high-traffic sites.) - if (isset($relationships['redissession'])) { - foreach ($relationships['redissession'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $container->setParameter('ibexa.session.handler_id', NativeSessionHandler::class); - $container->setParameter('ibexa.session.save_path', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - } - } elseif (isset($relationships['rediscache'])) { - foreach ($relationships['rediscache'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $container->setParameter('ibexa.session.handler_id', NativeSessionHandler::class); - $container->setParameter('ibexa.session.save_path', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - } - } - - if (isset($relationships['solr'])) { - foreach ($relationships['solr'] as $endpoint) { - if ($endpoint['scheme'] !== 'solr') { - continue; - } - - $container->setParameter('search_engine', 'solr'); - - $container->setParameter('solr_dsn', sprintf('http://%s:%d/%s', $endpoint['host'], $endpoint['port'], 'solr')); - // To set solr_core parameter we assume path is in form like: "solr/collection1" - $container->setParameter('solr_core', substr($endpoint['path'], 5)); - } - } - - if (isset($relationships['elasticsearch'])) { - foreach ($relationships['elasticsearch'] as $endpoint) { - $dsn = sprintf('%s:%d', $endpoint['host'], $endpoint['port']); - - if ($endpoint['username'] !== null && $endpoint['password'] !== null) { - $dsn = $endpoint['username'] . ':' . $endpoint['password'] . '@' . $dsn; - } - - if ($endpoint['path'] !== null) { - $dsn .= '/' . $endpoint['path']; - } - - $dsn = $endpoint['scheme'] . '://' . $dsn; - - $container->setParameter('search_engine', 'elasticsearch'); - $container->setParameter('elasticsearch_dsn', $dsn); - } - } - - // We will pick a varnish route by the following prioritization: - // - The first route found that has upstream: varnish - // - if primary route has upstream: varnish, that route will be prioritised - // If no route is found with upstream: varnish, then purge_server will not be set - $route = null; - foreach ($routes as $host => $info) { - if ($route === null && $info['type'] === 'upstream' && $info['upstream'] === 'varnish') { - $route = $host; - } - if ($info['type'] === 'upstream' && $info['upstream'] === 'varnish' && $info['primary'] === true) { - $route = $host; - break; - } - } - - if ($route !== null && !($_SERVER['SKIP_HTTPCACHE_PURGE'] ?? false)) { - $purgeServer = rtrim($route, '/'); - if (($_SERVER['HTTPCACHE_USERNAME'] ?? false) && ($_SERVER['HTTPCACHE_PASSWORD'] ?? false)) { - $domain = parse_url($purgeServer, PHP_URL_HOST); - $credentials = urlencode($_SERVER['HTTPCACHE_USERNAME']) . ':' . urlencode($_SERVER['HTTPCACHE_PASSWORD']); - $purgeServer = str_replace($domain, $credentials . '@' . $domain, $purgeServer); - } - - $container->setParameter('ibexa.http_cache.purge_type', 'varnish'); - $container->setParameter('purge_type', 'varnish'); - $container->setParameter('purge_server', $purgeServer); - } - // Setting default value for HTTPCACHE_VARNISH_INVALIDATE_TOKEN if it is not explicitly set - if (!($_SERVER['HTTPCACHE_VARNISH_INVALIDATE_TOKEN'] ?? false)) { - $container->setParameter('varnish_invalidate_token', $_SERVER['PLATFORM_PROJECT_ENTROPY']); - } - - // Adapt config based on enabled PHP extensions - // Get imagine to use imagick if enabled, to avoid using php memory for image conversions - if (\extension_loaded('imagick')) { - $container->setParameter('liip_imagine_driver', 'imagick'); - } - } - private function shouldLoadTestBehatServices(ContainerBuilder $container): bool { return $container->hasParameter('ibexa.behat.browser.enabled') diff --git a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php index cff112d523..e0846ddd58 100644 --- a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php +++ b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php @@ -15,8 +15,6 @@ final class TrustedHeaderClientIpEventSubscriber implements EventSubscriberInterface { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - private ?string $trustedHeaderName; public function __construct( @@ -40,9 +38,6 @@ public function onKernelRequest(RequestEvent $event): void $trustedHeaderSet = Request::getTrustedHeaderSet(); $trustedHeaderName = $this->trustedHeaderName; - if (null === $trustedHeaderName && $this->isPlatformShProxy($request)) { - $trustedHeaderName = self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP; - } if (null === $trustedHeaderName) { return; @@ -59,9 +54,4 @@ public function onKernelRequest(RequestEvent $event): void Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); } - - private function isPlatformShProxy(Request $request): bool - { - return null !== $request->server->get('PLATFORM_RELATIONSHIPS'); - } } diff --git a/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php b/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php index 6cf8bebe9c..912da421af 100644 --- a/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php +++ b/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php @@ -911,51 +911,6 @@ public function testLoadsTestServicesWhenParameterIsSpecified(): void $this->assertContainerBuilderHasService(QueryControllerContext::class); } - /** - * @throws \JsonException - */ - public function testConfigurePlatformShDFS(): void - { - $dsn = 'mysql://dfs:dfs@localhost:3306/dfs'; - $parts = parse_url($dsn); - - $relationship = [ - 'dfs_database' => [ - [ - 'host' => $parts['host'], - 'scheme' => $parts['scheme'], - 'username' => $parts['user'], - 'password' => $parts['pass'], - 'port' => $parts['port'], - 'path' => ltrim($parts['path'], '/'), - 'query' => [ - 'is_master' => true, - ], - ], - ], - ]; - - $_SERVER['PLATFORM_RELATIONSHIPS'] = base64_encode(json_encode($relationship, JSON_THROW_ON_ERROR)); - $_SERVER['PLATFORMSH_DFS_NFS_PATH'] = '/'; - $_SERVER['PLATFORM_ROUTES'] = base64_encode(json_encode([], JSON_THROW_ON_ERROR)); - $_SERVER['PLATFORM_PROJECT_ENTROPY'] = ''; - - $this->container->setParameter('database_charset', 'utf8mb4'); - $this->container->setParameter('database_collation', 'utf8mb4_general_ci'); - $this->container->setParameter('kernel.project_dir', __DIR__ . '/../Resources'); - $this->load(); - - $this->assertContainerBuilderHasParameter('dfs_database_url'); - self::assertEquals($dsn, $this->container->getParameter('dfs_database_url')); - - unset( - $_SERVER['PLATFORM_RELATIONSHIPS'], - $_SERVER['PLATFORMSH_DFS_NFS_PATH'], - $_SERVER['PLATFORM_ROUTES'], - $_SERVER['PLATFORM_PROJECT_ENTROPY'] - ); - } - /** * Prepare Core Container for compilation by mocking required parameters and compile it. */ diff --git a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php index a934f1fcbf..29de81a1b6 100644 --- a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php +++ b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php @@ -19,15 +19,11 @@ final class TrustedHeaderClientIpEventSubscriberTest extends TestCase { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - private ?string $originalRemoteAddr; - private const PROXY_IP = '127.100.100.1'; - - private const REAL_CLIENT_IP = '98.76.123.234'; + private const string PROXY_IP = '127.100.100.1'; - private const CUSTOM_CLIENT_IP = '234.123.78.98'; + private const string REAL_CLIENT_IP = '98.76.123.234'; /** * @param array $data @@ -74,40 +70,6 @@ public function getTrustedHeaderEventSubscriberTestData(): array null, ['X-Custom-Header' => self::REAL_CLIENT_IP], ], - 'default platform.sh behaviour' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - ['X-Client-IP' => self::REAL_CLIENT_IP], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use custom header name without valid value on platform.sh' => [ - self::PROXY_IP, - self::PROXY_IP, - 'X-Custom-Header', - [self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use custom header with valid value on platform.sh' => [ - self::CUSTOM_CLIENT_IP, - self::PROXY_IP, - 'X-Custom-Header', - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use valid value without custom header name on platform.sh' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], - ['PLATFORM_RELATIONSHIPS' => true], - ], ]; } @@ -120,10 +82,7 @@ public function testTrustedHeaderEventSubscriberWithoutTrustedProxy(): void new TrustedHeaderClientIpEventSubscriber('X-Custom-Header') ); - $request = Request::create('/', Request::METHOD_GET, [], [], [], array_merge( - $_SERVER, - ['PLATFORM_RELATIONSHIPS' => true], - )); + $request = Request::create('/', Request::METHOD_GET, [], [], [], $_SERVER); $request->headers->add([ 'X-Custom-Header' => self::REAL_CLIENT_IP, ]); @@ -147,8 +106,7 @@ public function testTrustedHeaderEventSubscriberWithTrustedProxy( string $expectedIp, string $remoteAddrIp, ?string $trustedHeaderName = null, - array $headers = [], - array $server = [] + array $headers = [] ): void { $_SERVER['REMOTE_ADDR'] = $remoteAddrIp; Request::setTrustedProxies(['REMOTE_ADDR'], Request::getTrustedHeaderSet()); @@ -158,10 +116,7 @@ public function testTrustedHeaderEventSubscriberWithTrustedProxy( new TrustedHeaderClientIpEventSubscriber($trustedHeaderName) ); - $request = Request::create('/', Request::METHOD_GET, [], [], [], array_merge( - $server, - ['REMOTE_ADDR' => $remoteAddrIp], - )); + $request = Request::create('/', Request::METHOD_GET, [], [], [], ['REMOTE_ADDR' => $remoteAddrIp]); $request->headers->add($headers); $event = $eventDispatcher->dispatch(new RequestEvent( From 4c723e6c0c8ec5d151c9be461b0e44b10c087812 Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Fri, 31 Oct 2025 10:07:58 +0100 Subject: [PATCH 2/3] IBX-10764: Remove dependencies to Platform.sh --- .../IbexaCoreExtension.php | 184 ------------------ .../TrustedHeaderClientIpEventSubscriber.php | 10 - .../IbexaCoreExtensionTest.php | 45 ----- ...ustedHeaderClientIpEventSubscriberTest.php | 55 +----- 4 files changed, 5 insertions(+), 289 deletions(-) diff --git a/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php b/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php index 854d1d057d..ae9624e320 100644 --- a/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php +++ b/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php @@ -19,7 +19,6 @@ use Ibexa\Bundle\Core\DependencyInjection\Configuration\Suggestion\Formatter\YamlSuggestionFormatter; use Ibexa\Bundle\Core\DependencyInjection\Security\PolicyProvider\PoliciesConfigBuilder; use Ibexa\Bundle\Core\DependencyInjection\Security\PolicyProvider\PolicyProviderInterface; -use Ibexa\Bundle\Core\Session\Handler\NativeSessionHandler; use Ibexa\Bundle\Core\SiteAccess\SiteAccessConfigurationFilter; use Ibexa\Contracts\Core\MVC\EventSubscriber\ConfigScopeChangeSubscriber; use Ibexa\Contracts\Core\Repository\Values\Filter\CriterionQueryBuilder as FilteringCriterionQueryBuilder; @@ -194,7 +193,6 @@ public function prepend(ContainerBuilder $container): void $this->handleDefaultSettingsLoading($container); $this->configureGenericSetup($container); - $this->configurePlatformShSetup($container); } /** @@ -803,188 +801,6 @@ private function configureGenericSetup(ContainerBuilder $container): void } } - /** - * @throws \Exception - */ - private function configurePlatformShSetup(ContainerBuilder $container): void - { - $projectDir = $container->getParameter('kernel.project_dir'); - - // Will not be executed on build step - $relationships = $_SERVER['PLATFORM_RELATIONSHIPS'] ?? false; - if (!$relationships) { - return; - } - $routes = $_SERVER['PLATFORM_ROUTES']; - - $relationships = json_decode(base64_decode($relationships), true); - $routes = json_decode(base64_decode($routes), true); - - // PLATFORMSH_DFS_NFS_PATH is different compared to DFS_NFS_PATH in the sense that it is relative to ezplatform dir - // DFS_NFS_PATH is an absolute path - if ($dfsNfsPath = $_SERVER['PLATFORMSH_DFS_NFS_PATH'] ?? false) { - $container->setParameter('dfs_nfs_path', sprintf('%s/%s', $projectDir, $dfsNfsPath)); - - // Map common parameters - $container->setParameter('dfs_database_charset', $container->getParameter('database_charset')); - $container->setParameter( - 'dfs_database_collation', - $container->getParameter('database_collation') - ); - if (\array_key_exists('dfs_database', $relationships)) { - // process dedicated P.sh dedicated config - foreach ($relationships['dfs_database'] as $endpoint) { - if (empty($endpoint['query']['is_master'])) { - continue; - } - $container->setParameter('dfs_database_driver', 'pdo_' . $endpoint['scheme']); - $container->setParameter( - 'dfs_database_url', - sprintf( - '%s://%s:%s@%s:%d/%s', - $endpoint['scheme'], - $endpoint['username'], - $endpoint['password'], - $endpoint['host'], - $endpoint['port'], - $endpoint['path'] - ) - ); - } - } else { - // or set fallback from the Repository database, if not configured - $container->setParameter('dfs_database_driver', $container->getParameter('database_driver')); - } - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/dfs')); - $loader->load('dfs.yaml'); - } - - // Use Redis-based caching if possible. - if (isset($relationships['rediscache'])) { - foreach ($relationships['rediscache'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/cache_pool')); - $loader->load('cache.redis.yaml'); - - $container->setParameter('cache_pool', 'cache.redis'); - $container->setParameter('cache_dsn', sprintf('%s:%d', $endpoint['host'], $endpoint['port']) . '?retry_interval=3'); - } - } elseif (isset($relationships['cache'])) { - // Fallback to memcached if here (deprecated, we will only handle redis here in the future) - foreach ($relationships['cache'] as $endpoint) { - if ($endpoint['scheme'] !== 'memcached') { - continue; - } - - @trigger_error('Usage of Memcached is deprecated, redis is recommended', E_USER_DEPRECATED); - - $container->setParameter('cache_pool', 'cache.memcached'); - $container->setParameter('cache_dsn', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - - $loader = new Loader\YamlFileLoader($container, new FileLocator($projectDir . '/config/packages/cache_pool')); - $loader->load('cache.memcached.yaml'); - } - } - - // Use Redis-based sessions if possible. If a separate Redis instance - // is available, use that. If not, share a Redis instance with the - // Cache. (That should be safe to do except on especially high-traffic sites.) - if (isset($relationships['redissession'])) { - foreach ($relationships['redissession'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $container->setParameter('ibexa.session.handler_id', NativeSessionHandler::class); - $container->setParameter('ibexa.session.save_path', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - } - } elseif (isset($relationships['rediscache'])) { - foreach ($relationships['rediscache'] as $endpoint) { - if ($endpoint['scheme'] !== 'redis') { - continue; - } - - $container->setParameter('ibexa.session.handler_id', NativeSessionHandler::class); - $container->setParameter('ibexa.session.save_path', sprintf('%s:%d', $endpoint['host'], $endpoint['port'])); - } - } - - if (isset($relationships['solr'])) { - foreach ($relationships['solr'] as $endpoint) { - if ($endpoint['scheme'] !== 'solr') { - continue; - } - - $container->setParameter('search_engine', 'solr'); - - $container->setParameter('solr_dsn', sprintf('http://%s:%d/%s', $endpoint['host'], $endpoint['port'], 'solr')); - // To set solr_core parameter we assume path is in form like: "solr/collection1" - $container->setParameter('solr_core', substr($endpoint['path'], 5)); - } - } - - if (isset($relationships['elasticsearch'])) { - foreach ($relationships['elasticsearch'] as $endpoint) { - $dsn = sprintf('%s:%d', $endpoint['host'], $endpoint['port']); - - if ($endpoint['username'] !== null && $endpoint['password'] !== null) { - $dsn = $endpoint['username'] . ':' . $endpoint['password'] . '@' . $dsn; - } - - if ($endpoint['path'] !== null) { - $dsn .= '/' . $endpoint['path']; - } - - $dsn = $endpoint['scheme'] . '://' . $dsn; - - $container->setParameter('search_engine', 'elasticsearch'); - $container->setParameter('elasticsearch_dsn', $dsn); - } - } - - // We will pick a varnish route by the following prioritization: - // - The first route found that has upstream: varnish - // - if primary route has upstream: varnish, that route will be prioritised - // If no route is found with upstream: varnish, then purge_server will not be set - $route = null; - foreach ($routes as $host => $info) { - if ($route === null && $info['type'] === 'upstream' && $info['upstream'] === 'varnish') { - $route = $host; - } - if ($info['type'] === 'upstream' && $info['upstream'] === 'varnish' && $info['primary'] === true) { - $route = $host; - break; - } - } - - if ($route !== null && !($_SERVER['SKIP_HTTPCACHE_PURGE'] ?? false)) { - $purgeServer = rtrim($route, '/'); - if (($_SERVER['HTTPCACHE_USERNAME'] ?? false) && ($_SERVER['HTTPCACHE_PASSWORD'] ?? false)) { - $domain = parse_url($purgeServer, PHP_URL_HOST); - $credentials = urlencode($_SERVER['HTTPCACHE_USERNAME']) . ':' . urlencode($_SERVER['HTTPCACHE_PASSWORD']); - $purgeServer = str_replace($domain, $credentials . '@' . $domain, $purgeServer); - } - - $container->setParameter('ibexa.http_cache.purge_type', 'varnish'); - $container->setParameter('purge_type', 'varnish'); - $container->setParameter('purge_server', $purgeServer); - } - // Setting default value for HTTPCACHE_VARNISH_INVALIDATE_TOKEN if it is not explicitly set - if (!($_SERVER['HTTPCACHE_VARNISH_INVALIDATE_TOKEN'] ?? false)) { - $container->setParameter('varnish_invalidate_token', $_SERVER['PLATFORM_PROJECT_ENTROPY']); - } - - // Adapt config based on enabled PHP extensions - // Get imagine to use imagick if enabled, to avoid using php memory for image conversions - if (\extension_loaded('imagick')) { - $container->setParameter('liip_imagine_driver', 'imagick'); - } - } - private function shouldLoadTestBehatServices(ContainerBuilder $container): bool { return $container->hasParameter('ibexa.behat.browser.enabled') diff --git a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php index cff112d523..e0846ddd58 100644 --- a/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php +++ b/src/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriber.php @@ -15,8 +15,6 @@ final class TrustedHeaderClientIpEventSubscriber implements EventSubscriberInterface { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - private ?string $trustedHeaderName; public function __construct( @@ -40,9 +38,6 @@ public function onKernelRequest(RequestEvent $event): void $trustedHeaderSet = Request::getTrustedHeaderSet(); $trustedHeaderName = $this->trustedHeaderName; - if (null === $trustedHeaderName && $this->isPlatformShProxy($request)) { - $trustedHeaderName = self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP; - } if (null === $trustedHeaderName) { return; @@ -59,9 +54,4 @@ public function onKernelRequest(RequestEvent $event): void Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); } - - private function isPlatformShProxy(Request $request): bool - { - return null !== $request->server->get('PLATFORM_RELATIONSHIPS'); - } } diff --git a/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php b/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php index 6cf8bebe9c..912da421af 100644 --- a/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php +++ b/tests/bundle/Core/DependencyInjection/IbexaCoreExtensionTest.php @@ -911,51 +911,6 @@ public function testLoadsTestServicesWhenParameterIsSpecified(): void $this->assertContainerBuilderHasService(QueryControllerContext::class); } - /** - * @throws \JsonException - */ - public function testConfigurePlatformShDFS(): void - { - $dsn = 'mysql://dfs:dfs@localhost:3306/dfs'; - $parts = parse_url($dsn); - - $relationship = [ - 'dfs_database' => [ - [ - 'host' => $parts['host'], - 'scheme' => $parts['scheme'], - 'username' => $parts['user'], - 'password' => $parts['pass'], - 'port' => $parts['port'], - 'path' => ltrim($parts['path'], '/'), - 'query' => [ - 'is_master' => true, - ], - ], - ], - ]; - - $_SERVER['PLATFORM_RELATIONSHIPS'] = base64_encode(json_encode($relationship, JSON_THROW_ON_ERROR)); - $_SERVER['PLATFORMSH_DFS_NFS_PATH'] = '/'; - $_SERVER['PLATFORM_ROUTES'] = base64_encode(json_encode([], JSON_THROW_ON_ERROR)); - $_SERVER['PLATFORM_PROJECT_ENTROPY'] = ''; - - $this->container->setParameter('database_charset', 'utf8mb4'); - $this->container->setParameter('database_collation', 'utf8mb4_general_ci'); - $this->container->setParameter('kernel.project_dir', __DIR__ . '/../Resources'); - $this->load(); - - $this->assertContainerBuilderHasParameter('dfs_database_url'); - self::assertEquals($dsn, $this->container->getParameter('dfs_database_url')); - - unset( - $_SERVER['PLATFORM_RELATIONSHIPS'], - $_SERVER['PLATFORMSH_DFS_NFS_PATH'], - $_SERVER['PLATFORM_ROUTES'], - $_SERVER['PLATFORM_PROJECT_ENTROPY'] - ); - } - /** * Prepare Core Container for compilation by mocking required parameters and compile it. */ diff --git a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php index a934f1fcbf..29de81a1b6 100644 --- a/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php +++ b/tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php @@ -19,15 +19,11 @@ final class TrustedHeaderClientIpEventSubscriberTest extends TestCase { - private const PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP = 'X-Client-IP'; - private ?string $originalRemoteAddr; - private const PROXY_IP = '127.100.100.1'; - - private const REAL_CLIENT_IP = '98.76.123.234'; + private const string PROXY_IP = '127.100.100.1'; - private const CUSTOM_CLIENT_IP = '234.123.78.98'; + private const string REAL_CLIENT_IP = '98.76.123.234'; /** * @param array $data @@ -74,40 +70,6 @@ public function getTrustedHeaderEventSubscriberTestData(): array null, ['X-Custom-Header' => self::REAL_CLIENT_IP], ], - 'default platform.sh behaviour' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - ['X-Client-IP' => self::REAL_CLIENT_IP], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use custom header name without valid value on platform.sh' => [ - self::PROXY_IP, - self::PROXY_IP, - 'X-Custom-Header', - [self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use custom header with valid value on platform.sh' => [ - self::CUSTOM_CLIENT_IP, - self::PROXY_IP, - 'X-Custom-Header', - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], - ['PLATFORM_RELATIONSHIPS' => true], - ], - 'use valid value without custom header name on platform.sh' => [ - self::REAL_CLIENT_IP, - self::PROXY_IP, - null, - [ - self::PLATFORM_SH_TRUSTED_HEADER_CLIENT_IP => self::REAL_CLIENT_IP, - 'X-Custom-Header' => self::CUSTOM_CLIENT_IP, - ], - ['PLATFORM_RELATIONSHIPS' => true], - ], ]; } @@ -120,10 +82,7 @@ public function testTrustedHeaderEventSubscriberWithoutTrustedProxy(): void new TrustedHeaderClientIpEventSubscriber('X-Custom-Header') ); - $request = Request::create('/', Request::METHOD_GET, [], [], [], array_merge( - $_SERVER, - ['PLATFORM_RELATIONSHIPS' => true], - )); + $request = Request::create('/', Request::METHOD_GET, [], [], [], $_SERVER); $request->headers->add([ 'X-Custom-Header' => self::REAL_CLIENT_IP, ]); @@ -147,8 +106,7 @@ public function testTrustedHeaderEventSubscriberWithTrustedProxy( string $expectedIp, string $remoteAddrIp, ?string $trustedHeaderName = null, - array $headers = [], - array $server = [] + array $headers = [] ): void { $_SERVER['REMOTE_ADDR'] = $remoteAddrIp; Request::setTrustedProxies(['REMOTE_ADDR'], Request::getTrustedHeaderSet()); @@ -158,10 +116,7 @@ public function testTrustedHeaderEventSubscriberWithTrustedProxy( new TrustedHeaderClientIpEventSubscriber($trustedHeaderName) ); - $request = Request::create('/', Request::METHOD_GET, [], [], [], array_merge( - $server, - ['REMOTE_ADDR' => $remoteAddrIp], - )); + $request = Request::create('/', Request::METHOD_GET, [], [], [], ['REMOTE_ADDR' => $remoteAddrIp]); $request->headers->add($headers); $event = $eventDispatcher->dispatch(new RequestEvent( From 37f125180739fccd8c7d426d3da041a6364a2d1c Mon Sep 17 00:00:00 2001 From: Bartek Wajda Date: Fri, 31 Oct 2025 10:26:38 +0100 Subject: [PATCH 3/3] IBX-10764: Baseline --- phpstan-baseline.neon | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 28cd9d91f0..ae8530b1cc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1551,13 +1551,13 @@ parameters: - message: '#^Binary operation "\." between array\|bool\|float\|int\|string\|null and ''/config/packages/dfs'' results in an error\.$#' identifier: binaryOp.invalid - count: 2 + count: 1 path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - message: '#^Binary operation "\." between array\|bool\|float\|int\|string\|null and ''/config/packages…'' results in an error\.$#' identifier: binaryOp.invalid - count: 3 + count: 1 path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - @@ -1788,24 +1788,12 @@ parameters: count: 1 path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - - - message: '#^Parameter \#1 \$search of function str_replace expects array\\|string, string\|false\|null given\.$#' - identifier: argument.type - count: 1 - path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - - message: '#^Parameter \#1 \.\.\.\$arrays of function array_merge expects array, array\|bool\|float\|int\|string\|null given\.$#' identifier: argument.type count: 1 path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - - - message: '#^Parameter \#2 \.\.\.\$values of function sprintf expects bool\|float\|int\|string\|null, array\|bool\|float\|int\|string\|null given\.$#' - identifier: argument.type - count: 1 - path: src/bundle/Core/DependencyInjection/IbexaCoreExtension.php - - message: '#^Property Ibexa\\Bundle\\Core\\DependencyInjection\\IbexaCoreExtension\:\:\$defaultSettingsCollection type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -22536,12 +22524,6 @@ parameters: count: 1 path: tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php - - - message: '#^Method Ibexa\\Tests\\Bundle\\Core\\EventSubscriber\\TrustedHeaderClientIpEventSubscriberTest\:\:testTrustedHeaderEventSubscriberWithTrustedProxy\(\) has parameter \$server with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: tests/bundle/Core/EventSubscriber/TrustedHeaderClientIpEventSubscriberTest.php - - message: '#^Parameter \#2 \$trustedHeaderSet of static method Symfony\\Component\\HttpFoundation\\Request\:\:setTrustedProxies\(\) expects int\<0, 63\>, \-1 given\.$#' identifier: argument.type