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

codeigniter4 / CodeIgniter4 / 25399569005

05 May 2026 08:08PM UTC coverage: 88.276% (+0.002%) from 88.274%
25399569005

Pull #10158

github

web-flow
Merge d7067f3ce into 3cdb4c5e1
Pull Request #10158: feat: add typed FormRequest accessors

65 of 73 new or added lines in 3 files covered. (89.04%)

28 existing lines in 4 files now uncovered.

23552 of 26680 relevant lines covered (88.28%)

218.03 hits per line

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

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

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

130
        $config ??= config(Cache::class);
2,134✔
131

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

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

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

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

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

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

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

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

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

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

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

195
        return new Commands();
57✔
196
    }
197

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

209
        $config ??= config(ContentSecurityPolicyConfig::class);
108✔
210

211
        return new ContentSecurityPolicy($config);
108✔
212
    }
213

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

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

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

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

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

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

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

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

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

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

292
        return new EnvironmentDetector($environment);
584✔
293
    }
294

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

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

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

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

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

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

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

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

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

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

364
        $config ??= config(HoneypotConfig::class);
7✔
365

366
        return new Honeypot($config);
7✔
367
    }
368

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

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

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

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

390
    /**
391
     * The Iterator class provides a simple way of looping over a function
392
     * and timing the results and memory usage. Used when debugging and
393
     * optimizing applications.
394
     *
395
     * @return Iterator
396
     */
397
    public static function iterator(bool $getShared = true)
398
    {
399
        if ($getShared) {
3✔
400
            return static::getSharedInstance('iterator');
1✔
401
        }
402

403
        return new Iterator();
3✔
404
    }
405

406
    /**
407
     * Responsible for loading the language string translations.
408
     *
409
     * @return Language
410
     */
411
    public static function language(?string $locale = null, bool $getShared = true)
412
    {
413
        if ($getShared) {
522✔
414
            return static::getSharedInstance('language', $locale)->setLocale($locale);
511✔
415
        }
416

417
        if (AppServices::get('request') instanceof IncomingRequest) {
521✔
418
            $requestLocale = AppServices::get('request')->getLocale();
520✔
419
        } else {
420
            $requestLocale = Locale::getDefault();
1✔
421
        }
422

423
        // Use '?:' for empty string check
424
        $locale = in_array($locale, [null, '', '0'], true) ? $requestLocale : $locale;
521✔
425

426
        return new Language($locale);
521✔
427
    }
428

429
    /**
430
     * The Logger class is a PSR-3 compatible Logging class that supports
431
     * multiple handlers that process the actual logging.
432
     *
433
     * @return Logger
434
     */
435
    public static function logger(bool $getShared = true)
436
    {
437
        if ($getShared) {
353✔
438
            return static::getSharedInstance('logger');
351✔
439
        }
440

441
        return new Logger(config(LoggerConfig::class));
351✔
442
    }
443

444
    /**
445
     * Return the appropriate Migration runner.
446
     *
447
     * @return MigrationRunner
448
     */
449
    public static function migrations(?Migrations $config = null, ?ConnectionInterface $db = null, bool $getShared = true)
450
    {
451
        if ($getShared) {
864✔
452
            return static::getSharedInstance('migrations', $config, $db);
2✔
453
        }
454

455
        $config ??= config(Migrations::class);
864✔
456

457
        return new MigrationRunner($config, $db);
864✔
458
    }
459

460
    /**
461
     * The Negotiate class provides the content negotiation features for
462
     * working the request to determine correct language, encoding, charset,
463
     * and more.
464
     *
465
     * @return Negotiate
466
     */
467
    public static function negotiator(?RequestInterface $request = null, bool $getShared = true)
468
    {
469
        if ($getShared) {
11✔
470
            return static::getSharedInstance('negotiator', $request);
9✔
471
        }
472

473
        $request ??= AppServices::get('request');
5✔
474

475
        return new Negotiate($request);
5✔
476
    }
477

478
    /**
479
     * Return the ResponseCache.
480
     *
481
     * @return ResponseCache
482
     */
483
    public static function responsecache(?Cache $config = null, ?CacheInterface $cache = null, bool $getShared = true)
484
    {
485
        if ($getShared) {
7,605✔
486
            return static::getSharedInstance('responsecache', $config, $cache);
7,605✔
487
        }
488

489
        $config ??= config(Cache::class);
2,133✔
490
        $cache ??= AppServices::get('cache');
2,133✔
491

492
        return new ResponseCache($config, $cache);
2,133✔
493
    }
