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

codeigniter4 / CodeIgniter4 / 24830748825

23 Apr 2026 10:41AM UTC coverage: 88.273% (+0.006%) from 88.267%
24830748825

Pull #10130

github

web-flow
Merge 72314819f into ec0756353
Pull Request #10130: feat: add the `EnvironmentDetector` utility class and `environmentdetector` service

40 of 42 new or added lines in 23 files covered. (95.24%)

29 existing lines in 3 files now uncovered.

22808 of 25838 relevant lines covered (88.27%)

220.98 hits per line

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

95.17
/system/Config/Services.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter\Config;
15

16
use CodeIgniter\Cache\CacheFactory;
17
use CodeIgniter\Cache\CacheInterface;
18
use CodeIgniter\Cache\ResponseCache;
19
use CodeIgniter\CLI\Commands;
20
use CodeIgniter\CodeIgniter;
21
use CodeIgniter\Context\Context;
22
use CodeIgniter\Database\ConnectionInterface;
23
use CodeIgniter\Database\MigrationRunner;
24
use CodeIgniter\Debug\Exceptions;
25
use CodeIgniter\Debug\Iterator;
26
use CodeIgniter\Debug\Timer;
27
use CodeIgniter\Debug\Toolbar;
28
use CodeIgniter\Email\Email;
29
use CodeIgniter\Encryption\EncrypterInterface;
30
use CodeIgniter\Encryption\Encryption;
31
use CodeIgniter\EnvironmentDetector;
32
use CodeIgniter\Filters\Filters;
33
use CodeIgniter\Format\Format;
34
use CodeIgniter\Honeypot\Honeypot;
35
use CodeIgniter\HTTP\CLIRequest;
36
use CodeIgniter\HTTP\ContentSecurityPolicy;
37
use CodeIgniter\HTTP\CURLRequest;
38
use CodeIgniter\HTTP\IncomingRequest;
39
use CodeIgniter\HTTP\Negotiate;
40
use CodeIgniter\HTTP\RedirectResponse;
41
use CodeIgniter\HTTP\Request;
42
use CodeIgniter\HTTP\RequestInterface;
43
use CodeIgniter\HTTP\Response;
44
use CodeIgniter\HTTP\ResponseInterface;
45
use CodeIgniter\HTTP\SiteURIFactory;
46
use CodeIgniter\HTTP\URI;
47
use CodeIgniter\HTTP\UserAgent;
48
use CodeIgniter\Images\Handlers\BaseHandler;
49
use CodeIgniter\Language\Language;
50
use CodeIgniter\Log\Logger;
51
use CodeIgniter\Pager\Pager;
52
use CodeIgniter\Router\RouteCollection;
53
use CodeIgniter\Router\RouteCollectionInterface;
54
use CodeIgniter\Router\Router;
55
use CodeIgniter\Security\Security;
56
use CodeIgniter\Session\Handlers\BaseHandler as SessionBaseHandler;
57
use CodeIgniter\Session\Handlers\Database\MySQLiHandler;
58
use CodeIgniter\Session\Handlers\Database\PostgreHandler;
59
use CodeIgniter\Session\Handlers\DatabaseHandler;
60
use CodeIgniter\Session\Session;
61
use CodeIgniter\Superglobals;
62
use CodeIgniter\Throttle\Throttler;
63
use CodeIgniter\Typography\Typography;
64
use CodeIgniter\Validation\Validation;
65
use CodeIgniter\Validation\ValidationInterface;
66
use CodeIgniter\View\Cell;
67
use CodeIgniter\View\Parser;
68
use CodeIgniter\View\RendererInterface;
69
use CodeIgniter\View\View;
70
use Config\App;
71
use Config\Cache;
72
use Config\ContentSecurityPolicy as ContentSecurityPolicyConfig;
73
use Config\ContentSecurityPolicy as CSPConfig;
74
use Config\Database;
75
use Config\Email as EmailConfig;
76
use Config\Encryption as EncryptionConfig;
77
use Config\Exceptions as ExceptionsConfig;
78
use Config\Filters as FiltersConfig;
79
use Config\Format as FormatConfig;
80
use Config\Honeypot as HoneypotConfig;
81
use Config\Images;
82
use Config\Logger as LoggerConfig;
83
use Config\Migrations;
84
use Config\Modules;
85
use Config\Pager as PagerConfig;
86
use Config\Paths;
87
use Config\Routing;
88
use Config\Security as SecurityConfig;
89
use Config\Services as AppServices;
90
use Config\Session as SessionConfig;
91
use Config\Toolbar as ToolbarConfig;
92
use Config\Validation as ValidationConfig;
93
use Config\View as ViewConfig;
94
use InvalidArgumentException;
95
use Locale;
96

97
/**
98
 * Services Configuration file.
99
 *
100
 * Services are simply other classes/libraries that the system uses
101
 * to do its job. This is used by CodeIgniter to allow the core of the
102
 * framework to be swapped out easily without affecting the usage within
103
 * the rest of your application.
104
 *
105
 * This is used in place of a Dependency Injection container primarily
106
 * due to its simplicity, which allows a better long-term maintenance
107
 * of the applications built on top of CodeIgniter. A bonus side-effect
108
 * is that IDEs are able to determine what class you are calling
109
 * whereas with DI Containers there usually isn't a way for them to do this.
110
 *
111
 * @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html
112
 * @see http://www.infoq.com/presentations/Simple-Made-Easy
113
 * @see \CodeIgniter\Config\ServicesTest
114
 */
115
class Services extends BaseService
116
{
117
    /**
118
     * The cache class provides a simple way to store and retrieve
119
     * complex data for later.
120
     *
121
     * @return CacheInterface
122
     */
123
    public static function cache(?Cache $config = null, bool $getShared = true)
124
    {
125
        if ($getShared) {
2,109✔
126
            return static::getSharedInstance('cache', $config);
2,106✔
127
        }
128

129
        $config ??= config(Cache::class);
2,109✔
130

131
        return CacheFactory::getHandler($config);
2,109✔
132
    }
133

134
    /**
135
     * The CLI Request class provides for ways to interact with
136
     * a command line request.
137
     *
138
     * @return CLIRequest
139
     *
140
     * @internal
141
     */
142
    public static function clirequest(?App $config = null, bool $getShared = true)
143
    {
144
        if ($getShared) {
10✔
145
            return static::getSharedInstance('clirequest', $config);
5✔
146
        }
147

148
        $config ??= config(App::class);
10✔
149

150
        return new CLIRequest($config);
10✔
151
    }
152

153
    /**
154
     * CodeIgniter, the core of the framework.
155
     *
156
     * @return CodeIgniter
157
     */
158
    public static function codeigniter(?App $config = null, bool $getShared = true)
159
    {
160
        if ($getShared) {
2✔
161
            return static::getSharedInstance('codeigniter', $config);
×
162
        }
163

164
        $config ??= config(App::class);
2✔
165

166
        return new CodeIgniter($config);
2✔
167
    }
168

169
    /**
170
     * The commands utility for running and working with CLI commands.
171
     *
172
     * @return Commands
173
     */
174
    public static function commands(bool $getShared = true)
175
    {
176
        if ($getShared) {
58✔
177
            return static::getSharedInstance('commands');
56✔
178
        }
179

180
        return new Commands();
58✔
181
    }
182

183
    /**
184
     * Content Security Policy
185
     *
186
     * @return ContentSecurityPolicy
187
     */
188
    public static function csp(?CSPConfig $config = null, bool $getShared = true)
189
    {
190
        if ($getShared) {
107✔
191
            return static::getSharedInstance('csp', $config);
105✔
192
        }
193

194
        $config ??= config(ContentSecurityPolicyConfig::class);
107✔
195

196
        return new ContentSecurityPolicy($config);
107✔
197
    }
198

199
    /**
200
     * The CURL Request class acts as a simple HTTP client for interacting
201
     * with other servers, typically through APIs.
202
     *
203
     * @todo v4.8.0 Remove $config parameter since unused
204
     *
205
     * @return CURLRequest
206
     */
207
    public static function curlrequest(array $options = [], ?ResponseInterface $response = null, ?App $config = null, bool $getShared = true)
208
    {
209
        if ($getShared) {
5✔
210
            return static::getSharedInstance('curlrequest', $options, $response, $config);
3✔
211
        }
212

213
        $config ??= config(App::class);
5✔
214
        $response ??= new Response();
5✔
215

216
        return new CURLRequest(
5✔
217
            $config,
5✔
218
            new URI($options['baseURI'] ?? null),
5✔
219
            $response,
5✔
220
            $options,
5✔
221
        );
5✔
222
    }
223

224
    /**
225
     * The Email class allows you to send email via mail, sendmail, SMTP.
226
     *
227
     * @param array|EmailConfig|null $config
228
     *
229
     * @return Email
230
     */
231
    public static function email($config = null, bool $getShared = true)
232
    {
233
        if ($getShared) {
5✔
234
            return static::getSharedInstance('email', $config);
1✔
235
        }
236

237
        if (empty($config) || (! is_array($config) && ! $config instanceof EmailConfig)) {
4✔
238
            $config = config(EmailConfig::class);
3✔
239
        }
240

241
        return new Email($config);
4✔
242
    }
243

244
    /**
245
     * The Encryption class provides two-way encryption.
246
     *
247
     * @param bool $getShared
248
     *
249
     * @return EncrypterInterface Encryption handler
250
     */
251
    public static function encrypter(?EncryptionConfig $config = null, $getShared = false)
252
    {
253
        if ($getShared === true) {
7✔
254
            return static::getSharedInstance('encrypter', $config);
1✔
255
        }
256

257
        $config ??= config(EncryptionConfig::class);
7✔
258
        $encryption = new Encryption($config);
7✔
259

260
        return $encryption->initialize($config);
6✔
261
    }
262

263
    /**
264
     * Provides a simple way to determine the current environment
265
     * of the application.
266
     *
267
     * @return EnvironmentDetector
268
     */
269
    public static function environmentdetector(?string $environment = null, bool $getShared = true)
270
    {
271
        if ($getShared) {
585✔
272
            return static::getSharedInstance('environmentdetector', $environment);
583✔
273
        }
274

275
        return new EnvironmentDetector($environment);
585✔
276
    }
277

278
    /**
279
     * The Exceptions class holds the methods that handle:
280
     *
281
     *  - set_exception_handler
282
     *  - set_error_handler
283
     *  - register_shutdown_function
284
     *
285
     * @return Exceptions
286
     */
287
    public static function exceptions(
288
        ?ExceptionsConfig $config = null,
289
        bool $getShared = true,
290
    ) {
291
        if ($getShared) {
4✔
292
            return static::getSharedInstance('exceptions', $config);
1✔
293
        }
294

295
        $config ??= config(ExceptionsConfig::class);
4✔
296

297
        return new Exceptions($config);
4✔
298
    }
299

300
    /**
301
     * Filters allow you to run tasks before and/or after a controller
302
     * is executed. During before filters, the request can be modified,
303
     * and actions taken based on the request, while after filters can
304
     * act on or modify the response itself before it is sent to the client.
305
     *
306
     * @return Filters
307
     */
308
    public static function filters(?FiltersConfig $config = null, bool $getShared = true)
309
    {
310
        if ($getShared) {
147✔
311
            return static::getSharedInstance('filters', $config);
145✔
312
        }
313

314
        $config ??= config(FiltersConfig::class);
147✔
315

316
        return new Filters($config, AppServices::get('request'), AppServices::get('response'));
147✔
317
    }
318

319
    /**
320
     * The Format class is a convenient place to create Formatters.
321
     *
322
     * @return Format
323
     */
324
    public static function format(?FormatConfig $config = null, bool $getShared = true)
325
    {
326
        if ($getShared) {
39✔
327
            return static::getSharedInstance('format', $config);
36✔
328
        }
329

330
        $config ??= config(FormatConfig::class);
39✔
331

332
        return new Format($config);
39✔
333
    }
334

335
    /**
336
     * The Honeypot provides a secret input on forms that bots should NOT
337
     * fill in, providing an additional safeguard when accepting user input.
338
     *
339
     * @return Honeypot
340
     */
341
    public static function honeypot(?HoneypotConfig $config = null, bool $getShared = true)
342
    {
343
        if ($getShared) {
7✔
344
            return static::getSharedInstance('honeypot', $config);
5✔
345
        }
346

347
        $config ??= config(HoneypotConfig::class);
7✔
348

349
        return new Honeypot($config);
7✔
350
    }
351

352
    /**
353
     * Acts as a factory for ImageHandler classes and returns an instance
354
     * of the handler. Used like service('image')->withFile($path)->rotate(90)->save();
355
     *
356
     * @return BaseHandler
357
     */
358
    public static function image(?string $handler = null, ?Images $config = null, bool $getShared = true)
359
    {
360
        if ($getShared) {
90✔
361
            return static::getSharedInstance('image', $handler, $config);
1✔
362
        }
363

364
        $config ??= config(Images::class);
90✔
365
        assert($config instanceof Images);
366

367
        $handler = in_array($handler, [null, '', '0'], true) ? $config->defaultHandler : $handler;
90✔
368
        $class   = $config->handlers[$handler];
90✔
369

370
        return new $class($config);
90✔
371
    }
372

373
    /**
374
     * The Iterator class provides a simple way of looping over a function
375
     * and timing the results and memory usage. Used when debugging and
376
     * optimizing applications.
377
     *
378
     * @return Iterator
379
     */
380
    public static function iterator(bool $getShared = true)
381
    {
382
        if ($getShared) {
3✔
383
            return static::getSharedInstance('iterator');
1✔
384
        }
385

386
        return new Iterator();
3✔
387
    }
388

389
    /**
390
     * Responsible for loading the language string translations.
391
     *
392
     * @return Language
393
     */
394
    public static function language(?string $locale = null, bool $getShared = true)
395
    {
396
        if ($getShared) {
523✔
397
            return static::getSharedInstance('language', $locale)->setLocale($locale);
512✔
398
        }
399

400
        if (AppServices::get('request') instanceof IncomingRequest) {
522✔
401
            $requestLocale = AppServices::get('request')->getLocale();
521✔
402
        } else {
403
            $requestLocale = Locale::getDefault();
1✔
404
        }
405

406
        // Use '?:' for empty string check
407
        $locale = in_array($locale, [null, '', '0'], true) ? $requestLocale : $locale;
522✔
408

409
        return new Language($locale);
522✔
410
    }
411

412
    /**
413
     * The Logger class is a PSR-3 compatible Logging class that supports
414
     * multiple handlers that process the actual logging.
415
     *
416
     * @return Logger
417
     */
418
    public static function logger(bool $getShared = true)
419
    {
420
        if ($getShared) {
353✔
421
            return static::getSharedInstance('logger');
351✔
422
        }
423

424
        return new Logger(config(LoggerConfig::class));
351✔
425
    }
426

427
    /**
428
     * Return the appropriate Migration runner.
429
     *
430
     * @return MigrationRunner
431
     */
432
    public static function migrations(?Migrations $config = null, ?ConnectionInterface $db = null, bool $getShared = true)
433
    {
434
        if ($getShared) {
837✔
435
            return static::getSharedInstance('migrations', $config, $db);
2✔
436
        }
437

438
        $config ??= config(Migrations::class);
837✔
439

440
        return new MigrationRunner($config, $db);
837✔
441
    }
442

443
    /**
444
     * The Negotiate class provides the content negotiation features for
445
     * working the request to determine correct language, encoding, charset,
446
     * and more.
447
     *
448
     * @return Negotiate
449
     */
450
    public static function negotiator(?RequestInterface $request = null, bool $getShared = true)
451
    {
452
        if ($getShared) {
11✔
453
            return static::getSharedInstance('negotiator', $request);
9✔
454
        }
455

456
        $request ??= AppServices::get('request');
5✔
457

458
        return new Negotiate($request);
5✔
459
    }
460

461
    /**
462
     * Return the ResponseCache.
463
     *
464
     * @return ResponseCache
465
     */
466
    public static function responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
467
    {
468
        if ($getShared) {
7,512✔
469
            return static::getSharedInstance('responsecache', $config, $cache);
7,512✔
470
        }
471

472
        $config ??= config(Cache::class);
2,108✔
473
        $cache ??= AppServices::get('cache');
2,108✔
474

475
        return new ResponseCache($config, $cache);
2,108✔
476
    }
477

478
    /**
479
     * Return the appropriate pagination handler.
480
     *
481
     * @return Pager
482
     */
483
    public static function pager(?PagerConfig $config = null, ?RendererInterface $view = null, bool $getShared = true)
484
    {
485
        if ($getShared) {
12✔
486
            return static::getSharedInstance('pager', $config, $view);
10✔
487
        }
488

489
        $config ??= config(PagerConfig::class);
12✔
490
        $view ??= AppServices::renderer(null, null, false);
12✔
491

492
        return new Pager($config, $view);
12✔
493
    }
494

495
    /**
496
     * The Parser is a simple template parser.
497
     *
498
     * @return Parser
499
     */
500
    public static function parser(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
501
    {
502
        if ($getShared) {
14✔
503
            return static::getSharedInstance('parser', $viewPath, $config);
12✔
504
        }
505

506
        $viewPath = in_array($viewPath, [null, '', '0'], true) ? (new Paths())->viewDirectory : $viewPath;
14✔
507
        $config ??= config(ViewConfig::class);
14✔
508

509
        return new Parser($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
14✔
510
    }
511

512
    /**
513
     * The Renderer class is the class that actually displays a file to the user.
514
     * The default View class within CodeIgniter is intentionally simple, but this
515
     * service could easily be replaced by a template engine if the user needed to.
516
     *
517
     * @return View
518
     */
519
    public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
520
    {
521
        if ($getShared) {
231✔
522
            return static::getSharedInstance('renderer', $viewPath, $config);
217✔
523
        }
524

525
        $viewPath = in_array($viewPath, [null, '', '0'], true) ? (new Paths())->viewDirectory : $viewPath;
231✔
526
        $config ??= config(ViewConfig::class);
231✔
527

528
        return new View($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
231✔
529
    }
530

531
    /**
532
     * Returns the current Request object.
533
     *
534
     * createRequest() injects IncomingRequest or CLIRequest.
535
     *
536
     * @return CLIRequest|IncomingRequest
537
     */
538
    public static function request()
539
    {
540
        return static::$instances['request'] ?? static::incomingrequest(getShared: false);
2,944✔
541
    }
542

543
    /**
544
     * Create the current Request object, either IncomingRequest or CLIRequest.
545
     *
546
     * This method is called from CodeIgniter::getRequestObject().
547
     *
548
     * @internal
549
     */
550
    public static function createRequest(App $config, bool $isCli = false): void
551
    {
552
        if ($isCli) {
81✔
553
            $request = AppServices::clirequest($config);
4✔
554
        } else {
555
            $request = AppServices::incomingrequest($config);
77✔
556

557
            // guess at protocol if needed
558
            $request->setProtocolVersion(static::superglobals()->server('SERVER_PROTOCOL', 'HTTP/1.1'));
77✔
559
        }
560

561
        // Inject the request object into Services.
562
        static::$instances['request'] = $request;
81✔
563
    }
564

565
    /**
566
     * The IncomingRequest class models an HTTP request.
567
     *
568
     * @return IncomingRequest
569
     *
570
     * @internal
571
     */
572
    public static function incomingrequest(?App $config = null, bool $getShared = true)
573
    {
574
        if ($getShared) {
2,988✔
575
            return static::getSharedInstance('request', $config);
78✔
576
        }
577

578
        $config ??= config(App::class);
2,988✔
579

580
        return new IncomingRequest(
2,988✔
581
            $config,
2,988✔
582
            AppServices::get('uri'),
2,988✔
583
            'php://input',
2,988✔
584
            new UserAgent(),
2,988✔
585
        );
2,988✔
586
    }
587

588
    /**
589
     * The Response class models an HTTP response.
590
     *
591
     * @todo v4.8.0 Remove $config parameter since unused
592
     *
593
     * @return ResponseInterface
594
     */
595
    public static function response(?App $config = null, bool $getShared = true)
596
    {
597
        if ($getShared) {
386✔
598
            return static::getSharedInstance('response', $config);
342✔
599
        }
600

601
        return new Response();
378✔
602
    }
603

604
    /**
605
     * The Redirect class provides nice way of working with redirects.
606
     *
607
     * @todo v4.8.0 Remove $config parameter since unused
608
     *
609
     * @return RedirectResponse
610
     */
611
    public static function redirectresponse(?App $config = null, bool $getShared = true)
612
    {
613
        if ($getShared) {
18✔
614
            return static::getSharedInstance('redirectresponse', $config);
14✔
615
        }
616

617
        $response = new RedirectResponse();
18✔
618
        $response->setProtocolVersion(AppServices::get('request')->getProtocolVersion());
18✔
619

620
        return $response;
18✔
621
    }
622

623
    /**
624
     * The Routes service is a class that allows for easily building
625
     * a collection of routes.
626
     *
627
     * @return RouteCollection
628
     */
629
    public static function routes(bool $getShared = true)
630
    {
631
        if ($getShared) {
258✔
632
            return static::getSharedInstance('routes');
256✔
633
        }
634

635
        return new RouteCollection(AppServices::get('locator'), new Modules(), config(Routing::class));
258✔
636
    }
637

638
    /**
639
     * The Router class uses a RouteCollection's array of routes, and determines
640
     * the correct Controller and Method to execute.
641
     *
642
     * @return Router
643
     */
644
    public static function router(?RouteCollectionInterface $routes = null, ?Request $request = null, bool $getShared = true)
645
    {
646
        if ($getShared) {
115✔
647
            return static::getSharedInstance('router', $routes, $request);
113✔
648
        }
649

650
        $routes ??= AppServices::get('routes');
112✔
651
        $request ??= AppServices::get('request');
112✔
652

653
        return new Router($routes, $request);
112✔
654
    }
655

656
    /**
657
     * The Security class provides a few handy tools for keeping the site
658
     * secure, most notably the CSRF protection tools.
659
     *
660
     * @return Security
661
     */
662
    public static function security(?SecurityConfig $config = null, bool $getShared = true)
663
    {
664
        if ($getShared) {
13✔
665
            return static::getSharedInstance('security', $config);
11✔
666
        }
667

668
        $config ??= config(SecurityConfig::class);
12✔
669

670
        return new Security($config);
12✔
671
    }
672

673
    /**
674
     * Return the session manager.
675
     *
676
     * @return Session
677
     */
678
    public static function session(?SessionConfig $config = null, bool $getShared = true)
679
    {
680
        if ($getShared) {
63✔
681
            return static::getSharedInstance('session', $config);
56✔
682
        }
683

684
        $config ??= config(SessionConfig::class);
62✔
685

686
        $logger = AppServices::get('logger');
62✔
687

688
        $driverName = $config->driver;
62✔
689

690
        if ($driverName === DatabaseHandler::class) {
62✔
691
            $DBGroup = $config->DBGroup ?? config(Database::class)->defaultGroup;
1✔
692

693
            $driverPlatform = Database::connect($DBGroup)->getPlatform();
1✔
694

695
            if ($driverPlatform === 'MySQLi') {
1✔
UNCOV
696
                $driverName = MySQLiHandler::class;
×
697
            } elseif ($driverPlatform === 'Postgre') {
1✔
698
                $driverName = PostgreHandler::class;
×
699
            } else {
700
                throw new InvalidArgumentException(sprintf(
1✔
701
                    'Invalid session database handler "%s" provided. Only "MySQLi" and "Postgre" are supported.',
1✔
702
                    $driverPlatform,
1✔
703
                ));
1✔
704
            }
705
        }
706

707
        if (! class_exists($driverName) || ! is_a($driverName, SessionBaseHandler::class, true)) {
61✔
708
            throw new InvalidArgumentException(sprintf(
3✔
709
                'Invalid session handler "%s" provided.',
3✔
710
                $driverName,
3✔
711
            ));
3✔
712
        }
713

714
        $driver = new $driverName($config, AppServices::get('request')->getIPAddress());
58✔
715
        $driver->setLogger($logger);
58✔
716

717
        $session = new Session($driver, $config);
58✔
718
        $session->setLogger($logger);
58✔
719

720
        if (session_status() === PHP_SESSION_NONE) {
58✔
721
            // PHP Session emits the headers according to `session.cache_limiter`.
722
            // See https://www.php.net/manual/en/function.session-cache-limiter.php.
723
            // The headers are not managed by CI's Response class.
724
            // So, we remove CI's default Cache-Control header.
725
            AppServices::get('response')->removeHeader('Cache-Control');
58✔
726

727
            $session->start();
58✔
728
        }
729

730
        return $session;
58✔
731
    }
732

733
    /**
734
     * The Factory for SiteURI.
735
     *
736
     * @return SiteURIFactory
737
     */
738
    public static function siteurifactory(
739
        ?App $config = null,
740
        ?Superglobals $superglobals = null,
741
        bool $getShared = true,
742
    ) {
743
        if ($getShared) {
22✔
744
            return static::getSharedInstance('siteurifactory', $config, $superglobals);
17✔
745
        }
746

747
        $config ??= config('App');
22✔
748
        $superglobals ??= AppServices::get('superglobals');
22✔
749

750
        return new SiteURIFactory($config, $superglobals);
22✔
751
    }
752

753
    /**
754
     * Superglobals.
755
     *
756
     * @return Superglobals
757
     */
758
    public static function superglobals(
759
        ?array $server = null,
760
        ?array $get = null,
761
        ?array $post = null,
762
        ?array $cookie = null,
763
        ?array $files = null,
764
        ?array $request = null,
765
        bool $getShared = true,
766
    ) {
767
        if ($getShared) {
1,315✔
768
            return static::getSharedInstance('superglobals', $server, $get, $post, $cookie, $files, $request);
1,313✔
769
        }
770

771
        return new Superglobals($server, $get, $post, $cookie, $files, $request);
779✔
772
    }
773

774
    /**
775
     * The Throttler class provides a simple method for implementing
776
     * rate limiting in your applications.
777
     *
778
     * @return Throttler
779
     */
780
    public static function throttler(bool $getShared = true)
781
    {
782
        if ($getShared) {
4✔
783
            return static::getSharedInstance('throttler');
1✔
784
        }
785

786
        return new Throttler(AppServices::get('cache'));
4✔
787
    }
788

789
    /**
790
     * The Timer class provides a simple way to Benchmark portions of your
791
     * application.
792
     *
793
     * @return Timer
794
     */
795
    public static function timer(bool $getShared = true)
796
    {
797
        if ($getShared) {
119✔
798
            return static::getSharedInstance('timer');
117✔
799
        }
800

801
        return new Timer();
117✔
802
    }
803

804
    /**
805
     * Return the debug toolbar.
806
     *
807
     * @return Toolbar
808
     */
809
    public static function toolbar(?ToolbarConfig $config = null, bool $getShared = true)
810
    {
811
        if ($getShared) {
107✔
812
            return static::getSharedInstance('toolbar', $config);
105✔
813
        }
814

815
        $config ??= config(ToolbarConfig::class);
107✔
816

817
        return new Toolbar($config);
107✔
818
    }
819

820
    /**
821
     * The URI class provides a way to model and manipulate URIs.
822
     *
823
     * @param string|null $uri The URI string
824
     *
825
     * @return URI The current URI if $uri is null.
826
     */
827
    public static function uri(?string $uri = null, bool $getShared = true)
828
    {
UNCOV
829
        if ($getShared) {
×
UNCOV
830
            return static::getSharedInstance('uri', $uri);
×
831
        }
832

UNCOV
833
        if ($uri === null) {
×
UNCOV
834
            $appConfig = config(App::class);
×
835
            $factory   = AppServices::siteurifactory($appConfig, AppServices::get('superglobals'));
×
836

837
            return $factory->createFromGlobals();
×
838
        }
839

UNCOV
840
        return new URI($uri);
×
841
    }
842

843
    /**
844
     * The Validation class provides tools for validating input data.
845
     *
846
     * @return ValidationInterface
847
     */
848
    public static function validation(?ValidationConfig $config = null, bool $getShared = true)
849
    {
850
        if ($getShared) {
150✔
851
            return static::getSharedInstance('validation', $config);
47✔
852
        }
853

854
        $config ??= config(ValidationConfig::class);
150✔
855

856
        return new Validation($config, AppServices::get('renderer'));
150✔
857
    }
858

859
    /**
860
     * View cells are intended to let you insert HTML into view
861
     * that has been generated by any callable in the system.
862
     *
863
     * @return Cell
864
     */
865
    public static function viewcell(bool $getShared = true)
866
    {
867
        if ($getShared) {
6✔
868
            return static::getSharedInstance('viewcell');
3✔
869
        }
870

871
        return new Cell(AppServices::get('cache'));
6✔
872
    }
873

874
    /**
875
     * The Typography class provides a way to format text in semantically relevant ways.
876
     *
877
     * @return Typography
878
     */
879
    public static function typography(bool $getShared = true)
880
    {
881
        if ($getShared) {
5✔
882
            return static::getSharedInstance('typography');
3✔
883
        }
884

885
        return new Typography();
5✔
886
    }
887

888
    /**
889
     * The Context class provides a way to store and retrieve static data throughout requests.
890
     */
891
    public static function context(bool $getShared = true): Context
892
    {
893
        if ($getShared) {
65✔
894
            return static::getSharedInstance('context');
2✔
895
        }
896

897
        return new Context();
65✔
898
    }
899
}
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