• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

valksor / php-sse / 19202040819

09 Nov 2025 02:25AM UTC coverage: 38.298% (-0.07%) from 38.372%
19202040819

push

github

k0d3r1s
update documentation

198 of 517 relevant lines covered (38.3%)

0.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.0
/DependencyInjection/SseConfiguration.php
1
<?php declare(strict_types = 1);
2

3
/*
4
 * This file is part of the Valksor package.
5
 *
6
 * (c) Davis Zalitis (k0d3r1s)
7
 * (c) SIA Valksor <packages@valksor.com>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12

13
namespace Valksor\Component\Sse\DependencyInjection;
14

15
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
18
use Valksor\Bundle\DependencyInjection\AbstractDependencyConfiguration;
19
use Valksor\Bundle\ValksorBundle;
20
use Valksor\Component\Sse\DependencyInjection\CompilerPass\TwigCompilerPass;
21
use Valksor\FullStack;
22
use Valksor\Functions\Local\Traits\_Exists;
23
use Valksor\Functions\Local\Traits\_IsInstalled;
24

25
use function dirname;
26
use function getcwd;
27
use function sprintf;
28
use function str_contains;
29

30
/**
31
 * Dependency Injection configuration for Valksor SSE (Server-Sent Events) component.
32
 *
33
 * This class manages the complete integration of SSE functionality into Symfony applications
34
 * through dependency injection configuration. It handles server configuration, asset mapping,
35
 * Twig integration, and SSL/TLS certificate management for secure SSE connections.
36
 *
37
 * Configuration Architecture:
38
 * The configuration system provides three main integration points:
39
 * 1. **Server Configuration**: Network settings, SSL/TLS setup, and endpoint configuration
40
 * 2. **Asset Integration**: Automatic registration of JavaScript assets with AssetMapper
41
 * 3. **Twig Integration**: Global variables for template access and runtime configuration
42
 *
43
 * SSL/TLS Support:
44
 * - Automatic certificate discovery based on domain configuration
45
 * - Support for custom certificate paths when using non-standard locations
46
 * - Integration with system certificate stores for development and production
47
 * - Flexible binding options for both development and deployment scenarios
48
 *
49
 * AssetMapper Integration:
50
 * - Automatically detects whether the package is installed as a dependency or in development
51
 * - Registers SSE JavaScript assets under the 'valksorsse' namespace
52
 * - Handles path resolution for both vendor and development installations
53
 * - Provides seamless integration with Symfony's modern asset management system
54
 *
55
 * Twig Template Integration:
56
 * - Exposes SSE configuration to templates through global variables
57
 * - Provides port and path information for client-side JavaScript configuration
58
 * - Enables template-level SSE endpoint configuration and customization
59
 * - Supports dynamic SSE server configuration in different environments
60
 *
61
 * Network Configuration:
62
 * - Flexible binding options (0.0.0.0 for production, 127.0.0.1 for development)
63
 * - Configurable port allocation with default fallbacks
64
 * - Custom endpoint paths for API versioning or routing flexibility
65
 * - Domain-based SSL certificate resolution
66
 *
67
 * Environment Considerations:
68
 * - Development-friendly defaults (localhost, port 3000, no SSL requirements)
69
 * - Production-ready security configurations (custom SSL, specific bindings)
70
 * - CLI vs web request detection for proper path resolution
71
 * - Support for containerized and traditional deployment environments
72
 *
73
 * Integration Points:
74
 *
75
 * **Framework Integration (AssetMapper)**:
76
 * ```yaml
77
 * # Automatically added to framework.yaml
78
 * framework:
79
 *     asset_mapper:
80
 *         paths:
81
 *             '/path/to/assets': 'valksorsse'
82
 * ```
83
 *
84
 * **Twig Integration**:
85
 * ```yaml
86
 * # Automatically added to twig.yaml
87
 * twig:
88
 *     globals:
89
 *         valksor_sse_port: '%env(default:3000:int:SSE_PORT)%'
90
 *         valksor_sse_path: '%env(default:/sse:string:SSE_PATH)%'
91
 * ```
92
 *
93
 * **SSE Configuration Structure**:
94
 * ```yaml
95
 * valksor:
96
 *     sse:
97
 *         bind: '0.0.0.0'              # Server bind address
98
 *         port: 3000                   # Server port
99
 *         path: '/sse'                 # Endpoint path
100
 *         domain: 'localhost'          # Domain for SSL cert lookup
101
 *         ssl_cert_path: null          # Custom SSL cert path (optional)
102
 *         ssl_key_path: null           # Custom SSL key path (optional)
103
 * ```
104
 *
105
 * Compiler Pass Integration:
106
 * - Registers TwigCompilerPass for runtime function registration
107
 * - Enables SSE-related Twig functions and templates
108
 * - Provides automatic dependency injection setup
109
 * - Ensures proper service container optimization
110
 *
111
 * Security Features:
112
 * - SSL/TLS encryption support for production deployments
113
 * - Configurable certificate paths for custom PKI setups
114
 * - Domain-based certificate validation
115
 * - Development-friendly insecure options for local testing
116
 *
117
 * Performance Optimizations:
118
 * - Compiler pass integration for optimal service container performance
119
 * - Conditional asset registration based on available extensions
120
 * - Path caching and intelligent resolution
121
 * - Minimal overhead when SSE is not used
122
 *
123
 * Usage Examples:
124
 *
125
 * **Development Configuration**:
126
 * ```yaml
127
 * valksor:
128
 *     sse:
129
 *         bind: '127.0.0.1'
130
 *         port: 3000
131
 *         path: '/sse'
132
 *         domain: 'localhost'
133
 * ```
134
 *
135
 * **Production Configuration**:
136
 * ```yaml
137
 * valksor:
138
 *     sse:
139
 *         bind: '0.0.0.0'
140
 *         port: 8080
141
 *         path: '/api/v1/sse'
142
 *         domain: 'app.example.com'
143
 *         ssl_cert_path: '/etc/ssl/certs/app.crt'
144
 *         ssl_key_path: '/etc/ssl/private/app.key'
145
 * ```
146
 *
147
 * **Template Usage**:
148
 * ```twig
149
 * {# Uses injected globals #}
150
 * <script>
151
 *     const sseUrl = `https://{{ app.request.host }}:{{ valksor_sse_port }}{{ valksor_sse_path }}`;
152
 *     const eventSource = new EventSource(sseUrl);
153
 * </script>
154
 * ```
155
 *
156
 * @see AbstractDependencyConfiguration For base configuration patterns
157
 * @see TwigCompilerPass For Twig runtime integration
158
 * @see AssetMapper For asset management integration
159
 *
160
 * @author Davis Zalitis (k0d3r1s)
161
 */
