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

codeigniter4 / CodeIgniter4 / 25902734269

15 May 2026 05:51AM UTC coverage: 88.459% (+0.2%) from 88.299%
25902734269

Pull #10159

github

web-flow
Merge f0573f3e0 into 170b89a6e
Pull Request #10159: feat: Add support for callable TTLs in cache handlers

6 of 10 new or added lines in 3 files covered. (60.0%)

446 existing lines in 24 files now uncovered.

24114 of 27260 relevant lines covered (88.46%)

219.07 hits per line

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

95.33
/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\Input\InputDataFactory;
50
use CodeIgniter\Language\Language;
51
use CodeIgniter\Lock\LockManager;
52
use CodeIgniter\Log\Logger;
53
use CodeIgniter\Pager\Pager;
54
use CodeIgniter\Router\RouteCollection;
55
use CodeIgniter\Router\RouteCollectionInterface;
56
use CodeIgniter\Router\Router;
57
use CodeIgniter\Security\Security;
58
use CodeIgniter\Session\Handlers\BaseHandler as SessionBaseHandler;
59
use CodeIgniter\Session\Handlers\Database\MySQLiHandler;
60
use CodeIgniter\Session\Handlers\Database\PostgreHandler;
61
use CodeIgniter\Session\Handlers\DatabaseHandler;
62
use CodeIgniter\Session\Session;
63
use CodeIgniter\Superglobals;
64
use CodeIgniter\Throttle\Throttler;
65
use CodeIgniter\Typography\Typography;
66
use CodeIgniter\Validation\Validation;
67
use CodeIgniter\Validation\ValidationInterface;
68
use CodeIgniter\View\Cell;
69
use CodeIgniter\View\Parser;
70
use CodeIgniter\View\RendererInterface;
71
use CodeIgniter\View\View;
72
use Config\App;
73
use Config\Cache;
74
use Config\ContentSecurityPolicy as ContentSecurityPolicyConfig;
75
use Config\ContentSecurityPolicy as CSPConfig;
76
use Config\Database;
77
use Config\Email as EmailConfig;
78
use Config\Encryption as EncryptionConfig;
79
use Config\Exceptions as ExceptionsConfig;
80
use Config\Filters as FiltersConfig;
81
use Config\Format as FormatConfig;
82
use Config\Honeypot as HoneypotConfig;
83
use Config\Images;
84
use Config\Logger as LoggerConfig;
85
use Config\Migrations;
86
use Config\Modules;
87
use Config\Pager as PagerConfig;
88
use Config\Paths;
89
use Config\Routing;
90
use Config\Security as SecurityConfig;
91
use Config\Services as AppServices;
92
use Config\Session as SessionConfig;
93
use Config\Toolbar as ToolbarConfig;
94
use Config\Validation as ValidationConfig;
95
use Config\View as ViewConfig;
96
use InvalidArgumentException;
97
use Locale;
98

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

131
        $config ??= config(Cache::class);
2,168✔
132

133
        return CacheFactory::getHandler($config);
2,168✔
134
    }
135

136
    /**
137
     * The locks service provides atomic locks backed by supported cache handlers.
138
     */
139
    public static function locks(?CacheInterface $cache = null, bool $getShared = true): LockManager
140
    {
141
        if ($getShared) {
4✔
142
            return static::getSharedInstance('locks', $cache);
1✔
143
        }
144

145
        $cache ??= AppServices::get('cache');
4✔
146

147
        return new LockManager($cache);
4✔
148
    }
149

150
    /**
151
     * The CLI Request class provides for ways to interact with
152
     * a command line request.
153
     *
154
     * @return CLIRequest
155
     *
156
     * @internal
157
     */
158
    public static function clirequest(?App $config = null, bool $getShared = true)
159
    {
160
        if ($getShared) {
10✔
161
            return static::getSharedInstance('clirequest', $config);
5✔
162
        }
163

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

166
        return new CLIRequest($config);
10✔
167
    }
168

169
    /**
170
     * CodeIgniter, the core of the framework.
171
     *
172
     * @return CodeIgniter
173
     */
174
    public static function codeigniter(?App $config = null, bool $getShared = true)
175
    {
176
        if ($getShared) {
2✔
UNCOV
177
            return static::getSharedInstance('codeigniter', $config);
×
178
        }
179

180
        $config ??= config(App::class);
2✔
181

182
        return new CodeIgniter($config);
2✔
183
    }
184

185
    /**
186
     * The commands utility for running and working with CLI commands.
187
     *
188
     * @return Commands
189
     */
190
    public static function commands(bool $getShared = true)
191
    {
192
        if ($getShared) {
63✔
193
            return static::getSharedInstance('commands');
61✔
194
        }
195

196
        return new Commands();
63✔
197
    }
198

199
    /**
200
     * Content Security Policy
201
     *
202
     * @return ContentSecurityPolicy
203
     */
204
    public static function csp(?CSPConfig $config = null, bool $getShared = true)
205
    {
206
        if ($getShared) {
110✔
207
            return static::getSharedInstance('csp', $config);
108✔
208
        }
209

210
        $config ??= config(ContentSecurityPolicyConfig::class);
110✔
211

212
        return new ContentSecurityPolicy($config);
110✔
213
    }
214

215
    /**
216
     * The CURL Request class acts as a simple HTTP client for interacting
217
     * with other servers, typically through APIs.
218
     *
219
     * @todo v4.8.0 Remove $config parameter since unused
220
     *
221
     * @return CURLRequest
222
     */
223
    public static function curlrequest(array $options = [], ?ResponseInterface $response = null, ?App $config = null, bool $getShared = true)
224
    {
225
        if ($getShared) {
5✔
226
            return static::getSharedInstance('curlrequest', $options, $response, $config);
3✔
227
        }
228

229
        $config ??= config(App::class);
5✔
230
        $response ??= new Response();
5✔
231

232
        return new CURLRequest(
5✔
233
            $config,
5✔
234
            new URI($options['baseURI'] ?? null),
5✔
235
            $response,
5✔
236
            $options,
5✔
237
        );
5✔
238
    }
239

240
    /**
241
     * The Email class allows you to send email via mail, sendmail, SMTP.
242
     *
243
     * @param array|EmailConfig|null $config
244
     *
245
     * @return Email
246
     */
247
    public static function email($config = null, bool $getShared = true)
248
    {
249
        if ($getShared) {
5✔
250
            return static::getSharedInstance('email', $config);
1✔
251
        }
252

253
        if (empty($config) || (! is_array($config) && ! $config instanceof EmailConfig)) {
4✔
254
            $config = config(EmailConfig::class);
3✔
255
        }
256

257
        return new Email($config);
4✔
258
    }
259

260
    /**
261
     * The Encryption class provides two-way encryption.
262
     *
263
     * @param bool $getShared
264
     *
265
     * @return EncrypterInterface Encryption handler
266
     */
267
    public static function encrypter(?EncryptionConfig $config = null, $getShared = false)
268
    {
269
        if ($getShared === true) {
7✔
270
            return static::getSharedInstance('encrypter', $config);
1✔
271
        }
272

273
        $config ??= config(EncryptionConfig::class);
7✔
274
        $encryption = new Encryption($config);
7✔
275

276
        return $encryption->initialize($config);
6✔
277
    }
278

279
    /**
280
     * Provides a simple way to determine the current environment
281
     * of the application.
282
     *
283
     * Primarily intended for testing environment-specific branches by
284
     * mocking this service. Mocking it does not modify the `ENVIRONMENT`
285
     * constant. It only affects code paths that resolve and use this service.
286
     */
287
    public static function environment(?string $environment = null, bool $getShared = true): EnvironmentDetector
288
    {
289
        if ($getShared) {
589✔
290
            return static::getSharedInstance('environment', $environment);
587✔
291
        }
292

293
        return new EnvironmentDetector($environment);
589✔
294
    }
295

296
    /**
297
     * The Exceptions class holds the methods that handle:
298
     *
299
     *  - set_exception_handler
300
     *  - set_error_handler
301
     *  - register_shutdown_function
302
     *
303
     * @return Exceptions
304
     */
305
    public static function exceptions(
306
        ?ExceptionsConfig $config = null,
307
        bool $getShared = true,
308
    ) {
309
        if ($getShared) {
4✔
310
            return static::getSharedInstance('exceptions', $config);
1✔
311
        }
312

313
        $config ??= config(ExceptionsConfig::class);
4✔
314

315
        return new Exceptions($config);
4✔
316
    }
317

318
    /**
319
     * Filters allow you to run tasks before and/or after a controller
320
     * is executed. During before filters, the request can be modified,
321
     * and actions taken based on the request, while after filters can
322
     * act on or modify the response itself before it is sent to the client.
323
     *
324
     * @return Filters
325
     */
326
    public static function filters(?FiltersConfig $config = null, bool $getShared = true)
327
    {
328
        if ($getShared) {
147✔
329
            return static::getSharedInstance('filters', $config);
145✔
330
        }
331

332
        $config ??= config(FiltersConfig::class);
147✔
333

334
        return new Filters($config, AppServices::get('request'), AppServices::get('response'));
147✔
335
    }
336

337
    /**
338
     * The Format class is a convenient place to create Formatters.
339
     *
340
     * @return Format
341
     */
342
    public static function format(?FormatConfig $config = null, bool $getShared = true)
343
    {
344
        if ($getShared) {
39✔
345
            return static::getSharedInstance('format', $config);
36✔
346
        }
347

348
        $config ??= config(FormatConfig::class);
39✔
349

350
        return new Format($config);
39✔
351
    }
352

353
    /**
354
     * The Honeypot provides a secret input on forms that bots should NOT
355
     * fill in, providing an additional safeguard when accepting user input.
356
     *
357
     * @return Honeypot
358
     */
359
    public static function honeypot(?HoneypotConfig $config = null, bool $getShared = true)
360
    {
361
        if ($getShared) {
8✔
362
            return static::getSharedInstance('honeypot', $config);
6✔
363
        }
364

365
        $config ??= config(HoneypotConfig::class);
8✔
366

367
        return new Honeypot($config);
8✔
368
    }
369

370
    /**
371
     * Acts as a factory for ImageHandler classes and returns an instance
372
     * of the handler. Used like service('image')->withFile($path)->rotate(90)->save();
373
     *
374
     * @return BaseHandler
375
     */
376
    public static function image(?string $handler = null, ?Images $config = null, bool $getShared = true)
377
    {
378
        if ($getShared) {
90✔
379
            return static::getSharedInstance('image', $handler, $config);
1✔
380
        }
381

382
        $config ??= config(Images::class);
90✔
383
        assert($config instanceof Images);
384

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

388
        return new $class($config);
90✔
389
    }
390

391
    /**
392
     * Returns the typed input data factory.
393
     */
394
    public static function inputdatafactory(bool $getShared = true): InputDataFactory
395
    {
396
        if ($getShared) {
5✔
397
            return static::getSharedInstance('inputdatafactory');
3✔
398
        }
399

400
        return new InputDataFactory();
5✔
401
    }
402

403
    /**
404
     * The Iterator class provides a simple way of looping over a function
405
     * and timing the results and memory usage. Used when debugging and
406
     * optimizing applications.
407
     *
408
     * @return Iterator
409
     */
410
    public static function iterator(bool $getShared = true)
411
    {
412
        if ($getShared) {
3✔
413
            return static::getSharedInstance('iterator');
1✔
414
        }
415

416
        return new Iterator();
3✔
417
    }
418

419
    /**
420
     * Responsible for loading the language string translations.
421
     *
422
     * @return Language
423
     */
424
    public static function language(?string $locale = null, bool $getShared = true)
425
    {
426
        if ($getShared) {
533✔
427
            return static::getSharedInstance('language', $locale)->setLocale($locale);
522✔
428
        }
429

430
        if (AppServices::get('request') instanceof IncomingRequest) {
532✔
431
            $requestLocale = AppServices::get('request')->getLocale();
531✔
432
        } else {
433
            $requestLocale = Locale::getDefault();
1✔
434
        }
435

436
        // Use '?:' for empty string check
437
        $locale = in_array($locale, [null, '', '0'], true) ? $requestLocale : $locale;
532✔
438

439
        return new Language($locale);
532✔
440
    }
441

442
    /**
443
     * The Logger class is a PSR-3 compatible Logging class that supports
444
     * multiple handlers that process the actual logging.
445
     *
446
     * @return Logger
447
     */
448
    public static function logger(bool $getShared = true)
449
    {
450
        if ($getShared) {
359✔
451
            return static::getSharedInstance('logger');
357✔
452
        }
453

454
        return new Logger(config(LoggerConfig::class));
357✔
455
    }
456

457
    /**
458
     * Return the appropriate Migration runner.
459
     *
460
     * @return MigrationRunner
461
     */
462
    public static function migrations(?Migrations $config = null, ?ConnectionInterface $db = null, bool $getShared = true)
463
    {
464
        if ($getShared) {
884✔
465
            return static::getSharedInstance('migrations', $config, $db);
2✔
466
        }
467

468
        $config ??= config(Migrations::class);
884✔
469

470
        return new MigrationRunner($config, $db);
884✔
471
    }
472

473
    /**
474
     * The Negotiate class provides the content negotiation features for
475
     * working the request to determine correct language, encoding, charset,
476
     * and more.
477
     *
478
     * @return Negotiate
479
     */
480
    public static function negotiator(?RequestInterface $request = null, bool $getShared = true)
481
    {
482
        if ($getShared) {
11✔
483
            return static::getSharedInstance('negotiator', $request);
9✔
484
        }
485

486
        $request ??= AppServices::get('request');
5✔
487

488
        return new Negotiate($request);
5✔
489
    }
490

491
    /**
492
     * Return the ResponseCache.
493
     *
494
     * @return ResponseCache
495
     */
496
    public static function responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
497
    {
498
        if ($getShared) {
7,791✔
499
            return static::getSharedInstance('responsecache', $config, $cache);
7,791✔
500
        }
501

502
        $config ??= config(Cache::class);
2,167✔
503
        $cache ??= AppServices::get('cache');
2,167✔
504

505
        return new ResponseCache($config, $cache);
2,167✔
506
    }
507

508
    /**
509
     * Return the appropriate pagination handler.
510
     *
511
     * @return Pager
512
     */
513
    public static function pager(?PagerConfig $config = null, ?RendererInterface $view = null, bool $getShared = true)
514
    {
515
        if ($getShared) {
12✔
516
            return static::getSharedInstance('pager', $config, $view);
10✔
517
        }
518

519
        $config ??= config(PagerConfig::class);
12✔
520
        $view ??= AppServices::renderer(null, null, false);
12✔
521

522
        return new Pager($config, $view);
12✔
523
    }
524

525
    /**
526
     * The Parser is a simple template parser.
527
     *
528
     * @return Parser
529
     */
530
    public static function parser(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
531
    {
532
        if ($getShared) {
14✔
533
            return static::getSharedInstance('parser', $viewPath, $config);
12✔
534
        }
535

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

539
        return new Parser($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
14✔
540
    }
541

542
    /**
543
     * The Renderer class is the class that actually displays a file to the user.
544
     * The default View class within CodeIgniter is intentionally simple, but this
545
     * service could easily be replaced by a template engine if the user needed to.
546
     *
547
     * @return View
548
     */
549
    public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
550
    {
551
        if ($getShared) {
233✔
552
            return static::getSharedInstance('renderer', $viewPath, $config);
219✔
553
        }
554

555
        $viewPath = in_array($viewPath, [null, '', '0'], true) ? (new Paths())->viewDirectory : $viewPath;
233✔
556
        $config ??= config(ViewConfig::class);
233✔
557

558
        return new View($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
233✔
559
    }
560

561
    /**
562
     * Returns the current Request object.
563
     *
564
     * createRequest() injects IncomingRequest or CLIRequest.
565
     *
566
     * @return CLIRequest|IncomingRequest
567
     */
568
    public static function request()
569
    {
570
        return static::$instances['request'] ?? static::incomingrequest(getShared: false);
2,958✔
571
    }
572

573
    /**
574
     * Create the current Request object, either IncomingRequest or CLIRequest.
575
     *
576
     * This method is called from CodeIgniter::getRequestObject().
577
     *
578
     * @internal
579
     */
580
    public static function createRequest(App $config, bool $isCli = false): void
581
    {
582
        if ($isCli) {
81✔
583
            $request = AppServices::clirequest($config);
4✔
584
        } else {
585
            $request = AppServices::incomingrequest($config);
77✔
586

587
            // guess at protocol if needed
588
            $request->setProtocolVersion(static::superglobals()->server('SERVER_PROTOCOL', 'HTTP/1.1'));
77✔
589
        }
590

591
        // Inject the request object into Services.
592
        static::$instances['request'] = $request;
81✔
593
    }
594

595
    /**
596
     * The IncomingRequest class models an HTTP request.
597
     *
598
     * @return IncomingRequest
599
     *
600
     * @internal
601
     */
602
    public static function incomingrequest(?App $config = null, bool $getShared = true)
603
    {
604
        if ($getShared) {
3,006✔
605
            return static::getSharedInstance('request', $config);
78✔
606
        }
607

608
        $config ??= config(App::class);
3,006✔
609

610
        return new IncomingRequest(
3,006✔
611
            $config,
3,006✔
612
            AppServices::get('uri'),
3,006✔
613
            'php://input',
3,006✔
614
            new UserAgent(),
3,006✔
615
        );
3,006✔
616
    }
617

618
    /**
619
     * The Response class models an HTTP response.
620
     *
621
     * @todo v4.8.0 Remove $config parameter since unused
622
     *
623
     * @return ResponseInterface
624
     */
625
    public static function response(?App $config = null, bool $getShared = true)
626
    {
627
        if ($getShared) {
397✔
628
            return static::getSharedInstance('response', $config);
354✔
629
        }
630

631
        return new Response();
389✔
632
    }
633

634
    /**
635
     * The Redirect class provides nice way of working with redirects.
636
     *
637
     * @todo v4.8.0 Remove $config parameter since unused
638
     *
639
     * @return RedirectResponse
640
     */
641
    public static function redirectresponse(?App $config = null, bool $getShared = true)
642
    {
643
        if ($getShared) {
18✔
644
            return static::getSharedInstance('redirectresponse', $config);
14✔
645
        }
646

647
        $response = new RedirectResponse();
18✔
648
        $response->setProtocolVersion(AppServices::get('request')->getProtocolVersion());
18✔
649

650
        return $response;
18✔
651
    }
652

653
    /**
654
     * The Routes service is a class that allows for easily building
655
     * a collection of routes.
656
     *
657
     * @return RouteCollection
658
     */
659
    public static function routes(bool $getShared = true)
660
    {
661
        if ($getShared) {
257✔
662
            return static::getSharedInstance('routes');
255✔
663
        }
664

665
        return new RouteCollection(AppServices::get('locator'), new Modules(), config(Routing::class));
257✔
666
    }
667

668
    /**
669
     * The Router class uses a RouteCollection's array of routes, and determines
670
     * the correct Controller and Method to execute.
671
     *
672
     * @return Router
673
     */
674
    public static function router(?RouteCollectionInterface $routes = null, ?Request $request = null, bool $getShared = true)
675
    {
676
        if ($getShared) {
115✔
677
            return static::getSharedInstance('router', $routes, $request);
113✔
678
        }
679

680
        $routes ??= AppServices::get('routes');
112✔
681
        $request ??= AppServices::get('request');
112✔
682

683
        return new Router($routes, $request);
112✔
684
    }
685

686
    /**
687
     * The Security class provides a few handy tools for keeping the site
688
     * secure, most notably the CSRF protection tools.
689
     *
690
     * @return Security
691
     */
692
    public static function security(?SecurityConfig $config = null, bool $getShared = true)
693
    {
694
        if ($getShared) {
13✔
695
            return static::getSharedInstance('security', $config);
11✔
696
        }
697

698
        $config ??= config(SecurityConfig::class);
12✔
699

700
        return new Security($config);
12✔
701
    }
702

703
    /**
704
     * Return the session manager.
705
     *
706
     * @return Session
707
     */
708
    public static function session(?SessionConfig $config = null, bool $getShared = true)
709
    {
710
        if ($getShared) {
63✔
711
            return static::getSharedInstance('session', $config);
56✔
712
        }
713

714
        $config ??= config(SessionConfig::class);
62✔
715

716
        $logger = AppServices::get('logger');
62✔
717

718
        $driverName = $config->driver;
62✔
719

720
        if ($driverName === DatabaseHandler::class) {
62✔
721
            $DBGroup = $config->DBGroup ?? config(Database::class)->defaultGroup;
1✔
722

723
            $driverPlatform = Database::connect($DBGroup)->getPlatform();
1✔
724

725
            if ($driverPlatform === 'MySQLi') {
1✔
UNCOV
726
                $driverName = MySQLiHandler::class;
×
727
            } elseif ($driverPlatform === 'Postgre') {
1✔
UNCOV
728
                $driverName = PostgreHandler::class;
×
729
            } else {
730
                throw new InvalidArgumentException(sprintf(
1✔
731
                    'Invalid session database handler "%s" provided. Only "MySQLi" and "Postgre" are supported.',
1✔
732
                    $driverPlatform,
1✔
733
                ));
1✔
734
            }
735
        }
736

737
        if (! class_exists($driverName) || ! is_a($driverName, SessionBaseHandler::class, true)) {
61✔
738
            throw new InvalidArgumentException(sprintf(
3✔
739
                'Invalid session handler "%s" provided.',
3✔
740
                $driverName,
3✔
741
            ));
3✔
742
        }
743

744
        $driver = new $driverName($config, AppServices::get('request')->getIPAddress());
58✔
745
        $driver->setLogger($logger);
58✔
746

747
        $session = new Session($driver, $config);
58✔
748
        $session->setLogger($logger);
58✔
749

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

757
            $session->start();
58✔
758
        }
759

760
        return $session;
58✔
761
    }
762

763
    /**
764
     * The Factory for SiteURI.
765
     *
766
     * @return SiteURIFactory
767
     */
768
    public static function siteurifactory(
769
        ?App $config = null,
770
        ?Superglobals $superglobals = null,
771
        bool $getShared = true,
772
    ) {
773
        if ($getShared) {
22✔
774
            return static::getSharedInstance('siteurifactory', $config, $superglobals);
17✔
775
        }
776

777
        $config ??= config('App');
22✔
778
        $superglobals ??= AppServices::get('superglobals');
22✔
779

780
        return new SiteURIFactory($config, $superglobals);
22✔
781
    }
782

783
    /**
784
     * Superglobals.
785
     *
786
     * @return Superglobals
787
     */
788
    public static function superglobals(
789
        ?array $server = null,
790
        ?array $get = null,
791
        ?array $post = null,
792
        ?array $cookie = null,
793
        ?array $files = null,
794
        ?array $request = null,
795
        bool $getShared = true,
796
    ) {
797
        if ($getShared) {
1,352✔
798
            return static::getSharedInstance('superglobals', $server, $get, $post, $cookie, $files, $request);
1,350✔
799
        }
800

801
        return new Superglobals($server, $get, $post, $cookie, $files, $request);
799✔
802
    }
803

804
    /**
805
     * The Throttler class provides a simple method for implementing
806
     * rate limiting in your applications.
807
     *
808
     * @return Throttler
809
     */
810
    public static function throttler(bool $getShared = true)
811
    {
812
        if ($getShared) {
4✔
813
            return static::getSharedInstance('throttler');
1✔
814
        }
815

816
        return new Throttler(AppServices::get('cache'));
4✔
817
    }
818

819
    /**
820
     * The Timer class provides a simple way to Benchmark portions of your
821
     * application.
822
     *
823
     * @return Timer
824
     */
825
    public static function timer(bool $getShared = true)
826
    {
827
        if ($getShared) {
119✔
828
            return static::getSharedInstance('timer');
117✔
829
        }
830

831
        return new Timer();
117✔
832
    }
833

834
    /**
835
     * Return the debug toolbar.
836
     *
837
     * @return Toolbar
838
     */
839
    public static function toolbar(?ToolbarConfig $config = null, bool $getShared = true)
840
    {
841
        if ($getShared) {
107✔
842
            return static::getSharedInstance('toolbar', $config);
105✔
843
        }
844

845
        $config ??= config(ToolbarConfig::class);
107✔
846

847
        return new Toolbar($config);
107✔
848
    }
849

850
    /**
851
     * The URI class provides a way to model and manipulate URIs.
852
     *
853
     * @param string|null $uri The URI string
854
     *
855
     * @return URI The current URI if $uri is null.
856
     */
857
    public static function uri(?string $uri = null, bool $getShared = true)
858
    {
UNCOV
859
        if ($getShared) {
×
UNCOV
860
            return static::getSharedInstance('uri', $uri);
×
861
        }
862

UNCOV
863
        if ($uri === null) {
×
UNCOV
864
            $appConfig = config(App::class);
×
UNCOV
865
            $factory   = AppServices::siteurifactory($appConfig, AppServices::get('superglobals'));
×
866

UNCOV
867
            return $factory->createFromGlobals();
×
868
        }
869

UNCOV
870
        return new URI($uri);
×
871
    }
872

873
    /**
874
     * The Validation class provides tools for validating input data.
875
     *
876
     * @return ValidationInterface
877
     */
878
    public static function validation(?ValidationConfig $config = null, bool $getShared = true)
879
    {
880
        if ($getShared) {
154✔
881
            return static::getSharedInstance('validation', $config);
48✔
882
        }
883

884
        $config ??= config(ValidationConfig::class);
154✔
885

886
        return new Validation($config, AppServices::get('renderer'));
154✔
887
    }
888

889
    /**
890
     * View cells are intended to let you insert HTML into view
891
     * that has been generated by any callable in the system.
892
     *
893
     * @return Cell
894
     */
895
    public static function viewcell(bool $getShared = true)
896
    {
897
        if ($getShared) {
6✔
898
            return static::getSharedInstance('viewcell');
3✔
899
        }
900

901
        return new Cell(AppServices::get('cache'));
6✔
902
    }
903

904
    /**
905
     * The Typography class provides a way to format text in semantically relevant ways.
906
     *
907
     * @return Typography
908
     */
909
    public static function typography(bool $getShared = true)
910
    {
911
        if ($getShared) {
5✔
912
            return static::getSharedInstance('typography');
3✔
913
        }
914

915
        return new Typography();
5✔
916
    }
917

918
    /**
919
     * The Context class provides a way to store and retrieve static data throughout requests.
920
     */
921
    public static function context(bool $getShared = true): Context
922
    {
923
        if ($getShared) {
65✔
924
            return static::getSharedInstance('context');
2✔
925
        }
926

927
        return new Context();
65✔
928
    }
929
}
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