494

495
    /**
496
     * Return the appropriate pagination handler.
497
     *
498
     * @return Pager
499
     */
500
    public static function pager(?PagerConfig $config = null, ?RendererInterface $view = null, bool $getShared = true)
501
    {
502
        if ($getShared) {
12✔
503
            return static::getSharedInstance('pager', $config, $view);
10✔
504
        }
505

506
        $config ??= config(PagerConfig::class);
12✔
507
        $view ??= AppServices::renderer(null, null, false);
12✔
508

509
        return new Pager($config, $view);
12✔
510
    }
511

512
    /**
513
     * The Parser is a simple template parser.
514
     *
515
     * @return Parser
516
     */
517
    public static function parser(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
518
    {
519
        if ($getShared) {
14✔
520
            return static::getSharedInstance('parser', $viewPath, $config);
12✔
521
        }
522

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

526
        return new Parser($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
14✔
527
    }
528

529
    /**
530
     * The Renderer class is the class that actually displays a file to the user.
531
     * The default View class within CodeIgniter is intentionally simple, but this
532
     * service could easily be replaced by a template engine if the user needed to.
533
     *
534
     * @return View
535
     */
536
    public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
537
    {
538
        if ($getShared) {
233✔
539
            return static::getSharedInstance('renderer', $viewPath, $config);
219✔
540
        }
541

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

545
        return new View($config, $viewPath, AppServices::get('locator'), CI_DEBUG, AppServices::get('logger'));
233✔
546
    }
547

548
    /**
549
     * Returns the current Request object.
550
     *
551
     * createRequest() injects IncomingRequest or CLIRequest.
552
     *
553
     * @return CLIRequest|IncomingRequest
554
     */
555
    public static function request()
556
    {
557
        return static::$instances['request'] ?? static::incomingrequest(getShared: false);
2,946✔
558
    }
559

560
    /**
561
     * Create the current Request object, either IncomingRequest or CLIRequest.
562
     *
563
     * This method is called from CodeIgniter::getRequestObject().
564
     *
565
     * @internal
566
     */
567
    public static function createRequest(App $config, bool $isCli = false): void
568
    {
569
        if ($isCli) {
81✔
570
            $request = AppServices::clirequest($config);
4✔
571
        } else {
572
            $request = AppServices::incomingrequest($config);
77✔
573

574
            // guess at protocol if needed
575
            $request->setProtocolVersion(static::superglobals()->server('SERVER_PROTOCOL', 'HTTP/1.1'));
77✔
576
        }
577

578
        // Inject the request object into Services.
579
        static::$instances['request'] = $request;
81✔
580
    }
581

582
    /**
583
     * The IncomingRequest class models an HTTP request.
584
     *
585
     * @return IncomingRequest
586
     *
587
     * @internal
588
     */
589
    public static function incomingrequest(?App $config = null, bool $getShared = true)
590
    {
591
        if ($getShared) {
2,990✔
592
            return static::getSharedInstance('request', $config);
78✔
593
        }
594

595
        $config ??= config(App::class);
2,990✔
596

597
        return new IncomingRequest(
2,990✔
598
            $config,
2,990✔
599
            AppServices::get('uri'),
2,990✔
600
            'php://input',
2,990✔
601
            new UserAgent(),
2,990✔
602
        );
2,990✔
603
    }
604

605
    /**
606
     * The Response class models an HTTP response.
607
     *
608
     * @todo v4.8.0 Remove $config parameter since unused
609
     *
610
     * @return ResponseInterface
611
     */
612
    public static function response(?App $config = null, bool $getShared = true)
613
    {
614
        if ($getShared) {
387✔
615
            return static::getSharedInstance('response', $config);
343✔
616
        }
617

618
        return new Response();
379✔
619
    }
620

621
    /**
622
     * The Redirect class provides nice way of working with redirects.
623
     *
624
     * @todo v4.8.0 Remove $config parameter since unused
625
     *
626
     * @return RedirectResponse
627
     */
628
    public static function redirectresponse(?App $config = null, bool $getShared = true)
629
    {
630
        if ($getShared) {
18✔
631
            return static::getSharedInstance('redirectresponse', $config);
14✔
632
        }
633

634
        $response = new RedirectResponse();
18✔
635
        $response->setProtocolVersion(AppServices::get('request')->getProtocolVersion());
18✔
636

637
        return $response;
18✔
638
    }
639

640
    /**
641
     * The Routes service is a class that allows for easily building
642
     * a collection of routes.
643
     *
644
     * @return RouteCollection
645
     */
646
    public static function routes(bool $getShared = true)
647
    {
648
        if ($getShared) {
257✔
649
            return static::getSharedInstance('routes');
255✔
650
        }
651

652
        return new RouteCollection(AppServices::get('locator'), new Modules(), config(Routing::class));
257✔
653
    }
654

655
    /**
656
     * The Router class uses a RouteCollection's array of routes, and determines
657
     * the correct Controller and Method to execute.
658
     *
659
     * @return Router
660
     */
661
    public static function router(?RouteCollectionInterface $routes = null, ?Request $request = null, bool $getShared = true)
662
    {
663
        if ($getShared) {
115✔
664
            return static::getSharedInstance('router', $routes, $request);
113✔
665
        }
666

667
        $routes ??= AppServices::get('routes');
112✔
668
        $request ??= AppServices::get('request');
112✔
669

670
        return new Router($routes, $request);
112✔
671
    }
672

673
    /**
674
     * The Security class provides a few handy tools for keeping the site
675
     * secure, most notably the CSRF protection tools.
676
     *
677
     * @return Security
678
     */
679
    public static function security(?SecurityConfig $config = null, bool $getShared = true)
680
    {
681
        if ($getShared) {
13✔
682
            return static::getSharedInstance('security', $config);
11✔
683
        }
684

685
        $config ??= config(SecurityConfig::class);
12✔
686

687
        return new Security($config);
12✔
688
    }
689

690
    /**
691
     * Return the session manager.
692
     *
693
     * @return Session
694
     */
695
    public static function session(?SessionConfig $config = null, bool $getShared = true)
696
    {
697
        if ($getShared) {
63✔
698
            return static::getSharedInstance('session', $config);
56✔
699
        }
700

701
        $config ??= config(SessionConfig::class);
62✔
702

703
        $logger = AppServices::get('logger');
62✔
704

705
        $driverName = $config->driver;
62✔
706

707
        if ($driverName === DatabaseHandler::class) {
62✔
708
            $DBGroup = $config->DBGroup ?? config(Database::class)->defaultGroup;
1✔
709

710
            $driverPlatform = Database::connect($DBGroup)->getPlatform();
1✔
711

712
            if ($driverPlatform === 'MySQLi') {
1✔
UNCOV
713
                $driverName = MySQLiHandler::class;
×
714
            } elseif ($driverPlatform === 'Postgre') {
1✔
UNCOV
715
                $driverName = PostgreHandler::class;
×
716
            } else {
717
                throw new InvalidArgumentException(sprintf(
1✔
718
                    'Invalid session database handler "%s" provided. Only "MySQLi" and "Postgre" are supported.',
1✔
719
                    $driverPlatform,
1✔
720
                ));
1✔
721
            }
722
        }
723

724
        if (! class_exists($driverName) || ! is_a($driverName, SessionBaseHandler::class, true)) {
61✔
725
            throw new InvalidArgumentException(sprintf(
3✔
726
                'Invalid session handler "%s" provided.',
3✔
727
                $driverName,
3✔
728
            ));
3✔
729
        }
730

731
        $driver = new $driverName($config, AppServices::get('request')->getIPAddress());
58✔
732
        $driver->setLogger($logger);
58✔
733

734
        $session = new Session($driver, $config);
58✔
735
        $session->setLogger($logger);
58✔
736

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

744
            $session->start();
58✔
745
        }
746

747
        return $session;
58✔
748
    }
749

750
    /**
751
     * The Factory for SiteURI.
752
     *
753
     * @return SiteURIFactory
754
     */
755
    public static function siteurifactory(
756
        ?App $config = null,
757
        ?Superglobals $superglobals = null,
758
        bool $getShared = true,
759
    ) {
760
        if ($getShared) {
22✔
761
            return static::getSharedInstance('siteurifactory', $config, $superglobals);
17✔
762
        }
763

764
        $config ??= config('App');
22✔
765
        $superglobals ??= AppServices::get('superglobals');
22✔
766

767
        return new SiteURIFactory($config, $superglobals);
22✔
768
    }
769

770
    /**
771
     * Superglobals.
772
     *
773
     * @return Superglobals
774
     */
775
    public static function superglobals(
776
        ?array $server = null,
777
        ?array $get = null,
778
        ?array $post = null,
779
        ?array $cookie = null,
780
        ?array $files = null,
781
        ?array $request = null,
782
        bool $getShared = true,
783
    ) {
784
        if ($getShared) {
1,315✔
785
            return static::getSharedInstance('superglobals', $server, $get, $post, $cookie, $files, $request);
1,313✔
786
        }
787

788
        return new Superglobals($server, $get, $post, $cookie, $files, $request);
780✔
789
    }
790

791
    /**
792
     * The Throttler class provides a simple method for implementing
793
     * rate limiting in your applications.
794
     *
795
     * @return Throttler
796
     */
797
    public static function throttler(bool $getShared = true)
798
    {
799
        if ($getShared) {
4✔
800
            return static::getSharedInstance('throttler');
1✔
801
        }
802

803
        return new Throttler(AppServices::get('cache'));
4✔
804
    }
805

806
    /**
807
     * The Timer class provides a simple way to Benchmark portions of your
808
     * application.
809
     *
810
     * @return Timer
811
     */
812
    public static function timer(bool $getShared = true)
813
    {
814
        if ($getShared) {
119✔
815
            return static::getSharedInstance('timer');
117✔
816
        }
817

818
        return new Timer();
117✔
819
    }
820

821
    /**
822
     * Return the debug toolbar.
823
     *
824
     * @return Toolbar
825
     */
826
    public static function toolbar(?ToolbarConfig $config = null, bool $getShared = true)
827
    {
828
        if ($getShared) {
107✔
829
            return static::getSharedInstance('toolbar', $config);
105✔
830
        }
831

832
        $config ??= config(ToolbarConfig::class);
107✔
833

834
        return new Toolbar($config);
107✔
835
    }
836

837
    /**
838
     * The URI class provides a way to model and manipulate URIs.
839
     *
840
     * @param string|null $uri The URI string
841
     *
842
     * @return URI The current URI if $uri is null.
843
     */
844
    public static function uri(?string $uri = null, bool $getShared = true)
845
    {
UNCOV
846
        if ($getShared) {
×
UNCOV
847
            return static::getSharedInstance('uri', $uri);
×
848
        }
849

UNCOV
850
        if ($uri === null) {
×
UNCOV
851
            $appConfig = config(App::class);
×
UNCOV
852
            $factory   = AppServices::siteurifactory($appConfig, AppServices::get('superglobals'));
×
853

UNCOV
854
            return $factory->createFromGlobals();
×
855
        }
856

UNCOV
857
        return new URI($uri);
×
858
    }
859

860
    /**
861
     * The Validation class provides tools for validating input data.
862
     *
863
     * @return ValidationInterface
864
     */
865
    public static function validation(?ValidationConfig $config = null, bool $getShared = true)
866
    {
867
        if ($getShared) {
151✔
868
            return static::getSharedInstance('validation', $config);
48✔
869
        }
870

871
        $config ??= config(ValidationConfig::class);
151✔
872

873
        return new Validation($config, AppServices::get('renderer'));
151✔
874
    }
875

876
    /**
877
     * View cells are intended to let you insert HTML into view
878
     * that has been generated by any callable in the system.
879
     *
880
     * @return Cell
881
     */
882
    public static function viewcell(bool $getShared = true)
883
    {
884
        if ($getShared) {
6✔
885
            return static::getSharedInstance('viewcell');
3✔
886
        }
887

888
        return new Cell(AppServices::get('cache'));
6✔
889
    }
890

891
    /**
892
     * The Typography class provides a way to format text in semantically relevant ways.
893
     *
894
     * @return Typography
895
     */
896
    public static function typography(bool $getShared = true)
897
    {
898
        if ($getShared) {
5✔
899
            return static::getSharedInstance('typography');
3✔
900
        }
901

902
        return new Typography();
5✔
903
    }
904

905
    /**
906
     * The Context class provides a way to store and retrieve static data throughout requests.
907
     */
908
    public static function context(bool $getShared = true): Context
909
    {
910
        if ($getShared) {
65✔
911
            return static::getSharedInstance('context');
2✔
912
        }
913

914
        return new Context();
65✔
915
    }
916
}
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