162
class SseConfiguration extends AbstractDependencyConfiguration
163
{
164
    /**
165
     * Define the configuration tree structure for SSE component settings.
166
     *
167
     * This method creates the comprehensive configuration schema that defines all
168
     * available options for the SSE server, network settings, and SSL/TLS configuration.
169
     * The configuration tree supports both development and production use cases
170
     * with appropriate defaults and validation rules.
171
     *
172
     * Configuration Structure:
173
     * The method defines a hierarchical configuration tree with the following main sections:
174
     *
175
     * **Network Configuration**:
176
     * - bind: Server bind address (default: '0.0.0.0' for production, '127.0.0.1' for development)
177
     * - port: Server port number (default: 3000, configurable for different environments)
178
     * - path: SSE endpoint path (default: '/sse', customizable for API versioning)
179
     *
180
     * **SSL/TLS Configuration**:
181
     * - domain: Domain name for SSL certificate lookup (default: 'localhost')
182
     * - ssl_cert_path: Custom SSL certificate file path (optional, auto-discovery if null)
183
     * - ssl_key_path: Custom SSL private key file path (optional, auto-discovery if null)
184
     *
185
     * Configuration Validation and Defaults:
186
     * - All values have sensible defaults for immediate development use
187
     * - SSL paths are optional to support both HTTP and HTTPS deployments
188
     * - Domain configuration enables automatic certificate discovery
189
     * - Network settings support both local and production deployment scenarios
190
     *
191
     * Environment-specific Configuration Patterns:
192
     *
193
     * **Development Environment**:
194
     * ```yaml
195
     * valksor:
196
     *     sse:
197
     *         bind: '127.0.0.1'    # Localhost only
198
     *         port: 3000           # Development port
199
     *         path: '/sse'         # Simple endpoint
200
     *         domain: 'localhost'  # Local development
201
     *         # SSL not required for development
202
     * ```
203
     *
204
     * **Staging Environment**:
205
     * ```yaml
206
     * valksor:
207
     *     sse:
208
     *         bind: '0.0.0.0'     # Accept external connections
209
     *         port: 8080           # Different port to avoid conflicts
210
     *         path: '/api/v1/sse'  # Versioned API endpoint
211
     *         domain: 'staging.example.com'
212
     *         # Optional SSL for staging
213
     * ```
214
     *
215
     * **Production Environment**:
216
     * ```yaml
217
     * valksor:
218
     *     sse:
219
     *         bind: '0.0.0.0'     # Production-ready binding
220
     *         port: 443            # Standard HTTPS port
221
     *         path: '/events'      # Clean endpoint path
222
     *         domain: 'app.example.com'
223
     *         ssl_cert_path: '/etc/ssl/certs/app.crt'
224
     *         ssl_key_path: '/etc/ssl/private/app.key'
225
     * ```
226
     *
227
     * SSL/TLS Certificate Handling:
228
     * - When ssl_cert_path and ssl_key_path are null, the system attempts automatic discovery
229
     * - Automatic discovery looks for certificates in /etc/ssl/private/<domain>.crt and .key
230
     * - Custom paths allow for non-standard certificate locations or PKI setups
231
     * - Domain-based discovery supports multiple SSL certificates on the same server
232
     *
233
     * Security Considerations:
234
     * - Bind address '0.0.0.0' exposes the SSE server to all network interfaces
235
     * - '127.0.0.1' limits access to localhost, recommended for development
236
     * - SSL/TLS configuration is optional but recommended for production
237
     * - Certificate paths should have appropriate file permissions
238
     *
239
     * Performance Considerations:
240
     * - Port selection should avoid conflicts with other services
241
     * - Path configuration affects client-side URL construction
242
     * - SSL/TLS adds overhead but provides essential security for production
243
     * - Domain configuration affects certificate lookup and validation
244
     *
245
     * @param ArrayNodeDefinition $rootNode           The root configuration node to attach SSE settings to
246
     *                                                This is typically the main Valksor configuration tree
247
     * @param callable            $enableIfStandalone Conditional enablement function for standalone mode
248
     *                                                Determines if SSE should be enabled when used independently
249
     * @param string              $component          The component name identifier ('sse' in this case)
250
     *                                                Used for namespacing and configuration tree construction
251
     *
252
     * @return void This method modifies the configuration tree by reference
253
     *
254
     * @see https://symfony.com/doc/current/components/config/definition.html For configuration tree syntax
255
     * @see SseService For the service that consumes this configuration
256
     *
257
     * @example Basic configuration usage
258
     * ```yaml
259
     * # config/packages/valksor.yaml
260
     * valksor:
261
     *     sse:
262
     *         port: 8080
263
     *         path: '/events'
264
     * ```
265
     * @example SSL configuration for production
266
     * ```yaml
267
     * valksor:
268
     *     sse:
269
     *         bind: '0.0.0.0'
270
     *         port: 443
271
     *         domain: 'secure.example.com'
272
     *         ssl_cert_path: '/etc/ssl/certs/secure.crt'
273
     *         ssl_key_path: '/etc/ssl/private/secure.key'
274
     * ```
275
     */
276
    public function addSection(
277
        ArrayNodeDefinition $rootNode,
278
        callable $enableIfStandalone,
279
        string $component,
280
    ): void {
281
        $rootNode
×
282
            ->children()
×
283
                ->arrayNode($component)
×
284
                ->{$enableIfStandalone(sprintf('%s/%s', ValksorBundle::VALKSOR, $component), self::class)}()
×
285
                ->addDefaultsIfNotSet()
×
286
                ->children()
×
287
                    ->scalarNode('bind')
×
288
                        ->info('Bind address for SSE server')
×
289
                        ->defaultValue('0.0.0.0')
×
290
                    ->end()
×
291
                    ->integerNode('port')
×
292
                        ->info('Port for SSE server')
×
293
                        ->defaultValue(3000)
×
294
                    ->end()
×
295
                    ->scalarNode('path')
×
296
                        ->info('Base path for SSE endpoint')
×
297
                        ->defaultValue('/sse')
×
298
                    ->end()
×
299
                    ->scalarNode('domain')
×
300
                        ->info('Domain for TLS certificate lookup')
×
301
                        ->defaultValue('localhost')
×
302
                    ->end()
×
303
                    ->scalarNode('ssl_cert_path')
×
304
                        ->info('SSL Cert path for TLS. If null, uses /etc/ssl/private/<domain>.crt')
×
305
                        ->defaultNull()
×
306
                    ->end()
×
307
                    ->scalarNode('ssl_key_path')
×
308
                        ->info('SSL Key for TLS. If null, uses /etc/ssl/private/<domain>.key')
×
309
                        ->defaultNull()
×
310
                    ->end()
×
311
            ->end();
×
312
    }
313

314
    public function build(
315
        ContainerBuilder $container,
316
    ): void {
317
        $container->addCompilerPass(new TwigCompilerPass());
1✔
318
    }
319

320
    public function registerPreConfiguration(
321
        ContainerConfigurator $container,
322
        ContainerBuilder $builder,
323
        string $component,
324
    ): void {
325
        if ($builder->hasExtension('framework')) {
1✔
326
            static $_helper = null;
×
327

328
            if (null === $_helper) {
×
329
                $_helper = new class {
×
330
                    use _Exists;
331
                    use _IsInstalled;
332
                };
×
333
            }
334

335
            if (str_contains(__DIR__, 'vendor')) {
×
336
                $path = '/vendor/valksor/php-sse/Resources/assets';
×
337

338
                if ($_helper->exists(FullStack::class)) {
×
339
                    $path = '/vendor/valksor/valksor/src/Valksor/Component/Sse/Resources/assets';
×
340
                }
341
            } else {
342
                $path = '/valksor/src/Valksor/Component/Sse/Resources/assets';
×
343
            }
344

345
            $prefix = getcwd();
×
346

347
            if ('cli' !== PHP_SAPI) {
×
348
                $prefix = dirname($prefix);
×
349
            }
350
            $builder->prependExtensionConfig('framework', [
×
351
                'asset_mapper' => [
×
352
                    'paths' => [
×
353
                        $prefix . $path => 'valksorsse',
×
354
                    ],
×
355
                ],
×
356
            ]);
×
357
        }
358

359
        if ($builder->hasExtension('twig')) {
1✔
360
            $valksor = $this->mergeConfig($builder, 'valksor');
×
361

362
            $builder->prependExtensionConfig('twig', [
×
363
                'globals' => [
×
364
                    'valksor_sse_port' => $valksor['sse']['port'],
×
365
                    'valksor_sse_path' => $valksor['sse']['path'],
×
366
                ],
×
367
            ]);
×
368
        }
369
    }
370
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc